Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DO NOT MERGE] Debug itn slow sl apply #14540

Closed
wants to merge 57 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
24159a6
Add tool to test application of txs to ledger
georgeee Nov 20, 2023
185cfcc
Break relation from the scan state
georgeee Nov 20, 2023
a86bcad
K mask test ledger apply
nholland94 Nov 21, 2023
5c146c4
Parametrize usage of masks in tool
georgeee Nov 21, 2023
fc61fa1
Decomission old ledgers in test-apply
georgeee Nov 24, 2023
1811f12
Add support of tracing to the tool
georgeee Nov 27, 2023
3022675
When comparing `Field.t` values, avoid the conversion to bigint
tizoc Nov 22, 2023
5651bce
Use `into_repr()` when comparing fields in Rust to ensure compatibili…
tizoc Nov 22, 2023
6fcd939
Field: More efficient conversion of into Bignum_bigint.t
tizoc Nov 22, 2023
b570c8f
Do not use binprot serialization when converting bigint fields, use Z…
tizoc Nov 27, 2023
da53792
Batch account location lookups for sparse ledger
mrmr1993 Nov 6, 2023
a96b86b
Fixup Masking_merkle_tree.location_of_account_batch
mrmr1993 Nov 8, 2023
d10bf7e
Fixup batching operations in masking ledger
georgeee Nov 8, 2023
f8c7017
Rename variable in merkle_path_dependencies_exn
georgeee Nov 28, 2023
85cf55c
Batch account lookups
mrmr1993 Nov 7, 2023
4271394
Refactor sparse ledger of_ledger_subset_exn
nholland94 Nov 22, 2023
fc58d3c
Add merkle_path_batch
mrmr1993 Nov 7, 2023
5147f71
Batch merkle_path lookups in Sparse_ledger
mrmr1993 Nov 7, 2023
0a01bd3
Return the merkle path from the current mask instead of from the ledger
mrmr1993 Nov 16, 2023
792b694
Always attempt to get the merkle path from the ledger mask
mrmr1993 Nov 17, 2023
a636e02
Update doc for copy method of masking ledger
mrmr1993 Nov 17, 2023
93ec85b
Fixup for self_merkle_path
georgeee Nov 28, 2023
d4442c4
Add helper to preload accounts and merkle paths in masks
mrmr1993 Nov 17, 2023
8961e65
Fixup set_merkle_path_unsafe
mrmr1993 Nov 17, 2023
ea94c34
Preload accounts for transactions
mrmr1993 Nov 21, 2023
683f708
Fixup: propagate unsafe_preload_accounts_from_parent
georgeee Nov 27, 2023
dcd469e
Add comment for unsafe_preload_accounts_from_parent
georgeee Nov 28, 2023
273ff38
Add get_hash_batch_exn to ledgers
mrmr1993 Nov 20, 2023
5e71099
Preload all hases for the merkle path and the self hashes in masks
mrmr1993 Nov 20, 2023
499fc6f
Allow fetching empty merkle paths from masks
mrmr1993 Nov 20, 2023
e889475
Handle known-empty accounts in merkle masks without hitting the db
mrmr1993 Nov 20, 2023
cc770e5
Handle known-empty accounts in get_batch for merkle masks
mrmr1993 Nov 20, 2023
8c66c3e
Remove invalid test: mask parents should not be changed
mrmr1993 Nov 21, 2023
df631b4
Remove a TODO in location_of_account_batch
georgeee Nov 28, 2023
a8b5b8e
Avoid ledger copy and mutation in Sparse_ledger.of_ledger_subset_exn
mrmr1993 Nov 21, 2023
40060b7
refactor the code a little bit
Nov 29, 2023
4ae3174
further clean up the code
Nov 29, 2023
717ff96
Small refactoring in of_ledger_subset_exn
georgeee Nov 29, 2023
479de73
Add Sparse_ledger.add_wide_path
mrmr1993 Nov 21, 2023
096bd02
Add add_wide_path_batch to Ledger_intf
mrmr1993 Nov 21, 2023
60525af
Use wide ledger paths for `Sparse_ledger.of_ledger_subset_exn`
mrmr1993 Nov 21, 2023
878f4a2
Refactor wide merkle path functions
georgeee Nov 27, 2023
7ead694
Small rewrite of path_batch_impl
georgeee Nov 27, 2023
f9c857e
Nit: rename variables
georgeee Nov 28, 2023
99ff560
Refactor wide_merkle_path_batch
Nov 29, 2023
2fd7006
fix the order of the locations
Nov 29, 2023
14890c4
fixup! Use wide ledger paths for `Sparse_ledger.of_ledger_subset_exn`
georgeee Nov 29, 2023
1dcc493
Refactor add_wide_path_unsafe
georgeee Nov 29, 2023
c2d3c16
Replace tables with maps in merkle masks
nholland94 Nov 21, 2023
9f7194d
Fix merkle ledger tests
nholland94 Nov 22, 2023
655e4ec
Use map refs instead of mutable map fields
nholland94 Nov 22, 2023
04e1b02
Fixup after rebase
georgeee Nov 27, 2023
dbc44f9
Merge remote-tracking branch 'om/optimization/efficient-bignum-bigint…
georgeee Nov 28, 2023
c22e2f1
Merge branch 'georgeee/test-max-block-ledger-application' into debug-…
georgeee Nov 28, 2023
5772b5b
Revert "Merge pull request #14397 from MinaProtocol/fix/itn-mangled-e…
nholland94 Nov 9, 2023
547e798
Staged ledger timing debug logs
nholland94 Nov 9, 2023
1583345
Preload accounts in test-apply tool
georgeee Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/app/cli/src/init/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,55 @@ let thread_graph =
(humanize_graphql_error ~graphql_endpoint e) ) ;
exit 1 ) )

