From 95faad2a37f5b6d258a815800feb7f5dfb16a9c8 Mon Sep 17 00:00:00 2001 From: Akosh Farkash Date: Thu, 9 Nov 2023 14:31:27 +0000 Subject: [PATCH] FIX: Debug genesis non determinism (#415) * LOG: Log interim state root hashes * TEST: Unit test for repeated genesis execution * FIX: Swith to BTreeSet * LOG: Log individual insertions into the HAMT * LOG: Log genesis content * FIX: Need to use f410 locally unless we want to set the network * FIX: Update IPC provider * LOG: Log system account addr-to-id --- Cargo.lock | 182 ++++++++++-------- fendermint/app/src/app.rs | 9 +- fendermint/vm/actor_interface/Cargo.toml | 1 + fendermint/vm/actor_interface/src/init.rs | 39 ++-- fendermint/vm/interpreter/src/fvm/genesis.rs | 111 +++++++++-- .../vm/interpreter/src/fvm/state/genesis.rs | 18 ++ 6 files changed, 237 insertions(+), 123 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b70ae485..363d428c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,7 +153,7 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "once_cell", "version_check", ] @@ -165,7 +165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", - "getrandom 0.2.10", + "getrandom 0.2.11", "once_cell", "version_check", "zerocopy", @@ -455,7 +455,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -697,7 +697,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1216,7 +1216,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1540,9 +1540,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4939f9ed1444bd8c896d37f3090012fa6e7834fe84ef8c9daa166109515732f9" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" @@ -1765,7 +1765,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1826,7 +1826,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1848,7 +1848,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1957,7 +1957,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2081,7 +2081,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2359,9 +2359,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -2513,7 +2513,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.38", + "syn 2.0.39", "toml 0.7.8", "walkdir", ] @@ -2531,7 +2531,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2557,7 +2557,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.38", + "syn 2.0.39", "tempfile", "thiserror", "tiny-keccak", @@ -2729,7 +2729,7 @@ checksum = "55a9a55d1dab3b07854648d48e366f684aefe2ac78ae28cec3bf65e3cd53d9a3" dependencies = [ "execute-command-tokens", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3070,6 +3070,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_tuple", + "tracing", ] [[package]] @@ -3262,9 +3263,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a481586acf778f1b1455424c343f71124b048ffa5f4fc3f8f6ae9dc432dcb3c7" +checksum = "f69037fe1b785e84986b4f2cbcf647381876a00671d25ceef715d7812dd7e1dd" [[package]] name = "fil_actors_evm_shared" @@ -3297,7 +3298,7 @@ dependencies = [ "fvm_ipld_hamt 0.5.1", "fvm_sdk", "fvm_shared", - "getrandom 0.2.10", + "getrandom 0.2.11", "indexmap 1.9.3", "integer-encoding", "itertools 0.10.5", @@ -3669,7 +3670,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -4008,9 +4009,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -4640,7 +4641,7 @@ dependencies = [ [[package]] name = "ipc-identity" version = "0.1.0" -source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#6d69633eb45d2af15b4a0ae6cb814c391e22338b" +source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#99b4528319bbd357079ecfd787afd5ee5809d3ba" dependencies = [ "ahash 0.8.6", "anyhow", @@ -4667,7 +4668,7 @@ dependencies = [ [[package]] name = "ipc-provider" version = "0.1.0" -source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#6d69633eb45d2af15b4a0ae6cb814c391e22338b" +source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#99b4528319bbd357079ecfd787afd5ee5809d3ba" dependencies = [ "anyhow", "async-channel", @@ -4707,7 +4708,7 @@ dependencies = [ [[package]] name = "ipc-sdk" version = "0.1.0" -source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#6d69633eb45d2af15b4a0ae6cb814c391e22338b" +source = "git+https://github.com/consensus-shipyard/ipc.git?branch=dev#99b4528319bbd357079ecfd787afd5ee5809d3ba" dependencies = [ "anyhow", "cid", @@ -4731,7 +4732,7 @@ dependencies = [ [[package]] name = "ipc_actors_abis" version = "0.1.0" -source = "git+https://github.com/consensus-shipyard/ipc-solidity-actors.git?branch=dev#b4c23f216b813f10dfa6fa54ea4cb248012cf312" +source = "git+https://github.com/consensus-shipyard/ipc-solidity-actors.git?branch=dev#9c85f9d110ba10737d258094085e70bb9f0ad54d" dependencies = [ "anyhow", "ethers", @@ -4978,9 +4979,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libipld" @@ -5075,7 +5076,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.10", + "getrandom 0.2.11", "instant", "libp2p-core 0.38.0", "libp2p-dns", @@ -5556,6 +5557,17 @@ dependencies = [ "yamux", ] +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "librocksdb-sys" version = "0.11.0+8.1.1" @@ -5651,9 +5663,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -6241,7 +6253,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6322,9 +6334,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.58" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dfc0783362704e97ef3bd24261995a699468440099ef95d869b4d9732f829a" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -6343,7 +6355,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6363,9 +6375,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.94" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f55da20b29f956fb01f0add8683eb26ee13ebe3ebd935e49898717c6b4b2830" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -6657,7 +6669,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6721,7 +6733,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6759,7 +6771,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -6924,7 +6936,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -7293,7 +7305,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -7388,12 +7400,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -7557,7 +7569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", - "getrandom 0.2.10", + "getrandom 0.2.11", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -7723,7 +7735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", - "errno 0.3.5", + "errno 0.3.6", "io-lifetimes 1.0.11", "libc", "linux-raw-sys 0.3.8", @@ -7737,9 +7749,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", - "errno 0.3.5", + "errno 0.3.6", "libc", - "linux-raw-sys 0.4.10", + "linux-raw-sys 0.4.11", "windows-sys 0.48.0", ] @@ -8021,9 +8033,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] @@ -8048,13 +8060,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -8098,7 +8110,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -8168,7 +8180,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -8660,7 +8672,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -8714,9 +8726,9 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "svm-rs" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0cc95be7cc2c384a2f57cac56548d2178650905ebe5725bc8970ccc25529060" +checksum = "20689c7d03b6461b502d0b95d6c24874c7d24dea2688af80486a130a06af3b07" dependencies = [ "dirs", "fs2", @@ -8745,9 +8757,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -8953,7 +8965,7 @@ dependencies = [ "bytes", "flex-error", "futures", - "getrandom 0.2.10", + "getrandom 0.2.11", "http", "hyper", "hyper-proxy", @@ -9023,7 +9035,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -9135,7 +9147,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -9375,7 +9387,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -9690,7 +9702,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", "serde", ] @@ -9700,7 +9712,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -9806,7 +9818,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] @@ -9840,7 +9852,7 @@ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9896,9 +9908,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.116.0" +version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53290b1276c5c2d47d694fb1a920538c01f51690e7e261acbe1d10c5fc306ea1" +checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" dependencies = [ "indexmap 2.1.0", "semver", @@ -9906,12 +9918,12 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.71" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f98260aa20f939518bcec1fac32c78898d5c68872e7363a4651f21f791b6c7e" +checksum = "9aff4df0cdf1906ec040e97d78c3fc8fd26d3f8d70adaac81f07f80957b63b54" dependencies = [ "anyhow", - "wasmparser 0.116.0", + "wasmparser 0.116.1", ] [[package]] @@ -10549,9 +10561,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.18" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -10717,22 +10729,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.23" +version = "0.7.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50cbb27c30666a6108abd6bc7577556265b44f243e2be89a8bc4e07a528c107" +checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.23" +version = "0.7.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25f293fe55f0a48e7010d65552bb63704f6ceb55a1a385da10d41d8f78e4a3d" +checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -10752,7 +10764,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] diff --git a/fendermint/app/src/app.rs b/fendermint/app/src/app.rs index e41397d8..00e54ba1 100644 --- a/fendermint/app/src/app.rs +++ b/fendermint/app/src/app.rs @@ -464,9 +464,16 @@ where "pre-genesis state created" ); + let genesis_bytes = request.app_state_bytes.to_vec(); + let genesis_hash = + fendermint_vm_message::cid(&genesis_bytes).context("failed to compute genesis CID")?; + + // Make it easy to spot any discrepancies between nodes. + tracing::info!(genesis_hash = genesis_hash.to_string(), "genesis"); + let (state, out) = self .interpreter - .init(state, request.app_state_bytes.to_vec()) + .init(state, genesis_bytes) .await .context("failed to init from genesis")?; diff --git a/fendermint/vm/actor_interface/Cargo.toml b/fendermint/vm/actor_interface/Cargo.toml index 4bb3cbcb..41ca2fea 100644 --- a/fendermint/vm/actor_interface/Cargo.toml +++ b/fendermint/vm/actor_interface/Cargo.toml @@ -17,6 +17,7 @@ merkle-tree-rs = { workspace = true } paste = { workspace = true } serde = { workspace = true } serde_tuple = { workspace = true } +tracing = { workspace = true } cid = { workspace = true } fvm_shared = { workspace = true } diff --git a/fendermint/vm/actor_interface/src/init.rs b/fendermint/vm/actor_interface/src/init.rs index 295ed931..7fca7cfb 100644 --- a/fendermint/vm/actor_interface/src/init.rs +++ b/fendermint/vm/actor_interface/src/init.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet}; // Copyright 2022-2023 Protocol Labs // SPDX-License-Identifier: Apache-2.0, MIT @@ -18,7 +18,7 @@ pub const FIRST_NON_SINGLETON_ADDR: ActorID = 100; define_singleton!(INIT { id: 1, code_id: 2 }); -pub type AddressMap = HashMap; +pub type AddressMap = BTreeMap; /// Delegated address of an Ethereum built-in actor. /// @@ -57,14 +57,23 @@ impl State { // Accounts from the Genesis file. accounts: &[Actor], // Pre-defined IDs for top-level EVM contracts. - eth_builtin_ids: &HashSet, + eth_builtin_ids: &BTreeSet, // Number of dynamically deployed EVM library contracts. eth_library_count: u64, ) -> anyhow::Result<(Self, AddressMap)> { // Returning only the addreses that belong to user accounts. let mut allocated_ids = AddressMap::new(); // Inserting both user accounts and built-in EVM actors. - let mut address_map = Hamt::<_, ActorID>::new_with_bit_width(store, HAMT_BIT_WIDTH); + let mut address_map = Hamt::<&BS, ActorID>::new_with_bit_width(store, HAMT_BIT_WIDTH); + + let mut set_address = |addr: Address, id: ActorID| { + tracing::debug!( + addr = addr.to_string(), + actor_id = id, + "setting init address" + ); + address_map.set(addr.to_bytes().into(), id) + }; let addresses = accounts.iter().flat_map(|a| match &a.meta { ActorMeta::Account(acc) => { @@ -80,9 +89,7 @@ impl State { continue; } allocated_ids.insert(addr, next_id); - address_map - .set(addr.to_bytes().into(), next_id) - .context("cannot set ID of address")?; + set_address(addr, next_id).context("cannot set ID of account address")?; next_id += 1; } @@ -99,28 +106,20 @@ impl State { // Insert top-level EVM contracts which have fixed IDs. for id in eth_builtin_ids { let addr = Address::from(builtin_actor_eth_addr(*id)); - address_map - .set(addr.to_bytes().into(), *id) - .context("cannot set ID of eth address")?; + set_address(addr, *id).context("cannot set ID of eth contract address")?; } // Insert dynamic EVM library contracts. for _ in 0..eth_library_count { let addr = Address::from(builtin_actor_eth_addr(next_id)); - address_map - .set(addr.to_bytes().into(), next_id) - .context("cannot set ID of eth address")?; + set_address(addr, next_id).context("cannot set ID of eth library address")?; next_id += 1; } // Insert the null-Ethereum address to equal the system actor, // so the system actor can be identified by 0xff00..00 as well as 0x00..00 - address_map - .set( - system::SYSTEM_ACTOR_ETH_ADDR.to_bytes().into(), - system::SYSTEM_ACTOR_ID, - ) - .context("cannot set ID of null eth address")?; + set_address(*system::SYSTEM_ACTOR_ETH_ADDR, system::SYSTEM_ACTOR_ID) + .context("cannot set ID of system eth address")?; #[cfg(feature = "m2-native")] let installed_actors = store.put_cbor(&Vec::::new(), Code::Blake2b256)?; @@ -133,6 +132,8 @@ impl State { installed_actors, }; + tracing::debug!(?state, "init actor state"); + Ok((state, allocated_ids)) } } diff --git a/fendermint/vm/interpreter/src/fvm/genesis.rs b/fendermint/vm/interpreter/src/fvm/genesis.rs index 18f476df..42cd05a2 100644 --- a/fendermint/vm/interpreter/src/fvm/genesis.rs +++ b/fendermint/vm/interpreter/src/fvm/genesis.rs @@ -1,7 +1,7 @@ // Copyright 2022-2023 Protocol Labs // SPDX-License-Identifier: Apache-2.0, MIT -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap}; use std::marker::PhantomData; use std::path::{Path, PathBuf}; @@ -30,6 +30,7 @@ use crate::GenesisInterpreter; use super::state::FvmGenesisState; use super::FvmMessageInterpreter; +#[derive(Debug, Clone, PartialEq, Eq)] pub struct FvmGenesisOutput { pub chain_id: ChainID, pub timestamp: Timestamp, @@ -77,6 +78,9 @@ where mut state: Self::State, genesis: Self::Genesis, ) -> anyhow::Result<(Self::State, Self::Output)> { + // Log the genesis in JSON format, hopefully it's not enormous. + tracing::debug!(genesis = serde_json::to_string(&genesis)?, "init"); + // NOTE: We could consider adding the chain ID to the interpreter // and rejecting genesis if it doesn't match the expectation, // but the Tendermint genesis file also has this field, and @@ -107,7 +111,7 @@ where // STAGE 0: Declare the built-in EVM contracts we'll have to deploy. // Pre-defined IDs for top-level Ethereum contracts. - let mut eth_builtin_ids = HashSet::new(); + let mut eth_builtin_ids = BTreeSet::new(); let mut eth_root_contracts = Vec::new(); let mut eth_contracts = EthContractMap::default(); @@ -463,11 +467,13 @@ fn circ_supply(g: &Genesis) -> TokenAmount { #[cfg(test)] mod tests { - use std::sync::Arc; + use std::{str::FromStr, sync::Arc}; + use cid::Cid; use fendermint_vm_genesis::{ipc::IpcParams, Genesis}; use fvm::engine::MultiEngine; use quickcheck::Arbitrary; + use tendermint_rpc::{MockClient, MockRequestMethodMatcher}; use crate::{ fvm::{ @@ -483,28 +489,17 @@ mod tests { #[tokio::test] async fn load_genesis() { - let mut g = quickcheck::Gen::new(5); - let mut genesis = Genesis::arbitrary(&mut g); - - // Make sure we have IPC enabled. - genesis.ipc = Some(IpcParams::arbitrary(&mut g)); + let genesis = make_genesis(); + let bundle = read_bundle(); + let interpreter = make_interpreter(); - eprintln!("genesis = {genesis:?}"); - - let bundle = std::fs::read(bundle_path()).expect("failed to read bundle"); - let store = MemoryBlockstore::new(); let multi_engine = Arc::new(MultiEngine::default()); + let store = MemoryBlockstore::new(); let state = FvmGenesisState::new(store, multi_engine, &bundle) .await .expect("failed to create state"); - let (client, _) = - tendermint_rpc::MockClient::new(tendermint_rpc::MockRequestMethodMatcher::default()); - - let interpreter = - FvmMessageInterpreter::new(client, None, contracts_path(), 1.05, 1.05, false); - let (mut state, out) = interpreter .init(state, genesis.clone()) .await @@ -524,4 +519,84 @@ mod tests { let _state_root = state.commit().expect("failed to commit"); } + + #[tokio::test] + async fn load_genesis_deterministic() { + let genesis = make_genesis(); + let bundle = read_bundle(); + let interpreter = make_interpreter(); + let multi_engine = Arc::new(MultiEngine::default()); + + // Create a couple of states and load the same thing. + let mut outputs = Vec::new(); + for _ in 0..3 { + let store = MemoryBlockstore::new(); + let state = FvmGenesisState::new(store, multi_engine.clone(), &bundle) + .await + .expect("failed to create state"); + + let (state, out) = interpreter + .init(state, genesis.clone()) + .await + .expect("failed to create actors"); + + let state_root_hash = state.commit().expect("failed to commit"); + outputs.push((state_root_hash, out)); + } + + for out in &outputs[1..] { + assert_eq!(out.0, outputs[0].0, "state root hash is different"); + } + } + + // This is a sort of canary test, if it fails means something changed in the way we do genesis, + // which is probably fine, but it's better to know about it, and if anybody doesn't get the same + // then we might have some non-determinism. + #[tokio::test] + async fn load_genesis_known() { + let genesis_json = "{\"chain_name\":\"/r314159/f410fnfmitm2ww7oehhtbokf6wulhrr62sgq3sgqmenq\",\"timestamp\":1073250,\"network_version\":18,\"base_fee\":\"1000\",\"power_scale\":3,\"validators\":[{\"public_key\":\"BLX9ojqB+8Z26aMmKoCRb3Te6AnSU6zY8hPcf1X5Q69XCNaHVcRxzYO2xx7o/2vgdS7nkDTMRRbkDGzy+FYdAFc=\",\"power\":\"1000000000000000000\"},{\"public_key\":\"BFcOveVieknZiscWsfXa06aGbBkKeucBycd/w0N1QHlaZfa/5dJcH7D0hvcdfv3B2Rv1OPuxo1PkgsEbWegWKcA=\",\"power\":\"1000000000000000000\"},{\"public_key\":\"BEP30ykovfrQp3zo+JVRvDVL2emC+Ju1Kpox3zMVYZyFKvYt64qyN/HOVjridDrkEsnQU8BVen4Aegja4fBZ+LU=\",\"power\":\"1000000000000000000\"}],\"accounts\":[{\"meta\":{\"Account\":{\"owner\":\"f410fggjevhgketpz6gw6ordusynlgcd5piyug4aomuq\"}},\"balance\":\"1000000000000000000\"},{\"meta\":{\"Account\":{\"owner\":\"f410frbdnwklaitcjsqe7swjwp5naple6vthq4woyfry\"}},\"balance\":\"2000000000000000000\"},{\"meta\":{\"Account\":{\"owner\":\"f410fxo4lih4n2acr3oadalidwqjgoqkzhp5dw3zwkvy\"}},\"balance\":\"1000000000000000000\"}],\"ipc\":{\"gateway\":{\"subnet_id\":\"/r314159/f410fnfmitm2ww7oehhtbokf6wulhrr62sgq3sgqmenq\",\"bottom_up_check_period\":30,\"msg_fee\":\"1000000000000\",\"majority_percentage\":60,\"min_collateral\":\"1000000000000000000\",\"active_validators_limit\":100}}}"; + + let genesis: Genesis = serde_json::from_str(genesis_json).expect("failed to parse genesis"); + + let bundle = read_bundle(); + let interpreter = make_interpreter(); + let multi_engine = Arc::new(MultiEngine::default()); + + let store = MemoryBlockstore::new(); + let state = FvmGenesisState::new(store, multi_engine.clone(), &bundle) + .await + .expect("failed to create state"); + + let (state, _) = interpreter + .init(state, genesis.clone()) + .await + .expect("failed to create actors"); + + let state_root_hash = state.commit().expect("failed to commit"); + + let expected_root_hash = + Cid::from_str("bafy2bzacecl5t5fxuqqbekae6racgvvoriv3o7xweerdngijwehukaao6bmlg") + .unwrap(); + + assert_eq!(state_root_hash, expected_root_hash); + } + + fn make_genesis() -> Genesis { + let mut g = quickcheck::Gen::new(5); + let mut genesis = Genesis::arbitrary(&mut g); + + // Make sure we have IPC enabled. + genesis.ipc = Some(IpcParams::arbitrary(&mut g)); + genesis + } + + fn make_interpreter( + ) -> FvmMessageInterpreter> { + let (client, _) = MockClient::new(MockRequestMethodMatcher::default()); + FvmMessageInterpreter::new(client, None, contracts_path(), 1.05, 1.05, false) + } + + fn read_bundle() -> Vec { + std::fs::read(bundle_path()).expect("failed to read bundle") + } } diff --git a/fendermint/vm/interpreter/src/fvm/state/genesis.rs b/fendermint/vm/interpreter/src/fvm/state/genesis.rs index 8143be95..16914aa5 100644 --- a/fendermint/vm/interpreter/src/fvm/state/genesis.rs +++ b/fendermint/vm/interpreter/src/fvm/state/genesis.rs @@ -189,6 +189,15 @@ where |s| s.set_actor(id, actor_state.clone()), ); + { + let cid = self.with_state_tree(|s| s.flush(), |s| s.flush())?; + tracing::debug!( + state_root = cid.to_string(), + actor_id = id, + "interim state root after actor creation" + ); + } + Ok(()) } @@ -331,6 +340,15 @@ where .context("failed to execute message")?, }; + { + let cid = self.with_state_tree(|s| s.flush(), |s| s.flush())?; + tracing::debug!( + state_root = cid.to_string(), + actor_id = id, + "interim state root after EVM actor initialisation" + ); + } + if !apply_ret.msg_receipt.exit_code.is_success() { let error_data = apply_ret.msg_receipt.return_data; let error_data = if error_data.is_empty() {