diff --git a/.gitignore b/.gitignore index c7073e8e3..cc1e9431d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist tests/rust_scripts/target .vscode output +.idea \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index eee3adaeb..08168a63d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,6 +128,38 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-primitives" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccb3ead547f4532bc8af961649942f0b9c16ee9226e26caa3f38420651cc0bf4" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal 0.4.1", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" +dependencies = [ + "arrayvec", + "bytes", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -843,6 +875,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -857,7 +900,7 @@ dependencies = [ "binary-merkle-tree", "derive_more", "frame-support", - "hex-literal", + "hex-literal 0.3.4", "itertools 0.10.5", "log", "once_cell", @@ -1108,6 +1151,21 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitcoin_hashes" version = "0.11.0" @@ -1305,6 +1363,9 @@ name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +dependencies = [ + "serde", +] [[package]] name = "bzip2-sys" @@ -1477,7 +1538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half", + "half 2.4.0", ] [[package]] @@ -1573,7 +1634,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex 0.7.0", - "strsim", + "strsim 0.11.1", "terminal_size", ] @@ -1656,6 +1717,25 @@ dependencies = [ "rand_chacha 0.3.1", ] +[[package]] +name = "common" +version = "0.5.5" +source = "git+https://github.com/a16z/helios.git#5d159575ceb0b46ca0c4ff6dab79799d3a5a7469" +dependencies = [ + "bytes", + "ethers-core", + "eyre", + "hex", + "serde", + "serde_json", + "snowbridge-milagro-bls", + "ssz_rs", + "superstruct", + "thiserror", + "tracing", + "zduny-wasm-timer", +] + [[package]] name = "common-path" version = "1.0.0" @@ -1677,6 +1757,26 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" +[[package]] +name = "consensus-core" +version = "0.1.0" +source = "git+https://github.com/a16z/helios.git#5d159575ceb0b46ca0c4ff6dab79799d3a5a7469" +dependencies = [ + "bytes", + "common 0.5.5", + "ethers-core", + "eyre", + "hex", + "serde", + "serde_json", + "snowbridge-milagro-bls", + "ssz_rs", + "superstruct", + "thiserror", + "tracing", + "zduny-wasm-timer", +] + [[package]] name = "console" version = "0.15.8" @@ -1690,6 +1790,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "const-hex" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -2147,7 +2260,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex", - "hex-literal", + "hex-literal 0.3.4", "iai", "iai-callgrind", "kate", @@ -2239,6 +2352,41 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -2773,7 +2921,13 @@ checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" dependencies = [ "ethereum-types", "hex", + "once_cell", + "regex", + "serde", + "serde_json", "sha3", + "thiserror", + "uint", ] [[package]] @@ -2793,6 +2947,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", "tiny-keccak", ] @@ -2804,10 +2962,40 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", "primitive-types", + "scale-info", "uint", ] +[[package]] +name = "ethers-core" +version = "2.0.13" +source = "git+https://github.com/gakonst/ethers-rs?rev=3bf1a9e0d698e9fdfc91d0353878901af5a5c5ef#3bf1a9e0d698e9fdfc91d0353878901af5a5c5ef" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array 0.14.7", + "k256", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum 0.26.3", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -2858,6 +3046,16 @@ dependencies = [ "syn 2.0.53", ] +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -2870,6 +3068,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "fdlimit" version = "0.3.0" @@ -3262,7 +3471,7 @@ dependencies = [ "derive_more", "docify", "frame-support", - "hex-literal", + "hex-literal 0.3.4", "itertools 0.10.5", "kate", "log", @@ -3656,6 +3865,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "half" version = "2.4.0" @@ -3798,6 +4013,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hkdf" version = "0.12.4" @@ -3930,7 +4151,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite 0.2.13", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -4014,6 +4235,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -4121,6 +4348,12 @@ dependencies = [ "quote", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.9.3" @@ -4463,7 +4696,7 @@ dependencies = [ "dusk-bytes", "dusk-plonk", "hex", - "hex-literal", + "hex-literal 0.3.4", "kate-recovery", "log", "nalgebra", @@ -4528,6 +4761,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-asm" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "keystream" version = "1.0.0" @@ -5826,6 +6069,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.53", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -5886,6 +6150,31 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -6487,17 +6776,20 @@ dependencies = [ name = "pallet-vector" version = "1.0.0" dependencies = [ + "alloy-primitives", "ark-bn254", "ark-ff 0.3.0", "ark-groth16", "ark-std 0.4.0", "avail-base", "avail-core", + "common 0.5.5", + "consensus-core", "ethabi", "frame-benchmarking", "frame-support", "frame-system", - "hex-literal", + "hex-literal 0.3.4", "log", "pallet-balances", "pallet-timestamp", @@ -6507,11 +6799,13 @@ dependencies = [ "rlp", "scale-info", "serde", + "serde_cbor", "serde_json", "sp-core", "sp-io", "sp-runtime", "sp-std", + "ssz_rs", "trie-db 0.24.0", ] @@ -6672,12 +6966,12 @@ dependencies = [ "hash-db 0.15.2", "hash256-std-hasher", "hex", - "hex-literal", + "hex-literal 0.3.4", "memory-db 0.30.0", "parity-scale-codec", "primitive-types", "rlp", - "rlp-derive", + "rlp-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "sp-io", "tiny-keccak", "trie-db 0.24.0", @@ -7081,6 +7375,26 @@ dependencies = [ "syn 2.0.53", ] +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.5.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha 0.3.1", + "rand_xorshift", + "regex-syntax 0.8.2", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "prost" version = "0.11.9" @@ -7307,6 +7621,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rawpointer" version = "0.2.1" @@ -7487,7 +7810,7 @@ dependencies = [ "ark-serialize 0.4.2", "ark-std 0.4.0", "blake2 0.10.6", - "common", + "common 0.1.0", "fflonk", "merlin", ] @@ -7537,6 +7860,7 @@ version = "0.5.2" source = "git+https://github.com/paritytech/parity-common.git?tag=rlp-v0.5.2#86676b08e89cb99fdff0c882453ad0746dd070cf" dependencies = [ "bytes", + "rlp-derive 0.1.0 (git+https://github.com/paritytech/parity-common.git?tag=rlp-v0.5.2)", "rustc-hex", ] @@ -7551,6 +7875,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "git+https://github.com/paritytech/parity-common.git?tag=rlp-v0.5.2#86676b08e89cb99fdff0c882453ad0746dd070cf" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rocksdb" version = "0.21.0" @@ -7603,6 +7937,36 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ruint" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -7736,6 +8100,18 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "rw-stream-sink" version = "0.3.0" @@ -9057,6 +9433,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.3", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.203" @@ -9146,6 +9532,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3-asm" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" +dependencies = [ + "cc", + "cfg-if", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -9248,6 +9644,30 @@ dependencies = [ "subtle 2.5.0", ] +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "snowbridge-milagro-bls" +version = "1.5.2" +source = "git+https://github.com/Snowfork/milagro_bls?rev=6a95c9e33c6a41d9137761e593d53742ebb964de#6a95c9e33c6a41d9137761e593d53742ebb964de" +dependencies = [ + "hex", + "lazy_static", + "parity-scale-codec", + "rand", + "scale-info", + "snowbridge-amcl", + "zeroize", +] + [[package]] name = "socket2" version = "0.4.10" @@ -10099,6 +10519,31 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ssz_rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057291e5631f280978fa9c8009390663ca4613359fc1318e36a8c24c392f6d1f" +dependencies = [ + "bitvec", + "hex", + "num-bigint", + "serde", + "sha2 0.9.9", + "ssz_rs_derive", +] + +[[package]] +name = "ssz_rs_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -10152,6 +10597,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -10173,6 +10624,15 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum_macros" version = "0.24.3" @@ -10199,6 +10659,19 @@ dependencies = [ "syn 2.0.53", ] +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.53", +] + [[package]] name = "substrate-bip39" version = "0.4.6" @@ -10308,6 +10781,20 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "superstruct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f4e1f478a7728f8855d7e620e9a152cf8932c6614f86564c886f9b8141f3201" +dependencies = [ + "darling", + "itertools 0.10.5", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", +] + [[package]] name = "syn" version = "1.0.109" @@ -11031,6 +11518,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -11163,6 +11656,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -11947,6 +12449,21 @@ dependencies = [ "time", ] +[[package]] +name = "zduny-wasm-timer" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f22d6a02cbc84ea1993b0b341833a55a0866a3378c3a76e0ca664bc2574e370" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.12.1", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index d8b962100..f2798f5d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,14 @@ homepage = "https://www.availproject.org/" [workspace.dependencies] -avail-core = { git = "https://github.com/availproject/avail-core", tag = "node-v2230-rc2", default-features = false, features = [ "runtime"] } +avail-core = { git = "https://github.com/availproject/avail-core", tag = "node-v2230-rc2", default-features = false, features = ["runtime"] } kate = { git = "https://github.com/availproject/avail-core", tag = "node-v2230-rc2", default-features = false } -kate-recovery = { git = "https://github.com/availproject/avail-core", tag = "node-v2230-rc2", default-features = false } +kate-recovery = { git = "https://github.com/availproject/avail-core", tag = "node-v2230-rc2", default-features = false } +ssz-rs = { package = "ssz_rs", version = "0.9.0" } +alloy-primitives = { version = "0.7.7", features = ["serde"] } +helios-common = { git = "https://github.com/a16z/helios.git", package = "common" } +helios-consensus-core = { git = "https://github.com/a16z/helios.git", package = "consensus-core" } +serde_cbor = "0.11.2" # avail-core = { path = "../avail-core/core", default-features = false, features = [ "runtime"] } # kate = { path = "../avail-core/kate/", default-features = false } # kate-recovery = { path = "../avail-core/kate/recovery/", default-features = false} @@ -47,7 +52,7 @@ frame-system-benchmarking = { path = "pallets/system/benchmarking", default-feat # benchmarking criterion = { version = "0.4", default-features = false } iai = "0.1.1" -iai-callgrind = "0.7.3" +iai-callgrind = "0.7.3" divan = "0.1.11" # codspeed-criterion-compat = "2.2.0" @@ -73,7 +78,7 @@ static_assertions = "1.1.0" serde = { version = "1.0.197", default-features = false, features = ["derive"] } serde_json = { version = "1.0", default-features = false } derive_more = { version = "0.99.17", default-features = false, features = ["from", "into", "display"] } -scale-info = { version = "2.5.0", default-features = false, features = ["derive","serde"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive", "serde"] } cfg-if = "1.0" impl-trait-for-tuples = "0.2.1" docify = "0.2.6" @@ -149,7 +154,7 @@ sp-runtime-interface = { git = "https://github.com/availproject/polkadot-sdk.git binary-merkle-tree = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } sp-staking = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } pallet-staking = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } -pallet-staking-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } +pallet-staking-runtime-api = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } sp-consensus-grandpa = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } sp-authority-discovery = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } sp-consensus-babe = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-7", default-features = false } diff --git a/avail-rust/src/api_dev.rs b/avail-rust/src/api_dev.rs index 067caf420..cc3f03feb 100644 --- a/avail-rust/src/api_dev.rs +++ b/avail-rust/src/api_dev.rs @@ -24017,6 +24017,11 @@ pub mod api { pub type SyncCommitteePoseidons = runtime_types::primitive_types::U256; pub type Param0 = ::core::primitive::u64; } + pub mod sync_committee_hashes{ + use super::runtime_types; + pub type SyncCommitteeHashes = runtime_types::primitive_types::U256; + pub type Param0 = ::core::primitive::u64; + } pub mod configuration_storage { use super::runtime_types; pub type ConfigurationStorage = diff --git a/pallets/vector/Cargo.toml b/pallets/vector/Cargo.toml index 1c901cfcd..9e1be8f75 100644 --- a/pallets/vector/Cargo.toml +++ b/pallets/vector/Cargo.toml @@ -8,7 +8,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] frame-system = { workspace = true, default-features = false } -avail-core = { workspace = true, default-features = false, features = ["runtime"]} +avail-core = { workspace = true, default-features = false, features = ["runtime"] } avail-base = { workspace = true, default-features = false } patricia-merkle-trie = { workspace = true, default-features = false } @@ -33,14 +33,17 @@ trie-db.workspace = true rlp.workspace = true primitive-types.workspace = true ethabi.workspace = true - - +helios-common.workspace = true +helios-consensus-core.workspace = true +alloy-primitives.workspace = true +ssz-rs.workspace = true +serde_cbor.workspace = true [dev-dependencies] pallet-balances = { workspace = true, default-features = false, features = ["std"] } pallet-timestamp = { workspace = true, default-features = false } [features] -default = [ "std" ] +default = ["std"] std = [ "avail-base/std", "avail-core/std", @@ -65,4 +68,4 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "sp-runtime/try-runtime", -] +] \ No newline at end of file diff --git a/pallets/vector/examples/rotate_call.cbor b/pallets/vector/examples/rotate_call.cbor new file mode 100644 index 000000000..e014f9ae6 Binary files /dev/null and b/pallets/vector/examples/rotate_call.cbor differ diff --git a/pallets/vector/examples/step_call.cbor b/pallets/vector/examples/step_call.cbor new file mode 100644 index 000000000..71e8541ba Binary files /dev/null and b/pallets/vector/examples/step_call.cbor differ diff --git a/pallets/vector/src/lib.rs b/pallets/vector/src/lib.rs index 3ff5d25bc..3bedacb36 100644 --- a/pallets/vector/src/lib.rs +++ b/pallets/vector/src/lib.rs @@ -4,6 +4,10 @@ use crate::{storage_utils::MessageStatusEnum, verifier::Verifier}; use avail_base::{MemoryTemporaryStorage, ProvidePostInherent}; use avail_core::data_proof::{tx_uid, AddressedMessage, Message, MessageType}; +use helios_common::config::types::Forks; +use helios_consensus_core::{apply_finality_update, apply_update, verify_finality_update, verify_update, types::{Bytes32, ByteVector, LightClientStore, Update, FinalityUpdate}}; +use alloy_primitives::B256; +use ssz_rs::prelude::*; use codec::Compact; use frame_support::{ @@ -22,8 +26,12 @@ pub mod constants; mod mock; mod state; mod storage_utils; + +// Use new tests made with light client inputs +// #[cfg(test)] +// mod tests; #[cfg(test)] -mod tests; +mod tests_new; mod verifier; mod weights; @@ -46,6 +54,7 @@ pub type BalanceOf = #[frame_support::pallet] pub mod pallet { + use helios_consensus_core::get_bits; use ethabi::Token; use ethabi::Token::Uint; use frame_support::dispatch::GetDispatchInfo; @@ -184,11 +193,17 @@ pub mod pallet { #[pallet::storage] pub type ExecutionStateRoots = StorageMap<_, Identity, u64, H256, ValueQuery>; + /// DEPRECATED: Use SyncCommitteeHashes instead. /// Maps from a period to the poseidon commitment for the sync committee. #[pallet::storage] #[pallet::getter(fn sync_committee_poseidons)] pub type SyncCommitteePoseidons = StorageMap<_, Identity, u64, U256, ValueQuery>; + /// Maps from a period to the Sha256 commitment for the sync committee. + #[pallet::storage] + #[pallet::getter(fn sync_committee_hashes)] + pub type SyncCommitteeHashes = StorageMap<_, Identity, u64, U256, ValueQuery>; + /// Storage for a config of finality threshold and slots per period. #[pallet::storage] pub type ConfigurationStorage = StorageValue<_, Configuration, ValueQuery>; @@ -323,7 +338,7 @@ pub mod pallet { pub slots_per_period: u64, pub finality_threshold: u16, pub function_ids: (H256, H256), - pub sync_committee_poseidon: U256, + pub sync_committee_hash: U256, pub period: u64, pub broadcaster: H256, pub broadcaster_domain: u32, @@ -368,7 +383,7 @@ pub mod pallet { .expect("Rotate verification key should be valid at genesis."); RotateVerificationKey::::set(Some(rotate_verification_key)); - SyncCommitteePoseidons::::insert(self.period, self.sync_committee_poseidon); + SyncCommitteeHashes::::insert(self.period, self.sync_committee_hash); GenesisValidatorRoot::::set(self.genesis_validator_root); @@ -395,7 +410,29 @@ pub mod pallet { Weight::zero() } } + // TODO: Rename to FunctionInput + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] + pub struct FunctionInputs { + pub updates: Vec, + pub finality_update: FinalityUpdate, + pub expected_current_slot: u64, + pub store: LightClientStore, + pub genesis_root: Bytes32, + pub forks: Forks, + pub execution_state_proof: ExecutionStateProof, + } + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] + pub struct ExecutionStateProof { + #[serde(rename = "executionStateRoot")] + pub execution_state_root: B256, + #[serde(rename = "executionStateBranch")] + pub execution_state_branch: Vec, + pub gindex: String, + } + /// Merkle branch index & depth for the execution state root proof. + pub const MERKLE_BRANCH_INDEX: usize = 802; + pub const MERKLE_BRANCH_DEPTH: usize = 9; #[pallet::call] impl Pallet where @@ -403,64 +440,158 @@ pub mod pallet { { /// The entrypoint for fulfilling a call. /// function_id Function identifier. - /// input Function input. - /// output Function output. - /// proof Function proof. - /// slot Function slot to update. + /// inputs Function input. #[pallet::call_index(0)] + // Unused parameter that's hard to remove, would mess up traits #[pallet::weight(weight_helper::fulfill_call::(* function_id))] pub fn fulfill_call( origin: OriginFor, function_id: H256, - input: FunctionInput, - output: FunctionOutput, - proof: FunctionProof, - #[pallet::compact] slot: u64, + inputs: Vec, // TODO: Convert to fixed bytes ) -> DispatchResultWithPostInfo { + let config = ConfigurationStorage::::get(); + let FunctionInputs { + updates, + finality_update, + expected_current_slot, + mut store, + genesis_root, + forks, + execution_state_proof, + } = serde_cbor::from_slice(&inputs).unwrap(); + + let mut is_valid = true; + let prev_head = store.finalized_header.slot; + + // 1. Apply sync committee updates, if any + for (index, update) in updates.iter().enumerate() { + is_valid = is_valid + && verify_update( + update, + expected_current_slot, + &store, + genesis_root.clone(), + &forks, + ) + .is_ok(); + + apply_update(&mut store, update); + } + + // 2. Apply finality update + is_valid = is_valid + && verify_finality_update( + &finality_update, + expected_current_slot, + &store, + genesis_root.clone(), + &forks, + ) + .is_ok(); + apply_finality_update(&mut store, &finality_update); + + // 3. Verify execution state root proof + let execution_state_branch_nodes: Vec = execution_state_proof + .execution_state_branch + .iter() + .map(|b| Node::try_from(b.as_ref()).unwrap()) + .collect(); + + is_valid = is_valid + && is_valid_merkle_branch( + &Node::try_from(execution_state_proof.execution_state_root.as_ref()).unwrap(), + execution_state_branch_nodes.iter(), + MERKLE_BRANCH_DEPTH, + MERKLE_BRANCH_INDEX, + &Node::try_from(store.finalized_header.body_root.as_ref()).unwrap(), + ); + + let finalized_header_root: [u8; 32] = store + .finalized_header + .hash_tree_root() + .unwrap().as_ref().try_into().unwrap(); + let execution_state_root: [u8; 32] = execution_state_proof.execution_state_root.as_slice().try_into().unwrap(); + + let head = store.finalized_header.slot; let sender: [u8; 32] = ensure_signed(origin)?.into(); let updater = Updater::::get(); + // ensure sender is preconfigured ensure!(H256(sender) == updater, Error::::UpdaterMisMatch); + ensure!(is_valid, Error::::VerificationFailed); - let config = ConfigurationStorage::::get(); - let input_hash = H256(sha2_256(input.as_slice())); - let output_hash = H256(sha2_256(output.as_slice())); - let (step_function_id, rotate_function_id) = Self::get_function_ids()?; - let verifier = Self::get_verifier(function_id, step_function_id, rotate_function_id)?; - - let is_success = verifier - .verify(input_hash, output_hash, proof.to_vec()) - .map_err(|_| Error::::VerificationError)?; + let mut function_called = false; - // make sure that verification call is valid - ensure!(is_success, Error::::VerificationFailed); + // 4. Store step if needed + if prev_head != head { + let verified_output = VerifiedStepOutput { + finalized_header_root: H256::from(finalized_header_root), + execution_state_root: H256::from(execution_state_root), + finalized_slot: store.finalized_header.slot.as_u64(), + participation: store.current_max_active_participants.try_into().unwrap(), + }; - // verification is success and, we can safely parse and validate output - if function_id == step_function_id { - let step_output = parse_step_output(output.to_vec()) - .map_err(|_| Error::::CannotParseOutputData)?; + let head = Head::::get(); + ensure!(verified_output.finalized_slot > head, Error::::SlotBehindHead); - let vs = VerifiedStep::new(function_id, input_hash, step_output); - - if Self::step_into(slot, &config, &vs, step_function_id)? { + if Self::set_slot_roots(verified_output)? { Self::deposit_event(Event::HeadUpdated { - slot: vs.verified_output.finalized_slot, - finalization_root: vs.verified_output.finalized_header_root, - execution_state_root: vs.verified_output.execution_state_root, + slot: verified_output.finalized_slot, + finalization_root: verified_output.finalized_header_root, + execution_state_root: verified_output.execution_state_root, }); + function_called = true; } - } else if function_id == rotate_function_id { - let rotate_output = parse_rotate_output(output.to_vec()) - .map_err(|_| Error::::CannotParseOutputData)?; - - let vr = VerifiedRotate::new(function_id, input_hash, rotate_output); + } - let period = Self::rotate_into(slot, &config, &vr, rotate_function_id)?; + // 5. Store rotate if needed + // a) Store current sync committee if stored one is empty (i.e. first time or after a range of updates) + let period = head.as_u64() + .checked_div(config.slots_per_period) + .ok_or(Error::::ConfigurationNotSet)?; + let stored_current_sync_committee = SyncCommitteeHashes::::get(period); + if stored_current_sync_committee.is_zero() { + let current_sync_committee_hash: U256 = store + .current_sync_committee + .hash_tree_root() + .unwrap() + .as_ref() + .try_into() + .unwrap(); Self::deposit_event(Event::SyncCommitteeUpdated { period, - root: vr.sync_committee_poseidon, + root: current_sync_committee_hash, }); - } else { + function_called = true; + + Self::set_sync_committee_hash(period, current_sync_committee_hash)?; + } + + // b) Store next sync committee if available + if let Some(mut next_sync_committee) = store.next_sync_committee { + let next_period = period + 1; + let stored_next_sync_committee_hash = SyncCommitteeHashes::::get(next_period); + let next_sync_committee_hash: [u8; 32] = next_sync_committee + .hash_tree_root() + .unwrap() + .as_ref() + .try_into() + .unwrap(); + let next_sync_committee_hash = U256::from(next_sync_committee_hash); + + // If the next sync committee is already correct, we don't need to update it. + if stored_next_sync_committee_hash != next_sync_committee_hash.into() { + Self::deposit_event(Event::SyncCommitteeUpdated { + period: next_period, + root: next_sync_committee_hash, + }); + function_called = true; + + Self::set_sync_committee_hash(next_period, next_sync_committee_hash)?; + } + } + + if !function_called { return Err(Error::::FunctionIdNotKnown.into()); } @@ -889,7 +1020,7 @@ pub mod pallet { ); let input = ethabi::encode(&[Token::FixedBytes(finalized_header_root.0.to_vec())]); - let sync_committee_poseidon: U256 = + let sync_committee_hash: U256 = Self::verified_rotate_call(rotate_function_id, input, verified_rotate_call)?; let period = finalized_slot @@ -897,7 +1028,7 @@ pub mod pallet { .ok_or(Error::::ConfigurationNotSet)?; let next_period = period + 1; - Self::set_sync_committee_poseidon(next_period, sync_committee_poseidon)?; + Self::set_sync_committee_hash(next_period, sync_committee_hash)?; Ok(next_period) } @@ -912,10 +1043,10 @@ pub mod pallet { .checked_div(cfg.slots_per_period) .ok_or(Error::::ConfigurationNotSet)?; - let sc_poseidon = SyncCommitteePoseidons::::get(period); - ensure!(sc_poseidon != U256::zero(), Error::::SyncCommitteeNotSet); + let sc_hash = SyncCommitteeHashes::::get(period); + ensure!(sc_hash != U256::zero(), Error::::SyncCommitteeNotSet); - let input = encode_packed(sc_poseidon, attested_slot); + let input = encode_packed(sc_hash, attested_slot); let result = Self::verified_step_call(step_function_id, input, verified_step_call)?; ensure!( result.participation >= cfg.finality_threshold, @@ -971,6 +1102,19 @@ pub mod pallet { Ok(()) } + /// Sets the sync committee hash for a given period. + fn set_sync_committee_hash(period: u64, hash: U256) -> Result<(), DispatchError> { + let sync_committee_hashes = SyncCommitteeHashes::::get(period); + ensure!( + sync_committee_hashes == U256::zero(), + Error::::SyncCommitteeAlreadySet + ); + + SyncCommitteeHashes::::set(period, hash); + + Ok(()) + } + /// get_verifier returns verifier based on the provided function id. fn get_verifier( function_id: H256, diff --git a/pallets/vector/src/tests_new.rs b/pallets/vector/src/tests_new.rs new file mode 100644 index 000000000..d0b2a3f90 --- /dev/null +++ b/pallets/vector/src/tests_new.rs @@ -0,0 +1,132 @@ +/// Tests for Vector that use CBOR encoded Ethereum light client inputs instead of ZKProofs. +/// Adapted from corresponding tests in src/tests.rs. +use std::fs; +use frame_support::{assert_err, assert_ok}; +use hex_literal::hex; +use primitive_types::{H256, U256}; +use sp_core::crypto::AccountId32; +use crate::mock::{new_test_ext, Bridge,RuntimeEvent, RuntimeOrigin, System, Test, ROTATE_FUNCTION_ID, STEP_FUNCTION_ID}; +use crate::{ConfigurationStorage,Error, Event, ExecutionStateRoots, FunctionInputs, Head, Headers, SyncCommitteeHashes, Updater}; +use crate::state::Configuration; +const TEST_SENDER_VEC: [u8; 32] = + hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"); +const TEST_SENDER_ACCOUNT: AccountId32 = AccountId32::new(TEST_SENDER_VEC); + +#[test] +fn test_fulfill_step_call() { + new_test_ext().execute_with(|| { + Updater::::set(H256(TEST_SENDER_VEC)); + + // These inputs, encoded in CBOR format, would be passed in via the operator + let inputs: Vec = fs::read("./examples/step_call.cbor").unwrap(); + + ConfigurationStorage::::set(Configuration { + slots_per_period: 8192, + finality_threshold: 461, + }); + + let result = Bridge::fulfill_call( + RuntimeOrigin::signed(TEST_SENDER_ACCOUNT), + H256::zero(), // Unused value + inputs.clone(), + ); + + assert_ok!(result); + + let parsed_inputs: FunctionInputs = serde_cbor::from_slice(&inputs).unwrap(); + + let finalized_slot = parsed_inputs.finality_update.finalized_header.slot.as_u64(); + // ensure that event is fired + let expected_event = RuntimeEvent::Bridge(Event::HeadUpdated { + slot: finalized_slot, + finalization_root: H256(hex!( + "a6e3468985f31ca58e34fe0a40a72f4bbc08d4d00a0933d28b07ddb95d1faf95" + )), + execution_state_root: H256(hex!( + "6518be340ee1bad6c6c6bef6ea3e99ecebc142e196b7edd56b3a5e513d0c6392" + )), + }); + + let header = Headers::::get(finalized_slot); + let head = Head::::get(); + let ex_state_root = ExecutionStateRoots::::get(finalized_slot); + + assert_eq!( + header, + H256(hex!( + "a6e3468985f31ca58e34fe0a40a72f4bbc08d4d00a0933d28b07ddb95d1faf95" + )) + ); + assert_eq!( + ex_state_root, + H256(hex!( + "6518be340ee1bad6c6c6bef6ea3e99ecebc142e196b7edd56b3a5e513d0c6392" + )) + ); + assert_eq!(head, finalized_slot); + assert_eq!(expected_event, System::events()[0].event); + }); +} + +#[test] +fn test_fulfill_step_call_slot_behind_head() { + new_test_ext().execute_with(|| { + Updater::::set(H256(TEST_SENDER_VEC)); + let inputs: Vec = fs::read("./examples/step_call.cbor").unwrap(); + + // move head forward + Head::::set(9678877); + + ConfigurationStorage::::set(Configuration { + slots_per_period: 8192, + finality_threshold: 461, + }); + + let result = Bridge::fulfill_call( + RuntimeOrigin::signed(TEST_SENDER_ACCOUNT), + H256::zero(), // Unused value + inputs, + ); + + assert_err!(result, Error::::SlotBehindHead); + }); +} + +#[test] +fn test_fulfill_rotate_call() { + new_test_ext().execute_with(|| { + Updater::::set(H256(TEST_SENDER_VEC)); + + // These inputs, encoded in CBOR format, would be passed in via the operator + let inputs: Vec = fs::read("./examples/rotate_call.cbor").unwrap(); + + ConfigurationStorage::::set(Configuration { + slots_per_period: 8192, + finality_threshold: 342, + }); + + let result = Bridge::fulfill_call( + RuntimeOrigin::signed(TEST_SENDER_ACCOUNT), + H256::zero(), // Unused value + inputs, + ); + + assert_ok!(result); + // ensure that event is fired + let expected_hash = U256::from_dec_str( + "78004113044439342907882478475913997887515213797155324584820998418219758944903", + ) + .unwrap(); + + let current_period = 1178; + let expected_event = RuntimeEvent::Bridge(Event::SyncCommitteeUpdated { + period: current_period + 1, + root: expected_hash, + }); + + let poseidon = SyncCommitteeHashes::::get(current_period + 1); + + assert_eq!(expected_event, System::events()[1].event); + assert_eq!(poseidon, expected_hash); + }); +} \ No newline at end of file diff --git a/runtime/src/apis.rs b/runtime/src/apis.rs index 9c414c977..6a5440539 100644 --- a/runtime/src/apis.rs +++ b/runtime/src/apis.rs @@ -58,6 +58,7 @@ decl_runtime_apis! { pub trait VectorApi { fn sync_committee_poseidons(slot: u64) -> U256; + fn sync_committee_hashes(slot: u64) -> U256; fn head() -> u64; fn headers(slot: u64) -> H256; } @@ -391,6 +392,10 @@ impl_runtime_apis! { pallet_vector::Pallet::::sync_committee_poseidons(slot) } + fn sync_committee_hashes(slot: u64) -> U256 { + pallet_vector::Pallet::::sync_committee_hashes(slot) + } + fn head() -> u64 { pallet_vector::Pallet::::head() }