let test_ledger_application =
Command.async ~summary:"Test ledger application"
(let%map_open.Command privkey_path = Cli_lib.Flag.privkey_read_path
and prev_block_path =
flag "--prev-block-path" ~doc:"FILE file with serialized block"
(required string)
and ledger_path =
flag "--ledger-path" ~doc:"FILE directory with ledger DB"
(required string)
and num_txs =
flag "--num-txs"
~doc:"NN Number of transactions to create after preparatory rounds"
(required int)
and num_txs_per_round =
flag "--num-txs-per-round"
~doc:
"NN Number of transactions to create per preparatory round \
(default: 3)"
(optional int)
and rounds =
flag "--rounds" ~doc:"NN Number of preparatory rounds (default: 580)"
(optional int)
and first_partition_slots =
flag "--first-partition-slots"
~doc:
"NN Number of slots in first partition of scan state (default: 128)"
(optional int)
and max_depth =
flag "--max-depth" ~doc:"NN Maximum depth of masks (default: 290)"
(optional int)
and no_new_stack =
flag "--old-stack" ~doc:"Use is_new_stack: false (scan state)" no_arg
and has_second_partition =
flag "--has-second-partition"
~doc:"Assume there is a second partition (scan state)" no_arg
and tracing = flag "--tracing" ~doc:"Wrap test into tracing" no_arg
and no_masks = flag "--no-masks" ~doc:"Do not create masks" no_arg in
Cli_lib.Exceptions.handle_nicely
@@ fun () ->
let first_partition_slots =
Option.value ~default:128 first_partition_slots
in
let num_txs_per_round = Option.value ~default:3 num_txs_per_round in
let rounds = Option.value ~default:580 rounds in
let max_depth = Option.value ~default:290 max_depth in
Test_ledger_application.test ~privkey_path ~ledger_path ~prev_block_path
~first_partition_slots ~no_new_stack ~has_second_partition
~num_txs_per_round ~rounds ~no_masks ~max_depth ~tracing num_txs )

