(*****************************************************************************) (* *) (* Open Source License *) (* Copyright (c) 2021 Nomadic Labs, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) (* to deal in the Software without restriction, including without limitation *) (* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) (* and/or sell copies of the Software, and to permit persons to whom the *) (* Software is furnished to do so, subject to the following conditions: *) (* *) (* The above copyright notice and this permission notice shall be included *) (* in all copies or substantial portions of the Software. *) (* *) (* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) (* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) (* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) (* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) (* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) (* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) (* DEALINGS IN THE SOFTWARE. *) (* *) (*****************************************************************************) open Protocol module Size = Gas_input_size let ns = Namespace.make Registration_helpers.ns "sapling" let fv s = Free_variable.of_namespace (ns s) module Apply_diff_bench : Benchmark.S = struct include Interpreter_benchmarks.Default_config include Interpreter_benchmarks.Default_boilerplate let name = ns "SAPLING_APPLY_DIFF" let info = "Benchmarking SAPLING_APPLY_DIFF" let module_filename = __FILE__ let generated_code_destination = None let tags = ["sapling"] let diff_from_tx (tx : Alpha_context.Sapling.transaction) = let open Environment.Sapling.UTXO in let commitments_and_ciphertexts = List.map (fun x -> (x.cm, x.ciphertext)) tx.outputs in { Protocol.Sapling_repr.commitments_and_ciphertexts; nullifiers = List.map (fun (x : input) -> x.nf) tx.inputs; } type workload = {nb_input : int; nb_output : int; nb_cm : int; nb_nf : int} let workload_encoding : workload Data_encoding.t = let open Data_encoding in def "diff_arg_encoding" @@ conv (fun {nb_input; nb_output; nb_cm; nb_nf} -> (nb_input, nb_output, nb_cm, nb_nf)) (fun (nb_input, nb_output, nb_cm, nb_nf) -> {nb_input; nb_output; nb_cm; nb_nf}) (tup4 Size.encoding Size.encoding Size.encoding Size.encoding) let workload_to_vector {nb_input; nb_output; nb_cm = _; nb_nf = _} = let l = [ ("nb_input", float_of_int nb_input); ("nb_output", float_of_int nb_output); ] in Sparse_vec.String.of_list l let model = Model.make ~conv:(fun {nb_input; nb_output; _} -> (nb_input, (nb_output, ()))) ~model: (Model.bilinear_affine ~name ~intercept:(fv "apply_diff_const") ~coeff1:(fv "apply_diff_inputs") ~coeff2:(fv "apply_diff_outputs")) let models = [("apply_diff", model)] let benchmark_apply_diff seed sapling_transition () = let sapling_forge_rng_state = Random.State.make @@ Option.fold ~none:Sapling_generation.shared_seed ~some:(fun seed -> [|seed|]) seed in Lwt_main.run ( Execution_context.make ~rng_state:sapling_forge_rng_state >>=? fun (ctxt, step_constants) -> Sapling_generation.prepare_seeded_state sapling_transition ctxt >>=? fun (_, _, _, _, ctxt, state_id) -> let external_state_id = Alpha_context.Sapling.Id.parse_z state_id in let internal_state_id = Lazy_storage_kind.Sapling_state.Id.parse_z state_id in Alpha_context.Sapling.(state_from_id ctxt external_state_id) >|= Environment.wrap_tzresult >>=? fun (state, ctxt) -> Format.eprintf "state hash: %d@." (Hashtbl.hash state.diff) ; Format.eprintf "tx hash: %d@." (Hashtbl.hash sapling_transition.sapling_tx) ; let address = Contract_hash.to_b58check step_constants.self in let chain_id = Environment.Chain_id.to_b58check step_constants.chain_id in let anti_replay = address ^ chain_id in Format.eprintf "anti-replay: %s@." anti_replay ; let diff = diff_from_tx sapling_transition.sapling_tx in let closure () = ignore (Lwt_main.run (Sapling_generation.apply_diff ctxt internal_state_id diff)) in let workload = { nb_input = List.length sapling_transition.sapling_tx.inputs; nb_output = List.length sapling_transition.sapling_tx.outputs; nb_cm = Int64.to_int sapling_transition.commitment_count; nb_nf = Int64.to_int sapling_transition.nullifier_count; } in return (Generator.Plain {workload; closure}) ) |> function | Ok closure -> closure | Error errs -> Format.eprintf "Runner.benchmarkable_from_instr_str:\n%a@." (Format.pp_print_list Error_monad.pp) errs ; exit 1 let create_benchmarks ~rng_state ~bench_num config = ignore rng_state ; match config.sapling with | {sapling_txs_file; seed} -> let transitions = Sapling_generation.load ~filename:sapling_txs_file Sapling_generation.Full_transaction in let length = List.length transitions in if length < bench_num then Format.eprintf "KSapling_verify_update: warning, only %d available transactions \ (requested %d)@." length bench_num ; let transitions = List.take_n (min bench_num length) transitions in List.map (fun (_filename, tx) -> benchmark_apply_diff seed tx) transitions end let () = Registration_helpers.register (module Apply_diff_bench)