diff --git a/lean_client/Cargo.lock b/lean_client/Cargo.lock index 970d374..bce89e2 100644 --- a/lean_client/Cargo.lock +++ b/lean_client/Cargo.lock @@ -61,15 +61,22 @@ dependencies = [ [[package]] name = "air" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ "multilinear-toolkit", - "p3-air", "p3-util 0.3.0", "tracing", "utils", ] +[[package]] +name = "air" +version = "0.3.0" +source = "git+https://github.com/leanEthereum/multilinear-toolkit.git?branch=lean-vm-simple#e06cba2e214879c00c7fbc0e5b12908ddfcba588" +dependencies = [ + "p3-field 0.3.0", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -89,7 +96,7 @@ dependencies = [ "derive_more", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.13.0", + "indexmap 2.12.1", "itoa", "k256", "keccak-asm", @@ -191,7 +198,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arithmetic" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "easy-ext", "typenum", @@ -261,7 +268,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.43", + "quote 1.0.42", "syn 1.0.109", ] @@ -271,7 +278,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.43", + "quote 1.0.42", "syn 1.0.109", ] @@ -281,8 +288,8 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ - "quote 1.0.43", - "syn 2.0.114", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -293,7 +300,7 @@ checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint", "num-traits", - "quote 1.0.43", + "quote 1.0.42", "syn 1.0.109", ] @@ -305,8 +312,8 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", ] @@ -318,9 +325,9 @@ checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -420,9 +427,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", "synstructure 0.13.2", ] @@ -432,9 +439,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -479,9 +486,9 @@ version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -534,9 +541,9 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -548,7 +555,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backend" version = "0.3.0" -source = "git+https://github.com/leanEthereum/multilinear-toolkit.git#62766141561550c3540f9f644085fec53d721f16" +source = "git+https://github.com/leanEthereum/multilinear-toolkit.git?branch=lean-vm-simple#e06cba2e214879c00c7fbc0e5b12908ddfcba588" dependencies = [ "fiat-shamir", "itertools 0.14.0", @@ -589,9 +596,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" [[package]] name = "bincode" @@ -709,9 +716,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.52" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ "find-msvc-tools", "shlex", @@ -782,9 +789,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" dependencies = [ "clap_builder", "clap_derive", @@ -792,9 +799,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" dependencies = [ "anstream", "anstyle", @@ -809,16 +816,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "clap_lex" -version = "0.7.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "colorchoice" @@ -883,18 +890,18 @@ version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "unicode-xid 0.2.6", ] [[package]] name = "constraints-folder" version = "0.3.0" -source = "git+https://github.com/leanEthereum/multilinear-toolkit.git#62766141561550c3540f9f644085fec53d721f16" +source = "git+https://github.com/leanEthereum/multilinear-toolkit.git?branch=lean-vm-simple#e06cba2e214879c00c7fbc0e5b12908ddfcba588" dependencies = [ + "air 0.3.0", "fiat-shamir", - "p3-air", "p3-field 0.3.0", ] @@ -905,9 +912,10 @@ dependencies = [ "alloy-primitives", "anyhow", "env-config", + "ethereum_ssz", "hex", "lean-multisig", - "leansig", + "leansig 0.1.0 (git+https://github.com/leanEthereum/leanSig?rev=73bedc26ed961b110df7ac2e234dc11361a4bf25)", "pretty_assertions", "rstest", "serde", @@ -917,6 +925,7 @@ dependencies = [ "ssz", "ssz_derive", "test-generator", + "tracing", "typenum", ] @@ -1063,9 +1072,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1086,10 +1095,10 @@ checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "strsim", - "syn 2.0.114", + "syn 2.0.111", ] [[package]] @@ -1099,8 +1108,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", - "quote 1.0.43", - "syn 2.0.114", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1119,15 +1128,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.10.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "data-encoding-macro" -version = "0.1.19" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8142a83c17aa9461d637e649271eae18bf2edd00e91f2e105df36c3c16355bdb" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1135,12 +1144,12 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.17" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" dependencies = [ "data-encoding", - "syn 2.0.114", + "syn 2.0.111", ] [[package]] @@ -1194,8 +1203,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", ] @@ -1215,10 +1224,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.111", "unicode-xid 0.2.6", ] @@ -1286,16 +1295,16 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "dtoa" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" [[package]] name = "dyn-clone" @@ -1355,9 +1364,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" dependencies = [ "enum-ordinalize", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1411,9 +1420,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ "heck", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1431,9 +1440,9 @@ version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1579,7 +1588,7 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "fiat-shamir" version = "0.1.0" -source = "git+https://github.com/leanEthereum/fiat-shamir.git#bcf23c766f2e930acf11e68777449483a55af077" +source = "git+https://github.com/leanEthereum/fiat-shamir.git?branch=lean-vm-simple#9d4dc22f06cfa65f15bf5f1b07912a64c7feff0f" dependencies = [ "p3-challenger 0.3.0", "p3-field 0.3.0", @@ -1589,9 +1598,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.7" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "fixed-hash" @@ -1725,9 +1734,9 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -1791,9 +1800,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.17" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", @@ -1845,9 +1854,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.13" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1855,7 +1864,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.0", + "indexmap 2.12.1", "slab", "tokio", "tokio-util", @@ -1902,7 +1911,7 @@ dependencies = [ [[package]] name = "hashing" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "ethereum-types", "generic-array", @@ -2318,9 +2327,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -2336,9 +2345,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -2417,9 +2426,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" @@ -2473,15 +2482,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lean-multisig" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ "clap", + "lean_vm", "multilinear-toolkit", "p3-koala-bear 0.3.0", - "poseidon_circuit", + "rand 0.9.2", "rec_aggregation", "whir-p3", - "xmss", ] [[package]] @@ -2504,13 +2513,12 @@ dependencies = [ [[package]] name = "lean_compiler" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ - "air", + "air 0.1.0", "lean_vm", "lookup", "multilinear-toolkit", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-poseidon2 0.3.0", @@ -2523,21 +2531,19 @@ dependencies = [ "tracing", "utils", "whir-p3", - "xmss", ] [[package]] name = "lean_prover" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ - "air", + "air 0.1.0", "itertools 0.14.0", "lean_compiler", "lean_vm", "lookup", "multilinear-toolkit", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-poseidon2 0.3.0", @@ -2545,29 +2551,26 @@ dependencies = [ "p3-util 0.3.0", "pest", "pest_derive", - "poseidon_circuit", "rand 0.9.2", "sub_protocols", "tracing", "utils", "whir-p3", "witness_generation", - "xmss", ] [[package]] name = "lean_vm" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ - "air", + "air 0.1.0", "colored", "derive_more", "itertools 0.14.0", "lookup", "multilinear-toolkit", "num_enum", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-poseidon2 0.3.0", @@ -2576,19 +2579,37 @@ dependencies = [ "pest", "pest_derive", "rand 0.9.2", - "strum", "sub_protocols", "thiserror 2.0.17", "tracing", "utils", "whir-p3", - "xmss", ] [[package]] name = "leansig" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanSig?branch=main#ae12a5feb25d917c42b6466444ebd56ec115a629" +source = "git+https://github.com/leanEthereum/leanSig?branch=main#73bedc26ed961b110df7ac2e234dc11361a4bf25" +dependencies = [ + "dashmap", + "ethereum_ssz", + "num-bigint", + "num-traits", + "p3-baby-bear 0.4.1", + "p3-field 0.4.1", + "p3-koala-bear 0.4.1", + "p3-symmetric 0.4.1", + "rand 0.9.2", + "rayon", + "serde", + "sha3", + "thiserror 2.0.17", +] + +[[package]] +name = "leansig" +version = "0.1.0" +source = "git+https://github.com/leanEthereum/leanSig?rev=73bedc26ed961b110df7ac2e234dc11361a4bf25#73bedc26ed961b110df7ac2e234dc11361a4bf25" dependencies = [ "dashmap", "ethereum_ssz", @@ -2612,9 +2633,9 @@ source = "git+https://github.com/0xPolygonHermez/zisk.git?tag=v0.13.0#ea1ed4c518 [[package]] name = "libc" -version = "0.2.180" +version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" [[package]] name = "libm" @@ -2632,10 +2653,10 @@ dependencies = [ "either", "futures", "futures-timer", - "getrandom 0.2.17", + "getrandom 0.2.16", "libp2p-allow-block-list", "libp2p-connection-limits", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-dns", "libp2p-gossipsub", "libp2p-identify", @@ -2661,7 +2682,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16ccf824ee859ca83df301e1c0205270206223fd4b1f2e512a693e1912a8f4a" dependencies = [ - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", ] @@ -2672,7 +2693,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18b8b607cf3bfa2f8c57db9c7d8569a315d5cc0a282e6bfd5ebfc0a9840b2a0" dependencies = [ - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", ] @@ -2707,9 +2728,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.43.2" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249128cd37a2199aff30a7675dffa51caf073b51aa612d2f544b19932b9aebca" +checksum = "4d28e2d2def7c344170f5c6450c0dbe3dfef655610dbfde2f6ac28a527abbe36" dependencies = [ "either", "fnv", @@ -2739,7 +2760,7 @@ dependencies = [ "async-trait", "futures", "hickory-resolver", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "parking_lot", "smallvec", @@ -2761,10 +2782,10 @@ dependencies = [ "fnv", "futures", "futures-timer", - "getrandom 0.2.17", + "getrandom 0.2.16", "hashlink", "hex_fmt", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", "quick-protobuf", @@ -2787,7 +2808,7 @@ dependencies = [ "futures", "futures-bounded", "futures-timer", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", "quick-protobuf", @@ -2844,7 +2865,7 @@ dependencies = [ "futures", "hickory-proto", "if-watch", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", "rand 0.8.5", @@ -2861,7 +2882,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "805a555148522cb3414493a5153451910cb1a146c53ffbf4385708349baf62b7" dependencies = [ "futures", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-gossipsub", "libp2p-identify", "libp2p-identity 0.2.13", @@ -2898,7 +2919,7 @@ dependencies = [ "asynchronous-codec 0.7.0", "bytes", "futures", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "multiaddr 0.18.2", "multihash 0.19.3", @@ -2921,7 +2942,7 @@ dependencies = [ "futures", "futures-timer", "if-watch", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-tls", "quinn", @@ -2943,7 +2964,7 @@ dependencies = [ "async-trait", "futures", "futures-bounded", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm", "rand 0.8.5", @@ -2961,7 +2982,7 @@ dependencies = [ "fnv", "futures", "futures-timer", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "libp2p-swarm-derive", "lru", @@ -2980,8 +3001,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd297cf53f0cb3dee4d2620bb319ae47ef27c702684309f682bdb7e55a18ae9c" dependencies = [ "heck", - "quote 1.0.43", - "syn 2.0.114", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -2994,7 +3015,7 @@ dependencies = [ "futures-timer", "if-watch", "libc", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "socket2 0.5.10", "tokio", "tracing", @@ -3008,7 +3029,7 @@ checksum = "96ff65a82e35375cbc31ebb99cacbbf28cb6c4fefe26bf13756ddcf708d40080" dependencies = [ "futures", "futures-rustls", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-identity 0.2.13", "rcgen", "ring", @@ -3028,7 +3049,7 @@ dependencies = [ "futures", "futures-timer", "igd-next", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "libp2p-swarm", "tokio", "tracing", @@ -3042,7 +3063,7 @@ checksum = "f15df094914eb4af272acf9adaa9e287baa269943f32ea348ba29cfb9bfc60d8" dependencies = [ "either", "futures", - "libp2p-core 0.43.2", + "libp2p-core 0.43.1", "thiserror 2.0.17", "tracing", "yamux 0.12.1", @@ -3079,7 +3100,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lookup" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ "multilinear-toolkit", "p3-challenger 0.3.0", @@ -3112,8 +3133,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", ] @@ -3151,9 +3172,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.12" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dec6bd31b08944e08b58fd99373893a6c17054d6f3ea5006cc894f4f4eee2a" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -3161,6 +3182,7 @@ dependencies = [ "equivalent", "parking_lot", "portable-atomic", + "rustc_version 0.4.1", "smallvec", "tagptr", "uuid", @@ -3251,8 +3273,8 @@ checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ "proc-macro-crate 1.1.3", "proc-macro-error", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", "synstructure 0.12.6", ] @@ -3260,8 +3282,9 @@ dependencies = [ [[package]] name = "multilinear-toolkit" version = "0.3.0" -source = "git+https://github.com/leanEthereum/multilinear-toolkit.git#62766141561550c3540f9f644085fec53d721f16" +source = "git+https://github.com/leanEthereum/multilinear-toolkit.git?branch=lean-vm-simple#e06cba2e214879c00c7fbc0e5b12908ddfcba588" dependencies = [ + "air 0.3.0", "backend", "constraints-folder", "fiat-shamir", @@ -3269,6 +3292,7 @@ dependencies = [ "p3-util 0.3.0", "rayon", "sumcheck", + "tracing", ] [[package]] @@ -3490,9 +3514,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate 3.4.0", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -3526,19 +3550,10 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "p3-air" -version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" -dependencies = [ - "p3-field 0.3.0", - "p3-matrix 0.3.0", -] - [[package]] name = "p3-baby-bear" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "p3-field 0.3.0", "p3-mds 0.3.0", @@ -3565,7 +3580,7 @@ dependencies = [ [[package]] name = "p3-challenger" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "p3-field 0.3.0", "p3-maybe-rayon 0.3.0", @@ -3590,7 +3605,7 @@ dependencies = [ [[package]] name = "p3-commit" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "p3-challenger 0.3.0", @@ -3604,7 +3619,7 @@ dependencies = [ [[package]] name = "p3-dft" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "p3-field 0.3.0", @@ -3631,7 +3646,7 @@ dependencies = [ [[package]] name = "p3-field" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "num-bigint", @@ -3661,7 +3676,7 @@ dependencies = [ [[package]] name = "p3-interpolation" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "p3-field 0.3.0", "p3-matrix 0.3.0", @@ -3672,7 +3687,7 @@ dependencies = [ [[package]] name = "p3-koala-bear" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "num-bigint", @@ -3701,7 +3716,7 @@ dependencies = [ [[package]] name = "p3-matrix" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "p3-field 0.3.0", @@ -3731,7 +3746,7 @@ dependencies = [ [[package]] name = "p3-maybe-rayon" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "rayon", ] @@ -3744,7 +3759,7 @@ source = "git+https://github.com/Plonky3/Plonky3.git?rev=d421e32#d421e32d3821174 [[package]] name = "p3-mds" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "p3-dft 0.3.0", "p3-field 0.3.0", @@ -3768,7 +3783,7 @@ dependencies = [ [[package]] name = "p3-merkle-tree" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "p3-commit", @@ -3785,7 +3800,7 @@ dependencies = [ [[package]] name = "p3-monty-31" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "num-bigint", @@ -3830,7 +3845,7 @@ dependencies = [ [[package]] name = "p3-poseidon2" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "p3-field 0.3.0", "p3-mds 0.3.0", @@ -3854,7 +3869,7 @@ dependencies = [ [[package]] name = "p3-symmetric" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "itertools 0.14.0", "p3-field 0.3.0", @@ -3874,7 +3889,7 @@ dependencies = [ [[package]] name = "p3-util" version = "0.3.0" -source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-multisig#1db9df28abd6db586eaa891af2416d94d1b026ae" +source = "git+https://github.com/TomWambsgans/Plonky3.git?branch=lean-vm-simple#4897086b6f460b969dc0baad5c4dff91a4eb1d67" dependencies = [ "rayon", "serde", @@ -3911,9 +3926,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate 3.4.0", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -3969,9 +3984,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.5" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" dependencies = [ "memchr", "ucd-trie", @@ -3979,9 +3994,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.5" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" +checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" dependencies = [ "pest", "pest_generator", @@ -3989,22 +4004,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.5" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" +checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "pest_meta" -version = "2.8.5" +version = "2.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" +checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" dependencies = [ "pest", "sha2 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4025,9 +4040,9 @@ version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -4091,25 +4106,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" - -[[package]] -name = "poseidon_circuit" -version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" -dependencies = [ - "multilinear-toolkit", - "p3-koala-bear 0.3.0", - "p3-monty-31 0.3.0", - "p3-poseidon2 0.3.0", - "rand 0.9.2", - "sub_protocols", - "tracing", - "utils", - "whir-p3", -] +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "potential_utf" @@ -4184,8 +4183,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", "version_check", ] @@ -4196,8 +4195,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "version_check", ] @@ -4212,9 +4211,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -4237,9 +4236,9 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -4356,11 +4355,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ - "proc-macro2 1.0.105", + "proc-macro2 1.0.103", ] [[package]] @@ -4393,7 +4392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.4", + "rand_core 0.9.3", "serde", ] @@ -4414,7 +4413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.4", + "rand_core 0.9.3", ] [[package]] @@ -4423,14 +4422,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.17", + "getrandom 0.2.16", ] [[package]] name = "rand_core" -version = "0.9.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1b3bc831f92381018fd9c6350b917c7b21f1eed35a65a51900e0e55a3d7afa" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.4", "serde", @@ -4442,14 +4441,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.9.4", + "rand_core 0.9.3", ] [[package]] name = "rapidhash" -version = "4.2.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8b5b858a440a0bc02625b62dd95131b9201aa9f69f411195dd4a7cfb1de3d7" +checksum = "d8e65c75143ce5d47c55b510297eeb1182f3c739b6043c537670e9fc18612dae" dependencies = [ "rustversion", ] @@ -4490,16 +4489,18 @@ dependencies = [ [[package]] name = "rec_aggregation" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ - "air", + "air 0.1.0", "bincode", + "ethereum_ssz", + "hex", "lean_compiler", "lean_prover", "lean_vm", + "leansig 0.1.0 (git+https://github.com/leanEthereum/leanSig?rev=73bedc26ed961b110df7ac2e234dc11361a4bf25)", "lookup", "multilinear-toolkit", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-poseidon2 0.3.0", @@ -4512,7 +4513,6 @@ dependencies = [ "tracing", "utils", "whir-p3", - "xmss", ] [[package]] @@ -4539,9 +4539,9 @@ version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -4609,7 +4609,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.17", + "getrandom 0.2.16", "libc", "untrusted", "windows-sys 0.52.0", @@ -4645,12 +4645,12 @@ checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" dependencies = [ "cfg-if", "glob", - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "regex", "relative-path", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.111", "unicode-ident", ] @@ -4674,9 +4674,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.2" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -4747,9 +4747,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags 2.10.0", "errno", @@ -4760,9 +4760,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ "once_cell", "ring", @@ -4774,9 +4774,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" dependencies = [ "web-time", "zeroize", @@ -4835,9 +4835,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schemars" @@ -4853,9 +4853,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" dependencies = [ "dyn-clone", "ref-cast", @@ -4932,29 +4932,29 @@ version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.12.1", "itoa", "memchr", + "ryu", "serde", "serde_core", - "zmij", ] [[package]] name = "serde_utils" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "const-hex", "generic-array", @@ -4977,9 +4977,9 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.12.1", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.1.0", "serde_core", "serde_json", "serde_with_macros", @@ -4993,9 +4993,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ "darling", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -5004,7 +5004,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.12.1", "itoa", "ryu", "serde", @@ -5070,11 +5070,10 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.8" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" dependencies = [ - "errno", "libc", ] @@ -5165,7 +5164,7 @@ dependencies = [ [[package]] name = "ssz" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "arithmetic", "bit_field", @@ -5197,15 +5196,15 @@ dependencies = [ [[package]] name = "ssz_derive" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "darling", "easy-ext", "itertools 0.14.0", "proc-macro-crate 3.4.0", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -5223,7 +5222,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "std_ext" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" dependencies = [ "easy-ext", "triomphe", @@ -5241,31 +5240,10 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", -] - [[package]] name = "sub_protocols" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ "derive_more", "lookup", @@ -5285,12 +5263,12 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sumcheck" version = "0.3.0" -source = "git+https://github.com/leanEthereum/multilinear-toolkit.git#62766141561550c3540f9f644085fec53d721f16" +source = "git+https://github.com/leanEthereum/multilinear-toolkit.git?branch=lean-vm-simple#e06cba2e214879c00c7fbc0e5b12908ddfcba588" dependencies = [ + "air 0.3.0", "backend", "constraints-folder", "fiat-shamir", - "p3-air", "p3-field 0.3.0", "p3-util 0.3.0", "rayon", @@ -5313,19 +5291,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.114" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "unicode-ident", ] @@ -5335,8 +5313,8 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", + "proc-macro2 1.0.103", + "quote 1.0.42", "syn 1.0.109", "unicode-xid 0.2.6", ] @@ -5347,9 +5325,9 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -5387,9 +5365,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", "getrandom 0.3.4", @@ -5434,9 +5412,9 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -5445,9 +5423,9 @@ version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -5526,9 +5504,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ "bytes", "libc", @@ -5547,16 +5525,16 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "tokio-util" -version = "0.7.18" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", @@ -5577,20 +5555,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" dependencies = [ "serde_core", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.23.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.12.1", "toml_datetime", "toml_parser", "winnow", @@ -5598,9 +5576,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" dependencies = [ "winnow", ] @@ -5613,9 +5591,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.44" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" dependencies = [ "log", "pin-project-lite", @@ -5629,21 +5607,33 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] name = "tracing-core" -version = "0.1.36" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" dependencies = [ "once_cell", "valuable", ] +[[package]] +name = "tracing-forest" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3298fe855716711a00474eceb89cc7dc254bbe67f6bc4afafdeec5f0c538771c" +dependencies = [ + "smallvec", + "thiserror 2.0.17", + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-forest" version = "0.3.0" @@ -5715,7 +5705,7 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "try_from_iterator" version = "0.0.0" -source = "git+https://github.com/grandinetech/grandine?branch=develop#8ac065da176067bc4eb8b79ebfc48a6433f52499" +source = "git+https://github.com/grandinetech/grandine?branch=develop#41fdb2f1595eb48e328ab6e43835e6df5376fc8b" [[package]] name = "typenum" @@ -5823,9 +5813,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.8" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", @@ -5848,17 +5838,16 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utils" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ "multilinear-toolkit", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-poseidon2 0.3.0", "p3-symmetric 0.3.0", "p3-util 0.3.0", "tracing", - "tracing-forest", + "tracing-forest 0.3.0", "tracing-subscriber", ] @@ -5880,7 +5869,7 @@ dependencies = [ "containers", "env-config", "fork-choice", - "leansig", + "leansig 0.1.0 (git+https://github.com/leanEthereum/leanSig?branch=main)", "serde_yaml", "tracing", "typenum", @@ -5956,7 +5945,7 @@ version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ - "quote 1.0.43", + "quote 1.0.42", "wasm-bindgen-macro-support", ] @@ -5967,9 +5956,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -5995,7 +5984,7 @@ dependencies = [ [[package]] name = "whir-p3" version = "0.1.0" -source = "git+https://github.com/TomWambsgans/whir-p3?branch=lean-multisig#04fb1c1f2e3bbd14e6e4aee32621656eb3f3949f" +source = "git+https://github.com/TomWambsgans/whir-p3?branch=lean-vm-simple#f74bc197415a597b1ca316a4ee207f43c8adee85" dependencies = [ "itertools 0.14.0", "multilinear-toolkit", @@ -6015,7 +6004,7 @@ dependencies = [ "rayon", "thiserror 2.0.17", "tracing", - "tracing-forest", + "tracing-forest 0.2.0", "tracing-subscriber", ] @@ -6086,9 +6075,9 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -6097,9 +6086,9 @@ version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -6394,15 +6383,14 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "witness_generation" version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" +source = "git+https://github.com/leanEthereum/leanMultisig?rev=e4474138487eeb1ed7c2e1013674fe80ac9f3165#e4474138487eeb1ed7c2e1013674fe80ac9f3165" dependencies = [ - "air", + "air 0.1.0", "derive_more", "lean_compiler", "lean_vm", "lookup", "multilinear-toolkit", - "p3-air", "p3-challenger 0.3.0", "p3-koala-bear 0.3.0", "p3-monty-31 0.3.0", @@ -6411,13 +6399,11 @@ dependencies = [ "p3-util 0.3.0", "pest", "pest_derive", - "poseidon_circuit", "rand 0.9.2", "sub_protocols", "tracing", "utils", "whir-p3", - "xmss", ] [[package]] @@ -6479,19 +6465,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "xmss" -version = "0.1.0" -source = "git+https://github.com/leanEthereum/leanMultisig?branch=main#72c27460314770dee435adf80494b2d684d3959b" -dependencies = [ - "multilinear-toolkit", - "p3-koala-bear 0.3.0", - "p3-util 0.3.0", - "rand 0.9.2", - "sha3", - "utils", -] - [[package]] name = "yamux" version = "0.12.1" @@ -6555,30 +6528,30 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", "synstructure 0.13.2", ] [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -6596,9 +6569,9 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", "synstructure 0.13.2", ] @@ -6613,13 +6586,13 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -6650,9 +6623,9 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ - "proc-macro2 1.0.105", - "quote 1.0.43", - "syn 2.0.114", + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", ] [[package]] @@ -6661,7 +6634,7 @@ version = "0.13.0" source = "git+https://github.com/0xPolygonHermez/zisk.git?tag=v0.13.0#ea1ed4c518992a170fc59ec19f1228eb4829a9e1" dependencies = [ "cfg-if", - "getrandom 0.2.17", + "getrandom 0.2.16", "lazy_static", "lib-c", "num-bigint", @@ -6670,9 +6643,3 @@ dependencies = [ "static_assertions", "tiny-keccak", ] - -[[package]] -name = "zmij" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac93432f5b761b22864c774aac244fa5c0fd877678a4c37ebf6cf42208f9c9ec" diff --git a/lean_client/Makefile b/lean_client/Makefile index fbecfc8..22f868a 100644 --- a/lean_client/Makefile +++ b/lean_client/Makefile @@ -78,11 +78,12 @@ docker: ./target/x86_64-unknown-linux-gnu/release/lean_client ./target/aarch64-u . .PHONY: docker-local -docker-local: ./target/x86_64-unknown-linux-gnu/release/lean_client ./target/aarch64-unknown-linux-gnu/release/lean_client +# docker-local: ./target/x86_64-unknown-linux-gnu/release/lean_client ./target/aarch64-unknown-linux-gnu/release/lean_client +docker-local: ./target/x86_64-unknown-linux-gnu/release/lean_client @mkdir -p ./bin/amd64 @cp ./target/x86_64-unknown-linux-gnu/release/lean_client ./bin/amd64/lean_client - @mkdir -p ./bin/arm64 - @cp ./target/aarch64-unknown-linux-gnu/release/lean_client ./bin/arm64/lean_client +# @mkdir -p ./bin/arm64 +# @cp ./target/aarch64-unknown-linux-gnu/release/lean_client ./bin/arm64/lean_client docker build \ --file Dockerfile \ --build-arg COMMIT_SHA=$(COMMIT_SHA) \ diff --git a/lean_client/containers/Cargo.toml b/lean_client/containers/Cargo.toml index ad85010..282fc6b 100644 --- a/lean_client/containers/Cargo.toml +++ b/lean_client/containers/Cargo.toml @@ -16,15 +16,18 @@ env-config = { path = "../env-config", default-features = false } ssz = { workspace = true } serde = { workspace = true } ssz_derive = { workspace = true } +tracing = "0.1" typenum = "1" serde_json = "1.0" serde_yaml = "0.9" hex = "0.4.3" sha2 = "0.10" -leansig = { git = "https://github.com/leanEthereum/leanSig", branch = "main" } -lean-multisig = { git = "https://github.com/leanEthereum/leanMultisig", branch = "main" } +leansig = { git = "https://github.com/leanEthereum/leanSig", rev = "73bedc26ed961b110df7ac2e234dc11361a4bf25" } +lean-multisig = { git = "https://github.com/leanEthereum/leanMultisig", rev = "e4474138487eeb1ed7c2e1013674fe80ac9f3165" } anyhow = "1.0.100" alloy-primitives = "1.5.2" +# ethereum_ssz for lean-multisig types (aliased to avoid conflict with grandine ssz) +eth_ssz = { package = "ethereum_ssz", version = "0.10.0" } [dev-dependencies] rstest = "0.18" diff --git a/lean_client/containers/src/attestation.rs b/lean_client/containers/src/attestation.rs index ba0596c..fb45e0c 100644 --- a/lean_client/containers/src/attestation.rs +++ b/lean_client/containers/src/attestation.rs @@ -1,5 +1,5 @@ use crate::{Checkpoint, Slot, Uint64}; -use leansig::serialization::Serializable; +use anyhow::anyhow; use serde::{Deserialize, Serialize}; use ssz::BitList; use ssz::ByteVector; @@ -70,18 +70,18 @@ impl MultisigAggregatedSignature { /// Uses lean-multisig zkVM to combine multiple signatures into a compact proof. /// /// # Arguments - /// * `public_keys` - Public keys of the signers + /// * `public_keys` - Slice of validator public keys /// * `signatures` - Individual XMSS signatures to aggregate - /// * `message` - The 32-byte message that was signed (as 8 field elements) + /// * `message` - The 32-byte message that was signed /// * `epoch` - The epoch/slot in which signatures were created /// /// # Returns /// Aggregated signature proof, or error if aggregation fails. pub fn aggregate( - public_keys: &[lean_multisig::XmssPublicKey], - signatures: &[lean_multisig::XmssSignature], - message: [lean_multisig::F; 8], - epoch: u64, + public_keys: &[crate::public_key::PublicKey], + signatures: &[Signature], + message: &[u8; 32], + epoch: u32, ) -> Result { if public_keys.is_empty() { return Err(AggregationError::EmptyInput); @@ -90,10 +90,30 @@ impl MultisigAggregatedSignature { return Err(AggregationError::MismatchedLengths); } - let proof_bytes = - lean_multisig::xmss_aggregate_signatures(public_keys, signatures, message, epoch) + // Convert to lean-multisig types + let lean_pks: Vec<_> = public_keys + .iter() + .map(|pk| pk.as_lean_sig()) + .collect::, _>>() + .map_err(|_| AggregationError::AggregationFailed)?; + + let lean_sigs: Vec<_> = signatures + .iter() + .map(|sig| { + // Convert ByteVector to crate::signature::Signature then to lean-sig + let sig_struct = crate::signature::Signature::from(sig.as_bytes()); + sig_struct.as_lean_sig() + }) + .collect::, _>>() + .map_err(|_| AggregationError::AggregationFailed)?; + + let aggregate_sig = + lean_multisig::xmss_aggregate_signatures(&lean_pks, &lean_sigs, message, epoch) .map_err(|_| AggregationError::AggregationFailed)?; + // Serialize the aggregate signature using ethereum_ssz (aliased as eth_ssz) + use eth_ssz::Encode; + let proof_bytes = aggregate_sig.as_ssz_bytes(); Self::new(proof_bytes) } @@ -106,23 +126,32 @@ impl MultisigAggregatedSignature { /// `Ok(())` if the proof is valid, `Err` with the proof error otherwise. pub fn verify( &self, - public_keys: &[lean_multisig::XmssPublicKey], - message: [lean_multisig::F; 8], - epoch: u64, + public_keys: &[crate::public_key::PublicKey], + message: &[u8; 32], + epoch: u32, ) -> Result<(), AggregationError> { - lean_multisig::xmss_verify_aggregated_signatures( - public_keys, - message, - self.0.as_bytes(), - epoch, - ) - .map_err(|_| AggregationError::VerificationFailed) + // Use ethereum_ssz (aliased as eth_ssz) for decoding + use eth_ssz::Decode; + + // Decode the aggregated signature from SSZ bytes + let aggregate_sig = + lean_multisig::Devnet2XmssAggregateSignature::from_ssz_bytes(self.0.as_bytes()) + .map_err(|_| AggregationError::VerificationFailed)?; + + // Convert public keys to lean-multisig format + let lean_pks: Vec<_> = public_keys + .iter() + .map(|pk| pk.as_lean_sig()) + .collect::, _>>() + .map_err(|_| AggregationError::VerificationFailed)?; + + lean_multisig::xmss_verify_aggregated_signatures(&lean_pks, message, &aggregate_sig, epoch) + .map_err(|_| AggregationError::VerificationFailed) } /// Verify the aggregated payload against validators and message. /// - /// This is a convenience method that extracts public keys from validators - /// and converts the message bytes to the field element format expected by lean-multisig. + /// This is a convenience method that extracts public keys from validators. /// /// # Arguments /// * `validators` - Slice of validator references to extract public keys from @@ -135,28 +164,13 @@ impl MultisigAggregatedSignature { &self, validators: &[&crate::validator::Validator], message: &[u8; 32], - epoch: u64, + epoch: u32, ) -> Result<(), AggregationError> { // Extract public keys from validators - let mut public_keys = Vec::new(); - for validator in validators { - // Convert PublicKey to lean_multisig::XmssPublicKey - let lean_sig_pk = validator - .pubkey - .as_lean_sig() - .map_err(|_| AggregationError::VerificationFailed)?; - let pk_bytes = lean_sig_pk.to_bytes(); - // TODO: Implement proper conversion from PublicKey bytes to lean_multisig::XmssPublicKey - // Once lean-multisig API is clarified, convert pk_bytes to XmssPublicKey - todo!("Convert PublicKey to lean_multisig::XmssPublicKey and implement message field conversion"); - } - - // Convert 32-byte message to 8 field elements - // TODO: Implement proper conversion from 32 bytes to 8 field elements - let message_fields = todo!("Convert 32-byte message to [lean_multisig::F; 8]"); + let public_keys: Vec<_> = validators.iter().map(|v| v.pubkey).collect(); - // Call verify with extracted keys and converted message - self.verify(&public_keys, message_fields, epoch) + // Call verify with extracted keys + self.verify(&public_keys, message, epoch) } } diff --git a/lean_client/containers/src/block.rs b/lean_client/containers/src/block.rs index 52d6d59..d9de1fb 100644 --- a/lean_client/containers/src/block.rs +++ b/lean_client/containers/src/block.rs @@ -158,24 +158,24 @@ impl SignedBlockWithAttestation { ); } - // let attestation_data_root: [u8; 32] = - // hash_tree_root(&aggregated_attestation.data).0.into(); + let attestation_data_root: [u8; 32] = + hash_tree_root(&aggregated_attestation.data).0.into(); // Verify the lean-multisig aggregated proof for this attestation // // The proof verifies that all validators in aggregation_bits signed // the same attestation_data_root at the given epoch (slot). - // TODO - // aggregated_signature_proof - // .verify_aggregated_payload( - // &validator_ids - // .iter() - // .map(|vid| validators.get(*vid).expect("validator must exist")) - // .collect::>(), - // &attestation_data_root, - // aggregated_attestation.data.slot.0, - // ) - // .expect("Attestation aggregated signature verification failed"); + _aggregated_signature_proof + .proof_data + .verify_aggregated_payload( + &validator_ids + .iter() + .map(|vid| validators.get(*vid).expect("validator must exist")) + .collect::>(), + &attestation_data_root, + aggregated_attestation.data.slot.0 as u32, + ) + .expect("Attestation aggregated signature verification failed"); } // Verify the proposer attestation signature (outside the attestation loop) @@ -214,11 +214,12 @@ pub fn verify_xmss_signature( signature: &Signature, ) -> bool { let epoch = slot.0 as u32; - let signature = crate::signature::Signature::from(signature.as_bytes()); - signature - .verify(&public_key, epoch, message_bytes) - .unwrap_or_else(|_| false) + // Create Signature from the raw bytes + let sig = crate::signature::Signature::from(signature.as_bytes()); + + sig.verify(&public_key, epoch, message_bytes) + .unwrap_or(false) } #[cfg(not(feature = "xmss-verify"))] diff --git a/lean_client/containers/src/state.rs b/lean_client/containers/src/state.rs index 5bb8a9e..cf8db72 100644 --- a/lean_client/containers/src/state.rs +++ b/lean_client/containers/src/state.rs @@ -399,6 +399,12 @@ impl State { let initial_finalized_slot = self.latest_finalized.slot; let justified_slots = self.justified_slots.clone(); + tracing::info!( + current_justified_slot = latest_justified.slot.0, + current_finalized_slot = latest_finalized.slot.0, + "Processing attestations in block" + ); + let mut justified_slots_working = Vec::new(); for i in 0..justified_slots.len() { justified_slots_working.push(justified_slots.get(i).map(|b| *b).unwrap_or(false)); @@ -455,10 +461,21 @@ impl State { .copied() .unwrap_or(false); + // Special case for slot 0 (genesis): historical_block_hashes[0] is initialized as 0x0 + // in genesis, but validators attest with the actual genesis block hash (set in + // get_forkchoice_store). Allow any source_root when source is slot 0 and + // historical_block_hashes[0] is the zero hash. let source_root_matches = self .historical_block_hashes .get(source_slot_int as u64) - .map(|r| *r == source_root) + .map(|r| { + if source_slot_int == 0 && r.0.is_zero() { + // Genesis slot: accept any root when historical hash is 0x0 + true + } else { + *r == source_root + } + }) .unwrap_or(false); let target_root_matches = self .historical_block_hashes @@ -472,7 +489,31 @@ impl State { && target_slot > source_slot && target_slot.is_justifiable_after(initial_finalized_slot); + // Debug logging for vote validation + tracing::debug!( + source_slot = source_slot.0, + target_slot = target_slot.0, + source_root = %format!("0x{:x}", source_root.0), + target_root = %format!("0x{:x}", target_root.0), + validator_count = validator_ids.len(), + source_is_justified, + target_already_justified, + source_root_matches, + target_root_matches, + is_valid_vote, + "Processing attestation vote" + ); + if !is_valid_vote { + tracing::warn!( + source_slot = source_slot.0, + target_slot = target_slot.0, + source_is_justified, + target_already_justified, + source_root_matches, + target_root_matches, + "Vote rejected" + ); return; } @@ -492,7 +533,25 @@ impl State { if let Some(votes) = justifications.get(&target_root) { let num_validators = self.validators.len_u64() as usize; let count = votes.iter().filter(|&&v| v).count(); + let threshold = (2 * num_validators + 2) / 3; // ceil(2/3) + + tracing::info!( + target_slot = target_slot.0, + target_root = %format!("0x{:x}", target_root.0), + vote_count = count, + num_validators, + threshold, + needs = format!("3*{} >= 2*{} = {} >= {}", count, num_validators, 3*count, 2*num_validators), + will_justify = 3 * count >= 2 * num_validators, + "Vote count for target" + ); + if 3 * count >= 2 * num_validators { + tracing::info!( + target_slot = target_slot.0, + target_root = %format!("0x{:x}", target_root.0), + "JUSTIFICATION THRESHOLD REACHED!" + ); *latest_justified = vote.target.clone(); justified_slots_working.extend(std::iter::repeat_n( @@ -507,6 +566,7 @@ impl State { .all(|s| !Slot(s as u64).is_justifiable_after(initial_finalized_slot)); if is_finalizable { + tracing::info!(source_slot = source_slot.0, "FINALIZATION!"); *latest_finalized = vote.source.clone(); } } @@ -628,11 +688,26 @@ impl State { .map_err(|e| format!("Failed to push attestation: {:?}", e))?; } + // IMPORTANT: Recompute post_state using the FINAL attestations. + // The original post_state was computed from candidate_block with ALL attestations, + // but final_attestations_list may have fewer attestations (only those with signatures). + // We must use the same attestations for state computation and the block body. + let final_candidate_block = Block { + slot, + proposer_index, + parent_root, + state_root: Bytes32(ssz::H256::zero()), + body: BlockBody { + attestations: final_attestations_list.clone(), + }, + }; + let final_post_state = pre_state.process_block(&final_candidate_block)?; + let final_block = Block { slot, proposer_index, parent_root, - state_root: hash_tree_root(&post_state), + state_root: hash_tree_root(&final_post_state), body: BlockBody { attestations: final_attestations_list, }, @@ -640,7 +715,7 @@ impl State { return Ok(( final_block, - post_state, + final_post_state, aggregated_attestations, aggregated_proofs, )); @@ -708,11 +783,26 @@ impl State { .map_err(|e| format!("Failed to push attestation: {:?}", e))?; } + // IMPORTANT: Recompute post_state using the FINAL attestations. + // The original post_state was computed from candidate_block with ALL attestations, + // but final_attestations_list may have fewer attestations (only those with signatures). + // We must use the same attestations for state computation and the block body. + let final_candidate_block = Block { + slot, + proposer_index, + parent_root, + state_root: Bytes32(ssz::H256::zero()), + body: BlockBody { + attestations: final_attestations_list.clone(), + }, + }; + let final_post_state = pre_state.process_block(&final_candidate_block)?; + let final_block = Block { slot, proposer_index, parent_root, - state_root: hash_tree_root(&post_state), + state_root: hash_tree_root(&final_post_state), body: BlockBody { attestations: final_attestations_list, }, @@ -720,7 +810,7 @@ impl State { return Ok(( final_block, - post_state, + final_post_state, aggregated_attestations, aggregated_proofs, )); diff --git a/lean_client/containers/tests/unit_tests/state_transition.rs b/lean_client/containers/tests/unit_tests/state_transition.rs index 4b763c6..bcf0ea1 100644 --- a/lean_client/containers/tests/unit_tests/state_transition.rs +++ b/lean_client/containers/tests/unit_tests/state_transition.rs @@ -40,19 +40,6 @@ fn test_state_transition_full() { let expected_state = state_after_header.process_attestations(&block.body.attestations); - #[cfg(feature = "devnet2")] - let expected_state = { - let mut unaggregated_attestations = Attestations::default(); - for aggregated_attestation in &block.body.attestations { - let plain_attestations = aggregated_attestation.to_plain(); - // For each attestatio in the vector, push to the list - for attestation in plain_attestations { - unaggregated_attestations.push(attestation); - } - } - state_after_header.process_attestations(&unaggregated_attestations) - }; - let block_with_correct_root = Block { state_root: hash_tree_root(&expected_state), ..block @@ -87,19 +74,6 @@ fn test_state_transition_invalid_signatures() { let expected_state = state_after_header.process_attestations(&block.body.attestations); - #[cfg(feature = "devnet2")] - let expected_state = { - let mut list = Attestations::default(); - for aggregated_attestation in &block.body.attestations { - let plain_attestations = aggregated_attestation.to_plain(); - // For each attestatio in the vector, push to the list - for attestation in plain_attestations { - list.push(attestation); - } - } - list - }; - let block_with_correct_root = Block { state_root: hash_tree_root(&expected_state), ..block diff --git a/lean_client/fork_choice/src/handlers.rs b/lean_client/fork_choice/src/handlers.rs index 3054052..5888942 100644 --- a/lean_client/fork_choice/src/handlers.rs +++ b/lean_client/fork_choice/src/handlers.rs @@ -1,4 +1,5 @@ use crate::store::*; +use containers::attestation::AttestationData; use containers::SignatureKey; use containers::{ attestation::SignedAttestation, block::SignedBlockWithAttestation, Bytes32, ValidatorIndex, @@ -20,6 +21,106 @@ pub fn on_tick(store: &mut Store, time: u64, has_proposal: bool) { } } +/// 1. The blocks voted for must exist in our store. +/// 2. A vote cannot span backwards in time (source > target). +/// 3. A vote cannot be for a future slot. +/// 4. Checkpoint slots must match block slots. +fn validate_attestation_data(store: &Store, data: &AttestationData) -> Result<(), String> { + // Cannot count a vote if we haven't seen the blocks involved + if !store.blocks.contains_key(&data.source.root) { + return Err(format!( + "Unknown source block: {:?}", + &data.source.root.0.as_bytes()[..8] + )); + } + if !store.blocks.contains_key(&data.target.root) { + return Err(format!( + "Unknown target block: {:?}", + &data.target.root.0.as_bytes()[..8] + )); + } + if !store.blocks.contains_key(&data.head.root) { + return Err(format!( + "Unknown head block: {:?}", + &data.head.root.0.as_bytes()[..8] + )); + } + + // Source must be older than Target. + if data.source.slot > data.target.slot { + return Err(format!( + "Source checkpoint slot {} must not exceed target slot {}", + data.source.slot.0, data.target.slot.0 + )); + } + + // Validate checkpoint slots match block slots + // Per devnet-2, store.blocks now contains Block (not SignedBlockWithAttestation) + let source_block = &store.blocks[&data.source.root]; + let target_block = &store.blocks[&data.target.root]; + + if source_block.slot != data.source.slot { + return Err(format!( + "Source checkpoint slot mismatch: checkpoint {} vs block {}", + data.source.slot.0, source_block.slot.0 + )); + } + if target_block.slot != data.target.slot { + return Err(format!( + "Target checkpoint slot mismatch: checkpoint {} vs block {}", + data.target.slot.0, target_block.slot.0 + )); + } + + // Validate attestation is not too far in the future + // We allow a small margin for clock disparity (1 slot), but no further. + let current_slot = store.time / INTERVALS_PER_SLOT; + if data.slot.0 > current_slot + 1 { + return Err(format!( + "Attestation too far in future: attestation slot {} > current slot {} + 1", + data.slot.0, current_slot + )); + } + + Ok(()) +} + +/// Process a signed attestation received via gossip network +/// +/// 1. Validates the attestation data +/// 2. Stores the signature in the gossip signature map +/// 3. Processes the attestation data via on_attestation +/// +#[inline] +pub fn on_gossip_attestation( + store: &mut Store, + signed_attestation: SignedAttestation, +) -> Result<(), String> { + let validator_id = ValidatorIndex(signed_attestation.validator_id); + let attestation_data = signed_attestation.message.clone(); + + // Validate the attestation data first + validate_attestation_data(store, &attestation_data)?; + + // Store signature for later lookup during block building + let data_root = attestation_data.data_root_bytes(); + let sig_key = SignatureKey::new(signed_attestation.validator_id, data_root); + store + .gossip_signatures + .insert(sig_key, signed_attestation.signature); + + // Process the attestation data (not from block) + on_attestation_internal(store, validator_id, attestation_data, false) +} + +/// Process an attestation and place it into the correct attestation stage +/// +/// Attestation processing logic that updates the attestation +/// maps used for fork choice. Per devnet-2, we store AttestationData only (not signatures). +/// +/// Attestations can come from: +/// - a block body (on-chain, `is_from_block=True`), or +/// - the gossip network (off-chain, `is_from_block=False`). #[inline] pub fn on_attestation( store: &mut Store, @@ -27,68 +128,72 @@ pub fn on_attestation( is_from_block: bool, ) -> Result<(), String> { let validator_id = ValidatorIndex(signed_attestation.validator_id); - let attestation_slot = signed_attestation.message.slot; - let source_slot = signed_attestation.message.source.slot; - let target_slot = signed_attestation.message.target.slot; + let attestation_data = signed_attestation.message.clone(); - // Validate attestation is not from future - let curr_slot = store.time / INTERVALS_PER_SLOT; - if attestation_slot.0 > curr_slot { - return Err(format!( - "Err: (Fork-choice::Handlers::OnAttestation) Attestation for slot {} has not yet occurred, out of sync. (CURRENT SLOT NUMBER: {})", - attestation_slot.0, curr_slot - )); - } + // Validate attestation data + validate_attestation_data(store, &attestation_data)?; - // Validate source slot does not exceed target slot (per leanSpec validate_attestation) - if source_slot > target_slot { - return Err(format!( - "Err: (Fork-choice::Handlers::OnAttestation) Source slot {} exceeds target slot {}", - source_slot.0, target_slot.0 - )); + if !is_from_block { + // Store signature for later aggregation during block building + let data_root = attestation_data.data_root_bytes(); + let sig_key = SignatureKey::new(signed_attestation.validator_id, data_root); + store + .gossip_signatures + .insert(sig_key, signed_attestation.signature); } + on_attestation_internal(store, validator_id, attestation_data, is_from_block) +} + +/// Internal attestation processing - stores AttestationData +fn on_attestation_internal( + store: &mut Store, + validator_id: ValidatorIndex, + attestation_data: AttestationData, + is_from_block: bool, +) -> Result<(), String> { + let attestation_slot = attestation_data.slot; + if is_from_block { - // On-chain attestation processing - immediately becomes "known" + // On-chain attestation processing if store .latest_known_attestations .get(&validator_id) - .map_or(true, |existing| existing.message.slot < attestation_slot) + .map_or(true, |existing| existing.slot < attestation_slot) { store .latest_known_attestations - .insert(validator_id, signed_attestation.clone()); + .insert(validator_id, attestation_data); } // Remove from new attestations if superseded if let Some(existing_new) = store.latest_new_attestations.get(&validator_id) { - if existing_new.message.slot <= attestation_slot { + if existing_new.slot <= attestation_slot { store.latest_new_attestations.remove(&validator_id); } } } else { // Network gossip attestation processing - goes to "new" stage - // Store signature for later aggregation during block building - let data_root = signed_attestation.message.data_root_bytes(); - let sig_key = SignatureKey::new(signed_attestation.validator_id, data_root); - store - .gossip_signatures - .insert(sig_key, signed_attestation.signature.clone()); - - // Track attestation for fork choice if store .latest_new_attestations .get(&validator_id) - .map_or(true, |existing| existing.message.slot < attestation_slot) + .map_or(true, |existing| existing.slot < attestation_slot) { store .latest_new_attestations - .insert(validator_id, signed_attestation); + .insert(validator_id, attestation_data); } } Ok(()) } +/// Process a new block and update the forkchoice state +/// +/// 1. Validating the block's parent exists +/// 2. Computing the post-state via the state transition function +/// 3. Processing attestations included in the block body (on-chain) +/// 4. Updating the forkchoice head +/// 5. Processing the proposer's attestation (as if gossiped) pub fn on_block(store: &mut Store, signed_block: SignedBlockWithAttestation) -> Result<(), String> { let block_root = Bytes32(signed_block.message.block.hash_tree_root()); @@ -122,7 +227,7 @@ fn process_block_internal( signed_block: SignedBlockWithAttestation, block_root: Bytes32, ) -> Result<(), String> { - let block = &signed_block.message.block; + let block = signed_block.message.block.clone(); // Get parent state for validation let state = match store.states.get(&block.parent_root) { @@ -137,8 +242,8 @@ fn process_block_internal( // Execute state transition to get post-state let new_state = state.state_transition_with_validation(signed_block.clone(), true, true)?; - // Store block and state - store.blocks.insert(block_root, signed_block.clone()); + // Store block and state, store the plain Block (not SignedBlockWithAttestation) + store.blocks.insert(block_root, block.clone()); store.states.insert(block_root, new_state.clone()); if new_state.latest_justified.slot > store.latest_justified.slot { @@ -150,8 +255,7 @@ fn process_block_internal( // Process block body attestations as on-chain (is_from_block=true) let signatures = &signed_block.signature; - - let aggregated_attestations = &signed_block.message.block.body.attestations; + let aggregated_attestations = &block.body.attestations; let proposer_attestation = &signed_block.message.proposer_attestation; // Store aggregated proofs for future block building @@ -177,7 +281,8 @@ fn process_block_internal( } // Process each aggregated attestation's validators for fork choice - // Note: Signature verification is done in verify_signatures() before on_block() + // Signature verification is done in verify_signatures() before on_block() + // Per Devnet-2, we process attestation data directly (not SignedAttestation) for aggregated_attestation in aggregated_attestations.into_iter() { let validator_ids: Vec = aggregated_attestation .aggregation_bits @@ -190,15 +295,11 @@ fn process_block_internal( // Each validator in the aggregation votes for this attestation data for validator_id in validator_ids { - on_attestation( + on_attestation_internal( store, - SignedAttestation { - validator_id, - message: aggregated_attestation.data.clone(), - // Use a default signature since verification already happened - signature: containers::Signature::default(), - }, - true, + ValidatorIndex(validator_id), + aggregated_attestation.data.clone(), + true, // is_from_block )?; } } @@ -206,15 +307,22 @@ fn process_block_internal( // Update head BEFORE processing proposer attestation update_head(store); - let proposer_signed_attestation = SignedAttestation { - validator_id: proposer_attestation.validator_id.0, - message: proposer_attestation.data.clone(), - signature: signed_block.signature.proposer_signature, - }; + // Store proposer's signature for later block building + let proposer_data_root = proposer_attestation.data.data_root_bytes(); + let proposer_sig_key = + SignatureKey::new(proposer_attestation.validator_id.0, proposer_data_root); + store + .gossip_signatures + .insert(proposer_sig_key, signed_block.signature.proposer_signature); // Process proposer attestation as if received via gossip (is_from_block=false) // This ensures it goes to "new" attestations and doesn't immediately affect fork choice - on_attestation(store, proposer_signed_attestation, false)?; + on_attestation_internal( + store, + ValidatorIndex(proposer_attestation.validator_id.0), + proposer_attestation.data.clone(), + false, // is_from_block + )?; Ok(()) } diff --git a/lean_client/fork_choice/src/store.rs b/lean_client/fork_choice/src/store.rs index 818b57d..07100ba 100644 --- a/lean_client/fork_choice/src/store.rs +++ b/lean_client/fork_choice/src/store.rs @@ -1,27 +1,44 @@ use containers::{ - attestation::SignedAttestation, block::SignedBlockWithAttestation, checkpoint::Checkpoint, - config::Config, state::State, Bytes32, Root, Slot, ValidatorIndex, + attestation::{AttestationData, SignedAttestation}, + block::{Block, SignedBlockWithAttestation}, + checkpoint::Checkpoint, + config::Config, + state::State, + Bytes32, Root, Slot, ValidatorIndex, }; use containers::{AggregatedSignatureProof, Signature, SignatureKey}; use ssz::SszHash; use std::collections::HashMap; + pub type Interval = u64; pub const INTERVALS_PER_SLOT: Interval = 4; pub const SECONDS_PER_SLOT: u64 = 4; pub const SECONDS_PER_INTERVAL: u64 = SECONDS_PER_SLOT / INTERVALS_PER_SLOT; +/// Forkchoice store tracking chain state and validator attestations + #[derive(Debug, Clone, Default)] pub struct Store { pub time: Interval, + pub config: Config, + pub head: Root, + pub safe_target: Root, + pub latest_justified: Checkpoint, + pub latest_finalized: Checkpoint, - pub blocks: HashMap, + + pub blocks: HashMap, + pub states: HashMap, - pub latest_known_attestations: HashMap, - pub latest_new_attestations: HashMap, + + pub latest_known_attestations: HashMap, + + pub latest_new_attestations: HashMap, + pub blocks_queue: HashMap>, pub gossip_signatures: HashMap, @@ -29,13 +46,16 @@ pub struct Store { pub aggregated_payloads: HashMap>, } +/// Initialize forkchoice store from an anchor state and block pub fn get_forkchoice_store( anchor_state: State, anchor_block: SignedBlockWithAttestation, config: Config, ) -> Store { - let block_root = Bytes32(anchor_block.message.block.hash_tree_root()); - let block_slot = anchor_block.message.block.slot; + // Extract the plain Block from the signed block + let block = anchor_block.message.block.clone(); + let block_root = Bytes32(block.hash_tree_root()); + let block_slot = block.slot; let latest_justified = if anchor_state.latest_justified.root.0.is_zero() { Checkpoint { @@ -62,7 +82,7 @@ pub fn get_forkchoice_store( safe_target: block_root, latest_justified, latest_finalized, - blocks: [(block_root, anchor_block)].into(), + blocks: [(block_root, block)].into(), states: [(block_root, anchor_state)].into(), latest_known_attestations: HashMap::new(), latest_new_attestations: HashMap::new(), @@ -75,37 +95,37 @@ pub fn get_forkchoice_store( pub fn get_fork_choice_head( store: &Store, mut root: Root, - latest_attestations: &HashMap, + latest_attestations: &HashMap, min_votes: usize, ) -> Root { if root.0.is_zero() { root = store .blocks .iter() - .min_by_key(|(_, block)| block.message.block.slot) + .min_by_key(|(_, block)| block.slot) .map(|(r, _)| *r) .expect("Error: Empty block."); } let mut vote_weights: HashMap = HashMap::new(); - let root_slot = store.blocks[&root].message.block.slot; + let root_slot = store.blocks[&root].slot; // stage 1: accumulate weights by walking up from each attestation's head - for attestation in latest_attestations.values() { - let mut curr = attestation.message.head.root; + for attestation_data in latest_attestations.values() { + let mut curr = attestation_data.head.root; if let Some(block) = store.blocks.get(&curr) { - let mut curr_slot = block.message.block.slot; + let mut curr_slot = block.slot; while curr_slot > root_slot { *vote_weights.entry(curr).or_insert(0) += 1; if let Some(parent_block) = store.blocks.get(&curr) { - curr = parent_block.message.block.parent_root; + curr = parent_block.parent_root; if curr.0.is_zero() { break; } if let Some(next_block) = store.blocks.get(&curr) { - curr_slot = next_block.message.block.slot; + curr_slot = next_block.slot; } else { break; } @@ -116,13 +136,13 @@ pub fn get_fork_choice_head( } } - // stage 2 + // stage 2: build adjacency tree (parent -> children) let mut child_map: HashMap> = HashMap::new(); for (block_hash, block) in &store.blocks { - if !block.message.block.parent_root.0.is_zero() { + if !block.parent_root.0.is_zero() { if vote_weights.get(block_hash).copied().unwrap_or(0) >= min_votes { child_map - .entry(block.message.block.parent_root) + .entry(block.parent_root) .or_default() .push(*block_hash); } @@ -138,7 +158,6 @@ pub fn get_fork_choice_head( }; // Choose best child: most attestations, then lexicographically highest hash - // This matches leanSpec: max(children, key=lambda x: (weights[x], x)) curr = *children .iter() .max_by(|&&a, &&b| { @@ -190,8 +209,8 @@ pub fn accept_new_attestations(store: &mut Store) { pub fn tick_interval(store: &mut Store, has_proposal: bool) { store.time += 1; - // Calculate current interval within slot: time % SECONDS_PER_SLOT % INTERVALS_PER_SLOT - let curr_interval = (store.time % SECONDS_PER_SLOT) % INTERVALS_PER_SLOT; + // Calculate current interval within slot: time % INTERVALS_PER_SLOT + let curr_interval = store.time % INTERVALS_PER_SLOT; match curr_interval { 0 if has_proposal => accept_new_attestations(store), @@ -201,45 +220,31 @@ pub fn tick_interval(store: &mut Store, has_proposal: bool) { } } +/// Algorithm: +/// 1. Start at Head: Begin with the current head block +/// 2. Walk Toward Safe: Move backward (up to JUSTIFICATION_LOOKBACK_SLOTS steps) +/// if safe target is newer +/// 3. Ensure Justifiable: Continue walking back until slot is justifiable +/// 4. Return Checkpoint: Create checkpoint from selected block pub fn get_vote_target(store: &Store) -> Checkpoint { let mut target = store.head; - let safe_slot = store.blocks[&store.safe_target].message.block.slot; - let source_slot = store.latest_justified.slot; + let safe_slot = store.blocks[&store.safe_target].slot; - // Walk back toward safe target (up to 3 steps per leanSpec JUSTIFICATION_LOOKBACK_SLOTS) + // Walk back toward safe target for _ in 0..3 { - if store.blocks[&target].message.block.slot > safe_slot { - let parent = store.blocks[&target].message.block.parent_root; - // Don't walk back if it would make target <= source (invalid attestation) - if let Some(parent_block) = store.blocks.get(&parent) { - if parent_block.message.block.slot <= source_slot { - break; - } - } - target = parent; + if store.blocks[&target].slot > safe_slot { + target = store.blocks[&target].parent_root; } else { break; } } let final_slot = store.latest_finalized.slot; - while !store.blocks[&target] - .message - .block - .slot - .is_justifiable_after(final_slot) - { - let parent = store.blocks[&target].message.block.parent_root; - // Don't walk back if it would make target <= source (invalid attestation) - if let Some(parent_block) = store.blocks.get(&parent) { - if parent_block.message.block.slot <= source_slot { - break; - } - } - target = parent; + while !store.blocks[&target].slot.is_justifiable_after(final_slot) { + target = store.blocks[&target].parent_root; } - let block_target = &store.blocks[&target].message.block; + let block_target = &store.blocks[&target]; Checkpoint { root: target, slot: block_target.slot, @@ -255,7 +260,7 @@ pub fn get_proposal_head(store: &mut Store, slot: Slot) -> Root { store.head } -/// Produce a block and aggregated signature proofs for the target slot. +/// Produce a block and aggregated signature proofs for the target slot per devnet-2. /// /// The proposer returns the block and `MultisigAggregatedSignature` proofs aligned /// with `block.body.attestations` so it can craft `SignedBlockWithAttestation`. @@ -306,12 +311,13 @@ pub fn produce_block_with_signatures( } // Convert AttestationData to Attestation objects for build_block + // Per devnet-2, store now holds AttestationData directly let available_attestations: Vec = store .latest_known_attestations .iter() - .map(|(validator_idx, signed_att)| Attestation { + .map(|(validator_idx, attestation_data)| Attestation { validator_id: containers::Uint64(validator_idx.0), - data: signed_att.message.clone(), + data: attestation_data.clone(), }) .collect(); @@ -335,7 +341,8 @@ pub fn produce_block_with_signatures( // Compute block root let block_root = Bytes32(final_block.hash_tree_root()); - // Store block and state + // Store block and state (per devnet-2, we store the plain Block) + store.blocks.insert(block_root, final_block.clone()); store.states.insert(block_root, final_post_state); Ok((block_root, final_block, signatures)) diff --git a/lean_client/fork_choice/tests/fork_choice_test_vectors.rs b/lean_client/fork_choice/tests/fork_choice_test_vectors.rs index 33ef9ee..689d20b 100644 --- a/lean_client/fork_choice/tests/fork_choice_test_vectors.rs +++ b/lean_client/fork_choice/tests/fork_choice_test_vectors.rs @@ -434,7 +434,8 @@ fn verify_checks( }; if let Some(expected_slot) = checks.head_slot { - let actual_slot = store.blocks[&store.head].message.block.slot.0; + // Per devnet-2, store.blocks now contains Block (not SignedBlockWithAttestation) + let actual_slot = store.blocks[&store.head].slot.0; if actual_slot != expected_slot { return Err(format!( "Step {}: Head slot mismatch - expected {}, got {}", @@ -448,15 +449,12 @@ fn verify_checks( .get(label) .ok_or_else(|| format!("Step {}: Block label '{}' not found", step_idx, label))?; if &store.head != expected_root { - let actual_slot = store - .blocks - .get(&store.head) - .map(|b| b.message.block.slot.0) - .unwrap_or(0); + // Per devnet-2, store.blocks now contains Block (not SignedBlockWithAttestation) + let actual_slot = store.blocks.get(&store.head).map(|b| b.slot.0).unwrap_or(0); let expected_slot = store .blocks .get(expected_root) - .map(|b| b.message.block.slot.0) + .map(|b| b.slot.0) .unwrap_or(0); return Err(format!( "Step {}: Head root mismatch for label '{}' - expected slot {}, got slot {} (known_attestations: {}, new_attestations: {})", @@ -479,11 +477,12 @@ fn verify_checks( )); } if let Some(target_slot) = check.target_slot { - let attestation = &store.latest_new_attestations[&validator]; - if attestation.message.target.slot.0 != target_slot { + // Per devnet-2, store now holds AttestationData directly (not SignedAttestation) + let attestation_data = &store.latest_new_attestations[&validator]; + if attestation_data.target.slot.0 != target_slot { return Err(format!( "Step {}: Validator {} new attestation target slot mismatch - expected {}, got {}", - step_idx, check.validator, target_slot, attestation.message.target.slot.0 + step_idx, check.validator, target_slot, attestation_data.target.slot.0 )); } } diff --git a/lean_client/fork_choice/tests/unit_tests/fork_choice.rs b/lean_client/fork_choice/tests/unit_tests/fork_choice.rs index d2b3833..684a799 100644 --- a/lean_client/fork_choice/tests/unit_tests/fork_choice.rs +++ b/lean_client/fork_choice/tests/unit_tests/fork_choice.rs @@ -23,7 +23,7 @@ fn test_get_proposal_head_advances_time() { #[test] fn test_get_vote_target_chain() { use containers::{ - block::{Block, BlockBody, BlockWithAttestation, SignedBlockWithAttestation}, + block::{Block, BlockBody}, Bytes32, ValidatorIndex, }; use ssz::SszHash; @@ -32,6 +32,7 @@ fn test_get_vote_target_chain() { let mut parent_root = store.head; // Create a chain of 10 blocks + // Per leanSpec, store.blocks now contains Block (not SignedBlockWithAttestation) for i in 1..=10 { let block = Block { slot: Slot(i), @@ -43,15 +44,8 @@ fn test_get_vote_target_chain() { let block_root = Bytes32(block.hash_tree_root()); - let signed_block = SignedBlockWithAttestation { - message: BlockWithAttestation { - block: block.clone(), - proposer_attestation: Default::default(), - }, - signature: Default::default(), - }; - - store.blocks.insert(block_root, signed_block); + // Insert Block directly per leanSpec + store.blocks.insert(block_root, block); parent_root = block_root; } diff --git a/lean_client/fork_choice/tests/unit_tests/votes.rs b/lean_client/fork_choice/tests/unit_tests/votes.rs index a3c9b8a..2b20fe2 100644 --- a/lean_client/fork_choice/tests/unit_tests/votes.rs +++ b/lean_client/fork_choice/tests/unit_tests/votes.rs @@ -1,12 +1,12 @@ //! Vote/attestation unit tests for devnet2 //! //! Tests for vote processing and fork choice weight calculations -//! using the devnet2 SignedAttestation structure. +//! using the devnet2 AttestationData structure per leanSpec. use super::common::create_test_store; use containers::{ - attestation::{AttestationData, SignedAttestation}, - block::{Block, BlockBody, BlockWithAttestation, SignedBlockWithAttestation}, + attestation::AttestationData, + block::{Block, BlockBody}, checkpoint::Checkpoint, Bytes32, Slot, ValidatorIndex, }; @@ -14,9 +14,8 @@ use fork_choice::store::get_fork_choice_head; use ssz::SszHash; use std::collections::HashMap; -/// Helper to create a SignedAttestation for devnet2 -fn create_signed_attestation( - validator_id: u64, +/// Helper to create an AttestationData for devnet2 (per leanSpec) +fn create_attestation_data( slot: u64, head_root: Bytes32, head_slot: u64, @@ -24,25 +23,21 @@ fn create_signed_attestation( target_slot: u64, source_root: Bytes32, source_slot: u64, -) -> SignedAttestation { - SignedAttestation { - validator_id, - message: AttestationData { - slot: Slot(slot), - head: Checkpoint { - root: head_root, - slot: Slot(head_slot), - }, - target: Checkpoint { - root: target_root, - slot: Slot(target_slot), - }, - source: Checkpoint { - root: source_root, - slot: Slot(source_slot), - }, +) -> AttestationData { + AttestationData { + slot: Slot(slot), + head: Checkpoint { + root: head_root, + slot: Slot(head_slot), + }, + target: Checkpoint { + root: target_root, + slot: Slot(target_slot), + }, + source: Checkpoint { + root: source_root, + slot: Slot(source_slot), }, - signature: Default::default(), } } @@ -52,8 +47,7 @@ fn test_single_vote_updates_head() { let genesis_root = store.head; // Create attestation pointing to genesis - let attestation = create_signed_attestation( - 0, // validator_id + let attestation = create_attestation_data( 1, // slot genesis_root, // head_root 0, // head_slot @@ -81,7 +75,7 @@ fn test_multiple_votes_same_block() { let mut attestations = HashMap::new(); for i in 0..5 { let attestation = - create_signed_attestation(i, 1, genesis_root, 0, genesis_root, 0, genesis_root, 0); + create_attestation_data(1, genesis_root, 0, genesis_root, 0, genesis_root, 0); attestations.insert(ValidatorIndex(i), attestation); } @@ -110,40 +104,22 @@ fn test_competing_votes_different_blocks() { block_b.proposer_index = ValidatorIndex(1); // Different proposer to get different root let block_b_root = Bytes32(block_b.hash_tree_root()); - store.blocks.insert( - block_a_root, - SignedBlockWithAttestation { - message: BlockWithAttestation { - block: block_a, - proposer_attestation: Default::default(), - }, - signature: Default::default(), - }, - ); - - store.blocks.insert( - block_b_root, - SignedBlockWithAttestation { - message: BlockWithAttestation { - block: block_b, - proposer_attestation: Default::default(), - }, - signature: Default::default(), - }, - ); + // Per leanSpec, store.blocks contains Block directly + store.blocks.insert(block_a_root, block_a); + store.blocks.insert(block_b_root, block_b); // 3 votes for block_a, 2 votes for block_b let mut attestations = HashMap::new(); for i in 0..3 { attestations.insert( ValidatorIndex(i), - create_signed_attestation(i, 1, block_a_root, 1, genesis_root, 0, genesis_root, 0), + create_attestation_data(1, block_a_root, 1, genesis_root, 0, genesis_root, 0), ); } for i in 3..5 { attestations.insert( ValidatorIndex(i), - create_signed_attestation(i, 1, block_b_root, 1, genesis_root, 0, genesis_root, 0), + create_attestation_data(1, block_b_root, 1, genesis_root, 0, genesis_root, 0), ); } @@ -177,32 +153,15 @@ fn test_vote_weight_accumulation() { }; let block2_root = Bytes32(block2.hash_tree_root()); - store.blocks.insert( - block1_root, - SignedBlockWithAttestation { - message: BlockWithAttestation { - block: block1, - proposer_attestation: Default::default(), - }, - signature: Default::default(), - }, - ); - store.blocks.insert( - block2_root, - SignedBlockWithAttestation { - message: BlockWithAttestation { - block: block2, - proposer_attestation: Default::default(), - }, - signature: Default::default(), - }, - ); + // Per leanSpec, store.blocks contains Block directly + store.blocks.insert(block1_root, block1); + store.blocks.insert(block2_root, block2); // Vote for block2 - should accumulate to block1 as well let mut attestations = HashMap::new(); attestations.insert( ValidatorIndex(0), - create_signed_attestation(0, 2, block2_root, 2, genesis_root, 0, genesis_root, 0), + create_attestation_data(2, block2_root, 2, genesis_root, 0, genesis_root, 0), ); let head = get_fork_choice_head(&store, genesis_root, &attestations, 0); @@ -222,13 +181,13 @@ fn test_duplicate_vote_uses_latest() { // Insert a vote attestations.insert( ValidatorIndex(0), - create_signed_attestation(0, 1, genesis_root, 0, genesis_root, 0, genesis_root, 0), + create_attestation_data(1, genesis_root, 0, genesis_root, 0, genesis_root, 0), ); // "Update" with same validator - only latest is kept attestations.insert( ValidatorIndex(0), - create_signed_attestation(0, 2, genesis_root, 0, genesis_root, 0, genesis_root, 0), + create_attestation_data(2, genesis_root, 0, genesis_root, 0, genesis_root, 0), ); // Should only have 1 attestation @@ -248,7 +207,7 @@ fn test_vote_for_unknown_block_ignored() { let mut attestations = HashMap::new(); attestations.insert( ValidatorIndex(0), - create_signed_attestation(0, 1, unknown_root, 1, genesis_root, 0, genesis_root, 0), + create_attestation_data(1, unknown_root, 1, genesis_root, 0, genesis_root, 0), ); let head = get_fork_choice_head(&store, genesis_root, &attestations, 0); diff --git a/lean_client/networking/src/enr_ext.rs b/lean_client/networking/src/enr_ext.rs index d7511e4..c515b92 100644 --- a/lean_client/networking/src/enr_ext.rs +++ b/lean_client/networking/src/enr_ext.rs @@ -217,13 +217,16 @@ impl EnrExt for Enr { } /// Returns a list of multiaddrs if the ENR has an `ip` and a `quic` key **or** an `ip6` and a `quic6`. + /// This also appends the `PeerId` into each multiaddr with the `P2p` protocol. fn multiaddr_quic(&self) -> Vec { + let peer_id = self.peer_id(); let mut multiaddrs: Vec = Vec::new(); if let Some(quic_port) = self.quic4() { if let Some(ip) = self.ip4() { let mut multiaddr: Multiaddr = ip.into(); multiaddr.push(Protocol::Udp(quic_port)); multiaddr.push(Protocol::QuicV1); + multiaddr.push(Protocol::P2p(peer_id)); multiaddrs.push(multiaddr); } } @@ -233,6 +236,7 @@ impl EnrExt for Enr { let mut multiaddr: Multiaddr = ip6.into(); multiaddr.push(Protocol::Udp(quic6_port)); multiaddr.push(Protocol::QuicV1); + multiaddr.push(Protocol::P2p(peer_id)); multiaddrs.push(multiaddr); } } diff --git a/lean_client/networking/src/gossipsub/config.rs b/lean_client/networking/src/gossipsub/config.rs index 67061bc..68bb069 100644 --- a/lean_client/networking/src/gossipsub/config.rs +++ b/lean_client/networking/src/gossipsub/config.rs @@ -14,7 +14,7 @@ pub struct GossipsubConfig { impl GossipsubConfig { pub fn new() -> Self { let justification_lookback_slots: u64 = 3; - let seconds_per_slot: u64 = 12; + let seconds_per_slot: u64 = 4; let seen_ttl_secs = seconds_per_slot * justification_lookback_slots * 2; @@ -61,7 +61,7 @@ pub fn compute_message_id(message: &Message) -> MessageId { let topic_len = topic_bytes.len() as u64; let mut digest_input = Vec::new(); - // Domain: 4 bytes + // Domain: 1 byte digest_input.extend_from_slice(MESSAGE_DOMAIN_VALID_SNAPPY); // Topic length: 8 bytes (uint64 little-endian) digest_input.extend_from_slice(&topic_len.to_le_bytes()); diff --git a/lean_client/networking/src/network/service.rs b/lean_client/networking/src/network/service.rs index 1c97353..47eaa9f 100644 --- a/lean_client/networking/src/network/service.rs +++ b/lean_client/networking/src/network/service.rs @@ -584,7 +584,11 @@ where match signed_block_with_attestation.to_ssz() { Ok(bytes) => { if let Err(err) = self.publish_to_topic(GossipsubKind::Block, bytes) { - warn!(slot = slot, ?err, "Publish block with attestation failed"); + // Duplicate errors are expected - we receive our own blocks back from peers + let err_str = format!("{:?}", err); + if !err_str.contains("Duplicate") { + warn!(slot = slot, ?err, "Publish block with attestation failed"); + } } else { info!(slot = slot, "Broadcasted block with attestation"); } @@ -600,7 +604,11 @@ where match signed_attestation.to_ssz() { Ok(bytes) => { if let Err(err) = self.publish_to_topic(GossipsubKind::Attestation, bytes) { - warn!(slot = slot, ?err, "Publish attestation failed"); + // Duplicate errors are expected - we receive our own attestations back from peers + let err_str = format!("{:?}", err); + if !err_str.contains("Duplicate") { + warn!(slot = slot, ?err, "Publish attestation failed"); + } } else { info!(slot = slot, "Broadcasted attestation"); } diff --git a/lean_client/networking/src/req_resp.rs b/lean_client/networking/src/req_resp.rs index bd6c414..592c746 100644 --- a/lean_client/networking/src/req_resp.rs +++ b/lean_client/networking/src/req_resp.rs @@ -14,7 +14,7 @@ use snap::write::FrameEncoder; pub const MAX_REQUEST_BLOCKS: usize = 1024; pub const STATUS_PROTOCOL_V1: &str = "/leanconsensus/req/status/1/ssz_snappy"; -pub const BLOCKS_BY_ROOT_PROTOCOL_V1: &str = "/leanconsensus/req/lean_blocks_by_root/1/ssz_snappy"; +pub const BLOCKS_BY_ROOT_PROTOCOL_V1: &str = "/leanconsensus/req/blocks_by_root/1/ssz_snappy"; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct LeanProtocol(pub String); diff --git a/lean_client/networking/src/types.rs b/lean_client/networking/src/types.rs index 124ca5a..4e7bde8 100644 --- a/lean_client/networking/src/types.rs +++ b/lean_client/networking/src/types.rs @@ -3,23 +3,75 @@ use std::{collections::HashMap, fmt::Display}; use anyhow::{Result, anyhow}; use async_trait::async_trait; use containers::{Bytes32, SignedAttestation, SignedBlockWithAttestation}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use tokio::sync::mpsc; use crate::serde_utils::quoted_u64; -pub const MESSAGE_DOMAIN_VALID_SNAPPY: &[u8; 4] = &[0x01, 0x00, 0x00, 0x00]; -pub const MESSAGE_DOMAIN_INVALID_SNAPPY: &[u8; 4] = &[0x00, 0x00, 0x00, 0x00]; +/// 1-byte domain for gossip message-id isolation of valid snappy messages. +/// Per leanSpec, prepended to the message hash when decompression succeeds. +pub const MESSAGE_DOMAIN_VALID_SNAPPY: &[u8; 1] = &[0x01]; +/// 1-byte domain for gossip message-id isolation of invalid snappy messages. +/// Per leanSpec, prepended to the message hash when decompression fails. +pub const MESSAGE_DOMAIN_INVALID_SNAPPY: &[u8; 1] = &[0x00]; + +/// Peer connection state machine per leanSpec. +/// +/// Tracks the lifecycle of a connection to a peer: +/// DISCONNECTED -> CONNECTING -> CONNECTED -> DISCONNECTING -> DISCONNECTED +/// +/// These states map directly to libp2p connection events. #[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq, Hash)] #[serde(rename_all = "lowercase")] pub enum ConnectionState { - Connected, - Connecting, + /// No active connection to this peer. Disconnected, + /// TCP/QUIC connection in progress. + Connecting, + /// Transport established, can exchange protocol messages. + Connected, + /// Graceful shutdown in progress (Goodbye sent/received). Disconnecting, } +/// Reason codes for the Goodbye request/response message per leanSpec. +/// +/// Sent when gracefully disconnecting from a peer to indicate why +/// the connection is being closed. +/// +/// Official codes (from spec): +/// - 1: Client shutdown +/// - 2: Irrelevant network +/// - 3: Fault/error +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[repr(u64)] +pub enum GoodbyeReason { + /// Node is shutting down normally. + ClientShutdown = 1, + /// Peer is on a different fork or network. + IrrelevantNetwork = 2, + /// Generic error detected in peer communication. + FaultOrError = 3, +} + +impl GoodbyeReason { + /// Convert from u64 code to GoodbyeReason. + pub fn from_code(code: u64) -> Option { + match code { + 1 => Some(GoodbyeReason::ClientShutdown), + 2 => Some(GoodbyeReason::IrrelevantNetwork), + 3 => Some(GoodbyeReason::FaultOrError), + _ => None, + } + } + + /// Get the u64 code for this reason. + pub fn code(&self) -> u64 { + *self as u64 + } +} + #[derive(Debug, Serialize, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum Direction { diff --git a/lean_client/src/main.rs b/lean_client/src/main.rs index 61a4d14..c32a4c5 100644 --- a/lean_client/src/main.rs +++ b/lean_client/src/main.rs @@ -44,11 +44,8 @@ fn load_node_key(path: &str) -> Result> { fn print_chain_status(store: &Store, connected_peers: u64) { let current_slot = store.time / INTERVALS_PER_SLOT; - let head_slot = store - .blocks - .get(&store.head) - .map(|b| b.message.block.slot.0) - .unwrap_or(0); + // Per leanSpec, store.blocks now contains Block (not SignedBlockWithAttestation) + let head_slot = store.blocks.get(&store.head).map(|b| b.slot.0).unwrap_or(0); let behind = if current_slot > head_slot { current_slot - head_slot @@ -56,10 +53,11 @@ fn print_chain_status(store: &Store, connected_peers: u64) { 0 }; + // Per leanSpec, store.blocks now contains Block (not SignedBlockWithAttestation) let (head_root, parent_root, state_root) = if let Some(block) = store.blocks.get(&store.head) { let head_root = store.head; - let parent_root = block.message.block.parent_root; - let state_root = block.message.block.state_root; + let parent_root = block.parent_root; + let state_root = block.state_root; (head_root, parent_root, state_root) } else { ( diff --git a/lean_client/validator/src/lib.rs b/lean_client/validator/src/lib.rs index 14ab340..f84b70a 100644 --- a/lean_client/validator/src/lib.rs +++ b/lean_client/validator/src/lib.rs @@ -9,7 +9,7 @@ use containers::{ block::{hash_tree_root, BlockWithAttestation, SignedBlockWithAttestation}, checkpoint::Checkpoint, types::{Uint64, ValidatorIndex}, - AggregatedAttestation, Slot, + Slot, }; use fork_choice::store::{get_proposal_head, get_vote_target, Store}; use tracing::{info, warn}; @@ -135,10 +135,11 @@ impl ValidatorService { let vote_target = get_vote_target(store); - // Validate that target slot is strictly greater than source slot - if vote_target.slot <= store.latest_justified.slot { + // Validate that target slot is greater than or equal to source slot + // At genesis, both target and source are slot 0, which is valid + if vote_target.slot < store.latest_justified.slot { return Err(format!( - "Invalid attestation: target slot {} must be greater than source slot {}", + "Invalid attestation: target slot {} must be >= source slot {}", vote_target.slot.0, store.latest_justified.slot.0 )); } @@ -149,7 +150,7 @@ impl ValidatorService { .ok_or("Head block not found")?; let head_checkpoint = Checkpoint { root: store.head, - slot: head_block.message.block.slot, + slot: head_block.slot, }; let proposer_attestation = Attestation { @@ -162,19 +163,20 @@ impl ValidatorService { }, }; - // Collect valid attestations from the NEW attestations pool (gossip attestations - // that haven't been included in any block yet). - // Do NOT use latest_known_attestations - those have already been included in blocks! + // Collect valid attestations from the KNOWN attestations pool. + // Note: get_proposal_head() calls accept_new_attestations() which moves attestations + // from latest_new_attestations to latest_known_attestations. So we must read from + // latest_known_attestations here, not latest_new_attestations. // Filter to only include attestations that: // 1. Have source matching the parent state's justified checkpoint // 2. Have target slot > source slot (valid attestations) // 3. Target block must be known - // Also collect the corresponding signatures - let valid_signed_attestations: Vec<&SignedAttestation> = store - .latest_new_attestations - .values() - .filter(|att| { - let data = &att.message; + // 4. Target is not already justified in parent state + // 5. Source is justified in parent state + let valid_attestations: Vec = store + .latest_known_attestations + .iter() + .filter(|(_, data)| { // Source must match the parent state's justified checkpoint (not store's!) let source_matches = data.source == parent_state.latest_justified; // Target must be strictly after source @@ -182,46 +184,89 @@ impl ValidatorService { // Target block must be known let target_known = store.blocks.contains_key(&data.target.root); - source_matches && target_after_source && target_known + // Check if target is NOT already justified (matching process_single_attestation) + let target_slot_idx = data.target.slot.0 as usize; + let target_already_justified = parent_state + .justified_slots + .get(target_slot_idx) + .map(|b| *b) + .unwrap_or(false); + + // Check if source is justified + let source_slot_idx = data.source.slot.0 as usize; + let source_is_justified = parent_state + .justified_slots + .get(source_slot_idx) + .map(|b| *b) + .unwrap_or(false); + + source_matches + && target_after_source + && target_known + && source_is_justified + && !target_already_justified + }) + .map(|(validator_idx, data)| Attestation { + validator_id: Uint64(validator_idx.0), + data: data.clone(), }) .collect(); - let valid_attestations: Vec = valid_signed_attestations - .iter() - .map(|att| att.message.clone()) - .collect(); + // De-duplicate by target slot: only include ONE aggregated attestation per target slot. + // This prevents the case where the first attestation justifies a slot and the second + // gets rejected (causing state root mismatch). + // Group by target slot, keeping attestations with the most common AttestationData. + use std::collections::HashMap; + + // First group by target slot + let mut target_slot_groups: HashMap> = HashMap::new(); + for att in valid_attestations { + let target_slot = att.data.target.slot.0; + target_slot_groups.entry(target_slot).or_default().push(att); + } - #[cfg(feature = "devnet2")] - let valid_attestations: Vec = valid_signed_attestations - .iter() - .map(|att| att.message.clone()) + // For each target slot, group by data root and pick the one with most votes + let valid_attestations: Vec = target_slot_groups + .into_iter() + .flat_map(|(_, slot_atts)| { + // Group by data root (Bytes32 implements Hash) + let mut data_groups: HashMap> = + HashMap::new(); + for att in slot_atts { + let data_root = att.data.data_root_bytes(); + data_groups.entry(data_root).or_default().push(att); + } + // Find the data with the most attestations + data_groups + .into_iter() + .max_by_key(|(_, atts)| atts.len()) + .map(|(_, atts)| atts) + .unwrap_or_default() + }) .collect(); + let num_attestations = valid_attestations.len(); + info!( slot = slot.0, - valid_attestations = valid_attestations.len(), - total_new = store.latest_new_attestations.len(), - "Collected new attestations for block" + valid_attestations = num_attestations, + total_known = store.latest_known_attestations.len(), + "Collected attestations for block" ); - // Build block with collected attestations (empty body - attestations go to state) + // Build block with collected attestations + // Pass gossip_signatures and aggregated_payloads from the store so that + // compute_aggregated_signatures can find signatures for the attestations let (block, _post_state, _collected_atts, sigs) = { - let valid_attestations: Vec = valid_attestations - .iter() - .map(|data| Attestation { - validator_id: Uint64(0), // Placeholder, real validator IDs should be used - data: data.clone(), - }) - .collect(); parent_state.build_block( slot, proposer_index, parent_root, Some(valid_attestations), - None, - None, - None, - None, + None, // available_attestations + None, // known_block_roots + Some(&store.gossip_signatures), // gossip_signatures + Some(&store.aggregated_payloads), // aggregated_payloads )? }; @@ -232,7 +277,7 @@ impl ValidatorService { proposer = block.proposer_index.0, parent_root = %format!("0x{:x}", block.parent_root.0), state_root = %format!("0x{:x}", block.state_root.0), - attestation_sigs = valid_signed_attestations.len(), + attestation_sigs = num_attestations, "Block built successfully" ); @@ -288,22 +333,20 @@ impl ValidatorService { pub fn create_attestations(&self, store: &Store, slot: Slot) -> Vec { let vote_target = get_vote_target(store); - // Skip attestation creation if target slot is not strictly greater than source slot - // This prevents creating invalid attestations when the node's view is behind - if vote_target.slot <= store.latest_justified.slot { + // Skip attestation creation if target slot is less than source slot + // At genesis, both target and source are slot 0, which is valid + if vote_target.slot < store.latest_justified.slot { warn!( target_slot = vote_target.slot.0, source_slot = store.latest_justified.slot.0, - "Skipping attestation: target slot must be greater than source slot" + "Skipping attestation: target slot must be >= source slot" ); return vec![]; } - let get_head_block_info = match store.blocks.get(&store.head) { + let head_block = match store.blocks.get(&store.head) { Some(b) => b, None => { - // Pasileiskit, su DEBUG. Kitaip galima pakeist i tiesiog - // println!("WARNING: Attestation skipped. (Reason: HEAD BLOCK NOT FOUND)\n"); warn!("WARNING: Attestation skipped. (Reason: HEAD BLOCK NOT FOUND)"); return vec![]; } @@ -311,7 +354,7 @@ impl ValidatorService { let head_checkpoint = Checkpoint { root: store.head, - slot: get_head_block_info.message.block.slot, + slot: head_block.slot, }; self.config @@ -325,14 +368,6 @@ impl ValidatorService { source: store.latest_justified.clone(), }; - #[cfg(feature = "devnet2")] - let attestation = AttestationData { - slot, - head: head_checkpoint.clone(), - target: vote_target.clone(), - source: store.latest_justified.clone(), - }; - let signature = if let Some(ref key_manager) = self.key_manager { // Sign with XMSS let message = hash_tree_root(&attestation); @@ -379,45 +414,3 @@ impl ValidatorService { .collect() } } - -// DI GENERUOTI TESTAI -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_proposer_selection() { - let config = ValidatorConfig { - node_id: "test_0".to_string(), - validator_indices: vec![2], - }; - let service = ValidatorService::new(config, 4); - - // Validator 2 should propose at slots 2, 6, 10, ... - assert!(service.get_proposer_for_slot(Slot(2)).is_some()); - assert!(service.get_proposer_for_slot(Slot(6)).is_some()); - assert!(service.get_proposer_for_slot(Slot(10)).is_some()); - - // Validator 2 should NOT propose at slots 0, 1, 3, 4, 5, ... - assert!(service.get_proposer_for_slot(Slot(0)).is_none()); - assert!(service.get_proposer_for_slot(Slot(1)).is_none()); - assert!(service.get_proposer_for_slot(Slot(3)).is_none()); - assert!(service.get_proposer_for_slot(Slot(4)).is_none()); - assert!(service.get_proposer_for_slot(Slot(5)).is_none()); - } - - #[test] - fn test_is_assigned() { - let config = ValidatorConfig { - node_id: "test_0".to_string(), - validator_indices: vec![2, 5, 8], - }; - - assert!(config.is_assigned(2)); - assert!(config.is_assigned(5)); - assert!(config.is_assigned(8)); - assert!(!config.is_assigned(0)); - assert!(!config.is_assigned(1)); - assert!(!config.is_assigned(3)); - } -} diff --git a/lean_client/validator/tests/unit_tests.rs b/lean_client/validator/tests/unit_tests.rs new file mode 100644 index 0000000..2da822d --- /dev/null +++ b/lean_client/validator/tests/unit_tests.rs @@ -0,0 +1,39 @@ +// AI Generated tests +use containers::Slot; +use validator::{ValidatorConfig, ValidatorService}; + +#[test] +fn test_proposer_selection() { + let config = ValidatorConfig { + node_id: "test_0".to_string(), + validator_indices: vec![2], + }; + let service = ValidatorService::new(config, 4); + + // Validator 2 should propose at slots 2, 6, 10, ... + assert!(service.get_proposer_for_slot(Slot(2)).is_some()); + assert!(service.get_proposer_for_slot(Slot(6)).is_some()); + assert!(service.get_proposer_for_slot(Slot(10)).is_some()); + + // Validator 2 should NOT propose at slots 0, 1, 3, 4, 5, ... + assert!(service.get_proposer_for_slot(Slot(0)).is_none()); + assert!(service.get_proposer_for_slot(Slot(1)).is_none()); + assert!(service.get_proposer_for_slot(Slot(3)).is_none()); + assert!(service.get_proposer_for_slot(Slot(4)).is_none()); + assert!(service.get_proposer_for_slot(Slot(5)).is_none()); +} + +#[test] +fn test_is_assigned() { + let config = ValidatorConfig { + node_id: "test_0".to_string(), + validator_indices: vec![2, 5, 8], + }; + + assert!(config.is_assigned(2)); + assert!(config.is_assigned(5)); + assert!(config.is_assigned(8)); + assert!(!config.is_assigned(0)); + assert!(!config.is_assigned(1)); + assert!(!config.is_assigned(3)); +}