let itn_create_accounts =
Command.async ~summary:"Fund new accounts for incentivized testnet"
(let open Command.Param in
Expand Down Expand Up @@ -2393,6 +2442,7 @@ let ledger =
[ ("export", export_ledger)
; ("hash", hash_ledger)
; ("currency", currency_in_ledger)
; ("test-apply", test_ledger_application)
]

let libp2p =
Expand Down
1 change: 1 addition & 0 deletions src/app/cli/src/init/dune
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
string_sign
zkapp_command_builder
internal_tracing
transaction_snark_scan_state
)
(instrumentation (backend bisect_ppx))
(preprocessor_deps ../../../../config.mlh
Expand Down
186 changes: 186 additions & 0 deletions src/app/cli/src/init/test_ledger_application.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
(* test_ledger_application.ml -- code to test application of transactions to a specific ledger *)

open Core_kernel
open Async_kernel
open Mina_ledger
open Mina_base
open Mina_state

let constraint_constants = Genesis_constants.Constraint_constants.compiled

let logger = Logger.create ()

let read_privkey privkey_path =
let password =
lazy (Secrets.Keypair.Terminal_stdin.prompt_password "Enter password: ")
in
match%map Secrets.Keypair.read ~privkey_path ~password with
| Ok keypair ->
keypair
| Error err ->
eprintf "Could not read the specified keypair: %s\n"
(Secrets.Privkey_error.to_string err) ;
exit 1

let mk_tx acc_creation_fee keypair nonce =
let num_acc_updates = 8 in
let multispec : Transaction_snark.For_tests.Multiple_transfers_spec.t =
let fee_payer = None in
let receivers =
List.init num_acc_updates ~f:(fun _ ->
let kp = Signature_lib.Keypair.create () in
(Signature_lib.Public_key.compress kp.public_key, Currency.Amount.zero) )
in
let zkapp_account_keypairs = [] in
let new_zkapp_account = false in
let snapp_update = Account_update.Update.dummy in
let actions = [] in
let events = [] in
let call_data = Snark_params.Tick.Field.zero in
let preconditions = Some Account_update.Preconditions.accept in
{ fee = Currency.Fee.of_mina_int_exn 1
; sender = (keypair, nonce)
; fee_payer
; receivers
; amount =
Currency.Amount.(scale (of_fee acc_creation_fee) num_acc_updates)
|> Option.value_exn
; zkapp_account_keypairs
; memo = Signed_command_memo.empty
; new_zkapp_account
; snapp_update
; actions
; events
; call_data
; preconditions
}
in
Transaction_snark.For_tests.multiple_transfers multispec

let apply_txs ~first_partition_slots ~no_new_stack ~has_second_partition
~num_txs ~prev_protocol_state ~(keypair : Signature_lib.Keypair.t) ~i ledger
=
let init_nonce =
let account_id = Account_id.of_public_key keypair.public_key in
let loc =
Ledger.location_of_account ledger account_id |> Option.value_exn
in
let account = Ledger.get ledger loc |> Option.value_exn in
account.nonce
in
let to_nonce =
Fn.compose (Unsigned.UInt32.add init_nonce) Unsigned.UInt32.of_int
in
let mk_txs' = mk_tx constraint_constants.account_creation_fee keypair in
let fork_slot =
Option.value_map ~default:Mina_numbers.Global_slot_since_genesis.zero
~f:(fun f -> f.genesis_slot)
constraint_constants.fork
in
let prev_protocol_state_body_hash =
Protocol_state.body prev_protocol_state |> Protocol_state.Body.hash
in
let prev_protocol_state_hash =
(Protocol_state.hashes_with_body ~body_hash:prev_protocol_state_body_hash
prev_protocol_state )
.state_hash
in
let prev_state_view =
Protocol_state.body prev_protocol_state
|> Mina_state.Protocol_state.Body.view
in
let global_slot =
Protocol_state.consensus_state prev_protocol_state
|> Consensus.Data.Consensus_state.curr_global_slot
|> Mina_numbers.Global_slot_since_hard_fork.succ
|> Mina_numbers.Global_slot_since_hard_fork.to_int
|> Mina_numbers.Global_slot_span.of_int
|> Mina_numbers.Global_slot_since_genesis.add fork_slot
in
let zkapps = List.init num_txs ~f:(Fn.compose mk_txs' to_nonce) in
let pending_coinbase =
Pending_coinbase.create ~depth:constraint_constants.pending_coinbase_depth
()
|> Or_error.ok_exn
in
let zkapps' =
List.map zkapps ~f:(fun tx ->
{ With_status.data =
Mina_transaction.Transaction.Command (User_command.Zkapp_command tx)
; status = Applied
} )
in
let accounts_accessed =
List.fold_left ~init:Account_id.Set.empty zkapps ~f:(fun set txn ->
Account_id.Set.(
union set (of_list (Zkapp_command.accounts_referenced txn))) )
|> Set.to_list
in
Ledger.unsafe_preload_accounts_from_parent ledger accounts_accessed ;
let start = Time.now () in
match%map
Staged_ledger.For_tests.update_coinbase_stack_and_get_data_impl
~first_partition_slots ~is_new_stack:(not no_new_stack)
~no_second_partition:(not has_second_partition) ~constraint_constants
~logger ~global_slot ledger pending_coinbase zkapps' prev_state_view
(prev_protocol_state_hash, prev_protocol_state_body_hash)
with
| Ok (b, _, _, _, _) ->
printf
!"Result of application %d: %B (took %s)\n%!"
i b
Time.(Span.to_string @@ diff (now ()) start)
| Error e ->
eprintf
!"Error applying staged ledger: %s\n%!"
(Staged_ledger.Staged_ledger_error.to_string e) ;
exit 1

let test ~privkey_path ~ledger_path ~prev_block_path ~first_partition_slots
~no_new_stack ~has_second_partition ~num_txs_per_round ~rounds ~no_masks
~max_depth ~tracing num_txs_final =
O1trace.thread "mina"
@@ fun () ->
let%bind keypair = read_privkey privkey_path in
let init_ledger =
Ledger.create ~directory_name:ledger_path
~depth:constraint_constants.ledger_depth ()
in
let prev_block_data = In_channel.read_all prev_block_path in
let prev_block =
Binable.of_string (module Mina_block.Stable.Latest) prev_block_data
in
let prev_protocol_state =
Mina_block.header prev_block |> Mina_block.Header.protocol_state
in
let apply =
apply_txs ~first_partition_slots ~no_new_stack ~has_second_partition
~prev_protocol_state ~keypair
in
let mask_handler ledger =
if no_masks then Fn.const ledger
else
Fn.compose (Ledger.register_mask ledger)
@@ Ledger.Mask.create ~depth:constraint_constants.ledger_depth
in
let drop_old_ledger ledger =
if not no_masks then (
Ledger.commit ledger ;
Ledger.remove_and_reparent_exn ledger ledger )
in
let stop_tracing =
if tracing then (fun x -> Mina_tracing.stop () ; x) else ident
in
Deferred.List.fold (List.init rounds ~f:ident) ~init:(init_ledger, [])
~f:(fun (ledger, ledgers) i ->
let%bind () =
if tracing && i = 1 then Mina_tracing.start "." else Deferred.unit
in
List.hd (List.drop ledgers (max_depth - 1))
|> Option.iter ~f:drop_old_ledger ;
apply ~num_txs:num_txs_per_round ~i ledger
>>| mask_handler ledger
>>| Fn.flip Tuple2.create (ledger :: ledgers) )
>>| fst
>>= apply ~num_txs:num_txs_final ~i:rounds
>>| stop_tracing
28 changes: 13 additions & 15 deletions src/lib/cli_lib/commands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,19 @@ open Async

let generate_keypair =
Command.async ~summary:"Generate a new public, private keypair"
(let open Command.Let_syntax in
let%map_open privkey_path = Flag.privkey_write_path in
Exceptions.handle_nicely
@@ fun () ->
let env = Secrets.Keypair.env in
if Option.is_some (Sys.getenv env) then
eprintf "Using password from environment variable %s\n" env ;
let open Deferred.Let_syntax in
let kp = Keypair.create () in
let%bind () = Secrets.Keypair.Terminal_stdin.write_exn kp ~privkey_path in
printf "Keypair generated\nPublic key: %s\nRaw public key: %s\n"
( kp.public_key |> Public_key.compress
|> Public_key.Compressed.to_base58_check )
(Rosetta_coding.Coding.of_public_key kp.public_key) ;
exit 0)
(let%map_open.Command privkey_path = Flag.privkey_write_path in
Exceptions.handle_nicely
@@ fun () ->
let env = Secrets.Keypair.env in
if Option.is_some (Sys.getenv env) then
eprintf "Using password from environment variable %s\n" env ;
let kp = Keypair.create () in
let%bind () = Secrets.Keypair.Terminal_stdin.write_exn kp ~privkey_path in
printf "Keypair generated\nPublic key: %s\nRaw public key: %s\n"
( kp.public_key |> Public_key.compress
|> Public_key.Compressed.to_base58_check )
(Rosetta_coding.Coding.of_public_key kp.public_key) ;
exit 0 )

let validate_keypair =
Command.async ~summary:"Validate a public, private keypair"
Expand Down
1 change: 1 addition & 0 deletions src/lib/crypto/kimchi_backend/common/dune
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
base.caml
ppx_inline_test.config
bignum.bigint
zarith
base.base_internalhash_types
;; local libraries
tuple_lib
Expand Down
26 changes: 13 additions & 13 deletions src/lib/crypto/kimchi_backend/common/field.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ module type Input_intf = sig

val is_square : t -> bool

val compare : t -> t -> int

val equal : t -> t -> bool

val print : t -> unit
Expand Down Expand Up @@ -177,24 +179,22 @@ module Make (F : Input_intf) :
let of_sexpable = of_bigint
end)

let to_bignum_bigint n =
let rec go i two_to_the_i acc =
if Int.equal i size_in_bits then acc
let to_bignum_bigint =
let zero = of_int 0 in
let one = of_int 1 in
fun n ->
if equal n zero then Bignum_bigint.zero
else if equal n one then Bignum_bigint.one
else
let acc' =
if Bigint.test_bit n i then Bignum_bigint.(acc + two_to_the_i)
else acc
in
go (i + 1) Bignum_bigint.(two_to_the_i + two_to_the_i) acc'
in
go 0 Bignum_bigint.one Bignum_bigint.zero
Bytes.unsafe_to_string
~no_mutation_while_string_reachable:(to_bytes n)
|> Z.of_bits |> Bignum_bigint.of_zarith_bigint

let hash_fold_t s x =
Bignum_bigint.hash_fold_t s (to_bignum_bigint (to_bigint x))
let hash_fold_t s x = Bignum_bigint.hash_fold_t s (to_bignum_bigint x)

let hash = Hash.of_fold hash_fold_t

let compare t1 t2 = Bigint.compare (to_bigint t1) (to_bigint t2)
let compare = compare

let equal = equal

Expand Down
4 changes: 2 additions & 2 deletions src/lib/crypto/kimchi_backend/kimchi_backend.mli
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ module Kimchi_backend_common : sig

val sexp_of_t : t -> Sexplib0.Sexp.t

val compare : t -> t -> int

val bin_size_t : t Bin_prot.Size.sizer

val bin_write_t : t Bin_prot.Write.writer
Expand Down Expand Up @@ -56,6 +54,8 @@ module Kimchi_backend_common : sig

val is_square : t -> bool

val compare : t -> t -> int

val equal : t -> t -> bool

val print : t -> unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl CamlFp {
unsafe extern "C" fn ocaml_compare(x: ocaml::Raw, y: ocaml::Raw) -> i32 {
let x = x.as_pointer::<Self>();
let y = y.as_pointer::<Self>();
match x.as_ref().0.cmp(&y.as_ref().0) {
match x.as_ref().0.into_repr().cmp(&y.as_ref().0.into_repr()) {
core::cmp::Ordering::Less => -1,
core::cmp::Ordering::Equal => 0,
core::cmp::Ordering::Greater => 1,
Expand Down Expand Up @@ -240,7 +240,7 @@ pub fn caml_pasta_fp_mut_square(mut x: ocaml::Pointer<CamlFp>) {
#[ocaml_gen::func]
#[ocaml::func]
pub fn caml_pasta_fp_compare(x: ocaml::Pointer<CamlFp>, y: ocaml::Pointer<CamlFp>) -> ocaml::Int {
match x.as_ref().0.cmp(&y.as_ref().0) {
match x.as_ref().0.into_repr().cmp(&y.as_ref().0.into_repr()) {
Less => -1,
Equal => 0,
Greater => 1,
Expand Down
Loading