diff --git a/Cargo.lock b/Cargo.lock index 5c4ea744..8f8f2862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "addchain" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" dependencies = [ "num-bigint 0.3.3", "num-integer", @@ -56,7 +56,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -102,34 +102,34 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", + "alloy-consensus 1.8.3", "alloy-contract", "alloy-core", - "alloy-eips 1.5.2", - "alloy-genesis 1.5.2", - "alloy-network 1.5.2", - "alloy-provider 1.5.2", + "alloy-eips 1.8.3", + "alloy-genesis 1.8.3", + "alloy-network 1.8.3", + "alloy-provider 1.8.3", "alloy-pubsub", - "alloy-rpc-client 1.5.2", - "alloy-rpc-types 1.5.2", - "alloy-serde 1.5.2", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-client 1.8.3", + "alloy-rpc-types 1.8.3", + "alloy-serde 1.8.3", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-signer-local", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", ] [[package]] name = "alloy-chains" -version = "0.2.30" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f374d3c6d729268bbe2d0e0ff992bb97898b2df756691a62ee1d5f0506bc39" +checksum = "f4e9e31d834fe25fe991b8884e4b9f0e59db4a97d86e05d1464d6899c013cd62" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -147,7 +147,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "alloy-tx-macros 1.0.41", "auto_impl", "c-kzg", @@ -165,15 +165,15 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-eips 1.5.2", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", - "alloy-trie 0.9.3", - "alloy-tx-macros 1.5.2", + "alloy-serde 1.8.3", + "alloy-trie 0.9.5", + "alloy-tx-macros 1.8.3", "auto_impl", "borsh", "c-kzg", @@ -204,44 +204,45 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "serde", ] [[package]] name = "alloy-contract" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", + "alloy-consensus 1.8.3", "alloy-dyn-abi", "alloy-json-abi", - "alloy-network 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-network 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", - "alloy-provider 1.5.2", + "alloy-provider 1.8.3", "alloy-pubsub", - "alloy-rpc-types-eth 1.5.2", + "alloy-rpc-types-eth 1.8.3", "alloy-sol-types", - "alloy-transport 1.5.2", + "alloy-transport 1.8.3", "futures", "futures-util", "serde_json", "thiserror 2.0.18", + "tracing", ] [[package]] name = "alloy-core" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfbc46fa201350bf859add798d818bbe68b84882a8af832e4433791d28a975d" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -252,9 +253,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14ff5ee5f27aa305bda825c735f686ad71bb65508158f059f513895abe69b8c3" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -263,7 +264,7 @@ dependencies = [ "itoa", "serde", "serde_json", - "winnow", + "winnow 0.7.15", ] [[package]] @@ -308,9 +309,9 @@ dependencies = [ [[package]] name = "alloy-eip7928" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3231de68d5d6e75332b7489cfcc7f4dfabeba94d990a10e4b923af0e6623540" +checksum = "f8222b1d88f9a6d03be84b0f5e76bb60cd83991b43ad8ab6477f0e4a7809b98d" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -341,8 +342,8 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -350,7 +351,7 @@ dependencies = [ "alloy-eip7928", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "auto_impl", "borsh", "c-kzg", @@ -359,7 +360,6 @@ dependencies = [ "serde", "serde_with", "sha2 0.10.9", - "thiserror 2.0.18", ] [[package]] @@ -390,20 +390,20 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-primitives", "alloy-serde 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "serde", "serde_with", ] [[package]] name = "alloy-genesis" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-eips 1.5.2", + "alloy-eips 1.8.3", "alloy-primitives", - "alloy-serde 1.5.2", - "alloy-trie 0.9.3", + "alloy-serde 1.8.3", + "alloy-trie 0.9.5", "borsh", "serde", "serde_with", @@ -424,9 +424,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8708475665cc00e081c085886e68eada2f64cfa08fc668213a9231655093d4de" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -450,8 +450,8 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -489,19 +489,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" -dependencies = [ - "alloy-consensus 1.5.2", - "alloy-consensus-any 1.5.2", - "alloy-eips 1.5.2", - "alloy-json-rpc 1.5.2", - "alloy-network-primitives 1.5.2", +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" +dependencies = [ + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-json-rpc 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", - "alloy-rpc-types-any 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-types-any 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-sol-types", "async-trait", "auto_impl", @@ -526,13 +526,13 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "serde", ] @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b88cf92ed20685979ed1d8472422f0c6c2d010cec77caf63aaa7669cc1a7bc2" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ "alloy-rlp", "bytes", @@ -578,16 +578,16 @@ dependencies = [ "derive_more 2.1.1", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.13.0", + "indexmap 2.14.0", "itoa", "k256", "keccak-asm", "paste", "proptest", - "rand 0.9.2", + "rand 0.9.3", "rapidhash", "ruint", - "rustc-hash 2.1.1", + "rustc-hash 2.1.2", "serde", "sha3", ] @@ -634,27 +634,27 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-chains", - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", - "alloy-json-rpc 1.5.2", - "alloy-network 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", + "alloy-json-rpc 1.8.3", + "alloy-network 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", "alloy-pubsub", - "alloy-rpc-client 1.5.2", + "alloy-rpc-client 1.8.3", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-rpc-types-trace 1.5.2", + "alloy-rpc-types-debug 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-rpc-types-trace 1.8.3", "alloy-rpc-types-txpool", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "alloy-sol-types", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", "async-stream", @@ -667,7 +667,7 @@ dependencies = [ "lru 0.16.3", "parking_lot", "pin-project", - "reqwest 0.12.28", + "reqwest 0.13.2", "serde", "serde_json", "thiserror 2.0.18", @@ -679,12 +679,12 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.3", "alloy-primitives", - "alloy-transport 1.5.2", + "alloy-transport 1.8.3", "auto_impl", "bimap", "futures", @@ -700,9 +700,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -711,13 +711,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -744,19 +744,19 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.3", "alloy-primitives", "alloy-pubsub", - "alloy-transport 1.5.2", - "alloy-transport-http 1.5.2", + "alloy-transport 1.8.3", + "alloy-transport-http 1.8.3", "alloy-transport-ipc", "alloy-transport-ws", "futures", "pin-project", - "reqwest 0.12.28", + "reqwest 0.13.2", "serde", "serde_json", "tokio", @@ -780,28 +780,28 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", - "alloy-rpc-types-debug 1.5.2", - "alloy-rpc-types-engine 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-rpc-types-trace 1.5.2", + "alloy-rpc-types-debug 1.8.3", + "alloy-rpc-types-engine 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-rpc-types-trace 1.8.3", "alloy-rpc-types-txpool", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "serde", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", ] @@ -817,12 +817,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus-any 1.5.2", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-consensus-any 1.8.3", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", ] [[package]] @@ -838,10 +838,11 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", + "alloy-rlp", "derive_more 2.1.1", "serde", "serde_with", @@ -862,14 +863,14 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-eips 1.5.2", + "alloy-consensus 1.8.3", + "alloy-eips 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "derive_more 2.1.1", "rand 0.8.5", "serde", @@ -898,16 +899,16 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-consensus-any 1.5.2", - "alloy-eips 1.5.2", - "alloy-network-primitives 1.5.2", + "alloy-consensus 1.8.3", + "alloy-consensus-any 1.8.3", + "alloy-eips 1.8.3", + "alloy-network-primitives 1.8.3", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.5.2", + "alloy-serde 1.8.3", "alloy-sol-types", "itertools 0.14.0", "serde", @@ -931,12 +932,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", "serde_json", "thiserror 2.0.18", @@ -944,12 +945,12 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", - "alloy-rpc-types-eth 1.5.2", - "alloy-serde 1.5.2", + "alloy-rpc-types-eth 1.8.3", + "alloy-serde 1.8.3", "serde", ] @@ -965,8 +966,8 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "serde", @@ -989,9 +990,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.5.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7481dc8316768f042495eaf305d450c32defbc9bce09d8bf28afcd956895bb" +checksum = "43f447aefab0f1c0649f71edc33f590992d4e122bc35fb9cdbbf67d4421ace85" dependencies = [ "alloy-primitives", "async-trait", @@ -1004,8 +1005,8 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-primitives", "async-trait", @@ -1018,13 +1019,13 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-consensus 1.5.2", - "alloy-network 1.5.2", + "alloy-consensus 1.8.3", + "alloy-network 1.8.3", "alloy-primitives", - "alloy-signer 1.5.2 (git+https://github.com/alloy-rs/alloy)", + "alloy-signer 1.8.3 (git+https://github.com/alloy-rs/alloy)", "async-trait", "k256", "rand 0.8.5", @@ -1033,42 +1034,42 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fa1ca7e617c634d2bd9fa71f9ec8e47c07106e248b9fcbd3eaddc13cabd625" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c00c0c3a75150a9dc7c8c679ca21853a137888b4e1c5569f92d7e2b15b5102" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.14.0", "proc-macro-error2", "proc-macro2", "quote", "sha3", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297db260eb4d67c105f68d6ba11b8874eec681caec5505eab8fbebee97f790bc" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ "alloy-json-abi", "const-hex", @@ -1078,25 +1079,25 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.117", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b91b13181d3bcd23680fd29d7bc861d1f33fbe90fdd0af67162434aeba902d" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", - "winnow", + "winnow 0.7.15", ] [[package]] name = "alloy-sol-types" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc442cc2a75207b708d481314098a0f8b6f7b58e3148dd8d8cc7407b0d6f9385" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -1129,10 +1130,10 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.3", "auto_impl", "base64 0.22.1", "derive_more 2.1.1", @@ -1165,12 +1166,13 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-json-rpc 1.5.2", - "alloy-transport 1.5.2", - "reqwest 0.12.28", + "alloy-json-rpc 1.8.3", + "alloy-transport 1.8.3", + "itertools 0.14.0", + "reqwest 0.13.2", "serde_json", "tower 0.5.3", "tracing", @@ -1179,12 +1181,12 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "alloy-json-rpc 1.5.2", + "alloy-json-rpc 1.8.3", "alloy-pubsub", - "alloy-transport 1.5.2", + "alloy-transport 1.8.3", "bytes", "futures", "interprocess", @@ -1198,17 +1200,19 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ "alloy-pubsub", - "alloy-transport 1.5.2", + "alloy-transport 1.8.3", "futures", "http 1.4.0", + "rustls 0.23.37", "serde_json", "tokio", - "tokio-tungstenite 0.26.2", + "tokio-tungstenite 0.28.0", "tracing", + "url", "ws_stream_wasm", ] @@ -1230,17 +1234,17 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428aa0f0e0658ff091f8f667c406e034b431cb10abd39de4f507520968acc499" +checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" dependencies = [ "alloy-primitives", "alloy-rlp", - "arrayvec", "derive_more 2.1.1", - "nybbles 0.4.7", + "nybbles 0.4.8", "serde", "smallvec", + "thiserror 2.0.18", "tracing", ] @@ -1250,21 +1254,21 @@ version = "1.0.41" source = "git+https://github.com/ziren-patches/alloy?branch=patch-1.0.41#08557d4e5f4ca766194a45c1925d8f1625258793" dependencies = [ "alloy-primitives", - "darling", + "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "alloy-tx-macros" -version = "1.5.2" -source = "git+https://github.com/alloy-rs/alloy#3203f839dd801e1966b4970136b59051f3856770" +version = "1.8.3" +source = "git+https://github.com/alloy-rs/alloy#f603b229c621a2a1697f24b2845595e451fd7af9" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1287,9 +1291,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -1302,15 +1306,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -1337,9 +1341,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "ark-bls12-381" @@ -1395,7 +1399,7 @@ checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1506,7 +1510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1544,7 +1548,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1634,7 +1638,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1692,9 +1696,6 @@ name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -dependencies = [ - "serde", -] [[package]] name = "ascii-canvas" @@ -1729,7 +1730,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -1741,14 +1742,14 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "asn1_der" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" +checksum = "4858a9d740c5007a9069007c3b4e91152d0506f13c1b31dd49051fd537656156" [[package]] name = "async-channel" @@ -1775,9 +1776,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -1815,7 +1816,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.3", + "rustix 1.1.4", "slab", "windows-sys 0.61.2", ] @@ -1849,7 +1850,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1897,7 +1898,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1914,7 +1915,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1985,7 +1986,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -1994,6 +1995,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.6.20" @@ -2035,7 +2058,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "itoa", "matchit 0.7.3", @@ -2070,7 +2093,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "itoa", "matchit 0.8.4", @@ -2155,7 +2178,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2269,7 +2292,7 @@ version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cexpr", "clang-sys", "itertools 0.13.0", @@ -2280,7 +2303,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2334,18 +2357,18 @@ checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "bitcoin" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" +checksum = "69197dee21fe23b45f5239bf88086efaa0cb8679f3e704906eb818e8ea169c14" dependencies = [ "bech32 0.10.0-beta", - "bitcoin-internals 0.2.0", - "bitcoin_hashes 0.13.0", + "bitcoin-internals 0.2.1", + "bitcoin_hashes 0.13.1", "hex-conservative 0.1.2", "hex_lit", "secp256k1 0.28.2", @@ -2371,9 +2394,9 @@ dependencies = [ [[package]] name = "bitcoin-internals" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +checksum = "994dc6fcc13751c85370b7de118e672b193b9b65167bf09e258f124c97fb9685" [[package]] name = "bitcoin-internals" @@ -2467,11 +2490,10 @@ dependencies = [ [[package]] name = "bitcoin_hashes" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +checksum = "446819536d8121575eeb7e89efdbadb3f055e87e4bb66c6679a6d5cc2f4b64fd" dependencies = [ - "bitcoin-internals 0.2.0", "hex-conservative 0.1.2", ] @@ -2518,9 +2540,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -2578,7 +2600,7 @@ dependencies = [ "ark-groth16", "ark-serialize 0.5.0", "bincode", - "bitcoin 0.31.2", + "bitcoin 0.31.3", "bitcoin 0.32.8", "bitcoin-light-client-circuit", "bitcoin-script", @@ -2600,7 +2622,7 @@ dependencies = [ "strum 0.26.3", "tokio", "tracing", - "uuid 1.20.0", + "uuid 1.23.0", ] [[package]] @@ -2634,7 +2656,7 @@ dependencies = [ "hex", "http 1.4.0", "http-body-util", - "indexmap 2.13.0", + "indexmap 2.14.0", "indicatif", "libp2p", "libp2p-metrics", @@ -2646,6 +2668,7 @@ dependencies = [ "rand 0.8.5", "reqwest 0.12.28", "secp256k1 0.29.1", + "semver 1.0.28", "serde", "serde_json", "sha2 0.10.9", @@ -2659,9 +2682,9 @@ dependencies = [ "tokio-util", "tower-http", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", - "uuid 1.20.0", + "uuid 1.23.0", "zeroize", "zkm-sdk", "zkm-verifier", @@ -2689,16 +2712,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2468ef7d57b3fb7e16b576e8377cdbde2320c60e1491e961d11da40fc4f02a2d" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq 0.4.2", - "cpufeatures", + "cpufeatures 0.3.0", ] [[package]] @@ -2782,25 +2805,26 @@ dependencies = [ [[package]] name = "borsh" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2815,9 +2839,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-slice-cast" @@ -2827,9 +2851,9 @@ checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -2842,7 +2866,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -2853,9 +2877,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2882,9 +2906,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.5" +version = "2.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" dependencies = [ "blst", "cc", @@ -2921,7 +2945,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "thiserror 1.0.69", @@ -2949,9 +2973,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.55" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -2959,6 +2983,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -2988,7 +3018,18 @@ checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", ] [[package]] @@ -2998,7 +3039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ "aead", - "chacha20", + "chacha20 0.9.1", "cipher", "poly1305", "zeroize", @@ -3006,9 +3047,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -3042,9 +3083,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.56" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -3052,9 +3093,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.56" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -3064,21 +3105,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.7" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "client" @@ -3098,7 +3139,16 @@ dependencies = [ "tempfile", "tokio", "tracing", - "uuid 1.20.0", + "uuid 1.23.0", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", ] [[package]] @@ -3155,9 +3205,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "colored" @@ -3169,6 +3219,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "commit-chain" version = "0.3.3" @@ -3214,7 +3274,7 @@ dependencies = [ "tendermint-light-client-verifier", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-build", "zkm-prover", "zkm-sdk", @@ -3254,12 +3314,12 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "proptest", "serde_core", ] @@ -3327,6 +3387,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -3363,6 +3433,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" version = "3.4.0" @@ -3522,12 +3601,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.30.1", + "nix 0.31.2", "windows-sys 0.61.2", ] @@ -3538,7 +3617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -3555,7 +3634,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3577,8 +3656,18 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -3593,7 +3682,21 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.117", ] [[package]] @@ -3602,9 +3705,20 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core", + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3722,7 +3836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3752,9 +3866,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -3773,13 +3887,13 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3790,7 +3904,7 @@ checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3819,7 +3933,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -3832,7 +3946,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.114", + "syn 2.0.117", "unicode-xid", ] @@ -3901,11 +4015,11 @@ dependencies = [ [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -3919,14 +4033,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "doctest-file" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" +checksum = "c2db04e74f0a9a93103b50e90b96024c9b2bdca8bce6a632ec71b88736d3d359" [[package]] name = "dotenv" @@ -4019,7 +4133,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4061,9 +4175,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -4110,7 +4224,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4131,7 +4245,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4151,7 +4265,30 @@ checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", +] + +[[package]] +name = "env_filter" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", ] [[package]] @@ -4332,7 +4469,7 @@ dependencies = [ "reqwest 0.11.27", "serde", "serde_json", - "syn 2.0.114", + "syn 2.0.117", "toml 0.8.23", "walkdir", ] @@ -4350,7 +4487,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4376,7 +4513,7 @@ dependencies = [ "serde", "serde_json", "strum 0.26.3", - "syn 2.0.114", + "syn 2.0.117", "tempfile", "thiserror 1.0.69", "tiny-keccak", @@ -4392,7 +4529,7 @@ dependencies = [ "chrono", "ethers-core", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "thiserror 1.0.69", @@ -4501,7 +4638,7 @@ dependencies = [ "path-slash", "rayon", "regex", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "solang-parser", @@ -4553,9 +4690,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fastrlp" @@ -4656,9 +4793,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -4736,6 +4873,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -4744,9 +4887,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -4769,9 +4912,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -4779,20 +4922,19 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", "futures-util", - "num_cpus", ] [[package]] @@ -4808,9 +4950,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -4837,13 +4979,13 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -4853,21 +4995,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" @@ -4881,9 +5023,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -4893,7 +5035,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -4962,11 +5103,25 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.0", + "wasip2", + "wasip3", +] + [[package]] name = "ghash" version = "0.5.1" @@ -4989,7 +5144,7 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", "libgit2-sys", "log", @@ -4998,9 +5153,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.31.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a4d85559e2637d3d839438b5b3d75c31e655276f9544d72475c36b92fabbed" +checksum = "f70749695b063ecbf6b62949ccccde2e733ec3ecbbd71d467dca4e5c6c97cca0" [[package]] name = "glob" @@ -5098,7 +5253,7 @@ dependencies = [ [[package]] name = "guest-executor" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-consensus 1.0.41", "alloy-evm", @@ -5147,7 +5302,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.13.0", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -5166,7 +5321,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.13.0", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -5281,6 +5436,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "hashers" version = "1.0.1" @@ -5345,7 +5506,7 @@ dependencies = [ "sha2 0.10.9", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", "zkm-build", "zkm-prover", @@ -5454,7 +5615,7 @@ dependencies = [ "idna", "ipnet", "once_cell", - "rand 0.9.2", + "rand 0.9.3", "socket2 0.5.10", "thiserror 2.0.18", "tinyvec", @@ -5497,7 +5658,7 @@ dependencies = [ "moka", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.9.3", "resolv-conf", "smallvec", "thiserror 2.0.18", @@ -5535,7 +5696,7 @@ dependencies = [ [[package]] name = "host-executor" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-chains", "alloy-consensus 1.0.41", @@ -5677,9 +5838,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -5692,7 +5853,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -5719,14 +5879,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.4.0", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -5756,23 +5916,22 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper 1.9.0", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.6.3", "tokio", "tower-service", "tracing", @@ -5804,12 +5963,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -5817,9 +5977,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -5830,9 +5990,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -5844,15 +6004,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -5864,15 +6024,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -5883,6 +6043,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -5912,22 +6078,22 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.10.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" +checksum = "c0a05c691e1fae256cf7013d99dad472dc52d5543322761f83ec8d47eab40d2b" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] name = "if-watch" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" +checksum = "71c02a5161c313f0cbdbadc511611893584a10a7b6153cb554bdf83ddce99ec2" dependencies = [ "async-io", - "core-foundation", + "core-foundation 0.9.4", "fnv", "futures", "if-addrs", @@ -5938,9 +6104,9 @@ dependencies = [ "netlink-proto", "netlink-sys", "rtnetlink", - "system-configuration 0.6.1", + "system-configuration 0.7.0", "tokio", - "windows 0.53.0", + "windows 0.62.2", ] [[package]] @@ -5955,7 +6121,7 @@ dependencies = [ "futures", "http 1.4.0", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-util", "log", "rand 0.8.5", @@ -5999,7 +6165,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6021,12 +6187,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -6074,9 +6240,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" +checksum = "6be5e5c847dbdb44564bd85294740d031f4f8aeb3464e5375ef7141f7538db69" dependencies = [ "doctest-file", "futures-core", @@ -6089,21 +6255,22 @@ dependencies = [ [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.5.10", + "socket2 0.6.3", "widestring", - "windows-sys 0.48.0", - "winreg", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "ipnetwork" @@ -6116,9 +6283,9 @@ dependencies = [ [[package]] name = "iri-string" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -6168,26 +6335,96 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] -name = "jobserver" -version = "0.1.34" +name = "jiff" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ - "getrandom 0.3.4", - "libc", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", ] [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -6249,18 +6486,18 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] name = "keccak-asm" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" +checksum = "fa468878266ad91431012b3e5ef1bf9b170eab22883503a318d46857afa4579a" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6327,11 +6564,17 @@ dependencies = [ "spin 0.9.8", ] +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" -version = "0.2.180" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libgit2-sys" @@ -6678,7 +6921,7 @@ dependencies = [ "quinn", "rand 0.8.5", "ring 0.17.14", - "rustls 0.23.36", + "rustls 0.23.37", "socket2 0.5.10", "thiserror 2.0.18", "tokio", @@ -6758,7 +7001,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6789,8 +7032,8 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.17.14", - "rustls 0.23.36", - "rustls-webpki 0.103.9", + "rustls 0.23.37", + "rustls-webpki 0.103.11", "thiserror 2.0.18", "x509-parser", "yasna", @@ -6844,18 +7087,19 @@ dependencies = [ "thiserror 2.0.18", "tracing", "yamux 0.12.1", - "yamux 0.13.8", + "yamux 0.13.10", ] [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.7.0", + "plain", + "redox_syscall 0.7.4", ] [[package]] @@ -6871,9 +7115,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.23" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "libc", @@ -6895,15 +7139,15 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -6973,7 +7217,7 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -6984,7 +7228,7 @@ checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7020,9 +7264,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memuse" @@ -7099,9 +7343,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", @@ -7131,9 +7375,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.13" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", @@ -7143,13 +7387,13 @@ dependencies = [ "portable-atomic", "smallvec", "tagptr", - "uuid 1.20.0", + "uuid 1.23.0", ] [[package]] name = "mpt" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7248,63 +7492,47 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.2.1", "openssl-sys", "schannel", - "security-framework", + "security-framework 3.7.0", "security-framework-sys", "tempfile", ] [[package]] name = "netlink-packet-core" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", + "paste", ] [[package]] name = "netlink-packet-route" -version = "0.17.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", + "bitflags 2.11.0", "libc", + "log", "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-utils" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", ] [[package]] name = "netlink-proto" -version = "0.11.5" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" dependencies = [ "bytes", "futures", @@ -7335,22 +7563,23 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.26.4" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.11.0", "cfg-if", + "cfg_aliases", "libc", ] [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -7380,9 +7609,9 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi", ] @@ -7459,9 +7688,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-integer" @@ -7531,9 +7760,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -7541,14 +7770,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7593,9 +7822,9 @@ dependencies = [ [[package]] name = "nybbles" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5676b5c379cf5b03da1df2b3061c4a4e2aa691086a56ac923e08c143f53f59" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" dependencies = [ "alloy-rlp", "cfg-if", @@ -7607,9 +7836,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -7640,9 +7869,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", @@ -7762,11 +7991,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -7783,7 +8012,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -7792,11 +8021,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" dependencies = [ "cc", "libc", @@ -7842,7 +8077,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "url", "util", "zkm-build", @@ -8225,7 +8460,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8397,9 +8632,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.5" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", "ucd-trie", @@ -8412,7 +8647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.13.0", + "indexmap 2.14.0", ] [[package]] @@ -8422,7 +8657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.13.0", + "indexmap 2.14.0", ] [[package]] @@ -8486,7 +8721,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8499,7 +8734,7 @@ dependencies = [ "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8522,29 +8757,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -8554,9 +8789,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -8590,6 +8825,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "pnet" version = "0.33.0" @@ -8691,7 +8932,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -8701,7 +8942,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] @@ -8713,22 +8954,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -8771,7 +9021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8800,7 +9050,7 @@ dependencies = [ [[package]] name = "primitives" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-eips 1.0.41", "alloy-genesis 1.0.41", @@ -8818,11 +9068,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.23.10+spec-1.0.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -8868,7 +9118,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8900,7 +9150,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -8952,23 +9202,23 @@ dependencies = [ "toml 0.8.23", "tower-http", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "util", - "uuid 1.20.0", + "uuid 1.23.0", "watchtower-proof", ] [[package]] name = "proptest" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.10.0", + "bitflags 2.11.0", "num-traits", - "rand 0.9.2", + "rand 0.9.3", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", @@ -9035,7 +9285,7 @@ dependencies = [ "prost 0.13.5", "prost-types 0.13.5", "regex", - "syn 2.0.114", + "syn 2.0.117", "tempfile", ] @@ -9062,7 +9312,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9086,7 +9336,7 @@ dependencies = [ [[package]] name = "provider" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-json-rpc 1.0.41", "alloy-provider 1.0.41", @@ -9135,9 +9385,9 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", - "rustls 0.23.36", - "socket2 0.6.2", + "rustc-hash 2.1.2", + "rustls 0.23.37", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -9146,17 +9396,18 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.3", "ring 0.17.14", - "rustc-hash 2.1.1", - "rustls 0.23.36", + "rustc-hash 2.1.2", + "rustls 0.23.37", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -9174,16 +9425,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -9194,6 +9445,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -9214,15 +9471,26 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", "serde", ] +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20 0.10.0", + "getrandom 0.4.2", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -9262,6 +9530,12 @@ dependencies = [ "serde", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -9273,9 +9547,9 @@ dependencies = [ [[package]] name = "rapidhash" -version = "4.2.1" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8b5b858a440a0bc02625b62dd95131b9201aa9f69f411195dd4a7cfb1de3d7" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" dependencies = [ "rustversion", ] @@ -9334,16 +9608,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -9374,14 +9648,14 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -9391,9 +9665,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -9402,9 +9676,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -9433,7 +9707,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls 0.21.12", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "rustls-pemfile", "serde", "serde_json", @@ -9468,7 +9742,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "hyper-rustls 0.27.7", "hyper-util", "js-sys", @@ -9477,7 +9751,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", @@ -9494,7 +9768,44 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.9.0", + "hyper-rustls 0.27.7", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.37", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper 1.0.2", + "tokio", + "tokio-rustls 0.26.4", + "tower 0.5.3", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -9514,7 +9825,7 @@ dependencies = [ "alloy-evm", "alloy-genesis 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "derive_more 2.1.1", "reth-ethereum-forks", @@ -9532,7 +9843,7 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-genesis 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "bytes", "modular-bitfield", "op-alloy-consensus", @@ -9548,7 +9859,7 @@ source = "git+https://github.com/ziren-patches/reth?branch=patch-1.9.3#fb7e5b4b3 dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -9693,7 +10004,7 @@ dependencies = [ "alloy-evm", "alloy-primitives", "alloy-rlp", - "nybbles 0.4.7", + "nybbles 0.4.8", "reth-storage-errors", "thiserror 2.0.18", ] @@ -9757,7 +10068,7 @@ dependencies = [ "alloy-consensus 1.0.41", "alloy-eips 1.0.41", "alloy-primitives", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "reth-chainspec", "reth-consensus", "reth-consensus-common", @@ -9840,7 +10151,7 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-rpc-types-eth 1.0.41", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "bytes", "derive_more 2.1.1", @@ -9934,7 +10245,7 @@ dependencies = [ "alloy-eips 1.0.41", "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "itertools 0.14.0", "reth-execution-errors", @@ -9955,10 +10266,10 @@ dependencies = [ "alloy-consensus 1.0.41", "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "derive_more 2.1.1", "itertools 0.14.0", - "nybbles 0.4.7", + "nybbles 0.4.8", "rayon", "reth-primitives-traits", "revm-database", @@ -9971,7 +10282,7 @@ source = "git+https://github.com/ziren-patches/reth?branch=patch-1.9.3#fb7e5b4b3 dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-trie 0.9.3", + "alloy-trie 0.9.5", "auto_impl", "reth-execution-errors", "reth-primitives-traits", @@ -10158,7 +10469,7 @@ name = "revm-state" version = "8.1.1" source = "git+https://github.com/ziren-patches/revm?branch=patch-31.0.2#0cd8a9cffabcc01fd92b8f12d6d601040e0ec88f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "revm-bytecode", "revm-primitives", "serde", @@ -10237,7 +10548,7 @@ dependencies = [ [[package]] name = "rpc-db" version = "0.1.0" -source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#0b280a7cc8cd7c12bcf28a06fbdef3cb9a9ae196" +source = "git+https://github.com/ProjectZKM/reth-processor?branch=feat%2Fslot-state-check#294aa06127be4bfda47a7fd4905b93bb8e664dca" dependencies = [ "alloy-consensus 1.0.41", "alloy-primitives", @@ -10281,18 +10592,18 @@ dependencies = [ [[package]] name = "rtnetlink" -version = "0.13.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" +checksum = "4b960d5d873a75b5be9761b1e73b146f52dddcd27bac75263f40fba686d4d7b5" dependencies = [ - "futures", + "futures-channel", + "futures-util", "log", "netlink-packet-core", "netlink-packet-route", - "netlink-packet-utils", "netlink-proto", "netlink-sys", - "nix 0.26.4", + "nix 0.30.1", "thiserror 1.0.69", "tokio", ] @@ -10317,7 +10628,7 @@ dependencies = [ "primitive-types", "proptest", "rand 0.8.5", - "rand 0.9.2", + "rand 0.9.3", "rlp", "ruint-macro", "serde_core", @@ -10345,9 +10656,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc-hex" @@ -10370,7 +10681,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver 1.0.28", ] [[package]] @@ -10388,7 +10699,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -10397,14 +10708,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -10434,14 +10745,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ + "aws-lc-rs", "once_cell", "ring 0.17.14", "rustls-pki-types", - "rustls-webpki 0.103.9", + "rustls-webpki 0.103.11", "subtle", "zeroize", ] @@ -10452,10 +10764,22 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", ] [[package]] @@ -10477,6 +10801,33 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.37", + "rustls-native-certs 0.8.3", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.11", + "security-framework 3.7.0", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -10489,10 +10840,11 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.9" +version = "0.103.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" +checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" dependencies = [ + "aws-lc-rs", "ring 0.17.14", "rustls-pki-types", "untrusted 0.9.0", @@ -10529,9 +10881,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "salsa20" @@ -10572,7 +10924,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10586,9 +10938,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -10607,9 +10959,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -10698,7 +11050,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "bitcoin_hashes 0.13.0", + "bitcoin_hashes 0.13.1", "secp256k1-sys 0.9.2", ] @@ -10750,8 +11102,21 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", - "core-foundation", + "bitflags 2.11.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -10759,9 +11124,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -10778,9 +11143,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -10873,7 +11238,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10908,7 +11273,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10934,17 +11299,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.14.0", "schemars 0.9.0", - "schemars 1.2.0", + "schemars 1.2.1", "serde_core", "serde_json", "serde_with_macros", @@ -10953,14 +11318,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -10975,9 +11340,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ "futures-executor", "futures-util", @@ -10990,13 +11355,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11006,7 +11371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -11018,7 +11383,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -11030,7 +11395,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -11046,9 +11411,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" +checksum = "59cbb88c189d6352cc8ae96a39d19c7ecad8f7330b29461187f2587fdc2988d5" dependencies = [ "cc", "cfg-if", @@ -11112,15 +11477,15 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simple_asn1" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint 0.4.6", "num-traits", @@ -11142,9 +11507,9 @@ checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -11194,12 +11559,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -11287,7 +11652,7 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink 0.10.0", - "indexmap 2.13.0", + "indexmap 2.14.0", "log", "memchr", "once_cell", @@ -11301,7 +11666,7 @@ dependencies = [ "tokio-stream", "tracing", "url", - "uuid 1.20.0", + "uuid 1.23.0", ] [[package]] @@ -11314,7 +11679,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11337,7 +11702,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.114", + "syn 2.0.117", "tokio", "url", ] @@ -11350,7 +11715,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "bytes", "crc", @@ -11381,7 +11746,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.20.0", + "uuid 1.23.0", "whoami", ] @@ -11393,7 +11758,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "crc", "dotenvy", @@ -11419,7 +11784,7 @@ dependencies = [ "stringprep", "thiserror 2.0.18", "tracing", - "uuid 1.20.0", + "uuid 1.23.0", "whoami", ] @@ -11445,7 +11810,7 @@ dependencies = [ "thiserror 2.0.18", "tracing", "url", - "uuid 1.20.0", + "uuid 1.23.0", ] [[package]] @@ -11515,7 +11880,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "url", "util", "zkm-build", @@ -11544,7 +11909,7 @@ dependencies = [ "bitcoin 0.32.8", "futures", "hex", - "indexmap 2.13.0", + "indexmap 2.14.0", "reqwest 0.12.28", "serde", "serde_json", @@ -11554,7 +11919,7 @@ dependencies = [ "tokio", "tokio-util", "tracing", - "uuid 1.20.0", + "uuid 1.23.0", "walkdir", ] @@ -11621,7 +11986,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11633,7 +11998,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11711,7 +12076,7 @@ dependencies = [ "hex", "once_cell", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "sha2 0.10.9", @@ -11733,9 +12098,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -11744,14 +12109,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.4" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2379beea9476b89d0237078be761cf8e012d92d5ae4ae0c9a329f974838870fc" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11777,7 +12142,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -11802,18 +12167,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.5.0", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", - "core-foundation", + "bitflags 2.11.0", + "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -11851,14 +12216,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -11959,7 +12324,7 @@ dependencies = [ "pin-project", "rand 0.8.5", "reqwest 0.11.27", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_bytes", "serde_json", @@ -11973,7 +12338,7 @@ dependencies = [ "tokio", "tracing", "url", - "uuid 1.20.0", + "uuid 1.23.0", "walkdir", ] @@ -12014,7 +12379,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12025,7 +12390,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12048,9 +12413,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", @@ -12071,9 +12436,9 @@ checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -12090,9 +12455,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -12100,9 +12465,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -12115,17 +12480,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.49.0" +version = "1.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ "bytes", "libc", - "mio 1.1.1", + "mio 1.2.0", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -12142,13 +12507,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12188,7 +12553,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls 0.23.37", "tokio", ] @@ -12233,17 +12598,17 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.26.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", - "tungstenite 0.26.2", + "tungstenite 0.28.0", "webpki-roots 0.26.11", ] @@ -12292,9 +12657,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] @@ -12305,33 +12670,33 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.14.0", "serde", "serde_spanned", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", ] [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.1", ] [[package]] @@ -12362,7 +12727,7 @@ dependencies = [ "pin-project", "prost 0.11.9", "prost-derive 0.11.9", - "rustls-native-certs", + "rustls-native-certs 0.6.3", "rustls-pemfile", "tokio", "tokio-rustls 0.23.4", @@ -12430,7 +12795,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http 1.4.0", @@ -12486,7 +12851,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -12509,7 +12874,7 @@ dependencies = [ "smallvec", "thiserror 1.0.69", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", ] [[package]] @@ -12544,9 +12909,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -12598,17 +12963,17 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.26.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", "http 1.4.0", "httparse", "log", - "rand 0.9.2", - "rustls 0.23.36", + "rand 0.9.3", + "rustls 0.23.37", "rustls-pki-types", "sha1", "thiserror 2.0.18", @@ -12635,7 +13000,7 @@ dependencies = [ "futures", "http 1.4.0", "http-body-util", - "hyper 1.8.1", + "hyper 1.9.0", "prost 0.13.5", "reqwest 0.12.28", "serde", @@ -12702,9 +13067,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -12723,9 +13088,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" @@ -12834,13 +13199,13 @@ dependencies = [ [[package]] name = "uuid" -version = "1.20.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", - "rand 0.9.2", + "rand 0.10.1", "serde_core", "wasm-bindgen", ] @@ -12934,6 +13299,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasite" version = "0.1.0" @@ -12942,9 +13316,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -12955,23 +13329,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", - "futures-util", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12979,26 +13349,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -13012,6 +13404,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver 1.0.28", +] + [[package]] name = "wasmtimer" version = "0.4.3" @@ -13055,7 +13459,7 @@ dependencies = [ "state-chain", "tokio", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-build", "zkm-prover", "zkm-sdk", @@ -13064,9 +13468,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -13092,6 +13496,15 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -13104,14 +13517,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -13187,30 +13600,31 @@ dependencies = [ [[package]] name = "windows" -version = "0.53.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-core 0.53.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", ] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows-collections" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.62.2", ] [[package]] name = "windows-core" -version = "0.53.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-result 0.1.2", "windows-targets 0.52.6", ] @@ -13223,10 +13637,21 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link", - "windows-result 0.4.1", + "windows-result", "windows-strings", ] +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -13235,7 +13660,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13246,7 +13671,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13256,12 +13681,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-numerics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-targets 0.52.6", + "windows-core 0.62.2", + "windows-link", +] + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -13282,6 +13719,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -13327,6 +13773,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -13375,6 +13836,21 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -13393,6 +13869,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -13411,6 +13893,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -13441,6 +13929,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -13459,6 +13953,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -13477,6 +13977,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -13495,6 +14001,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -13515,9 +14027,18 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" dependencies = [ "memchr", ] @@ -13537,12 +14058,94 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease 0.2.37", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease 0.2.37", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver 1.0.28", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "ws_stream_wasm" @@ -13633,16 +14236,16 @@ dependencies = [ [[package]] name = "yamux" -version = "0.13.8" +version = "0.13.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deab71f2e20691b4728b349c6cee8fc7223880fa67b6b4f92225ec32225447e5" +checksum = "1991f6690292030e31b0144d73f5e8368936c58e45e7068254f7138b23b00672" dependencies = [ "futures", "log", "nohash-hasher", "parking_lot", "pin-project", - "rand 0.9.2", + "rand 0.9.3", "static_assertions", "web-time", ] @@ -13664,9 +14267,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -13675,54 +14278,54 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.36" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dafd85c832c1b68bbb4ec0c72c7f6f4fc5179627d2bc7c26b30e4c0cc11e76cc" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.36" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb7e4e8436d9db52fbd6625dbf2f45243ab84994a72882ec8227b99e72b439a" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", "synstructure", ] @@ -13743,14 +14346,14 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -13759,9 +14362,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -13770,13 +14373,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.117", ] [[package]] @@ -13828,8 +14431,8 @@ dependencies = [ [[package]] name = "zkm-build" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "cargo_metadata", @@ -13839,14 +14442,15 @@ dependencies = [ [[package]] name = "zkm-core-executor" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", "bytemuck", "elf", "enum-map", + "env_logger", "eyre", "hashbrown 0.14.5", "hex", @@ -13854,6 +14458,7 @@ dependencies = [ "log", "nohash-hasher", "num", + "num_enum", "p3-field", "p3-koala-bear", "p3-maybe-rayon", @@ -13868,6 +14473,7 @@ dependencies = [ "thiserror 1.0.69", "tiny-keccak", "tracing", + "tracing-subscriber 0.3.23", "typenum", "vec_map", "zkm-curves", @@ -13877,8 +14483,8 @@ dependencies = [ [[package]] name = "zkm-core-machine" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -13917,7 +14523,7 @@ dependencies = [ "tiny-keccak", "tracing", "tracing-forest", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "typenum", "web-time", "zkm-core-executor", @@ -13929,8 +14535,8 @@ dependencies = [ [[package]] name = "zkm-cuda" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "ctrlc", @@ -13947,8 +14553,8 @@ dependencies = [ [[package]] name = "zkm-curves" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "cfg-if", "curve25519-dalek", @@ -13971,17 +14577,18 @@ dependencies = [ [[package]] name = "zkm-derive" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ + "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "zkm-lib" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -13993,8 +14600,8 @@ dependencies = [ [[package]] name = "zkm-primitives" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "hex", @@ -14011,8 +14618,8 @@ dependencies = [ [[package]] name = "zkm-prover" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", @@ -14033,10 +14640,9 @@ dependencies = [ "rayon", "serde", "serde_json", - "serial_test", "thiserror 1.0.69", "tracing", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-core-executor", "zkm-core-machine", "zkm-primitives", @@ -14049,8 +14655,8 @@ dependencies = [ [[package]] name = "zkm-recursion-circuit" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "hashbrown 0.14.5", "itertools 0.13.0", @@ -14082,8 +14688,8 @@ dependencies = [ [[package]] name = "zkm-recursion-compiler" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "backtrace", "itertools 0.13.0", @@ -14103,8 +14709,8 @@ dependencies = [ [[package]] name = "zkm-recursion-core" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "backtrace", "ff 0.13.1", @@ -14140,8 +14746,8 @@ dependencies = [ [[package]] name = "zkm-recursion-derive" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "quote", "syn 1.0.109", @@ -14149,8 +14755,8 @@ dependencies = [ [[package]] name = "zkm-recursion-gnark-ffi" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "bincode", @@ -14173,11 +14779,11 @@ dependencies = [ [[package]] name = "zkm-sdk" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "alloy-primitives", - "alloy-signer 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "alloy-signer 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "anyhow", "async-trait", "bincode", @@ -14207,7 +14813,7 @@ dependencies = [ "tonic-build", "tracing", "twirp-rs", - "uuid 1.20.0", + "uuid 1.23.0", "vergen", "zkm-build", "zkm-core-executor", @@ -14220,8 +14826,8 @@ dependencies = [ [[package]] name = "zkm-stark" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "arrayref", "hashbrown 0.14.5", @@ -14254,7 +14860,7 @@ dependencies = [ "sysinfo", "tracing", "tracing-forest", - "tracing-subscriber 0.3.22", + "tracing-subscriber 0.3.23", "zkm-derive", "zkm-primitives", "zkm-zkvm", @@ -14262,8 +14868,8 @@ dependencies = [ [[package]] name = "zkm-verifier" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "anyhow", "ark-bn254", @@ -14276,6 +14882,7 @@ dependencies = [ "itertools 0.13.0", "lazy_static", "once_cell", + "p3-bn254-fr", "p3-commit", "p3-field", "p3-koala-bear", @@ -14297,8 +14904,8 @@ dependencies = [ [[package]] name = "zkm-zkvm" -version = "1.2.4" -source = "git+https://github.com/ProjectZKM/Ziren#980997f64e258c706d280dd4f2d0c3829341a4f2" +version = "1.2.5" +source = "git+https://github.com/ProjectZKM/Ziren#c736a41cccd623427295f89b53306673adc89966" dependencies = [ "bincode", "cfg-if", @@ -14316,9 +14923,9 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zstd" diff --git a/Cargo.toml b/Cargo.toml index df96280d..fc503f7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,13 +86,15 @@ zkm-build = { git = "https://github.com/ProjectZKM/Ziren" } zkm-core-executor = { git = "https://github.com/ProjectZKM/Ziren" } zkm-prover = { git = "https://github.com/ProjectZKM/Ziren" } zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren" } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", features = ["ark"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } #zkm-build = { path = "../Ziren/crates/build" } #zkm-core-executor = { path = "../Ziren/crates/core/executor" } #zkm-prover = { path = "../Ziren/crates/prover" } #zkm-sdk = { path = "../Ziren/crates/sdk" } -#zkm-verifier = { path = "../Ziren/crates/verifier", features = ["ark"] } +#zkm-verifier = { path = "../Ziren/crates/verifier" } bitvm2-lib = { path = "crates/bitvm2-ga" } store = { path = "crates/store" } diff --git a/circuits/README.md b/circuits/README.md index 43376730..a740c67f 100644 --- a/circuits/README.md +++ b/circuits/README.md @@ -56,7 +56,7 @@ For case 2, > * If there is no Ziren upgrade during this interval, and the inputs of the proof aggregation are compressed proofs, but with different `start_pc`, `pc`, etc. > * If there is some Ziren upgrades during this interval, once we support the multiple verification keys in Ziren, this problem can be reduced to the former one. -With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify(proof, zkm_public_values, zkm_vk_hash, groth16_vk)`. +With multiple proof recursions, we generate a Groth16 proof, and verify with `Groth16Verifier::verify_by_imm_groth16_vk(proof, zkm_public_values, zkm_vk_hash, groth16_vk, part_stark_vk)`. ## Preparation diff --git a/circuits/commit-chain-proof/guest/Cargo.toml b/circuits/commit-chain-proof/guest/Cargo.toml index d83b9014..395813bd 100644 --- a/circuits/commit-chain-proof/guest/Cargo.toml +++ b/circuits/commit-chain-proof/guest/Cargo.toml @@ -11,8 +11,8 @@ bincode = "1.3.3" commit-chain = { path = "../../../crates/commit-chain" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -36,4 +36,4 @@ alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } diff --git a/circuits/commit-chain-proof/guest/src/main.rs b/circuits/commit-chain-proof/guest/src/main.rs index c26ed23f..e994e13c 100644 --- a/circuits/commit-chain-proof/guest/src/main.rs +++ b/circuits/commit-chain-proof/guest/src/main.rs @@ -1,6 +1,6 @@ #![no_main] zkm_zkvm::entrypoint!(main); -use commit_chain::{CommitChainCircuitInput, commit_chain_circuit}; +use commit_chain::commit_chain_circuit; pub fn main() { let input = zkm_zkvm::io::read(); diff --git a/circuits/commit-chain-proof/host/src/lib.rs b/circuits/commit-chain-proof/host/src/lib.rs index 545e91df..72963ff6 100644 --- a/circuits/commit-chain-proof/host/src/lib.rs +++ b/circuits/commit-chain-proof/host/src/lib.rs @@ -19,6 +19,7 @@ const COMMIT_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -114,12 +115,19 @@ pub async fn fetch_commit_chain( .iter() .map(|compressed_pk| PublicKey::from_str(compressed_pk).unwrap()) .collect(); + let next_publisher_public_keys = ci.next_publisher_public_keys.as_ref().map(|keys| { + keys.iter() + .map(|compressed_pk| PublicKey::from_str(compressed_pk).unwrap()) + .collect::>() + }); tracing::info!("sequencer_hash: {:?}", sequencer_hash(&ci.sequencers)); let commit = CircuitCommit { commit_txn, sequencers: ci.sequencers.clone(), publisher_public_keys, threshold: ci.threshold, + next_publisher_public_keys, + next_threshold: ci.next_threshold, genesis_txid: Txid::from_str(&ci.genesis_txid)?.as_raw_hash().to_byte_array(), block_height, }; @@ -181,26 +189,45 @@ impl ProofBuilder for CommitChainProofBuilder { //let prev: CommitChainCircuitOutput = serde_json::from_slice(&public_inputs).unwrap(); Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file")?; - let zkm_vk_hash = - fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk hash")?; - let prev_output: CommitChainCircuitOutput = - zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - CommitChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - ) - } - None => (CommitChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), - }; + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file")?; + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) + .context("Read vk hash")?; + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; + let prev_output: CommitChainCircuitOutput = + zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + CommitChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + CommitChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + "v1.2.5".into(), + ), + }; let input: CommitChainCircuitInput = CommitChainCircuitInput { zkm_vk_hash, + zkm_version, zkm_proof, prev_proof, commits: commits.to_vec(), @@ -238,9 +265,10 @@ impl ProofBuilder for CommitChainProofBuilder { tracing::info!("Commit chain proof cycles: {}", cycles); - if let Err(e) = self.client.verify(&proof, &self.verifying_key) { - panic!("{}", e); - } + // todo: verify the proof laterr + // if let Err(e) = self.client.verify(&proof, &self.verifying_key) { + // panic!("{}", e); + // } let input = bincode::serialize(&input)?; Ok((input, proof, cycles, proving_time)) @@ -267,11 +295,13 @@ impl ProofBuilder for CommitChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; Ok((public_value_hex, proof_size)) } } diff --git a/circuits/data/commit-chain/0-1.bin.commits b/circuits/data/commit-chain/0-1.bin.commits index 897f0754..47fa016c 100644 --- a/circuits/data/commit-chain/0-1.bin.commits +++ b/circuits/data/commit-chain/0-1.bin.commits @@ -1 +1 @@ -[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"622eeea26cd959df530643268a94d859ebcb3ba0917691a77b830481af640501:0","script_sig":"","sequence":4294967295,"witness":["30440220411d76ca263fee5bcb6b0e18d7aad8232ca0f2e99eaaed0bc8b977169e2f1b6d022053186175329f8714d7802ad0e92365744d087dfdf858f9819142351dbb697d5281","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a4035e3a5a2736974eac20a6290f79fd153ba4d45df444ec953704f03f8cb3dd5b5070292c12aec12a7b213f65b1deb03c6b59b69620b6a1d9b110bda3a00346878"}]},"genesis_txid":[62,113,183,217,27,117,122,227,144,26,0,59,106,246,51,184,53,250,56,55,165,81,188,30,132,254,190,180,247,102,127,10],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1000000,"name":null}],"block_height":119164}] \ No newline at end of file +[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"dc3ab4f512c412f417347ee8624bec6fa9ddef4e4ab832e0749986b8fac41812:0","script_sig":"","sequence":4294967295,"witness":["30440220055614d8ae09d309d24df5ff37ccdf0bfd3343abbf92bf72065f8fb5f8526efe022044da12fc0f78d65890dd09dea787d6113f3c511c177db00207ca00bae4df8d4281","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a40600316026949ac291ff23c2f2b045a92868a9be546ff440d74524ba97d25f22b2b9791b90336e820684537ded50aeb9c5fdf591d5d1992cd5e04a1d74e07a2f7"}]},"genesis_txid":[38,32,132,254,96,19,216,150,70,107,27,2,105,4,169,155,65,232,159,113,86,110,97,178,230,248,167,101,45,5,250,154],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"next_publisher_public_keys":null,"next_threshold":null,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1100000,"name":null}],"block_height":120054}] \ No newline at end of file diff --git a/circuits/data/commit-chain/1-1.bin.commits b/circuits/data/commit-chain/1-1.bin.commits index 32e2c7a0..7557444f 100644 --- a/circuits/data/commit-chain/1-1.bin.commits +++ b/circuits/data/commit-chain/1-1.bin.commits @@ -1 +1 @@ -[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"0a7f66f7b4befe841ebc51a53738fa35b833f66a3b001a90e37a751bd9b7713e:0","script_sig":"","sequence":4294967295,"witness":["","3045022100b4257b7dacefc591048fc816052c899c710943dd3c4c39bfa818c53035994243022018256e7e1bea6b2dbcfdb62e58b0bc98ef7aa26c678a7298ac0dc4b9552825bc81","3044022068f8468be22db5613d0b3a6fda5fa70110b178b11c2ea5fcdc5714e04557202a022009c2e10755678389deb00eb872114a7529afc2e3e8f4bb211c1984245914e51d81","522102add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce421025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa42102cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e23353ae"]},{"previous_output":"7d0f6eadd008275745a3eb1d57b85f5387aa3b6488106f5bcf4868a5edcbd5f3:0","script_sig":"","sequence":4294967295,"witness":["304402206b5a5c8c0de45e121ea382c09d63b6cf87ed889db2024c2f66504cf3b5b5c49e022077edb94b793e01d78f54d874d640880540ec79e645cbd944d9f4c30568334ebe81","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a4035e3a5a2736974eac20a6290f79fd153ba4d45df444ec953704f03f8cb3dd5b5070292c12aec12a7b213f65b1deb03c6b59b69620b6a1d9b110bda3a00346878"}]},"genesis_txid":[62,113,183,217,27,117,122,227,144,26,0,59,106,246,51,184,53,250,56,55,165,81,188,30,132,254,190,180,247,102,127,10],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"sequencers":[{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":2000000,"name":null},{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1000000,"name":null}],"block_height":119166}] \ No newline at end of file +[{"commit_txn":{"version":2,"lock_time":0,"input":[{"previous_output":"9afa052d65a7f8e6b2616e56719fe8419ba90469021b6b4696d81360fe842026:0","script_sig":"","sequence":4294967295,"witness":["","3044022036aea0879bb34a78225ba291c4b812b0a4b5a699471648a048b3b54b277b600102200a723b69e171740a01d03cb19ab90f3aaa94f3e1267d64bed23df1e60546f33381","3044022044a53670d03d464c710ba0b65547b7ead2a916c0d4821273e6d37de1ee923bd802206d0639be92e8e6d76e870b3fd9086ab7644122b2b47cb7684115a6265a1a801f81","522102add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce421025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa42102cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e23353ae"]},{"previous_output":"f650ed861a45a849004e75c5203d27365ff2fba8954c2af0c1d57612485954dd:0","script_sig":"","sequence":4294967295,"witness":["3045022100f43050df85a8daa024a7f49cde271bca25bef857e00b224700185b756a0095000220771508ae331a3fb17e21ec762b0839f8928c7ae03fa1c61fa96f3b0388772fcb81","02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4"]}],"output":[{"value":500,"script_pubkey":"0020e38259e612b85728633fa8b8d00457594ed650fb5c6559b881575f49226d048a"},{"value":0,"script_pubkey":"6a402beffe4c53efd70f42c04ac0c83002a2a062bfeabaa5fffc6eb1280d411f0bb22b9791b90336e820684537ded50aeb9c5fdf591d5d1992cd5e04a1d74e07a2f7"}]},"genesis_txid":[38,32,132,254,96,19,216,150,70,107,27,2,105,4,169,155,65,232,159,113,86,110,97,178,230,248,167,101,45,5,250,154],"publisher_public_keys":["02add57ae77706046bc4af1e9533fb2ccaa96316e656756dd0884407ae72501ce4","025d415767660a937ee954d08fa09dc055b4a14e5ffc22c38372499dd198cf7aa4","02cb5075f2ff841fa49728a8e7d6b22b471f756cf6b3f7c625dcc5e325ebe7e233"],"threshold":2,"next_publisher_public_keys":null,"next_threshold":null,"sequencers":[{"address":"70cce9b7fb446d4ccf793c8cbc12dbef99a10f83","pub_key":[3,196,102,123,104,171,225,100,11,219,187,51,186,113,186,15,45,4,175,100,30,205,166,95,208,95,225,161,219,63,153,87,105],"power":1750000,"name":null},{"address":"9104a28cdf6a00a546a1c365007ebf017b0645af","pub_key":[2,164,213,70,208,195,228,161,14,136,64,141,227,85,111,57,106,134,108,153,204,28,225,73,21,111,180,225,54,254,104,172,110],"power":1500000,"name":null},{"address":"fc139929ae753d5580dc6145d9bc8c5c25f73298","pub_key":[3,212,171,157,196,79,116,160,72,222,230,127,158,112,84,118,51,1,46,182,155,255,134,203,202,133,13,89,35,37,29,185,128],"power":1100000,"name":null}],"block_height":121470}] \ No newline at end of file diff --git a/circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin b/circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin new file mode 100644 index 00000000..7fb52b0c Binary files /dev/null and b/circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin differ diff --git a/circuits/header-chain-proof/guest/Cargo.toml b/circuits/header-chain-proof/guest/Cargo.toml index d12b95c5..42e819c2 100644 --- a/circuits/header-chain-proof/guest/Cargo.toml +++ b/circuits/header-chain-proof/guest/Cargo.toml @@ -10,11 +10,11 @@ publish = false bincode = "1.3.3" # workspace header-chain = { path = "../../../crates/header-chain" } -borsh = {version = "1.5.3", features = ["derive"] } +borsh = { version = "1.5.3", features = ["derive"] } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -36,5 +36,5 @@ p256 = { git = "https://github.com/ziren-patches/elliptic-curves", branch = "pat alloy-primitives-v1-0-0 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.0.0" } alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.0" } alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } -#secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } diff --git a/circuits/header-chain-proof/guest/src/main.rs b/circuits/header-chain-proof/guest/src/main.rs index 462d0195..6d6aa768 100644 --- a/circuits/header-chain-proof/guest/src/main.rs +++ b/circuits/header-chain-proof/guest/src/main.rs @@ -1,15 +1,10 @@ #![no_main] zkm_zkvm::entrypoint!(main); -use header_chain::{ - verify_merkle_proof, BlockHeaderCircuitOutput, BlockInclusionProof, ChainState, - CircuitTransaction, HeaderChainCircuitInput, HeaderChainPrevProofType, - header_chain_circuit, -}; +use header_chain::{header_chain_circuit, HeaderChainCircuitInput}; use borsh::{BorshDeserialize, BorshSerialize}; - pub fn main() { let input: HeaderChainCircuitInput = zkm_zkvm::io::read(); let output = header_chain_circuit(input); diff --git a/circuits/header-chain-proof/host/src/lib.rs b/circuits/header-chain-proof/host/src/lib.rs index e415969a..9710a5d6 100644 --- a/circuits/header-chain-proof/host/src/lib.rs +++ b/circuits/header-chain-proof/host/src/lib.rs @@ -203,21 +203,39 @@ impl ProofBuilder for HeaderChainProofBuilder { Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file").unwrap(); - let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); - let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - HeaderChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - ) - } - None => (HeaderChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), - }; + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file").unwrap(); + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)).unwrap(); + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; + let prev_output = zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + HeaderChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + HeaderChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + "v1.2.5".into(), + ), + }; tracing::info!( "header-chain length: {}, start: {}, batch_size: {}", @@ -232,6 +250,7 @@ impl ProofBuilder for HeaderChainProofBuilder { zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers, }; @@ -290,11 +309,13 @@ impl ProofBuilder for HeaderChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; tracing::info!("Generate proof successfully, proof: {:?}", proof); Ok((public_value_hex, proof_size)) diff --git a/circuits/operator-proof/guest/Cargo.toml b/circuits/operator-proof/guest/Cargo.toml index 519efdeb..521f3c95 100644 --- a/circuits/operator-proof/guest/Cargo.toml +++ b/circuits/operator-proof/guest/Cargo.toml @@ -14,8 +14,8 @@ state-chain = { path = "../../../crates/state-chain" } bitcoin-light-client-circuit = { path = "../../../crates/bitcoin-light-client-circuit" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -42,3 +42,4 @@ alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", p secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } + diff --git a/circuits/operator-proof/guest/src/main.rs b/circuits/operator-proof/guest/src/main.rs index abaa74be..f5c6dbcd 100644 --- a/circuits/operator-proof/guest/src/main.rs +++ b/circuits/operator-proof/guest/src/main.rs @@ -5,7 +5,7 @@ use header_chain::{ HeaderChainCircuitInput, SPV, }; use alloy_primitives::{U256, Address}; -use bitcoin_light_client_circuit::EthClientExecutorInput; +use bitcoin_light_client_circuit::{EthClientExecutorInput, OperatorAttestationInputs}; use commit_chain::CommitChainCircuitInput; use state_chain::StateChainCircuitInput; use bitcoin::{ScriptBuf, TxOut, Transaction}; @@ -27,10 +27,11 @@ pub fn main() { let operator_header_chain: HeaderChainCircuitInput = zkm_zkvm::io::read(); let operator_commit_chain: CommitChainCircuitInput = zkm_zkvm::io::read(); let operator_state_chain: StateChainCircuitInput = zkm_zkvm::io::read(); + let attestation: OperatorAttestationInputs = zkm_zkvm::io::read(); let spv_ss_commit: SPV = zkm_zkvm::io::read(); let operator_committed_blockhash: [u8; 32] = zkm_zkvm::io::read(); - let (btc_best_block_hash, constant, included_watchtowers) = bitcoin_light_client_circuit::propose_longest_chain( + let output = bitcoin_light_client_circuit::propose_longest_chain( included_watchertowers, graph_id, operator_genesis_sequencer_commit_txid, @@ -41,12 +42,10 @@ pub fn main() { operator_header_chain, operator_commit_chain, operator_state_chain, + attestation, spv_ss_commit, operator_committed_blockhash, ); - zkm_zkvm::io::commit(&btc_best_block_hash); - zkm_zkvm::io::commit(&constant); - zkm_zkvm::io::commit(&included_watchtowers); + zkm_zkvm::io::commit(&output); } - diff --git a/circuits/operator-proof/host/Cargo.toml b/circuits/operator-proof/host/Cargo.toml index 86968e7a..2bc6c649 100644 --- a/circuits/operator-proof/host/Cargo.toml +++ b/circuits/operator-proof/host/Cargo.toml @@ -47,7 +47,7 @@ proof-builder.workspace = true # Ziren zkm-sdk.workspace = true zkm-prover.workspace = true -zkm-verifier.workspace = true +zkm-verifier = { workspace = true, features = ["ark"] } [dev-dependencies] bitvm2-lib.workspace = true diff --git a/circuits/operator-proof/host/src/lib.rs b/circuits/operator-proof/host/src/lib.rs index 0e63d730..a1585a4a 100644 --- a/circuits/operator-proof/host/src/lib.rs +++ b/circuits/operator-proof/host/src/lib.rs @@ -6,22 +6,32 @@ use bitcoin::{ hashes::Hash, secp256k1::{PublicKey, XOnlyPublicKey}, }; -use bitcoin_light_client_circuit::build_spv; -use bitcoin_script::script; use borsh::BorshDeserialize; use client::btc_chain::BTCClient; -use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; -use header_chain::{CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType}; +use commit_chain::{ + CommitChainCircuitInput, CommitChainPrevProofType, extract_data_from_commitment_outputs, +}; +use header_chain::{ + BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, +}; use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; -use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use state_chain::{StateChainCircuitInput, StateChainCircuitOutput, StateChainPrevProofType}; use std::str::FromStr; use util::get_btc_block_confirms; use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; +use zkm_verifier::Groth16Verifier; +use bincode::deserialize; +use bitcoin_light_client_circuit::{ + OperatorAttestationInputs, build_spv, load_unique_part_stark_vk_witnesses, + parse_watchtower_commitment, part_stark_vk_attestation_dir, +}; +use bitcoin_script::script; use clap::Parser; + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -83,7 +93,9 @@ impl LongRunning for Args { /// A program that aggregates the proofs of the simple program. const OPERATOR: &[u8] = include_elf!("guest"); +use serde::de::DeserializeOwned; use std::fs; +use std::panic::{AssertUnwindSafe, catch_unwind}; use sha2::{Digest, Sha256}; use std::sync::OnceLock; @@ -101,10 +113,10 @@ pub async fn fetch_target_block_and_watchtower_tx( u32, bitcoin::Block, BlockHash, - bitcoin::Transaction, + Transaction, Vec, Vec, - Vec, + Vec, Vec, )> { let watchtower_challenge_txids: Vec<&str> = watchtower_challenge_txids.split(",").collect(); @@ -229,6 +241,46 @@ impl OperatorProofBuilder { } } +fn load_proof_public_output(proof_path: &str) -> anyhow::Result { + let public_inputs = fs::read(format!("{proof_path}.public_inputs.bin")) + .context("Failed to read public inputs")?; + deserialize(&public_inputs).context("Failed to decode proof public outputs") +} + +fn extract_watchtower_part_stark_vk(tx: &Transaction) -> Option> { + let commitment = extract_data_from_commitment_outputs(&tx.output); + let (_, _, _, _, proof_part_stark_vk) = parse_watchtower_commitment(&commitment).ok()?; + Some(proof_part_stark_vk) +} + +fn load_part_stark_vk(zkm_version: &str) -> anyhow::Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) +} + +/// Collect both the version-derived verifier key and the recursive inner verifier key +/// for header/state subproofs, plus each watchtower proof verifier key from commitments. +fn collect_requested_part_stark_vks( + header_chain_input: &HeaderChainCircuitInput, + header_chain_output: &BlockHeaderCircuitOutput, + state_chain_input: &StateChainCircuitInput, + state_chain_output: &StateChainCircuitOutput, + watchtower_challenge_txns: &[Transaction], +) -> anyhow::Result>> { + let mut requested_part_stark_vks = vec![ + load_part_stark_vk(&header_chain_input.zkm_version)?, + header_chain_output.part_stark_vk.clone(), + load_part_stark_vk(&state_chain_input.zkm_version)?, + state_chain_output.part_stark_vk.clone(), + ]; + for tx in watchtower_challenge_txns { + if let Some(part_stark_vk) = extract_watchtower_part_stark_vk(tx) { + requested_part_stark_vks.push(part_stark_vk); + } + } + Ok(requested_part_stark_vks) +} + impl ProofBuilder for OperatorProofBuilder { fn client(&self) -> &zkm_sdk::ProverClient { &self.client @@ -284,11 +336,20 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); + let version_path = format!("{header_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers: vec![], } }; @@ -302,11 +363,20 @@ impl ProofBuilder for OperatorProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); + let version_path = format!("{commit_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, commits: vec![], } }; @@ -320,15 +390,42 @@ impl ProofBuilder for OperatorProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); + let version_path = format!("{state_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; + StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: vec![], } }; + let header_chain_output: BlockHeaderCircuitOutput = + load_proof_public_output(header_chain_input_proof)?; + let state_chain_output: StateChainCircuitOutput = + load_proof_public_output(state_chain_input_proof)?; + let requested_part_stark_vks = collect_requested_part_stark_vks( + &header_chain_input, + &header_chain_output, + &state_chain_input, + &state_chain_output, + watchtower_challenge_txns, + )?; + let attestation_dir = part_stark_vk_attestation_dir(); + let (unique_witnesses, _) = + load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) + .map_err(anyhow::Error::msg)?; + let attestation_inputs = OperatorAttestationInputs { unique_witnesses }; + // --- spv --- // //let latest_sequencer_commit_txid = Txid::from_str(&latest_sequencer_commit_txid).unwrap(); @@ -387,6 +484,7 @@ impl ProofBuilder for OperatorProofBuilder { stdin.write(&header_chain_input); stdin.write(&commit_chain_input); stdin.write(&state_chain_input); + stdin.write(&attestation_inputs); stdin.write(&spv_ss_commit); stdin.write(&operator_committed_blockhash.to_byte_array()); @@ -426,7 +524,10 @@ impl ProofBuilder for OperatorProofBuilder { }; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; let proof = bincode::serialize(&proof).unwrap(); std::fs::write(&format!("{}", output), proof)?; Ok((public_value_hex, proof_size)) @@ -439,7 +540,81 @@ mod tests { use ark_bn254::Bn254; use ark_groth16::{Groth16, r1cs_to_qap::LibsnarkReduction}; - use zkm_verifier::{GROTH16_VK_BYTES, convert_ark}; + use std::panic::{AssertUnwindSafe, catch_unwind}; + + use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; + + fn sample_header_input(zkm_version: &str) -> HeaderChainCircuitInput { + HeaderChainCircuitInput { + prev_proof: HeaderChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + block_headers: vec![], + } + } + + fn sample_state_input(zkm_version: &str) -> StateChainCircuitInput { + StateChainCircuitInput { + prev_proof: StateChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + blocks: vec![], + } + } + + fn sample_header_output(part_stark_vk: Vec) -> BlockHeaderCircuitOutput { + BlockHeaderCircuitOutput { chain_state: header_chain::ChainState::new(), part_stark_vk } + } + + fn sample_state_output(part_stark_vk: Vec) -> StateChainCircuitOutput { + StateChainCircuitOutput { + chain_state: state_chain::StateChainState::new(0, [0u8; 32], Vec::new()), + part_stark_vk, + } + } + + #[test] + fn test_collect_requested_part_stark_vks_includes_outer_inner_and_watchtower_keys() { + let old_vk = load_part_stark_vk("v1.2.4").unwrap(); + let new_vk = load_part_stark_vk("v1.2.5").unwrap(); + + let graph_id = [7u8; 16]; + let proof = vec![3u8; 260]; + let public_inputs = vec![9u8; 36]; + let vk_hash = "ab".repeat(33); + let watchtower_comm = bitcoin_light_client_circuit::build_watchtower_commitment( + &graph_id, + &proof, + &public_inputs, + &vk_hash, + &new_vk, + ) + .unwrap(); + let watchtower_tx = Transaction { + version: bitcoin::transaction::Version::TWO, + lock_time: bitcoin::absolute::LockTime::ZERO, + input: vec![], + output: vec![TxOut { + value: bitcoin::Amount::ZERO, + script_pubkey: bitcoin::ScriptBuf::new_op_return(watchtower_comm.as_ref()), + }], + }; + + let requested = collect_requested_part_stark_vks( + &sample_header_input("v1.2.5"), + &sample_header_output(old_vk.clone()), + &sample_state_input("v1.2.5"), + &sample_state_output(old_vk.clone()), + &[watchtower_tx], + ) + .unwrap(); + + assert_eq!(requested, vec![new_vk.clone(), old_vk.clone(), new_vk.clone(), old_vk, new_vk]); + } #[tokio::test] #[ignore = "local test"] @@ -450,17 +625,26 @@ mod tests { let proof: ZKMProofWithPublicValues = bincode::deserialize(&proof_bytes).unwrap(); - let a: ([u8; 32], [u8; 32], [u8; 32]) = proof.public_values.clone().read(); + let a: bitcoin_light_client_circuit::OperatorPublicOutputs = + proof.public_values.clone().read(); println!( "block hash: {:?}, constant: {:?}, included map: {:?}", - hex::encode(a.0), - hex::encode(a.1), - U256::from_le_bytes(a.2.clone()) + hex::encode(a.btc_best_block_hash), + hex::encode(a.constant), + U256::from_le_bytes(a.included_watchtowers) ); - let groth16_vk = &GROTH16_VK_BYTES; let vk_hash = String::from_utf8(vk_bytes).unwrap(); - let ark_proof = convert_ark(&proof, &vk_hash, groth16_vk).unwrap(); + let part_stark_vk = catch_unwind(AssertUnwindSafe(|| { + Groth16Verifier::get_part_stark_vk(&proof.zkm_version) + })) + .map_err(|_| { + anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {}", proof.zkm_version) + }) + .unwrap(); + let ark_proof = + convert_ark_imm_wrap_vk(&proof, &vk_hash, &IMM_GROTH16_VK_BYTES, part_stark_vk) + .unwrap(); // Verify the arkworks proof. let ok = Groth16::::verify_proof( diff --git a/circuits/proof-builder/src/lib.rs b/circuits/proof-builder/src/lib.rs index f14a7c50..710d9098 100644 --- a/circuits/proof-builder/src/lib.rs +++ b/circuits/proof-builder/src/lib.rs @@ -205,6 +205,8 @@ pub struct ProofData { pub proof: Vec, pub vk: String, pub public_inputs: Vec, + pub zkm_version: String, + pub proof_part_stark_vk: Vec, } impl ProofData { @@ -222,6 +224,12 @@ impl ProofData { proof_data.vk = String::from_utf8(fs::read(format!("{path}.vk_hash.bin")).unwrap_or_default()) .unwrap_or_default(); + proof_data.zkm_version = String::from_utf8( + fs::read(format!("{path}.zkm_version.bin")).unwrap_or_default(), + ) + .unwrap_or_default(); + proof_data.proof_part_stark_vk = + fs::read(format!("{path}.proof_part_stark_vk.bin")).unwrap_or_default(); } } proof_data @@ -277,3 +285,40 @@ pub struct WatchtowerProofTimeoutUpdateResponse { pub data: Option, pub error: Option, } + +#[cfg(test)] +mod tests { + use super::*; + use std::path::PathBuf; + use std::time::{SystemTime, UNIX_EPOCH}; + + fn temp_proof_base() -> PathBuf { + let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); + std::env::temp_dir().join(format!("proof-data-test-{nanos}")) + } + + #[test] + fn load_proof_data_reads_proof_part_stark_vk_sidecar() { + let base = temp_proof_base(); + let base_str = base.to_string_lossy().to_string(); + fs::write(&base, [1u8, 2, 3]).unwrap(); + fs::write(format!("{base_str}.public_inputs.bin"), [4u8, 5, 6]).unwrap(); + fs::write(format!("{base_str}.vk_hash.bin"), b"vk-hash").unwrap(); + fs::write(format!("{base_str}.zkm_version.bin"), b"v1.2.5").unwrap(); + fs::write(format!("{base_str}.proof_part_stark_vk.bin"), [9u8, 8, 7]).unwrap(); + + let proof_data = ProofData::load_proof_data(&base_str, ProofType::Watchtower); + + assert_eq!(proof_data.proof, vec![1u8, 2, 3]); + assert_eq!(proof_data.public_inputs, vec![4u8, 5, 6]); + assert_eq!(proof_data.vk, "vk-hash"); + assert_eq!(proof_data.zkm_version, "v1.2.5"); + assert_eq!(proof_data.proof_part_stark_vk, vec![9u8, 8, 7]); + + let _ = fs::remove_file(&base); + let _ = fs::remove_file(format!("{base_str}.public_inputs.bin")); + let _ = fs::remove_file(format!("{base_str}.vk_hash.bin")); + let _ = fs::remove_file(format!("{base_str}.zkm_version.bin")); + let _ = fs::remove_file(format!("{base_str}.proof_part_stark_vk.bin")); + } +} diff --git a/circuits/state-chain-proof/guest/Cargo.toml b/circuits/state-chain-proof/guest/Cargo.toml index 3e17dffe..9e195a81 100644 --- a/circuits/state-chain-proof/guest/Cargo.toml +++ b/circuits/state-chain-proof/guest/Cargo.toml @@ -11,8 +11,8 @@ bincode = "1.3.3" state-chain = { path = "../../../crates/state-chain" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -34,4 +34,4 @@ alloy-primitives-v1-1-0 = { git = "https://github.com/ziren-patches/core.git", p alloy-primitives-v1-1-2 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.1.2" } alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", package = "alloy-primitives", branch = "patch-alloy-primitives-1.4.1" } secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } -#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } \ No newline at end of file +#secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } diff --git a/circuits/state-chain-proof/host/src/lib.rs b/circuits/state-chain-proof/host/src/lib.rs index f52e8bc6..e908c95a 100644 --- a/circuits/state-chain-proof/host/src/lib.rs +++ b/circuits/state-chain-proof/host/src/lib.rs @@ -32,6 +32,7 @@ const STATE_CHAIN: &[u8] = include_elf!("guest"); use std::fs; use clap::Parser; + /// The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -317,29 +318,48 @@ impl ProofBuilder for StateChainProofBuilder { Some(public_inputs) }; - let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash) = match prev_receipt.clone() { - Some(public_inputs) => { - let proof_bytes = - fs::read(input_proof).context("Failed to read input proof file")?; - let zkm_vk_hash = - fs::read(&format!("{}.vk_hash.bin", input_proof)).context("Read vk_hash")?; - let prev_output: StateChainCircuitOutput = - zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); - ( - StateChainPrevProofType::PrevProof(prev_output), - proof_bytes, - public_inputs, - zkm_vk_hash.to_vec(), - ) - } - None => (StateChainPrevProofType::GenesisBlock, Vec::new(), Vec::new(), Vec::new()), - }; + let (prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, zkm_version) = + match prev_receipt.clone() { + Some(public_inputs) => { + let proof_bytes = + fs::read(input_proof).context("Failed to read input proof file")?; + let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", input_proof)) + .context("Read vk_hash")?; + let version_path = format!("{input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| { + format!("failed to read zkm_version file '{version_path}'") + }) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; + let prev_output: StateChainCircuitOutput = + zkm_sdk::ZKMPublicValues::from(&public_inputs).read(); + ( + StateChainPrevProofType::PrevProof(prev_output), + proof_bytes, + public_inputs, + zkm_vk_hash.to_vec(), + zkm_version, + ) + } + None => ( + StateChainPrevProofType::GenesisBlock, + Vec::new(), + Vec::new(), + Vec::new(), + "v1.2.5".into(), + ), + }; let input: StateChainCircuitInput = StateChainCircuitInput { prev_proof, zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: blocks.clone(), }; // Generate the proofs. @@ -390,11 +410,13 @@ impl ProofBuilder for StateChainProofBuilder { std::fs::write(&format!("{}", output_proof), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); std::fs::write( &format!("{}.public_inputs.bin", output_proof), proof.public_values.to_vec(), )?; std::fs::write(&format!("{}.vk_hash.bin", output_proof), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output_proof), zkm_version)?; tracing::info!("Generate proof successfully, proof: {:?}", proof); Ok((public_value_hex, proof_size)) diff --git a/circuits/watchtower-proof/guest/Cargo.toml b/circuits/watchtower-proof/guest/Cargo.toml index 2db98cac..fca4952e 100644 --- a/circuits/watchtower-proof/guest/Cargo.toml +++ b/circuits/watchtower-proof/guest/Cargo.toml @@ -14,8 +14,8 @@ state-chain = { path = "../../../crates/state-chain" } bitcoin-light-client-circuit = { path = "../../../crates/bitcoin-light-client-circuit" } # Ziren -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", features = ["verify"] } +zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren" } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -42,3 +42,4 @@ alloy-primitives-v1-4-1 = { git = "https://github.com/ziren-patches/core.git", p secp256k1-v0-29-1 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.29.1" } #secp256k1-v0-30-0 = { git = "https://github.com/ziren-patches/rust-secp256k1", package = "secp256k1", branch = "patch-0.30.0" } #bitcoin = { git = "https://github.com/ProjectZKM/rust-bitcoin", branch = "patch-0.32.7" } + diff --git a/circuits/watchtower-proof/guest/src/main.rs b/circuits/watchtower-proof/guest/src/main.rs index cda108ac..c522794c 100644 --- a/circuits/watchtower-proof/guest/src/main.rs +++ b/circuits/watchtower-proof/guest/src/main.rs @@ -6,6 +6,7 @@ use header_chain::{ HeaderChainCircuitInput, SPV, }; +use bitcoin_light_client_circuit::WatchtowerAttestationInputs; use commit_chain::CommitChainCircuitInput; use state_chain::StateChainCircuitInput; @@ -15,16 +16,17 @@ pub fn main() { let header_chain: HeaderChainCircuitInput = zkm_zkvm::io::read(); // private inputs let commit_chain: CommitChainCircuitInput = zkm_zkvm::io::read(); let state_chain: StateChainCircuitInput = zkm_zkvm::io::read(); + let attestation: WatchtowerAttestationInputs = zkm_zkvm::io::read(); let spv: SPV = zkm_zkvm::io::read(); - let (total_work, btc_best_block_height) = bitcoin_light_client_circuit::watch_longest_chain( + let output = bitcoin_light_client_circuit::watch_longest_chain( genesis_sequencer_commit_txid, latest_sequencer_commit_txid, header_chain, commit_chain, state_chain, + attestation, spv ); - zkm_zkvm::io::commit(&total_work); - zkm_zkvm::io::commit(&btc_best_block_height); + zkm_zkvm::io::commit(&output); } diff --git a/circuits/watchtower-proof/host/src/lib.rs b/circuits/watchtower-proof/host/src/lib.rs index 114a444d..d01589a9 100644 --- a/circuits/watchtower-proof/host/src/lib.rs +++ b/circuits/watchtower-proof/host/src/lib.rs @@ -1,26 +1,36 @@ #![feature(trim_prefix_suffix)] //! Generate watchtower proof +use anyhow::Context; +use bincode::deserialize; use borsh::BorshDeserialize; -use header_chain::{CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType}; +use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; +use header_chain::{ + BlockHeaderCircuitOutput, CircuitBlockHeader, HeaderChainCircuitInput, HeaderChainPrevProofType, +}; use zkm_sdk::{ HashableKey, Prover, ProverClient, ZKMProofKind, ZKMProofWithPublicValues, ZKMStdin, include_elf, }; use bitcoin::{Block, Network, Transaction, Txid, hashes::Hash}; -use bitcoin_light_client_circuit::build_spv; -use commit_chain::{CommitChainCircuitInput, CommitChainPrevProofType}; +use bitcoin_light_client_circuit::{ + WatchtowerAttestationInputs, build_spv, load_unique_part_stark_vk_witnesses, + part_stark_vk_attestation_dir, +}; use sha2::{Digest, Sha256}; -use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use state_chain::{StateChainCircuitInput, StateChainCircuitOutput, StateChainPrevProofType}; use std::str::FromStr; use std::sync::OnceLock; static ELF_ID: OnceLock = OnceLock::new(); -use anyhow::Context; use proof_builder::{LongRunning, ProofBuilder, ProofRequest}; use clap::Parser; +use serde::de::DeserializeOwned; use std::fs; +use std::panic::{AssertUnwindSafe, catch_unwind}; +use zkm_verifier::Groth16Verifier; + // The arguments for the cli. #[derive(Debug, Clone, Parser, serde::Deserialize, serde::Serialize)] pub struct Args { @@ -94,6 +104,33 @@ impl WatchtowerProofBuilder { } } +fn load_proof_public_output(proof_path: &str) -> anyhow::Result { + let public_inputs = fs::read(format!("{proof_path}.public_inputs.bin")) + .context("Failed to read public inputs")?; + deserialize(&public_inputs).context("Failed to decode proof public outputs") +} + +fn load_part_stark_vk(zkm_version: &str) -> anyhow::Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow::anyhow!("Failed to load part_stark_vk for zkm_version {zkm_version}")) +} + +/// Collect both the version-derived verifier key and the recursive inner verifier key +/// for header/state subproofs so witness loading survives Ziren upgrades. +fn collect_requested_part_stark_vks( + header_chain_input: &HeaderChainCircuitInput, + header_chain_output: &BlockHeaderCircuitOutput, + state_chain_input: &StateChainCircuitInput, + state_chain_output: &StateChainCircuitOutput, +) -> anyhow::Result>> { + Ok(vec![ + load_part_stark_vk(&header_chain_input.zkm_version)?, + header_chain_output.part_stark_vk.clone(), + load_part_stark_vk(&state_chain_input.zkm_version)?, + state_chain_output.part_stark_vk.clone(), + ]) +} + impl ProofBuilder for WatchtowerProofBuilder { fn client(&self) -> &zkm_sdk::ProverClient { &self.client @@ -140,12 +177,21 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", header_chain_input_proof)).unwrap(); + let version_path = format!("{header_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; HeaderChainCircuitInput { prev_proof: HeaderChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, block_headers: vec![], } }; @@ -159,11 +205,20 @@ impl ProofBuilder for WatchtowerProofBuilder { .unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", commit_chain_input_proof)).unwrap(); + let version_path = format!("{commit_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; CommitChainCircuitInput { prev_proof: CommitChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, commits: vec![], } }; @@ -177,14 +232,38 @@ impl ProofBuilder for WatchtowerProofBuilder { fs::read(&format!("{}.public_inputs.bin", state_chain_input_proof)).unwrap(); let zkm_vk_hash = fs::read(&format!("{}.vk_hash.bin", state_chain_input_proof)).unwrap(); + let version_path = format!("{state_chain_input_proof}.zkm_version.bin"); + let zkm_version = fs::read(&version_path) + .with_context(|| format!("failed to read zkm_version file '{version_path}'")) + .and_then(|raw_zkm_version| { + String::from_utf8(raw_zkm_version).with_context(|| { + format!("invalid UTF-8 in zkm_version file '{version_path}'") + }) + })?; StateChainCircuitInput { prev_proof: StateChainPrevProofType::GenesisBlock, // unused zkm_proof, zkm_public_values, zkm_vk_hash, + zkm_version, blocks: vec![], } }; + let header_chain_output: BlockHeaderCircuitOutput = + load_proof_public_output(header_chain_input_proof)?; + let state_chain_output: StateChainCircuitOutput = + load_proof_public_output(state_chain_input_proof)?; + let attestation_dir = part_stark_vk_attestation_dir(); + let requested_part_stark_vks = collect_requested_part_stark_vks( + &header_chain_input, + &header_chain_output, + &state_chain_input, + &state_chain_output, + )?; + let (unique_witnesses, _) = + load_unique_part_stark_vk_witnesses(&attestation_dir, &requested_part_stark_vks) + .map_err(anyhow::Error::msg)?; + let attestation_inputs = WatchtowerAttestationInputs { unique_witnesses }; // --- spv --- // let genesis_sequencer_commit_txid = Txid::from_str(&genesis_sequencer_commit_txid)?; @@ -224,6 +303,7 @@ impl ProofBuilder for WatchtowerProofBuilder { stdin.write(&header_chain_input); stdin.write(&commit_chain_input); stdin.write(&state_chain_input); + stdin.write(&attestation_inputs); stdin.write(&spv); let elf_id = if ELF_ID.get().is_none() { ELF_ID @@ -263,8 +343,66 @@ impl ProofBuilder for WatchtowerProofBuilder { std::fs::write(&format!("{}", output), proof.bytes())?; let public_value_hex = hex::encode(proof.public_values.to_vec()); let proof_size = proof.bytes().len(); + let zkm_version = proof.zkm_version.clone(); + let proof_part_stark_vk = load_part_stark_vk(&zkm_version)?; std::fs::write(&format!("{}.public_inputs.bin", output), proof.public_values.to_vec())?; std::fs::write(&format!("{}.vk_hash.bin", output), self.verifying_key.bytes32())?; + std::fs::write(&format!("{}.zkm_version.bin", output), zkm_version)?; + std::fs::write(&format!("{}.proof_part_stark_vk.bin", output), proof_part_stark_vk)?; Ok((public_value_hex, proof_size)) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn sample_header_input(zkm_version: &str) -> HeaderChainCircuitInput { + HeaderChainCircuitInput { + prev_proof: HeaderChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + block_headers: vec![], + } + } + + fn sample_state_input(zkm_version: &str) -> StateChainCircuitInput { + StateChainCircuitInput { + prev_proof: StateChainPrevProofType::GenesisBlock, + zkm_proof: vec![], + zkm_public_values: vec![], + zkm_vk_hash: vec![], + zkm_version: zkm_version.to_string(), + blocks: vec![], + } + } + + fn sample_header_output(part_stark_vk: Vec) -> BlockHeaderCircuitOutput { + BlockHeaderCircuitOutput { chain_state: header_chain::ChainState::new(), part_stark_vk } + } + + fn sample_state_output(part_stark_vk: Vec) -> StateChainCircuitOutput { + StateChainCircuitOutput { + chain_state: state_chain::StateChainState::new(0, [0u8; 32], Vec::new()), + part_stark_vk, + } + } + + #[test] + fn test_collect_requested_part_stark_vks_includes_outer_and_inner_versions() { + let old_vk = load_part_stark_vk("v1.2.4").unwrap(); + let new_vk = load_part_stark_vk("v1.2.5").unwrap(); + + let requested = collect_requested_part_stark_vks( + &sample_header_input("v1.2.5"), + &sample_header_output(old_vk.clone()), + &sample_state_input("v1.2.5"), + &sample_state_output(old_vk.clone()), + ) + .unwrap(); + + assert_eq!(requested, vec![new_vk.clone(), old_vk.clone(), new_vk, old_vk]); + } +} diff --git a/crates/bitcoin-light-client-circuit/Cargo.toml b/crates/bitcoin-light-client-circuit/Cargo.toml index 7baefa63..172e5530 100644 --- a/crates/bitcoin-light-client-circuit/Cargo.toml +++ b/crates/bitcoin-light-client-circuit/Cargo.toml @@ -9,15 +9,15 @@ bitcoin = { workspace = true, features = ["serde", "rand", "secp-recovery"] } bincode = "1.3.3" # workspace -guest-executor = { workspace = true } -header-chain = { path = "../header-chain" } -commit-chain = { path = "../commit-chain" } -state-chain = { path = "../state-chain" } +guest-executor = { workspace = true } +header-chain = { workspace = true } +commit-chain = { workspace = true } +state-chain = { workspace = true } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-primitives = { git = "https://github.com/ProjectZKM/Ziren" } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } +zkm-primitives = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -29,7 +29,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, branch = "patch-31.0.2", features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } #prost = { version = "0.13", features = ["prost-derive"], default-features = false } #prost-derive = { version = "0.13", default-features = true } diff --git a/crates/bitcoin-light-client-circuit/src/attestation.rs b/crates/bitcoin-light-client-circuit/src/attestation.rs new file mode 100644 index 00000000..dd4b166b --- /dev/null +++ b/crates/bitcoin-light-client-circuit/src/attestation.rs @@ -0,0 +1,1494 @@ +use bitcoin::secp256k1::{Message, PublicKey, Secp256k1, SecretKey, ecdsa::Signature}; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; +use std::collections::{BTreeMap, BTreeSet}; +use std::path::{Path, PathBuf}; + +pub const PART_STARK_VK_TREE_HEIGHT: usize = 6; +pub const PART_STARK_VK_TREE_LEAFS: usize = 1 << PART_STARK_VK_TREE_HEIGHT; +pub const PART_STARK_VK_ROOT_SIGNATURE_DOMAIN: &[u8] = b"bitvm2:part_stark_vk_root:v2"; +pub const PART_STARK_VK_PUBLISHER_SET_DOMAIN: &[u8] = b"bitvm2:publisher_set:v1"; +pub const PART_STARK_VK_ATTESTATION_DIR_ENV: &str = "PART_STARK_VK_ATTESTATION_DIR"; +pub const DEFAULT_PART_STARK_VK_ATTESTATION_DIR: &str = "data/psv-attestations"; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkRootSignature { + pub signer_pubkey_index: usize, + pub signature: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkAttestationBundle { + pub part_stark_vk: Vec, + pub leaf_index: usize, + pub merkle_path: Vec<[u8; 32]>, + pub root: [u8; 32], + pub threshold: u16, + pub publisher_set_id: [u8; 32], + pub signatures: Vec, +} + +pub type UniquePartStarkVkWitness = PartStarkVkAttestationBundle; + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WatchtowerAttestationInputs { + pub unique_witnesses: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct OperatorAttestationInputs { + pub unique_witnesses: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct PartStarkVkTreeState { + pub tree_height: usize, + pub leaves: Vec>, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct LatestPartStarkVkAttestationManifest { + pub tree_height: usize, + pub ordered_versions: Vec, + pub root: [u8; 32], + pub threshold: Option, + pub publisher_set_id: Option<[u8; 32]>, + pub publisher_public_keys: Option>, + pub signatures: Vec, + pub part_stark_vk_leaf_hashes: BTreeMap, +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct VersionedPartStarkVkMerkleProof { + pub version: String, + pub part_stark_vk: Vec, + pub leaf_index: usize, + pub merkle_path: Vec<[u8; 32]>, +} + +pub fn part_stark_vk_attestation_dir() -> PathBuf { + std::env::var(PART_STARK_VK_ATTESTATION_DIR_ENV) + .map(PathBuf::from) + .unwrap_or_else(|_| PathBuf::from(DEFAULT_PART_STARK_VK_ATTESTATION_DIR)) +} + +/// Hash the ordered publisher set together with the active threshold. +pub fn compute_publisher_set_id(publisher_public_keys: &[PublicKey], threshold: u16) -> [u8; 32] { + let mut bytes = Vec::with_capacity( + PART_STARK_VK_PUBLISHER_SET_DOMAIN.len() + 1 + 2 + 4 + publisher_public_keys.len() * 33, + ); + bytes.extend_from_slice(PART_STARK_VK_PUBLISHER_SET_DOMAIN); + bytes.push(0x00); + bytes.extend_from_slice(&threshold.to_le_bytes()); + bytes.extend_from_slice(&(publisher_public_keys.len() as u32).to_le_bytes()); + for pubkey in publisher_public_keys { + bytes.extend_from_slice(&pubkey.serialize()); + } + + Sha256::digest(bytes).into() +} + +pub fn part_stark_vk_leaf_hash(part_stark_vk: &[u8]) -> [u8; 32] { + let mut bytes = Vec::with_capacity(1 + 4 + part_stark_vk.len()); + bytes.push(0x00); + bytes.extend_from_slice(&(part_stark_vk.len() as u32).to_le_bytes()); + bytes.extend_from_slice(part_stark_vk); + + Sha256::digest(bytes).into() +} + +pub fn part_stark_vk_internal_hash(left: [u8; 32], right: [u8; 32]) -> [u8; 32] { + let mut bytes = Vec::with_capacity(1 + 32 + 32); + bytes.push(0x01); + bytes.extend_from_slice(&left); + bytes.extend_from_slice(&right); + + Sha256::digest(bytes).into() +} + +pub fn empty_part_stark_vk_leaf_hash() -> [u8; 32] { + part_stark_vk_leaf_hash(&[]) +} + +pub fn part_stark_vk_bundle_id(part_stark_vk: &[u8]) -> String { + hex::encode(part_stark_vk_leaf_hash(part_stark_vk)) +} + +pub fn part_stark_vk_tree_state_path(dir: &Path) -> PathBuf { + dir.join("tree_state.json") +} + +pub fn part_stark_vk_bundle_path(dir: &Path, part_stark_vk: &[u8]) -> PathBuf { + dir.join("bundles").join(format!("{}.json", part_stark_vk_bundle_id(part_stark_vk))) +} + +pub fn latest_part_stark_vk_attestation_manifest_path(dir: &Path) -> PathBuf { + dir.join("manifest.json") +} + +pub fn latest_part_stark_vk_attestation_proofs_dir(dir: &Path) -> PathBuf { + dir.join("proofs") +} + +pub fn latest_part_stark_vk_attestation_proof_path(dir: &Path, version: &str) -> PathBuf { + latest_part_stark_vk_attestation_proofs_dir(dir).join(format!("{version}.json")) +} + +fn build_part_stark_vk_leaf_layer( + part_stark_vks: &[Vec], + tree_height: usize, +) -> Result, String> { + let total_leafs = 1usize << tree_height; + if part_stark_vks.len() > total_leafs { + return Err(format!( + "too many part_stark_vk leafs: {}, max {}", + part_stark_vks.len(), + total_leafs + )); + } + + let mut nodes = vec![empty_part_stark_vk_leaf_hash(); total_leafs]; + for (index, part_stark_vk) in part_stark_vks.iter().enumerate() { + nodes[index] = part_stark_vk_leaf_hash(part_stark_vk); + } + Ok(nodes) +} + +pub fn build_part_stark_vk_merkle_root( + part_stark_vks: &[Vec], + tree_height: usize, +) -> Result<[u8; 32], String> { + let mut level = build_part_stark_vk_leaf_layer(part_stark_vks, tree_height)?; + while level.len() > 1 { + level = level + .chunks_exact(2) + .map(|pair| part_stark_vk_internal_hash(pair[0], pair[1])) + .collect(); + } + Ok(level[0]) +} + +pub fn build_part_stark_vk_merkle_path( + part_stark_vks: &[Vec], + tree_height: usize, + leaf_index: usize, +) -> Result, String> { + let total_leafs = 1usize << tree_height; + if leaf_index >= total_leafs { + return Err(format!("leaf index {} out of range {}", leaf_index, total_leafs)); + } + + let mut level = build_part_stark_vk_leaf_layer(part_stark_vks, tree_height)?; + let mut index = leaf_index; + let mut path = Vec::with_capacity(tree_height); + while level.len() > 1 { + path.push(level[index ^ 1]); + level = level + .chunks_exact(2) + .map(|pair| part_stark_vk_internal_hash(pair[0], pair[1])) + .collect(); + index /= 2; + } + Ok(path) +} + +pub fn verify_part_stark_vk_merkle_path( + part_stark_vk: &[u8], + leaf_index: usize, + merkle_path: &[[u8; 32]], + expected_root: [u8; 32], + tree_height: usize, +) -> Result<(), String> { + if merkle_path.len() != tree_height { + return Err(format!( + "invalid merkle path length: {}, expected {}", + merkle_path.len(), + tree_height + )); + } + + let total_leafs = 1usize << tree_height; + if leaf_index >= total_leafs { + return Err(format!("leaf index {} out of range {}", leaf_index, total_leafs)); + } + + let mut node = part_stark_vk_leaf_hash(part_stark_vk); + let mut index = leaf_index; + for sibling in merkle_path { + node = if index.is_multiple_of(2) { + part_stark_vk_internal_hash(node, *sibling) + } else { + part_stark_vk_internal_hash(*sibling, node) + }; + index /= 2; + } + + if node != expected_root { + return Err("part_stark_vk merkle root mismatch".to_string()); + } + Ok(()) +} + +/// Domain-separate the attestation root by tree height, threshold and publisher set identity. +pub fn build_attestation_message_digest( + tree_height: usize, + root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], +) -> [u8; 32] { + let mut bytes = + Vec::with_capacity(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN.len() + 1 + 1 + 1 + 2 + 32 + 32); + bytes.extend_from_slice(PART_STARK_VK_ROOT_SIGNATURE_DOMAIN); + bytes.push(0x00); + bytes.push(tree_height as u8); + bytes.push(0x00); + bytes.extend_from_slice(&threshold.to_le_bytes()); + bytes.extend_from_slice(&publisher_set_id); + bytes.extend_from_slice(&root); + + Sha256::digest(bytes).into() +} + +fn verify_part_stark_vk_root_signatures( + signatures: &[PartStarkVkRootSignature], + publisher_public_keys: &[PublicKey], + threshold: u16, + tree_height: usize, + root: [u8; 32], + publisher_set_id: [u8; 32], +) -> Result<(), String> { + if publisher_public_keys.is_empty() { + return Err("publisher_public_keys is empty".to_string()); + } + let required = usize::from(threshold); + if required == 0 { + return Err("threshold must be greater than 0".to_string()); + } + if required > publisher_public_keys.len() { + return Err(format!( + "threshold {} exceeds publisher_public_keys length {}", + required, + publisher_public_keys.len() + )); + } + let message = Message::from_digest(build_attestation_message_digest( + tree_height, + root, + threshold, + publisher_set_id, + )); + let secp = Secp256k1::verification_only(); + let mut seen = std::collections::BTreeSet::new(); + let mut valid = 0usize; + + for root_signature in signatures { + if root_signature.signer_pubkey_index >= publisher_public_keys.len() { + return Err(format!( + "signer_pubkey_index {} out of range {}", + root_signature.signer_pubkey_index, + publisher_public_keys.len() + )); + } + if !seen.insert(root_signature.signer_pubkey_index) { + continue; + } + + let signature = Signature::from_compact(&root_signature.signature) + .map_err(|err| format!("invalid signature encoding: {err}"))?; + let mut normalized = signature; + normalized.normalize_s(); + if normalized != signature { + return Err("signature is not low-s normalized".to_string()); + } + + secp.verify_ecdsa( + &message, + &signature, + &publisher_public_keys[root_signature.signer_pubkey_index], + ) + .map_err(|err| format!("invalid publisher root signature: {err}"))?; + valid += 1; + } + + if valid < required { + return Err(format!( + "not enough valid publisher signatures: got {}, required {}", + valid, required + )); + } + Ok(()) +} + +/// Verify that a `part_stark_vk` belongs to the fixed-height history tree and that the root is +/// approved by the current commit-chain publisher set. +pub fn verify_part_stark_vk_attestation( + bundle: &PartStarkVkAttestationBundle, + publisher_public_keys: &[PublicKey], + threshold: u16, + tree_height: usize, +) -> Result<(), String> { + if bundle.threshold != threshold { + return Err(format!( + "attestation threshold mismatch: bundle {}, expected {}", + bundle.threshold, threshold + )); + } + let expected_publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + if bundle.publisher_set_id != expected_publisher_set_id { + return Err("attestation publisher_set_id mismatch".to_string()); + } + verify_part_stark_vk_merkle_path( + &bundle.part_stark_vk, + bundle.leaf_index, + &bundle.merkle_path, + bundle.root, + tree_height, + )?; + verify_part_stark_vk_root_signatures( + &bundle.signatures, + publisher_public_keys, + threshold, + tree_height, + bundle.root, + bundle.publisher_set_id, + )?; + + Ok(()) +} + +/// Verify each unique witness once so later lookups can reuse the verified payload. +pub fn verify_unique_part_stark_vk_witnesses( + unique_witnesses: &[UniquePartStarkVkWitness], + publisher_public_keys: &[PublicKey], + threshold: u16, + tree_height: usize, +) -> Result<(), String> { + for witness in unique_witnesses { + verify_part_stark_vk_attestation(witness, publisher_public_keys, threshold, tree_height)?; + } + Ok(()) +} + +/// Check whether a target `part_stark_vk` is present in the verified witness set. +pub fn assert_part_stark_vk_in_verified_witnesses( + unique_witnesses: &[UniquePartStarkVkWitness], + expected_part_stark_vk: &[u8], +) -> Result<(), String> { + if unique_witnesses.iter().any(|witness| witness.part_stark_vk == expected_part_stark_vk) { + return Ok(()); + } + Err("part_stark_vk not found in verified witnesses".to_string()) +} + +pub fn load_part_stark_vk_tree_state(dir: &Path) -> Result { + let path = part_stark_vk_tree_state_path(dir); + let bytes = std::fs::read(&path) + .map_err(|err| format!("failed to read tree state '{}': {err}", path.display()))?; + serde_json::from_slice(&bytes) + .map_err(|err| format!("failed to decode tree state '{}': {err}", path.display())) +} + +fn remove_path_if_exists(path: &Path) -> Result<(), String> { + if !path.exists() { + return Ok(()); + } + if path.is_dir() { + std::fs::remove_dir_all(path) + .map_err(|err| format!("failed to remove dir '{}': {err}", path.display()))?; + } else { + std::fs::remove_file(path) + .map_err(|err| format!("failed to remove file '{}': {err}", path.display()))?; + } + Ok(()) +} + +/// Build the latest snapshot manifest and per-version merkle proofs from ordered versions. +fn build_latest_part_stark_vk_attestation_snapshot( + ordered_versions: &[String], + part_stark_vks: &[Vec], + threshold: Option, + publisher_set_id: Option<[u8; 32]>, + publisher_public_keys: Option>, + signatures: Vec, +) -> Result<(LatestPartStarkVkAttestationManifest, Vec), String> { + if ordered_versions.is_empty() { + return Err("ordered_versions is empty".to_string()); + } + if ordered_versions.len() != part_stark_vks.len() { + return Err(format!( + "ordered_versions length {} does not match part_stark_vks length {}", + ordered_versions.len(), + part_stark_vks.len() + )); + } + + let root = build_part_stark_vk_merkle_root(part_stark_vks, PART_STARK_VK_TREE_HEIGHT)?; + let mut part_stark_vk_leaf_hashes = BTreeMap::new(); + let mut proofs = Vec::with_capacity(ordered_versions.len()); + for (leaf_index, (version, part_stark_vk)) in + ordered_versions.iter().zip(part_stark_vks).enumerate() + { + let leaf_hash = part_stark_vk_bundle_id(part_stark_vk); + if part_stark_vk_leaf_hashes.insert(version.clone(), leaf_hash).is_some() { + return Err(format!("duplicate ordered version '{version}'")); + } + proofs.push(VersionedPartStarkVkMerkleProof { + version: version.clone(), + part_stark_vk: part_stark_vk.clone(), + leaf_index, + merkle_path: build_part_stark_vk_merkle_path( + part_stark_vks, + PART_STARK_VK_TREE_HEIGHT, + leaf_index, + )?, + }); + } + + Ok(( + LatestPartStarkVkAttestationManifest { + tree_height: PART_STARK_VK_TREE_HEIGHT, + ordered_versions: ordered_versions.to_vec(), + root, + threshold, + publisher_set_id, + publisher_public_keys, + signatures, + part_stark_vk_leaf_hashes, + }, + proofs, + )) +} + +/// Rewrite the attestation directory so it only contains the current snapshot files. +fn write_latest_part_stark_vk_attestation_snapshot( + dir: &Path, + manifest: &LatestPartStarkVkAttestationManifest, + proofs: &[VersionedPartStarkVkMerkleProof], +) -> Result<(), String> { + std::fs::create_dir_all(dir) + .map_err(|err| format!("failed to create attestation dir '{}': {err}", dir.display()))?; + remove_path_if_exists(&latest_part_stark_vk_attestation_proofs_dir(dir))?; + remove_path_if_exists(&dir.join("bundles"))?; + remove_path_if_exists(&part_stark_vk_tree_state_path(dir))?; + remove_path_if_exists(&latest_part_stark_vk_attestation_manifest_path(dir))?; + + let proofs_dir = latest_part_stark_vk_attestation_proofs_dir(dir); + std::fs::create_dir_all(&proofs_dir).map_err(|err| { + format!("failed to create attestation proofs dir '{}': {err}", proofs_dir.display()) + })?; + + for proof in proofs { + let path = latest_part_stark_vk_attestation_proof_path(dir, &proof.version); + let bytes = serde_json::to_vec_pretty(proof) + .map_err(|err| format!("failed to encode proof '{}': {err}", path.display()))?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write proof '{}': {err}", path.display()))?; + } + + let manifest_path = latest_part_stark_vk_attestation_manifest_path(dir); + let manifest_bytes = serde_json::to_vec_pretty(manifest).map_err(|err| { + format!("failed to encode latest attestation manifest '{}': {err}", manifest_path.display()) + })?; + std::fs::write(&manifest_path, manifest_bytes).map_err(|err| { + format!("failed to write latest attestation manifest '{}': {err}", manifest_path.display()) + })?; + Ok(()) +} + +/// Persist a full latest snapshot, optionally including publisher metadata and signatures. +pub fn save_latest_part_stark_vk_attestation_snapshot( + dir: &Path, + ordered_versions: &[String], + part_stark_vks: &[Vec], + threshold: Option, + publisher_set_id: Option<[u8; 32]>, + publisher_public_keys: Option>, + signatures: Vec, +) -> Result<(), String> { + let publisher_public_keys = + publisher_public_keys.map(|keys| keys.into_iter().map(|key| key.to_string()).collect()); + let (manifest, proofs) = build_latest_part_stark_vk_attestation_snapshot( + ordered_versions, + part_stark_vks, + threshold, + publisher_set_id, + publisher_public_keys, + signatures, + )?; + write_latest_part_stark_vk_attestation_snapshot(dir, &manifest, &proofs) +} + +/// Load the latest manifest that describes the current attestation snapshot. +pub fn load_latest_part_stark_vk_attestation_manifest( + dir: &Path, +) -> Result { + let path = latest_part_stark_vk_attestation_manifest_path(dir); + let bytes = std::fs::read(&path).map_err(|err| { + format!("failed to read latest attestation manifest '{}': {err}", path.display()) + })?; + serde_json::from_slice(&bytes).map_err(|err| { + format!("failed to decode latest attestation manifest '{}': {err}", path.display()) + }) +} + +/// Load every version proof referenced by the latest manifest in manifest order. +pub fn load_latest_part_stark_vk_attestation_proofs( + dir: &Path, + ordered_versions: &[String], +) -> Result, String> { + let mut proofs = Vec::with_capacity(ordered_versions.len()); + for version in ordered_versions { + let path = latest_part_stark_vk_attestation_proof_path(dir, version); + let bytes = std::fs::read(&path).map_err(|err| { + format!("failed to read attestation proof '{}': {err}", path.display()) + })?; + let proof: VersionedPartStarkVkMerkleProof = + serde_json::from_slice(&bytes).map_err(|err| { + format!("failed to decode attestation proof '{}': {err}", path.display()) + })?; + proofs.push(proof); + } + Ok(proofs) +} + +/// Merge one signer into the latest snapshot, resetting signatures when the signing context changes. +pub fn sign_latest_part_stark_vk_snapshot( + dir: &Path, + ordered_versions: &[String], + part_stark_vks: &[Vec], + publisher_public_keys: &[PublicKey], + threshold: u16, + signer_pubkey_index: usize, + secret_key: &SecretKey, +) -> Result { + if publisher_public_keys.is_empty() { + return Err("publisher_public_keys is empty".to_string()); + } + let required = usize::from(threshold); + if required == 0 { + return Err("threshold must be greater than 0".to_string()); + } + if required > publisher_public_keys.len() { + return Err(format!( + "threshold {} exceeds publisher_public_keys length {}", + required, + publisher_public_keys.len() + )); + } + if signer_pubkey_index >= publisher_public_keys.len() { + return Err(format!( + "signer_pubkey_index {} out of range {}", + signer_pubkey_index, + publisher_public_keys.len() + )); + } + + let signer_public_key = PublicKey::from_secret_key(&Secp256k1::new(), secret_key); + if publisher_public_keys[signer_pubkey_index] != signer_public_key { + return Err(format!( + "publisher_secret_key does not match publisher public key at index {}", + signer_pubkey_index + )); + } + + let root = build_part_stark_vk_merkle_root(part_stark_vks, PART_STARK_VK_TREE_HEIGHT)?; + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let mut signatures = match load_latest_part_stark_vk_attestation_manifest(dir) { + Ok(existing) + if existing.ordered_versions == ordered_versions + && existing.root == root + && existing.publisher_set_id == Some(publisher_set_id) => + { + existing.signatures + } + _ => Vec::new(), + }; + + let signature = PartStarkVkRootSignature { + signer_pubkey_index, + signature: sign_part_stark_vk_root( + secret_key, + PART_STARK_VK_TREE_HEIGHT, + root, + threshold, + publisher_set_id, + ), + }; + + if let Some(existing_signature) = + signatures.iter_mut().find(|existing| existing.signer_pubkey_index == signer_pubkey_index) + { + *existing_signature = signature; + } else { + signatures.push(signature); + } + signatures.sort_by_key(|existing| existing.signer_pubkey_index); + + save_latest_part_stark_vk_attestation_snapshot( + dir, + ordered_versions, + part_stark_vks, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.to_vec()), + signatures, + )?; + load_latest_part_stark_vk_attestation_manifest(dir) +} + +pub fn save_part_stark_vk_tree_state( + dir: &Path, + state: &PartStarkVkTreeState, +) -> Result<(), String> { + std::fs::create_dir_all(dir) + .map_err(|err| format!("failed to create attestation dir '{}': {err}", dir.display()))?; + let path = part_stark_vk_tree_state_path(dir); + let bytes = serde_json::to_vec_pretty(state) + .map_err(|err| format!("failed to encode tree state '{}': {err}", path.display()))?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write tree state '{}': {err}", path.display())) +} + +pub fn load_part_stark_vk_attestation_bundle( + dir: &Path, + part_stark_vk: &[u8], +) -> Result { + let path = part_stark_vk_bundle_path(dir, part_stark_vk); + let bytes = std::fs::read(&path) + .map_err(|err| format!("failed to read attestation bundle '{}': {err}", path.display()))?; + serde_json::from_slice(&bytes) + .map_err(|err| format!("failed to decode attestation bundle '{}': {err}", path.display())) +} + +pub fn save_part_stark_vk_attestation_bundle( + dir: &Path, + bundle: &PartStarkVkAttestationBundle, +) -> Result<(), String> { + let bundle_dir = dir.join("bundles"); + std::fs::create_dir_all(&bundle_dir).map_err(|err| { + format!("failed to create attestation bundle dir '{}': {err}", bundle_dir.display()) + })?; + let path = part_stark_vk_bundle_path(dir, &bundle.part_stark_vk); + let bytes = serde_json::to_vec_pretty(bundle).map_err(|err| { + format!("failed to encode attestation bundle '{}': {err}", path.display()) + })?; + std::fs::write(&path, bytes) + .map_err(|err| format!("failed to write attestation bundle '{}': {err}", path.display())) +} + +pub fn sign_part_stark_vk_root( + secret_key: &SecretKey, + tree_height: usize, + root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], +) -> Vec { + let secp = Secp256k1::new(); + let message = Message::from_digest(build_attestation_message_digest( + tree_height, + root, + threshold, + publisher_set_id, + )); + let signature = secp.sign_ecdsa(&message, secret_key); + signature.serialize_compact().to_vec() +} + +pub fn build_part_stark_vk_root_signatures( + signer_secret_keys: &[(usize, &SecretKey)], + tree_height: usize, + root: [u8; 32], + threshold: u16, + publisher_set_id: [u8; 32], +) -> Result, String> { + if signer_secret_keys.is_empty() { + return Err("publisher_secret_keys is empty".to_string()); + } + + let mut seen = BTreeSet::new(); + let mut signatures = Vec::with_capacity(signer_secret_keys.len()); + for (signer_pubkey_index, secret_key) in signer_secret_keys { + if !seen.insert(*signer_pubkey_index) { + return Err(format!( + "duplicate signer_pubkey_index {} in publisher_secret_keys", + signer_pubkey_index + )); + } + signatures.push(PartStarkVkRootSignature { + signer_pubkey_index: *signer_pubkey_index, + signature: sign_part_stark_vk_root( + secret_key, + tree_height, + root, + threshold, + publisher_set_id, + ), + }); + } + + Ok(signatures) +} + +pub fn build_part_stark_vk_attestation_bundle( + leaves: &[Vec], + tree_height: usize, + leaf_index: usize, + threshold: u16, + publisher_set_id: [u8; 32], + signatures: Vec, +) -> Result { + let part_stark_vk = leaves + .get(leaf_index) + .ok_or_else(|| format!("leaf index {} out of range {}", leaf_index, leaves.len()))? + .clone(); + Ok(PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index, + merkle_path: build_part_stark_vk_merkle_path(leaves, tree_height, leaf_index)?, + root: build_part_stark_vk_merkle_root(leaves, tree_height)?, + threshold, + publisher_set_id, + signatures, + }) +} + +pub fn append_part_stark_vk_and_sign( + dir: &Path, + part_stark_vk: Vec, + publisher_public_keys: &[PublicKey], + threshold: u16, + publisher_secret_keys: &[SecretKey], +) -> Result { + let indexed_secret_keys = + publisher_secret_keys.iter().enumerate().collect::>(); + append_part_stark_vk_and_sign_with_signers( + dir, + part_stark_vk, + publisher_public_keys, + threshold, + &indexed_secret_keys, + ) +} + +pub fn append_part_stark_vk_and_sign_with_signers( + dir: &Path, + part_stark_vk: Vec, + publisher_public_keys: &[PublicKey], + threshold: u16, + publisher_secret_keys: &[(usize, &SecretKey)], +) -> Result { + let mut state = if part_stark_vk_tree_state_path(dir).exists() { + load_part_stark_vk_tree_state(dir)? + } else { + PartStarkVkTreeState { tree_height: PART_STARK_VK_TREE_HEIGHT, leaves: vec![] } + }; + if state.tree_height != PART_STARK_VK_TREE_HEIGHT { + return Err(format!( + "unsupported tree height {}, expected {}", + state.tree_height, PART_STARK_VK_TREE_HEIGHT + )); + } + if state.leaves.len() >= (1usize << state.tree_height) { + return Err("part_stark_vk history tree is full".to_string()); + } + if state.leaves.iter().any(|leaf| leaf == &part_stark_vk) { + return Err("part_stark_vk already exists in tree".to_string()); + } + state.leaves.push(part_stark_vk.clone()); + let bundle = resign_part_stark_vk_tree( + dir, + &state, + publisher_public_keys, + threshold, + publisher_secret_keys, + state.leaves.len() - 1, + )?; + save_part_stark_vk_tree_state(dir, &state)?; + Ok(bundle) +} + +pub fn resign_current_part_stark_vk_root( + dir: &Path, + publisher_public_keys: &[PublicKey], + threshold: u16, + publisher_secret_keys: &[SecretKey], +) -> Result<(), String> { + let indexed_secret_keys = + publisher_secret_keys.iter().enumerate().collect::>(); + resign_current_part_stark_vk_root_with_signers( + dir, + publisher_public_keys, + threshold, + &indexed_secret_keys, + ) +} + +pub fn resign_current_part_stark_vk_root_with_signers( + dir: &Path, + publisher_public_keys: &[PublicKey], + threshold: u16, + publisher_secret_keys: &[(usize, &SecretKey)], +) -> Result<(), String> { + let state = load_part_stark_vk_tree_state(dir)?; + if state.leaves.is_empty() { + return Err("part_stark_vk tree is empty".to_string()); + } + for leaf_index in 0..state.leaves.len() { + let _ = resign_part_stark_vk_tree( + dir, + &state, + publisher_public_keys, + threshold, + publisher_secret_keys, + leaf_index, + )?; + } + Ok(()) +} + +fn resign_part_stark_vk_tree( + dir: &Path, + state: &PartStarkVkTreeState, + publisher_public_keys: &[PublicKey], + threshold: u16, + publisher_secret_keys: &[(usize, &SecretKey)], + leaf_index: usize, +) -> Result { + let root = build_part_stark_vk_merkle_root(&state.leaves, state.tree_height)?; + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + publisher_secret_keys, + state.tree_height, + root, + threshold, + publisher_set_id, + )?; + let bundle = build_part_stark_vk_attestation_bundle( + &state.leaves, + state.tree_height, + leaf_index, + threshold, + publisher_set_id, + signatures, + )?; + save_part_stark_vk_attestation_bundle(dir, &bundle)?; + Ok(bundle) +} + +pub fn load_unique_part_stark_vk_witnesses( + dir: &Path, + part_stark_vks: &[Vec], +) -> Result<(Vec, Vec), String> { + if !latest_part_stark_vk_attestation_manifest_path(dir).exists() { + return Err(format!( + "missing latest attestation manifest '{}'", + latest_part_stark_vk_attestation_manifest_path(dir).display() + )); + } + + load_unique_part_stark_vk_witnesses_from_latest_snapshot(dir, part_stark_vks) +} + +fn load_unique_part_stark_vk_witnesses_from_latest_snapshot( + dir: &Path, + part_stark_vks: &[Vec], +) -> Result<(Vec, Vec), String> { + let manifest = load_latest_part_stark_vk_attestation_manifest(dir)?; + let threshold = manifest + .threshold + .ok_or_else(|| "latest attestation manifest is missing threshold".to_string())?; + let publisher_set_id = manifest + .publisher_set_id + .ok_or_else(|| "latest attestation manifest is missing publisher_set_id".to_string())?; + let proofs = load_latest_part_stark_vk_attestation_proofs(dir, &manifest.ordered_versions)?; + let mut available_witnesses = BTreeMap::, UniquePartStarkVkWitness>::new(); + + for proof in proofs { + let expected_leaf_hash = + manifest.part_stark_vk_leaf_hashes.get(&proof.version).ok_or_else(|| { + format!("missing part_stark_vk leaf hash for version '{}'", proof.version) + })?; + let actual_leaf_hash = part_stark_vk_bundle_id(&proof.part_stark_vk); + if *expected_leaf_hash != actual_leaf_hash { + return Err(format!( + "part_stark_vk leaf hash mismatch for version '{}': expected {}, got {}", + proof.version, expected_leaf_hash, actual_leaf_hash + )); + } + + verify_part_stark_vk_merkle_path( + &proof.part_stark_vk, + proof.leaf_index, + &proof.merkle_path, + manifest.root, + manifest.tree_height, + )?; + available_witnesses.entry(proof.part_stark_vk.clone()).or_insert_with(|| { + PartStarkVkAttestationBundle { + part_stark_vk: proof.part_stark_vk, + leaf_index: proof.leaf_index, + merkle_path: proof.merkle_path, + root: manifest.root, + threshold, + publisher_set_id, + signatures: manifest.signatures.clone(), + } + }); + } + + let mut unique_witnesses = Vec::new(); + let mut witness_indexes = Vec::with_capacity(part_stark_vks.len()); + let mut seen = BTreeMap::, usize>::new(); + + for part_stark_vk in part_stark_vks { + if let Some(index) = seen.get(part_stark_vk) { + witness_indexes.push(*index); + continue; + } + let bundle = available_witnesses + .get(part_stark_vk) + .cloned() + .ok_or_else(|| "part_stark_vk not found in latest snapshot".to_string())?; + let index = unique_witnesses.len(); + unique_witnesses.push(bundle); + seen.insert(part_stark_vk.clone(), index); + witness_indexes.push(index); + } + + Ok((unique_witnesses, witness_indexes)) +} + +#[cfg(test)] +mod tests { + use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature}; + use std::time::{SystemTime, UNIX_EPOCH}; + + use super::{ + PART_STARK_VK_TREE_HEIGHT, PartStarkVkAttestationBundle, PartStarkVkRootSignature, + assert_part_stark_vk_in_verified_witnesses, build_attestation_message_digest, + build_part_stark_vk_merkle_path, build_part_stark_vk_merkle_root, + build_part_stark_vk_root_signatures, compute_publisher_set_id, + load_latest_part_stark_vk_attestation_manifest, load_unique_part_stark_vk_witnesses, + part_stark_vk_leaf_hash, save_latest_part_stark_vk_attestation_snapshot, + save_part_stark_vk_attestation_bundle, sign_latest_part_stark_vk_snapshot, + verify_part_stark_vk_attestation, verify_unique_part_stark_vk_witnesses, + }; + + fn sample_part_stark_vk() -> Vec { + hex::decode("2000000000000000d157a916a6350249c6e4efd850dcdac3abf5489d36de2d1aa233c9253522871000000000") + .unwrap() + } + + fn sample_part_stark_vk_alt() -> Vec { + b"alternate-part-stark-vk".to_vec() + } + + fn sample_publishers() -> (Vec, Vec) { + let secp = Secp256k1::new(); + let secret_keys = vec![ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + (secret_keys, publisher_public_keys) + } + + fn sample_attestation_bundle( + leaves: &[Vec], + leaf_index: usize, + threshold: u16, + publisher_public_keys: &[bitcoin::secp256k1::PublicKey], + signer_secret_keys: &[SecretKey], + ) -> PartStarkVkAttestationBundle { + let root = build_part_stark_vk_merkle_root(leaves, 6).unwrap(); + let publisher_set_id = compute_publisher_set_id(publisher_public_keys, threshold); + let indexed_secret_keys = + signer_secret_keys.iter().enumerate().collect::>(); + let signatures = build_part_stark_vk_root_signatures( + &indexed_secret_keys[..usize::from(threshold)], + 6, + root, + threshold, + publisher_set_id, + ) + .unwrap(); + + PartStarkVkAttestationBundle { + part_stark_vk: leaves[leaf_index].clone(), + leaf_index, + merkle_path: build_part_stark_vk_merkle_path(leaves, 6, leaf_index).unwrap(), + root, + threshold, + publisher_set_id, + signatures, + } + } + + fn unique_test_dir(prefix: &str) -> std::path::PathBuf { + let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); + std::env::temp_dir().join(format!("bitvm2-{prefix}-{nanos}")) + } + + #[test] + fn test_part_stark_vk_leaf_hash_matches_spec() { + assert_eq!( + hex::encode(part_stark_vk_leaf_hash(&[])), + "8855508aade16ec573d21e6a485dfd0a7624085c1a14b5ecdd6485de0c6839a4" + ); + } + + #[test] + fn test_build_part_stark_vk_merkle_root_matches_spec() { + let leaves = vec![sample_part_stark_vk(), b"hello".to_vec()]; + + assert_eq!( + hex::encode(build_part_stark_vk_merkle_root(&leaves, 6).unwrap()), + "8a091f11cab951f0c1228a891c902475b84709e568885a45658840e1b88599d4" + ); + } + + #[test] + fn test_build_attestation_message_digest_matches_spec() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + let root = hex::decode("8a091f11cab951f0c1228a891c902475b84709e568885a45658840e1b88599d4") + .unwrap() + .try_into() + .unwrap(); + let threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let mut reversed_public_keys = publisher_public_keys.clone(); + reversed_public_keys.reverse(); + + assert_ne!( + build_attestation_message_digest(6, root, threshold, publisher_set_id), + build_attestation_message_digest(6, root, threshold - 1, publisher_set_id) + ); + assert_ne!(publisher_set_id, compute_publisher_set_id(&reversed_public_keys, threshold)); + } + + #[test] + fn test_verify_part_stark_vk_attestation_accepts_quorum_and_ignores_duplicate_signers() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let part_stark_vk = sample_part_stark_vk(); + let leaves = vec![part_stark_vk.clone()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let digest = build_attestation_message_digest(6, root, threshold, publisher_set_id); + let message = Message::from_digest(digest); + + let sig0 = secp.sign_ecdsa(&message, &secret_keys[0]); + let sig1 = secp.sign_ecdsa(&message, &secret_keys[1]); + let sig2 = secp.sign_ecdsa(&message, &secret_keys[2]); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + threshold, + publisher_set_id, + signatures: vec![ + PartStarkVkRootSignature { + signer_pubkey_index: 0, + signature: sig0.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 1, + signature: sig1.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 1, + signature: sig1.serialize_compact().to_vec(), + }, + PartStarkVkRootSignature { + signer_pubkey_index: 2, + signature: sig2.serialize_compact().to_vec(), + }, + ], + }; + + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6).is_ok() + ); + } + + #[test] + fn test_verify_part_stark_vk_attestation_rejects_non_member_signer() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let outsider = SecretKey::from_slice(&[9u8; 32]).unwrap(); + let part_stark_vk = sample_part_stark_vk(); + let leaves = vec![part_stark_vk.clone()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let threshold = 2u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let digest = build_attestation_message_digest(6, root, threshold, publisher_set_id); + let message = Message::from_digest(digest); + let outsider_sig: Signature = secp.sign_ecdsa(&message, &outsider); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + threshold, + publisher_set_id, + signatures: vec![PartStarkVkRootSignature { + signer_pubkey_index: 0, + signature: outsider_sig.serialize_compact().to_vec(), + }], + }; + + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6) + .is_err() + ); + } + + #[test] + fn test_build_part_stark_vk_root_signatures_supports_sparse_signer_indexes() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + SecretKey::from_slice(&[5u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + + let leaves = vec![sample_part_stark_vk()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let threshold = 4u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + &[ + (0, &secret_keys[0]), + (2, &secret_keys[2]), + (3, &secret_keys[3]), + (4, &secret_keys[4]), + ], + 6, + root, + threshold, + publisher_set_id, + ) + .unwrap(); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk: leaves[0].clone(), + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + threshold, + publisher_set_id, + signatures, + }; + + assert!( + verify_part_stark_vk_attestation(&bundle, &publisher_public_keys, threshold, 6).is_ok() + ); + } + + #[test] + fn test_verify_part_stark_vk_attestation_rejects_threshold_mismatch() { + let secp = Secp256k1::new(); + let secret_keys = [ + SecretKey::from_slice(&[1u8; 32]).unwrap(), + SecretKey::from_slice(&[2u8; 32]).unwrap(), + SecretKey::from_slice(&[3u8; 32]).unwrap(), + SecretKey::from_slice(&[4u8; 32]).unwrap(), + ]; + let publisher_public_keys = secret_keys + .iter() + .map(|sk| bitcoin::secp256k1::PublicKey::from_secret_key(&secp, sk)) + .collect::>(); + let leaves = vec![sample_part_stark_vk()]; + let root = build_part_stark_vk_merkle_root(&leaves, 6).unwrap(); + let signed_threshold = 3u16; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, signed_threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + 6, + root, + signed_threshold, + publisher_set_id, + ) + .unwrap(); + + let bundle = PartStarkVkAttestationBundle { + part_stark_vk: leaves[0].clone(), + leaf_index: 0, + merkle_path: build_part_stark_vk_merkle_path(&leaves, 6, 0).unwrap(), + root, + threshold: signed_threshold, + publisher_set_id, + signatures, + }; + + assert!( + verify_part_stark_vk_attestation( + &bundle, + &publisher_public_keys, + signed_threshold - 1, + 6 + ) + .is_err() + ); + } + + #[test] + fn test_verify_unique_part_stark_vk_witnesses_accepts_multiple_bundles() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let unique_witnesses = vec![ + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), + ]; + + assert!( + verify_unique_part_stark_vk_witnesses(&unique_witnesses, &publisher_public_keys, 3, 6) + .is_ok() + ); + } + + #[test] + fn test_assert_part_stark_vk_in_verified_witnesses_checks_membership() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let unique_witnesses = vec![ + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys), + sample_attestation_bundle(&leaves, 1, 3, &publisher_public_keys, &secret_keys), + ]; + + verify_unique_part_stark_vk_witnesses(&unique_witnesses, &publisher_public_keys, 3, 6) + .unwrap(); + assert!(assert_part_stark_vk_in_verified_witnesses(&unique_witnesses, &leaves[1]).is_ok()); + assert!( + assert_part_stark_vk_in_verified_witnesses(&unique_witnesses, b"missing-part-stark-vk") + .is_err() + ); + } + + #[test] + fn test_load_unique_part_stark_vk_witnesses_reuses_duplicate_indexes_from_latest_snapshot() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let dir = unique_test_dir("attestation-duplicate-indexes"); + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let threshold = 3; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + PART_STARK_VK_TREE_HEIGHT, + build_part_stark_vk_merkle_root(&leaves, PART_STARK_VK_TREE_HEIGHT).unwrap(), + threshold, + publisher_set_id, + ) + .unwrap(); + + save_latest_part_stark_vk_attestation_snapshot( + &dir, + &ordered_versions, + &leaves, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.clone()), + signatures, + ) + .unwrap(); + + let requested = vec![leaves[0].clone(), leaves[1].clone(), leaves[0].clone()]; + let (unique_witnesses, witness_indexes) = + load_unique_part_stark_vk_witnesses(&dir, &requested).unwrap(); + + assert_eq!(unique_witnesses.len(), 2); + assert_eq!(witness_indexes, vec![0, 1, 0]); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_load_unique_part_stark_vk_witnesses_requires_latest_manifest() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let dir = unique_test_dir("attestation-requires-latest-manifest"); + std::fs::create_dir_all(dir.join("bundles")).unwrap(); + + let first_bundle = + sample_attestation_bundle(&leaves, 0, 3, &publisher_public_keys, &secret_keys); + save_part_stark_vk_attestation_bundle(&dir, &first_bundle).unwrap(); + + let err = load_unique_part_stark_vk_witnesses(&dir, &[leaves[0].clone()]).unwrap_err(); + assert!(err.contains("missing latest attestation manifest")); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_save_and_load_latest_snapshot_reuses_duplicate_indexes() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-snapshot"); + let threshold = 3; + let publisher_set_id = compute_publisher_set_id(&publisher_public_keys, threshold); + let signatures = build_part_stark_vk_root_signatures( + &[(0, &secret_keys[0]), (1, &secret_keys[1]), (2, &secret_keys[2])], + PART_STARK_VK_TREE_HEIGHT, + build_part_stark_vk_merkle_root(&leaves, PART_STARK_VK_TREE_HEIGHT).unwrap(), + threshold, + publisher_set_id, + ) + .unwrap(); + + save_latest_part_stark_vk_attestation_snapshot( + &dir, + &ordered_versions, + &leaves, + Some(threshold), + Some(publisher_set_id), + Some(publisher_public_keys.clone()), + signatures, + ) + .unwrap(); + + let requested = vec![leaves[0].clone(), leaves[1].clone(), leaves[0].clone()]; + let (unique_witnesses, witness_indexes) = + load_unique_part_stark_vk_witnesses(&dir, &requested).unwrap(); + + assert_eq!(unique_witnesses.len(), 2); + assert_eq!(witness_indexes, vec![0, 1, 0]); + assert_eq!(unique_witnesses[0].part_stark_vk, leaves[0]); + assert_eq!(unique_witnesses[1].part_stark_vk, leaves[1]); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_sign_latest_snapshot_preserves_existing_signatures_for_same_identity() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-signatures"); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 0, + &secret_keys[0], + ) + .unwrap(); + let first_manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(first_manifest.signatures.len(), 1); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 2, + &secret_keys[2], + ) + .unwrap(); + let second_manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(second_manifest.signatures.len(), 2); + + std::fs::remove_dir_all(dir).unwrap(); + } + + #[test] + fn test_sign_latest_snapshot_clears_stale_signatures_when_publisher_set_changes() { + let (secret_keys, publisher_public_keys) = sample_publishers(); + let leaves = vec![sample_part_stark_vk(), sample_part_stark_vk_alt()]; + let ordered_versions = vec!["v1.2.4".to_string(), "v1.2.5".to_string()]; + let dir = unique_test_dir("latest-attestation-publisher-reset"); + + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 0, + &secret_keys[0], + ) + .unwrap(); + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &publisher_public_keys, + 3, + 1, + &secret_keys[1], + ) + .unwrap(); + + let reordered_publisher_public_keys = vec![ + publisher_public_keys[1], + publisher_public_keys[0], + publisher_public_keys[2], + publisher_public_keys[3], + ]; + sign_latest_part_stark_vk_snapshot( + &dir, + &ordered_versions, + &leaves, + &reordered_publisher_public_keys, + 3, + 0, + &secret_keys[1], + ) + .unwrap(); + + let manifest = load_latest_part_stark_vk_attestation_manifest(&dir).unwrap(); + assert_eq!(manifest.signatures.len(), 1); + assert_eq!(manifest.signatures[0].signer_pubkey_index, 0); + + std::fs::remove_dir_all(dir).unwrap(); + } +} diff --git a/crates/bitcoin-light-client-circuit/src/lib.rs b/crates/bitcoin-light-client-circuit/src/lib.rs index 59b5f78a..bd3560d3 100644 --- a/crates/bitcoin-light-client-circuit/src/lib.rs +++ b/crates/bitcoin-light-client-circuit/src/lib.rs @@ -1,6 +1,8 @@ +mod attestation; mod signature; mod utils; use alloy_primitives::U32; +pub use attestation::*; pub use signature::*; use state_chain::verify_sequencer_commit; pub use utils::*; @@ -11,53 +13,65 @@ use bitcoin::Transaction; use bitcoin::hashes::{Hash, HashEngine, sha256}; use commit_chain::sequencer_hash; use commit_chain::{ - CommitChainCircuitInput, CommitChainPrevProofType, extract_data_from_commitment_outputs, + CommitChainCircuitInput, CommitChainCircuitOutput, extract_data_from_commitment_outputs, }; use header_chain::{ BitcoinMerkleTree, CircuitBlockHeader, CircuitTransaction, HeaderChainCircuitInput, HeaderChainPrevProofType, MMRHost, SPV, verify_merkle_proof, }; use state_chain::{StateChainCircuitInput, StateChainPrevProofType}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use zkm_primitives::io::ZKMPublicValues; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; use bitcoin::{ScriptBuf, TxOut, Txid, secp256k1::PublicKey}; pub use guest_executor::io::EthClientExecutorInput; +use serde::{Deserialize, Serialize}; pub const GRAPH_ID_SIZE: usize = 16; pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; +pub const WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE: usize = 4; +pub const WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE: usize = 4; pub const VK_HASH_SIZE: usize = 66; -pub const COMMITMENT_SIZE: usize = GRAPH_ID_SIZE + PROOF_SIZE + PUBLIC_INPUTS_SIZE + VK_HASH_SIZE; pub const TOTAL_WORK_SIZE: usize = 32; pub const CONSENSUS_BLOCK_HEIGHT_SIZE: usize = 4; +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct WatchtowerPublicOutputs { + pub total_work: [u8; TOTAL_WORK_SIZE], + pub consensus_block_height: [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct OperatorPublicOutputs { + pub btc_best_block_hash: [u8; 32], + pub constant: [u8; 32], + pub included_watchtowers: [u8; 32], +} + pub fn watch_longest_chain( genesis_sequencer_commit_txid: [u8; 32], latest_sequencer_commit_txid: [u8; 32], header_chain: HeaderChainCircuitInput, commit_chain: CommitChainCircuitInput, state_chain: StateChainCircuitInput, + attestation: WatchtowerAttestationInputs, spv: SPV, -) -> ([u8; 32], u32) { +) -> WatchtowerPublicOutputs { println!("commit header, size: {}", commit_chain.commits.len()); - // verify latest_sequencer_commit is valid: - // * Check both latest_sequencer_commit_txid and genesis_sequencer_commit_txid are in all_sequencer_commit_txids (which is a private input) - // * Check latest_sequencer_commit_txid is derived from genesis_sequencer_commit_txid - // verify the commit chain proof - verify_proof( - &commit_chain.zkm_proof, - &commit_chain.zkm_public_values, - &commit_chain.zkm_vk_hash, + let commit_chain_output = + verify_commit_chain_output(&commit_chain).expect("Failed to verify commit chain proof"); + let (publisher_public_keys, threshold) = + commit_chain_attestation_authority(&commit_chain_output); + verify_unique_part_stark_vk_witnesses( + &attestation.unique_witnesses, + publisher_public_keys, + threshold, + PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify commit chain proof"); - - let prev_output = ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); - let prev_proof = CommitChainPrevProofType::PrevProof(prev_output); - let CommitChainPrevProofType::PrevProof(commit_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in watch_longest_chain"); - }; + .expect("Failed to verify unique part_stark_vk attestations"); assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), @@ -67,10 +81,16 @@ pub fn watch_longest_chain( println!("header chain: applying: {}", header_chain.block_headers.len()); // verify header_chain is valid - verify_proof( + let header_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &header_chain.zkm_version, + ) + .expect("Failed to resolve attested header-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &header_chain.zkm_proof, &header_chain.zkm_public_values, &header_chain.zkm_vk_hash, + &header_part_stark_vk, ) .expect("Failed to verify header chain proof"); @@ -83,13 +103,34 @@ pub fn watch_longest_chain( println!("SPV"); assert!(spv.verify(&btc_header_chain_output.chain_state.block_hashes_mmr)); - verify_proof(&state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash) - .expect("Failed to verify state chain proof"); + let state_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &state_chain.zkm_version, + ) + .expect("Failed to resolve attested state-chain part_stark_vk"); + verify_proof_with_part_stark_vk( + &state_chain.zkm_proof, + &state_chain.zkm_public_values, + &state_chain.zkm_vk_hash, + &state_part_stark_vk, + ) + .expect("Failed to verify state chain proof"); let prev_output = ZKMPublicValues::from(&state_chain.zkm_public_values).read(); let prev_proof = StateChainPrevProofType::PrevProof(prev_output); let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in watch_longest_chain"); }; + assert_part_stark_vk_in_verified_witnesses( + &attestation.unique_witnesses, + &btc_header_chain_output.part_stark_vk, + ) + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); + assert_part_stark_vk_in_verified_witnesses( + &attestation.unique_witnesses, + &state_chain_output.part_stark_vk, + ) + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); + // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -113,7 +154,10 @@ pub fn watch_longest_chain( println!("commit public inputs"); // commit public inputs - (btc_header_chain_output.chain_state.total_work, commit_chain_output.chain_state.block_height) + WatchtowerPublicOutputs { + total_work: btc_header_chain_output.chain_state.total_work, + consensus_block_height: commit_chain_output.chain_state.block_height.to_le_bytes(), + } } pub fn u256_to_le_bits(u: U256) -> [bool; 256] { @@ -149,22 +193,24 @@ pub fn propose_longest_chain( operator_header_chain: HeaderChainCircuitInput, commit_chain: CommitChainCircuitInput, state_chain: StateChainCircuitInput, + attestation: OperatorAttestationInputs, spv_ss_commit: SPV, operator_committed_blockhash: [u8; 32], -) -> ([u8; 32], [u8; 32], [u8; 32]) { +) -> OperatorPublicOutputs { // verify operator_latest_sequencer_commit_txid is valid, and on operator head chain // * Check operator_latest_sequencer_commit_txid is derived from genesis_sequencer_commit_txid - verify_proof( - &commit_chain.zkm_proof, - &commit_chain.zkm_public_values, - &commit_chain.zkm_vk_hash, + let commit_chain_output = + verify_commit_chain_output(&commit_chain).expect("Failed to verify commit chain proof"); + let (publisher_public_keys, threshold) = + commit_chain_attestation_authority(&commit_chain_output); + verify_unique_part_stark_vk_witnesses( + &attestation.unique_witnesses, + publisher_public_keys, + threshold, + PART_STARK_VK_TREE_HEIGHT, ) - .expect("Failed to verify commit chain proof"); - let prev_output = ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); - let prev_proof = CommitChainPrevProofType::PrevProof(prev_output); - let CommitChainPrevProofType::PrevProof(commit_chain_output) = &prev_proof else { - panic!("Only PrevProof is supported in propose_longest_chain"); - }; + .expect("Failed to verify unique part_stark_vk attestations"); + assert_eq!( commit_chain_output.chain_state.commit_txn.compute_txid(), spv_ss_commit.transaction.0.compute_txid() @@ -176,10 +222,16 @@ pub fn propose_longest_chain( // https://github.com/KSlashh/BitVM/blob/v2/goat/src/transactions/watchtower_challenge.rs#L128 // verify operator_header_chain is valid - verify_proof( + let header_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &operator_header_chain.zkm_version, + ) + .expect("Failed to resolve attested header-chain part_stark_vk"); + verify_proof_with_part_stark_vk( &operator_header_chain.zkm_proof, &operator_header_chain.zkm_public_values, &operator_header_chain.zkm_vk_hash, + &header_part_stark_vk, ) .expect("Failed to verify header chain proof"); let prev_output = ZKMPublicValues::from(&operator_header_chain.zkm_public_values).read(); @@ -187,6 +239,11 @@ pub fn propose_longest_chain( let HeaderChainPrevProofType::PrevProof(btc_header_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; + assert_part_stark_vk_in_verified_witnesses( + &attestation.unique_witnesses, + &btc_header_chain_output.part_stark_vk, + ) + .expect("Failed to match header-chain part_stark_vk in verified witnesses"); let operator_total_work = btc_header_chain_output.chain_state.total_work; let operator_consensus_block_height = U32::from(commit_chain_output.chain_state.block_height); // commit header chain best block hash as pis @@ -205,97 +262,61 @@ pub fn propose_longest_chain( for i in 0..watchtower_challenge_txns.len() { if included_watchertowers_bits[i] { let tx = &watchtower_challenge_txns[i]; - println!("Verify watchtower[{i}] tx: {}, {:?}", tx.compute_txid(), tx); let prev_out = &watchtower_challenge_txn_prev_outs[i]; - let prev_index = tx.input[0].previous_output.vout as usize; let pubkey = &watchtower_challenge_txn_pubkey[i]; - - let sig = bitcoin::taproot::Signature::from_slice(&tx.input[0].witness[0]).unwrap(); - // check tx signature is valid - match verify_taproot_leaf_schnorr_signature( - &watchtower_challenge_txn_scripts[i], + let watchtower_outputs = verify_included_watchtower_challenge( + i, + &graph_id, tx, - prev_index, prev_out, + &watchtower_challenge_txn_scripts[i], pubkey, - &sig, - ) { - Ok(_) => {} - Err(msg) => { - println!("Watchtower[{i}] signature verification: {msg}"); - continue; - } - }; - - let commitment = &extract_data_from_commitment_outputs(&tx.output)[..]; - println!("commitment: {commitment:?}"); - println!("commitment hex: {}", hex::encode(commitment)); - let ( - parsed_graph_id, - proof, - public_values, - vk, - watchtower_total_work, - watchtower_consensus_block_height, - ) = match parse_watchtower_commitment(commitment) { - Ok(c) => c, - Err(err) => { - println!("Watchtower[{i}] parse commitment error, {err}"); - continue; - } - }; - - match verify_proof(&proof, &public_values, &vk) { - Ok(_) => {} - Err(err) => { - println!("Watchtower[{i}] invalid proof: {err}"); - continue; - } - } - - if parsed_graph_id != graph_id { - println!( - "Watchtower[{i}] invalid commitment: graph id: parsed = {}, expected = {}", - hex::encode(parsed_graph_id), - hex::encode(graph_id) - ); - continue; - } - println!("check total work with watchtower {i}"); + &attestation.unique_witnesses, + operator_total_work, + operator_consensus_block_height, + ) + .unwrap_or_else(|err| panic!("Watchtower[{i}] invalid included challenge: {err}")); - // extract ChainState - // check watchtower_chain_state.total_work <= operator_header_chain.total_work - println!("watchtower total work: {:?}", U256::from_be_bytes(watchtower_total_work)); + println!( + "watchtower total work: {:?}", + U256::from_be_bytes(watchtower_outputs.total_work) + ); println!("operator total work: {operator_total_work:?}"); - println!( "watchtower_consensus_block_height : {:?}", - U32::from_le_bytes(watchtower_consensus_block_height) + U32::from_le_bytes(watchtower_outputs.consensus_block_height) ); println!("operator_consensus_block_height : {operator_consensus_block_height:?}"); - - assert!( - U256::from_be_bytes(watchtower_total_work) - <= U256::from_be_bytes(operator_total_work) - ); - // check watchtower.consensus.block_height <= consensus.block_height - assert!( - U32::from_le_bytes(watchtower_consensus_block_height) - <= operator_consensus_block_height - ); } } println!("verify el block"); - verify_proof(&state_chain.zkm_proof, &state_chain.zkm_public_values, &state_chain.zkm_vk_hash) - .expect("Failed to verify state chain proof"); + let state_part_stark_vk = attested_part_stark_vk_for_zkm_version( + &attestation.unique_witnesses, + &state_chain.zkm_version, + ) + .expect("Failed to resolve attested state-chain part_stark_vk"); + verify_proof_with_part_stark_vk( + &state_chain.zkm_proof, + &state_chain.zkm_public_values, + &state_chain.zkm_vk_hash, + &state_part_stark_vk, + ) + .expect("Failed to verify state chain proof"); let prev_output = ZKMPublicValues::from(&state_chain.zkm_public_values).read(); let prev_proof = StateChainPrevProofType::PrevProof(prev_output); let StateChainPrevProofType::PrevProof(state_chain_output) = &prev_proof else { panic!("Only PrevProof is supported in propose_longest_chain"); }; + + assert_part_stark_vk_in_verified_witnesses( + &attestation.unique_witnesses, + &state_chain_output.part_stark_vk, + ) + .expect("Failed to match state-chain part_stark_vk in verified witnesses"); + // check the signature. let cosmos_block_bytes = &state_chain_output.chain_state.latest_cosmos_block; let cosmos_block: LightBlock = @@ -343,13 +364,17 @@ pub fn propose_longest_chain( // .iter() // .position(|header| header.compute_block_hash() == operator_committed_blockhash); //assert!(included.is_some(), "operator committed blockhash is not included in header chain"); - assert!( - operator_committed_blockhash == btc_best_block_hash, + assert_eq!( + operator_committed_blockhash, btc_best_block_hash, "operator committed blockhash is not included in header chain" ); //operator_public_input - (operator_committed_blockhash, constant, included_watchtowers.to_le_bytes::<32>()) + OperatorPublicOutputs { + btc_best_block_hash: operator_committed_blockhash, + constant, + included_watchtowers: included_watchtowers.to_le_bytes::<32>(), + } } pub fn hash_operator_constant( @@ -427,87 +452,258 @@ pub fn build_spv( pub fn build_watchtower_commitment( graph_id: &[u8; GRAPH_ID_SIZE], - proof: &[u8; PROOF_SIZE], - public_inputs: &[u8; PUBLIC_INPUTS_SIZE], + proof: &[u8], + public_inputs: &[u8], vk_hash: &str, -) -> Vec { - let mut comm = graph_id.to_vec(); + proof_part_stark_vk: &[u8], +) -> Result, String> { + if proof.len() != PROOF_SIZE { + return Err(format!("invalid proof length: {}, expected {}", proof.len(), PROOF_SIZE)); + } + if proof_part_stark_vk.is_empty() { + return Err("proof_part_stark_vk must not be empty".to_string()); + } + let mut comm = Vec::with_capacity( + GRAPH_ID_SIZE + + PROOF_SIZE + + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE + + public_inputs.len() + + VK_HASH_SIZE + + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE + + proof_part_stark_vk.len(), + ); + comm.extend_from_slice(graph_id); comm.extend_from_slice(proof); + comm.extend_from_slice(&(public_inputs.len() as u32).to_le_bytes()); comm.extend_from_slice(public_inputs); - assert_eq!(vk_hash.len(), VK_HASH_SIZE); + if vk_hash.len() != VK_HASH_SIZE { + return Err(format!( + "invalid vk_hash length: {}, expected {}", + vk_hash.len(), + VK_HASH_SIZE + )); + } comm.extend_from_slice(vk_hash.as_bytes()); - comm + comm.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + comm.extend_from_slice(proof_part_stark_vk); + Ok(comm) } -pub type WatchtowerCommitmentResult = ( - [u8; GRAPH_ID_SIZE], - [u8; PROOF_SIZE], - [u8; PUBLIC_INPUTS_SIZE], - [u8; VK_HASH_SIZE], - [u8; TOTAL_WORK_SIZE], - [u8; CONSENSUS_BLOCK_HEIGHT_SIZE], -); +pub type WatchtowerCommitmentResult = + ([u8; GRAPH_ID_SIZE], Vec, Vec, [u8; VK_HASH_SIZE], Vec); pub fn parse_watchtower_commitment( commitment: &[u8], ) -> Result { - if commitment.len() != COMMITMENT_SIZE { + let min_commitment_size = GRAPH_ID_SIZE + + PROOF_SIZE + + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE + + VK_HASH_SIZE + + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE; + if commitment.len() < min_commitment_size { return Err(format!( - "invalid commitment size: {}, expected: {}", + "invalid commitment size: {}, expected at least {}", commitment.len(), - COMMITMENT_SIZE + min_commitment_size )); } let mut end = GRAPH_ID_SIZE; let mut graph_id = [0u8; GRAPH_ID_SIZE]; - graph_id.copy_from_slice(&commitment[0..GRAPH_ID_SIZE]); + graph_id.copy_from_slice(&commitment[..end]); - let mut proof = [0u8; PROOF_SIZE]; - proof.copy_from_slice(&commitment[end..end + PROOF_SIZE]); + let proof = commitment[end..end + PROOF_SIZE].to_vec(); end += PROOF_SIZE; - let mut zkm_public_values = [0u8; PUBLIC_INPUTS_SIZE]; - zkm_public_values.copy_from_slice(&commitment[end..end + PUBLIC_INPUTS_SIZE]); - end += PUBLIC_INPUTS_SIZE; + let public_inputs_len = u32::from_le_bytes( + commitment[end..end + WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE].try_into().unwrap(), + ) as usize; + end += WATCHTOWER_COMMITMENT_PUBLIC_INPUTS_LEN_SIZE; + + let proof_part_stark_vk_len_offset = end + public_inputs_len + VK_HASH_SIZE; + if commitment.len() + < proof_part_stark_vk_len_offset + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE + { + return Err(format!( + "invalid commitment size: {}, missing proof_part_stark_vk length field", + commitment.len() + )); + } + let proof_part_stark_vk_len = u32::from_le_bytes( + commitment[proof_part_stark_vk_len_offset + ..proof_part_stark_vk_len_offset + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE] + .try_into() + .unwrap(), + ) as usize; + let expected_size = min_commitment_size + public_inputs_len + proof_part_stark_vk_len; + if commitment.len() != expected_size { + return Err(format!( + "invalid commitment size: {}, expected {}", + commitment.len(), + expected_size + )); + } + + let zkm_public_values = commitment[end..end + public_inputs_len].to_vec(); + end += public_inputs_len; let mut zkm_vk_hash_bytes = [0u8; VK_HASH_SIZE]; zkm_vk_hash_bytes.copy_from_slice(&commitment[end..end + VK_HASH_SIZE]); + end += VK_HASH_SIZE; + + let proof_part_stark_vk_len = u32::from_le_bytes( + commitment[end..end + WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE] + .try_into() + .unwrap(), + ) as usize; + if proof_part_stark_vk_len == 0 { + return Err("proof_part_stark_vk must not be empty".to_string()); + } + end += WATCHTOWER_COMMITMENT_PROOF_PART_STARK_VK_LEN_SIZE; + let proof_part_stark_vk = commitment[end..end + proof_part_stark_vk_len].to_vec(); + Ok((graph_id, proof, zkm_public_values, zkm_vk_hash_bytes, proof_part_stark_vk)) +} - // extract ChainState - let mut watchtower_total_work = [0u8; TOTAL_WORK_SIZE]; - watchtower_total_work.copy_from_slice(&zkm_public_values[0..TOTAL_WORK_SIZE]); - let mut watchtower_consensus_block_height = [0u8; CONSENSUS_BLOCK_HEIGHT_SIZE]; - watchtower_consensus_block_height.copy_from_slice( - &zkm_public_values[TOTAL_WORK_SIZE..TOTAL_WORK_SIZE + CONSENSUS_BLOCK_HEIGHT_SIZE], - ); +pub fn parse_watchtower_public_outputs( + zkm_public_values: &[u8], +) -> Result { + let mut public_values = ZKMPublicValues::from(zkm_public_values); + catch_unwind(AssertUnwindSafe(|| public_values.read::())) + .map_err(|_| "failed to deserialize watchtower public outputs".to_string()) +} - println!("watchtower total work: {watchtower_total_work:?}"); - println!("watchtower total work: {:?}", U256::from_be_bytes(watchtower_total_work)); - println!("watchtower consensus block height: {watchtower_consensus_block_height:?}"); - println!( - "watchtower consensus block height: {:?}", - U32::from_le_bytes(watchtower_consensus_block_height) - ); +// Check the public values are consistent with the total work and block hash +fn groth16_verifier_keys(zkm_version: &str) -> Result<(&'static [u8], &'static [u8]), String> { + let imm_groth16_vk = *IMM_GROTH16_VK_BYTES; + let part_stark_vk = + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version))) + .map_err(|_| format!("failed to load part_stark_vk for zkm_version '{zkm_version}'"))?; + Ok((imm_groth16_vk, part_stark_vk)) +} - Ok(( - graph_id, - proof, - zkm_public_values, - zkm_vk_hash_bytes, - watchtower_total_work, - watchtower_consensus_block_height, - )) +/// Resolve the version-derived `part_stark_vk` and require it to be attested before use. +fn attested_part_stark_vk_for_zkm_version( + unique_witnesses: &[UniquePartStarkVkWitness], + zkm_version: &str, +) -> Result, String> { + let (_, part_stark_vk) = groth16_verifier_keys(zkm_version)?; + assert_part_stark_vk_in_verified_witnesses(unique_witnesses, part_stark_vk)?; + Ok(part_stark_vk.to_vec()) +} + +/// Verify one included watchtower challenge end-to-end and return its parsed public outputs. +#[allow(clippy::too_many_arguments)] +fn verify_included_watchtower_challenge( + index: usize, + graph_id: &[u8; GRAPH_ID_SIZE], + tx: &Transaction, + prev_out: &TxOut, + script: &ScriptBuf, + pubkey: &PublicKey, + unique_witnesses: &[UniquePartStarkVkWitness], + operator_total_work: [u8; TOTAL_WORK_SIZE], + operator_consensus_block_height: U32, +) -> Result { + println!("Verify watchtower[{index}] tx: {}, {:?}", tx.compute_txid(), tx); + let input = tx + .input + .first() + .ok_or_else(|| "watchtower tx must contain at least one input".to_string())?; + let witness = input + .witness + .iter() + .next() + .ok_or_else(|| "watchtower tx witness must contain a taproot signature".to_string())?; + let sig = bitcoin::taproot::Signature::from_slice(witness) + .map_err(|err| format!("invalid taproot signature: {err}"))?; + let prev_index = input.previous_output.vout as usize; + verify_taproot_leaf_schnorr_signature(script, tx, prev_index, prev_out, pubkey, &sig) + .map_err(|err| format!("signature verification failed: {err}"))?; + + let commitment = extract_data_from_commitment_outputs(&tx.output); + println!("commitment: {commitment:?}"); + println!("commitment hex: {}", hex::encode(&commitment)); + + let (parsed_graph_id, proof, public_values, vk, proof_part_stark_vk) = + parse_watchtower_commitment(&commitment)?; + if parsed_graph_id != *graph_id { + return Err(format!( + "graph id mismatch: parsed={}, expected={}", + hex::encode(parsed_graph_id), + hex::encode(graph_id) + )); + } + assert_part_stark_vk_in_verified_witnesses(unique_witnesses, &proof_part_stark_vk)?; + verify_proof_with_part_stark_vk(&proof, &public_values, &vk, &proof_part_stark_vk)?; + + println!("check total work with watchtower {index}"); + let watchtower_outputs = parse_watchtower_public_outputs(&public_values)?; + if U256::from_be_bytes(watchtower_outputs.total_work) > U256::from_be_bytes(operator_total_work) + { + return Err("watchtower total work exceeds operator total work".to_string()); + } + if U32::from_le_bytes(watchtower_outputs.consensus_block_height) + > operator_consensus_block_height + { + return Err( + "watchtower consensus block height exceeds operator consensus block height".to_string() + ); + } + Ok(watchtower_outputs) +} + +/// Verify commit-chain with the trusted base-layer verifier and return its output. +fn verify_commit_chain_output( + commit_chain: &CommitChainCircuitInput, +) -> Result { + let trusted_part_stark_vk = commit_chain::trusted_commit_chain_part_stark_vk(); + verify_proof_with_part_stark_vk( + &commit_chain.zkm_proof, + &commit_chain.zkm_public_values, + &commit_chain.zkm_vk_hash, + &trusted_part_stark_vk, + )?; + let output: CommitChainCircuitOutput = + ZKMPublicValues::from(&commit_chain.zkm_public_values).read(); + + Ok(output) +} + +/// Return the publisher set that authorizes part_stark_vk attestations for this commit-chain output. +fn commit_chain_attestation_authority( + commit_chain_output: &CommitChainCircuitOutput, +) -> (&[PublicKey], u16) { + ( + &commit_chain_output.chain_state.publisher_public_keys, + commit_chain_output.chain_state.threshold, + ) } -// Check the public values are consistent with the total work and block hash pub fn verify_proof( proof: &[u8], zkm_public_values: &[u8], zkm_vk_hash: &[u8], + zkm_version: &str, +) -> Result<(), String> { + let (_, part_stark_vk) = groth16_verifier_keys(zkm_version)?; + verify_proof_with_part_stark_vk(proof, zkm_public_values, zkm_vk_hash, part_stark_vk) +} + +/// Verify a Groth16 proof against an explicit part_stark_vk instead of a version lookup. +pub fn verify_proof_with_part_stark_vk( + proof: &[u8], + zkm_public_values: &[u8], + zkm_vk_hash: &[u8], + part_stark_vk: &[u8], ) -> Result<(), String> { - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(zkm_vk_hash.to_vec()).map_err(|e| e.to_string())?; - match Groth16Verifier::verify(proof, zkm_public_values, &zkm_vk_hash, groth16_vk) { + match Groth16Verifier::verify_by_imm_groth16_vk( + proof, + zkm_public_values, + &zkm_vk_hash, + groth16_vk, + part_stark_vk, + ) { Ok(_) => Ok(()), Err(err) => Err(format!("Verify Groth16 proof, err: {err:?}")), } @@ -516,26 +712,51 @@ pub fn verify_proof( #[cfg(test)] mod tests { use super::*; + use crate::PartStarkVkAttestationBundle; use bitcoin::Transaction; const PROOF: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.proof.bin"); const PUBLIC_INPUTS: &[u8] = include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); + const ZKM_VERSION: &str = "v1.2.4"; + + #[test] + fn test_groth16_verifier_keys_keep_common_vk_available() { + assert!(!IMM_GROTH16_VK_BYTES.is_empty()); + + match groth16_verifier_keys(ZKM_VERSION) { + Ok((imm_groth16_vk, part_stark_vk)) => { + assert_eq!(imm_groth16_vk, *IMM_GROTH16_VK_BYTES); + assert!(!part_stark_vk.is_empty()); + } + Err(err) => { + assert!(err.contains("failed to load part_stark_vk")); + } + } + } #[test] fn test_build_watchtower_commitment() { let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); - let total_work = 1006120; - let block_height = 503043; + let total_work = 1006120u64; + let block_height = 503043u32; + let proof_part_stark_vk = vec![8u8; 52]; + let expected_outputs = WatchtowerPublicOutputs { + total_work: U256::from(total_work).to_be_bytes(), + consensus_block_height: U32::from(block_height).to_le_bytes(), + }; + let public_inputs = bincode::serialize(&expected_outputs).unwrap(); println!("public inputs: {:?}", PUBLIC_INPUTS.len()); println!("vk hash: {:?}", VK_HASH.len()); let comm = build_watchtower_commitment( &graph_id, - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), + PROOF, + &public_inputs, VK_HASH, - ); + &proof_part_stark_vk, + ) + .unwrap(); println!("comm: {:?}", comm.len()); println!("comm hex: {:?}", hex::encode(&comm)); @@ -544,10 +765,11 @@ mod tests { assert_eq!(expected.0, graph_id); assert_eq!(expected.1, PROOF); - assert_eq!(expected.2, PUBLIC_INPUTS); + assert_eq!(expected.2, public_inputs); assert_eq!(expected.3, VK_HASH.as_bytes()); - assert_eq!(expected.4, U256::from(total_work).to_be_bytes()); - assert_eq!(expected.5, U32::from(block_height).to_le_bytes()); + assert_eq!(expected.4, proof_part_stark_vk); + let parsed_outputs = parse_watchtower_public_outputs(&expected.2).unwrap(); + assert_eq!(parsed_outputs, expected_outputs); } #[test] @@ -590,14 +812,221 @@ mod tests { let tx: Transaction = deserialize(&bytes).unwrap(); let commitment = extract_data_from_commitment_outputs(&tx.output); - let ( - parsed_graph_id, - _proof, - _public_values, - _vk, - _watchtower_total_work, - _watchtower_consensus_block_height, - ) = parse_watchtower_commitment(&commitment).unwrap(); - assert_eq!(hex::encode(parsed_graph_id), "9bf28a9ccba44a0cbdd17ce6bb8262a1"); + let parse_result = parse_watchtower_commitment(&commitment); + assert!(parse_result.is_err(), "legacy commitment with trailing zkm_version should fail"); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_legacy_v1_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut legacy = graph_id.to_vec(); + legacy.extend_from_slice(PROOF); + legacy.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + legacy.extend_from_slice(PUBLIC_INPUTS); + legacy.extend_from_slice(VK_HASH.as_bytes()); + let mut legacy_zkm_version = [0u8; 16]; + legacy_zkm_version[..ZKM_VERSION.len()].copy_from_slice(ZKM_VERSION.as_bytes()); + legacy.extend_from_slice(&legacy_zkm_version); + assert!(parse_watchtower_commitment(&legacy).is_err()); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_missing_proof_part_stark_vk() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + assert!(parse_watchtower_commitment(&commitment).is_err()); + } + + #[test] + fn test_parse_watchtower_commitment_accepts_versionless_dual_key_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let proof_part_stark_vk = vec![9u8; 48]; + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + commitment.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + commitment.extend_from_slice(&proof_part_stark_vk); + + assert!( + parse_watchtower_commitment(&commitment).is_ok(), + "versionless dual-key commitment should parse" + ); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_empty_proof_part_stark_vk() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let mut commitment = graph_id.to_vec(); + commitment.extend_from_slice(PROOF); + commitment.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + commitment.extend_from_slice(PUBLIC_INPUTS); + commitment.extend_from_slice(VK_HASH.as_bytes()); + commitment.extend_from_slice(&0u32.to_le_bytes()); + + assert!(parse_watchtower_commitment(&commitment).is_err()); + } + + #[test] + fn test_parse_watchtower_commitment_rejects_versioned_payload() { + let graph_id: [u8; GRAPH_ID_SIZE] = + hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); + let proof_part_stark_vk = vec![3u8; 12]; + let mut versioned = vec![2u8]; + versioned.extend_from_slice(&graph_id); + versioned.extend_from_slice(PROOF); + versioned.extend_from_slice(&(PUBLIC_INPUTS.len() as u32).to_le_bytes()); + versioned.extend_from_slice(PUBLIC_INPUTS); + versioned.extend_from_slice(VK_HASH.as_bytes()); + versioned.extend_from_slice(&(proof_part_stark_vk.len() as u32).to_le_bytes()); + versioned.extend_from_slice(&proof_part_stark_vk); + + assert!( + parse_watchtower_commitment(&versioned).is_err(), + "versioned watchtower commitment should be rejected" + ); + } + + #[test] + fn test_parse_watchtower_public_outputs_rejects_short_public_inputs() { + let result = parse_watchtower_public_outputs(&[0u8; TOTAL_WORK_SIZE + 1]); + assert!(result.is_err()); + } + + #[test] + fn test_parse_watchtower_public_outputs_reads_bincode_serialized_struct() { + let expected = WatchtowerPublicOutputs { + total_work: [9u8; TOTAL_WORK_SIZE], + consensus_block_height: 123u32.to_le_bytes(), + }; + + let public_inputs = bincode::serialize(&expected).unwrap(); + let parsed = parse_watchtower_public_outputs(&public_inputs).unwrap(); + + assert_eq!(parsed, expected); + } + + #[test] + fn test_verify_proof_accepts_non_fixed_length_version() { + let long_version = "v1.12.15-rc1+build.20260319"; + let result = verify_proof(&[], &[], &[], long_version); + assert!(result.is_err()); + assert!(!result.unwrap_err().contains("too long")); + } + + #[test] + fn test_verify_proof_with_part_stark_vk_uses_explicit_vk_bytes() { + let part_stark_vk = groth16_verifier_keys(ZKM_VERSION).unwrap().1.to_vec(); + let result = verify_proof_with_part_stark_vk(&[], &[], &[], &part_stark_vk); + assert!(result.is_err()); + } + + #[test] + fn test_groth16_verifier_keys_reject_unknown_version_without_panic() { + let result = groth16_verifier_keys("v0.0.0-test"); + assert!(result.is_err()); + } + + fn sample_unique_witness(part_stark_vk: Vec) -> PartStarkVkAttestationBundle { + PartStarkVkAttestationBundle { + part_stark_vk, + leaf_index: 0, + merkle_path: vec![], + root: [0u8; 32], + threshold: 1, + publisher_set_id: [0u8; 32], + signatures: vec![], + } + } + + #[test] + fn test_attested_part_stark_vk_for_zkm_version_accepts_verified_witness_payload() { + let part_stark_vk = groth16_verifier_keys(ZKM_VERSION).unwrap().1.to_vec(); + let unique_witnesses = vec![sample_unique_witness(part_stark_vk.clone())]; + + assert_eq!( + attested_part_stark_vk_for_zkm_version(&unique_witnesses, ZKM_VERSION).unwrap(), + part_stark_vk + ); + } + + #[test] + fn test_attested_part_stark_vk_for_zkm_version_rejects_missing_witness_payload() { + let unique_witnesses = vec![sample_unique_witness(vec![7u8; 32])]; + + assert!(attested_part_stark_vk_for_zkm_version(&unique_witnesses, ZKM_VERSION).is_err()); + } + + fn sample_commit_tx() -> Transaction { + use bitcoin::{absolute::LockTime, transaction::Version}; + + Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![], + output: vec![], + } + } + + fn sample_commit_chain_output( + genesis_txid: [u8; 32], + commit_txn: Transaction, + publisher_public_keys: Vec, + threshold: u16, + ) -> CommitChainCircuitOutput { + CommitChainCircuitOutput { + chain_state: commit_chain::CommitChainState { + block_height: 7, + commit_txn, + genesis_txid, + sequencers: vec![], + publisher_public_keys, + threshold, + }, + } + } + + #[test] + fn test_commit_chain_attestation_authority_uses_chain_state() { + let publisher_public_keys = + commit_chain::create_dummy_publisher_keys(3, bitcoin::Network::Regtest) + .into_iter() + .map(|(_, pk)| pk) + .collect::>(); + let threshold = 2u16; + let commit_chain_output = sample_commit_chain_output( + [3u8; 32], + sample_commit_tx(), + publisher_public_keys.clone(), + threshold, + ); + + let (actual_keys, actual_threshold) = + commit_chain_attestation_authority(&commit_chain_output); + assert_eq!(actual_keys, publisher_public_keys.as_slice()); + assert_eq!(actual_threshold, threshold); + } + + #[test] + fn test_operator_public_outputs_bincode_shape_excludes_part_stark_vk() { + let expected = OperatorPublicOutputs { + btc_best_block_hash: [1u8; 32], + constant: [2u8; 32], + included_watchtowers: [3u8; 32], + }; + + let public_inputs = bincode::serialize(&expected).unwrap(); + let parsed: OperatorPublicOutputs = bincode::deserialize(&public_inputs).unwrap(); + + assert_eq!(parsed, expected); } } diff --git a/crates/bitvm2-ga/src/tests.rs b/crates/bitvm2-ga/src/tests.rs index c5dc119a..4a254c18 100644 --- a/crates/bitvm2-ga/src/tests.rs +++ b/crates/bitvm2-ga/src/tests.rs @@ -429,10 +429,6 @@ mod tests { (guest_pubs, proof, pis, vk) } - fn get_test_operator_proof() { - // data/operator-proof/output.bin.* - } - async fn gen_test_graph( esplora: &EsploraClient, disprove_scripts: Vec, @@ -568,7 +564,6 @@ mod tests { .collect(), hashlocks: hashlocks().1.to_vec(), guest_constant_value: [0u8; 32], // all zero for test - zkm_version: "v1.2.3".to_string(), }; generate_bitvm_graph(graph_parameters, disprove_scripts).unwrap() @@ -996,21 +991,21 @@ mod tests { include_bytes!("../../../circuits/data/watchtower/output3.bin.public_inputs.bin"); const VK_HASH: &str = include_str!("../../../circuits/data/watchtower/output3.bin.vk_hash.bin"); + const PROOF_PART_STARK_VK: &[u8] = + include_bytes!("../../../circuits/data/watchtower/output3.bin.proof_part_stark_vk.bin"); + let proof_part_stark_vk = PROOF_PART_STARK_VK.to_vec(); - let graph_id = hex::decode("00112233445566778899aabbccddeeff").unwrap().try_into().unwrap(); //graph.parameters.graph_id.to_bytes_le(); + let graph_id = *graph.parameters.graph_id.as_bytes(); //let total_work = 1006120; //let consensus_commit_block_height = 503043; let comm = bitcoin_light_client_circuit::build_watchtower_commitment( &graph_id, - //&[0u8; PROOF_SIZE], - //&[0u8; PUBLIC_INPUTS_SIZE], - //"", - &PROOF.try_into().unwrap(), - &PUBLIC_INPUTS.try_into().unwrap(), + PROOF, + PUBLIC_INPUTS, VK_HASH, - //total_work, - //consensus_commit_block_height, - ); + &proof_part_stark_vk, + ) + .unwrap(); let mut watchtower_0_challenge = build_watchtower_challenge_tx( &graph, diff --git a/crates/bitvm2-ga/src/types.rs b/crates/bitvm2-ga/src/types.rs index ab41581a..5229ab89 100644 --- a/crates/bitvm2-ga/src/types.rs +++ b/crates/bitvm2-ga/src/types.rs @@ -110,7 +110,6 @@ pub struct Bitvm2GraphParameters { pub watchtower_pubkeys: Vec, pub hashlocks: Vec<[u8; 20]>, // one for each watchtower pub guest_constant_value: [u8; 32], - pub zkm_version: String, } impl Bitvm2InstanceParameters { diff --git a/crates/client/src/goat_chain/goat_adaptor.rs b/crates/client/src/goat_chain/goat_adaptor.rs index 354aba8c..babad5f0 100644 --- a/crates/client/src/goat_chain/goat_adaptor.rs +++ b/crates/client/src/goat_chain/goat_adaptor.rs @@ -16,6 +16,7 @@ use alloy::providers::ext::DebugApi; use alloy::providers::fillers::{FillProvider, JoinFill, RecommendedFillers}; use alloy::rpc::types::TransactionReceipt; use alloy::rpc::types::trace::geth::{CallConfig, GethDebugTracingOptions, GethTrace}; +use alloy::transports::http::reqwest::Client as AlloyReqwestClient; use alloy::{ network::{Ethereum, EthereumWallet, NetworkWallet, eip2718::Encodable2718}, primitives::{Address, B256, Bytes, ChainId, FixedBytes, TxHash, U256, keccak256}, @@ -37,16 +38,16 @@ const EIP1559_MAX_BASE_FEE_WEI: u128 = 2_000_000_000; const EIP1559_BASE_FEE_MULTIPLIER_NUM: u128 = 125; const EIP1559_BASE_FEE_MULTIPLIER_DEN: u128 = 100; -fn build_goat_rpc_client() -> reqwest::Client { +fn build_goat_rpc_client() -> AlloyReqwestClient { let timeout = Duration::from_secs(get_goat_rpc_timeout_secs()); - match reqwest::Client::builder().timeout(timeout).build() { + match AlloyReqwestClient::builder().timeout(timeout).build() { Ok(client) => client, Err(err) => { tracing::warn!( timeout_secs = timeout.as_secs(), "failed to build GOAT RPC reqwest client with timeout: {err}, fallback to default client" ); - reqwest::Client::new() + AlloyReqwestClient::new() } } } diff --git a/crates/commit-chain/Cargo.toml b/crates/commit-chain/Cargo.toml index a0afcbd6..05a2c247 100644 --- a/crates/commit-chain/Cargo.toml +++ b/crates/commit-chain/Cargo.toml @@ -13,8 +13,8 @@ guest-executor = { workspace = true } #header-chain = { path = "../header-chain" } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -26,7 +26,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } #prost = { version = "0.13", features = ["prost-derive"], default-features = false } #prost-derive = { version = "0.13", default-features = true } diff --git a/crates/commit-chain/src/commit_chain.rs b/crates/commit-chain/src/commit_chain.rs index d66fee85..18e3519a 100644 --- a/crates/commit-chain/src/commit_chain.rs +++ b/crates/commit-chain/src/commit_chain.rs @@ -15,6 +15,10 @@ use bitcoin::{Transaction, TxOut, Witness, secp256k1::PublicKey}; pub struct CommitInfo { pub threshold: u16, pub publisher_public_keys: Vec, + #[serde(default)] + pub next_threshold: Option, + #[serde(default)] + pub next_publisher_public_keys: Option>, pub txid: String, pub genesis_txid: String, pub sequencers: Vec, @@ -34,10 +38,24 @@ pub struct CircuitCommit { pub genesis_txid: [u8; 32], pub publisher_public_keys: Vec, pub threshold: u16, + #[serde(default)] + pub next_publisher_public_keys: Option>, + #[serde(default)] + pub next_threshold: Option, pub sequencers: Vec, pub block_height: u32, // Bitcoin block height of current commitment } +impl CommitInfo { + /// Return the publisher set that becomes active after this commit is mined. + pub fn active_publisher_set(&self) -> (&[String], u16) { + match (self.next_publisher_public_keys.as_deref(), self.next_threshold) { + (Some(next_keys), Some(next_threshold)) => (next_keys, next_threshold), + _ => (&self.publisher_public_keys, self.threshold), + } + } +} + #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct SequencerInfo { /// Validator account address @@ -83,6 +101,16 @@ pub struct CommitChainState { pub threshold: u16, } +impl CircuitCommit { + /// Return the publisher set that is committed into this tx's next update connector. + pub fn active_publisher_set(&self) -> (&[PublicKey], u16) { + match (self.next_publisher_public_keys.as_deref(), self.next_threshold) { + (Some(next_keys), Some(next_threshold)) => (next_keys, next_threshold), + _ => (&self.publisher_public_keys, self.threshold), + } + } +} + pub const PROOF_SIZE: usize = 260; pub const PUBLIC_INPUTS_SIZE: usize = 36; pub const VK_HASH_SIZE: usize = 66; @@ -98,6 +126,7 @@ pub struct CommitChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: String, pub commits: Vec, } @@ -128,8 +157,7 @@ impl CommitChainState { for commit in &commits { let mut latest_commit_txn_with_wtns = commit.commit_txn.clone(); let latest_sequencers = &commit.sequencers; - let publisher_public_keys = &commit.publisher_public_keys; - let threshold = commit.threshold; + let (next_publisher_public_keys, next_threshold) = commit.active_publisher_set(); assert_eq!(commit.genesis_txid, self.genesis_txid); @@ -157,23 +185,35 @@ impl CommitChainState { let prev_commit_txid = prev_commit_txn_value.compute_txid(); assert_eq!(update_connector.previous_output.txid, prev_commit_txid); assert_eq!(update_connector.previous_output.vout, 0); - // check the latest publishing txn's signature is signed by prev publishers + // Verify that the spending witness matches the publisher set committed by the + // previous update connector. let prevout = &prev_commit_txn_value.output[0]; let redeem_script = crate::create_sequencer_update_script( - &publisher_public_keys[..], - threshold as usize, + &self.publisher_public_keys[..], + self.threshold as usize, ); crate::publisher::verify_p2wsh_multisig_witness( &latest_commit_txn_with_wtns, 0, prevout, &redeem_script, - publisher_public_keys, - threshold as usize, + &self.publisher_public_keys, + self.threshold as usize, ) .unwrap(); } + let expected_next_connector_script = crate::create_sequencer_update_script( + next_publisher_public_keys, + next_threshold as usize, + ); + let expected_next_connector_script_pubkey = + bitcoin::ScriptBuf::new_p2wsh(&expected_next_connector_script.wscript_hash()); + assert_eq!( + latest_commit_txn_with_wtns.output[0].script_pubkey, + expected_next_connector_script_pubkey + ); + // remove witness latest_commit_txn_with_wtns.input.iter_mut().for_each(|input| { input.witness = Witness::new(); @@ -181,8 +221,8 @@ impl CommitChainState { self.sequencers = latest_sequencers.clone(); self.commit_txn = latest_commit_txn_with_wtns.clone(); - self.publisher_public_keys = publisher_public_keys.clone(); - self.threshold = threshold; + self.publisher_public_keys = next_publisher_public_keys.to_vec(); + self.threshold = next_threshold; self.block_height = commit.block_height; } } @@ -230,7 +270,14 @@ pub fn extract_op_return_data(tx_output: &[TxOut]) -> Vec { #[cfg(test)] mod tests { use super::*; + use crate::{ + create_dummy_publisher_keys, create_sequencer_update_script, finalize, sign_partial, + }; use bitcoin::{Amount, ScriptBuf}; + use bitcoin::{ + EcdsaSighashType, OutPoint, Sequence, TxIn, Witness, absolute::LockTime, + transaction::Version, + }; #[test] fn test_extract_op_return() { // Example: construct a fake tx with OP_RETURN @@ -272,4 +319,188 @@ mod tests { chain_state.commit_txn.compute_txid() ); } + + #[test] + fn test_apply_commit_tracks_next_publisher_set_as_active_state() { + let current_keys = create_dummy_publisher_keys(3, bitcoin::Network::Regtest); + let current_pubkeys: Vec = current_keys.iter().map(|(_, pk)| *pk).collect(); + let next_keys = create_dummy_publisher_keys(4, bitcoin::Network::Regtest); + let next_pubkeys: Vec = next_keys.iter().map(|(_, pk)| *pk).collect(); + let final_keys = create_dummy_publisher_keys(5, bitcoin::Network::Regtest); + let final_pubkeys: Vec = final_keys.iter().map(|(_, pk)| *pk).collect(); + + let current_threshold = 2u16; + let next_threshold = 3u16; + let final_threshold = 4u16; + let empty_sequencers = vec![]; + let commit0_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let commit0 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![], + output: vec![ + TxOut { + value: Amount::from_sat(100_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script( + ¤t_pubkeys, + current_threshold as usize, + ) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit0_op_return }, + ], + }; + let mut genesis_txid = [0u8; 32]; + genesis_txid.copy_from_slice(commit0.compute_txid().as_raw_hash().as_ref()); + + let commit0_info = CircuitCommit { + commit_txn: commit0.clone(), + genesis_txid, + publisher_public_keys: vec![], + threshold: 0, + next_publisher_public_keys: Some(current_pubkeys.clone()), + next_threshold: Some(current_threshold), + sequencers: empty_sequencers.clone(), + block_height: 1, + }; + + let commit1_redeem_script = + create_sequencer_update_script(¤t_pubkeys, current_threshold as usize); + let commit1_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let mut commit1 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::new(commit0.compute_txid(), 0), + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![ + TxOut { + value: Amount::from_sat(90_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script(&next_pubkeys, next_threshold as usize) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit1_op_return }, + ], + }; + let (sig1, _) = sign_partial( + &mut commit1, + ¤t_keys[0].0, + &commit1_redeem_script, + Amount::from_sat(100_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig2, _) = sign_partial( + &mut commit1, + ¤t_keys[1].0, + &commit1_redeem_script, + Amount::from_sat(100_000), + EcdsaSighashType::All, + ) + .unwrap(); + finalize(&mut commit1, vec![sig1, sig2], &commit1_redeem_script).unwrap(); + let commit1_info = CircuitCommit { + commit_txn: commit1.clone(), + genesis_txid, + publisher_public_keys: current_pubkeys.clone(), + threshold: current_threshold, + next_publisher_public_keys: Some(next_pubkeys.clone()), + next_threshold: Some(next_threshold), + sequencers: empty_sequencers.clone(), + block_height: 2, + }; + + let commit2_redeem_script = + create_sequencer_update_script(&next_pubkeys, next_threshold as usize); + let commit2_op_return = if let tendermint_light_client_verifier::types::Hash::Sha256(hash) = + sequencer_hash(&empty_sequencers) + { + ScriptBuf::new_op_return(&hash) + } else { + panic!("expected sha256 sequencer hash"); + }; + let mut commit2 = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: OutPoint::new(commit1.compute_txid(), 0), + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![ + TxOut { + value: Amount::from_sat(80_000), + script_pubkey: ScriptBuf::new_p2wsh( + &create_sequencer_update_script(&final_pubkeys, final_threshold as usize) + .wscript_hash(), + ), + }, + TxOut { value: Amount::ZERO, script_pubkey: commit2_op_return }, + ], + }; + let (sig3, _) = sign_partial( + &mut commit2, + &next_keys[0].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig4, _) = sign_partial( + &mut commit2, + &next_keys[1].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + let (sig5, _) = sign_partial( + &mut commit2, + &next_keys[2].0, + &commit2_redeem_script, + Amount::from_sat(90_000), + EcdsaSighashType::All, + ) + .unwrap(); + finalize(&mut commit2, vec![sig3, sig4, sig5], &commit2_redeem_script).unwrap(); + let commit2_info = CircuitCommit { + commit_txn: commit2.clone(), + genesis_txid, + publisher_public_keys: next_pubkeys.clone(), + threshold: next_threshold, + next_publisher_public_keys: Some(final_pubkeys.clone()), + next_threshold: Some(final_threshold), + sequencers: empty_sequencers, + block_height: 3, + }; + + let mut chain_state = CommitChainState::new(genesis_txid); + chain_state.apply_commit(vec![commit0_info]); + assert_eq!(chain_state.publisher_public_keys, current_pubkeys); + assert_eq!(chain_state.threshold, current_threshold); + + chain_state.apply_commit(vec![commit1_info, commit2_info]); + assert_eq!(chain_state.publisher_public_keys, final_pubkeys); + assert_eq!(chain_state.threshold, final_threshold); + } } diff --git a/crates/commit-chain/src/lib.rs b/crates/commit-chain/src/lib.rs index 079aa141..bc9d5d37 100644 --- a/crates/commit-chain/src/lib.rs +++ b/crates/commit-chain/src/lib.rs @@ -2,22 +2,32 @@ mod publisher; pub use publisher::*; mod commit_chain; pub use commit_chain::*; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; + +pub const TRUSTED_COMMIT_CHAIN_ZKM_VERSION: &str = "v1.2.5"; + +/// Return the fixed `part_stark_vk` used by commit-chain's internal recursive verifier. +pub fn trusted_commit_chain_part_stark_vk() -> Vec { + Groth16Verifier::get_part_stark_vk(TRUSTED_COMMIT_CHAIN_ZKM_VERSION).to_vec() +} pub fn commit_chain_circuit(input: CommitChainCircuitInput) -> CommitChainCircuitOutput { + let current_part_stark_vk = trusted_commit_chain_part_stark_vk(); let mut chain_state = match input.prev_proof { CommitChainPrevProofType::GenesisBlock => { CommitChainState::new(input.commits[0].genesis_txid) } CommitChainPrevProofType::PrevProof(prev_proof) => { println!("verify commit chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - Groth16Verifier::verify( + assert_eq!(input.zkm_version, TRUSTED_COMMIT_CHAIN_ZKM_VERSION); + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, + ¤t_part_stark_vk, ) .unwrap(); prev_proof.chain_state diff --git a/crates/commit-chain/src/publisher.rs b/crates/commit-chain/src/publisher.rs index d69239f5..193a3d86 100644 --- a/crates/commit-chain/src/publisher.rs +++ b/crates/commit-chain/src/publisher.rs @@ -86,6 +86,11 @@ pub fn verify_p2wsh_multisig_witness( let secp = Secp256k1::verification_only(); let txin = &tx.input[input_index]; let witness: &Witness = &txin.witness; + let expected_script_pubkey = ScriptBuf::new_p2wsh(&redeem_script.wscript_hash()); + + if prevout.script_pubkey != expected_script_pubkey { + return Err("prevout script_pubkey does not match redeem_script".into()); + } // Expect witness: [, sig1, sig2, ..., redeem_script_bytes] if witness.len() < 2 { @@ -261,4 +266,57 @@ mod tests { assert!(ok, "2-of-3 multisig witness should verify"); } + + #[test] + fn test_verify_p2wsh_multisig_witness_rejects_prevout_script_mismatch() { + let keys = create_dummy_publisher_keys(3, bitcoin::Network::Regtest); + let pubkeys: Vec = keys.iter().map(|(_, pk)| *pk).collect(); + let threshold = 2; + let redeem_script = create_sequencer_update_script(&pubkeys, threshold); + let prev_value = Amount::from_sat(100_000); + let prevout = TxOut { + value: prev_value, + script_pubkey: ScriptBuf::new_p2wsh(&ScriptBuf::new().wscript_hash()), + }; + let prev_outpoint = + OutPoint { txid: bitcoin::Txid::from_byte_array([0u8; 32].into()), vout: 0 }; + + let mut tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![TxIn { + previous_output: prev_outpoint, + script_sig: ScriptBuf::new(), + sequence: Sequence::MAX, + witness: Witness::default(), + }], + output: vec![TxOut { + value: Amount::from_sat(99_000), + script_pubkey: { + let btc_pk0 = bitcoin::PublicKey::from(pubkeys[0]); + Address::p2pkh(&btc_pk0, Network::Testnet).script_pubkey() + }, + }], + }; + + let (sig1, _) = + sign_partial(&mut tx, &keys[0].0, &redeem_script, prev_value, EcdsaSighashType::All) + .unwrap(); + let (sig2, _) = + sign_partial(&mut tx, &keys[1].0, &redeem_script, prev_value, EcdsaSighashType::All) + .unwrap(); + finalize(&mut tx, vec![sig1, sig2], &redeem_script).unwrap(); + + assert!( + verify_p2wsh_multisig_witness( + &tx, + 0, + &prevout, + &redeem_script, + &pubkeys, + threshold as usize, + ) + .is_err() + ); + } } diff --git a/crates/header-chain/Cargo.toml b/crates/header-chain/Cargo.toml index 7febffd3..cf16b1bc 100644 --- a/crates/header-chain/Cargo.toml +++ b/crates/header-chain/Cargo.toml @@ -7,11 +7,11 @@ edition.workspace = true [dependencies] borsh = {version = "1.5.3", features = ["derive"] } sha2 = { version = "0.10.9", default-features = false } -bitcoin = { workspace = true, features = ["serde", "rand", "secp-recovery"] } +bitcoin = { version = "0.32.6", default-features = false, features = ["serde"] } serde = { workspace = true, default-features = false } crypto-bigint = { version = "0.5.5", default-features = false } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } +zkm-zkvm = { workspace = true } +zkm-verifier = { workspace = true } [dev-dependencies] -hex-literal = "1.0.0" \ No newline at end of file +hex-literal = "1.0.0" diff --git a/crates/header-chain/src/header_chain.rs b/crates/header-chain/src/header_chain.rs index 473fad16..cd7f452a 100644 --- a/crates/header-chain/src/header_chain.rs +++ b/crates/header-chain/src/header_chain.rs @@ -363,6 +363,7 @@ fn calculate_work(target: &[u8; 32]) -> U256 { )] pub struct BlockHeaderCircuitOutput { pub chain_state: ChainState, + pub part_stark_vk: Vec, } /// The input proof of the header chain circuit. @@ -379,6 +380,7 @@ pub struct HeaderChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: String, pub prev_proof: HeaderChainPrevProofType, pub block_headers: Vec, } diff --git a/crates/header-chain/src/lib.rs b/crates/header-chain/src/lib.rs index 7d995b64..f2ca0147 100644 --- a/crates/header-chain/src/lib.rs +++ b/crates/header-chain/src/lib.rs @@ -12,23 +12,25 @@ pub use transaction::*; pub mod spv; pub use spv::SPV; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; /// The main entry point of the header chain circuit. pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircuitOutput { + let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); // println!("Detected network: {:?}", NETWORK_TYPE); // println!("NETWORK_CONSTANTS: {:?}", NETWORK_CONSTANTS); let mut chain_state = match input.prev_proof { HeaderChainPrevProofType::GenesisBlock => ChainState::new(), HeaderChainPrevProofType::PrevProof(prev_proof) => { println!("verify header chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - Groth16Verifier::verify( + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, + ¤t_part_stark_vk, ) .unwrap(); @@ -37,5 +39,5 @@ pub fn header_chain_circuit(input: HeaderChainCircuitInput) -> BlockHeaderCircui }; chain_state.apply_blocks(input.block_headers); - BlockHeaderCircuitOutput { chain_state } + BlockHeaderCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } } diff --git a/crates/state-chain/Cargo.toml b/crates/state-chain/Cargo.toml index 6ff57a35..c7a1aa50 100644 --- a/crates/state-chain/Cargo.toml +++ b/crates/state-chain/Cargo.toml @@ -13,8 +13,8 @@ guest-executor = { workspace = true } header-chain = { path = "../header-chain" } # Ziren -zkm-verifier = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-verifier" } -zkm-zkvm = { git = "https://github.com/ProjectZKM/Ziren", package = "zkm-zkvm", features = ["verify"] } +zkm-verifier = { workspace = true } +zkm-zkvm = { workspace = true } #zkm-verifier = { path = "../../../Ziren/crates/verifier" } #zkm-zkvm = { path = "../../../Ziren/crates/zkvm/entrypoint", features = ["verify"] } @@ -26,7 +26,7 @@ revm-database-interface = { workspace = true, features = ["serde"]} #revm = { workspace = true, features = ["serde", "bn"], default-features = false } sha2 = "0.10.9" -hex = "0.4.3" +hex = { workspace = true } prost = { version = "0.13", features = ["prost-derive"], default-features = false } prost-derive = { version = "0.13", default-features = true } @@ -54,4 +54,4 @@ blake3 = "1.6.1" [build-dependencies] prost-build = "0.13" #pbjson-build = "0.8" -#pbjson-types = "0.8" \ No newline at end of file +#pbjson-types = "0.8" diff --git a/crates/state-chain/src/lib.rs b/crates/state-chain/src/lib.rs index a21c185b..49c959c5 100644 --- a/crates/state-chain/src/lib.rs +++ b/crates/state-chain/src/lib.rs @@ -3,9 +3,10 @@ mod state_chain; pub use cbft::*; pub use state_chain::*; -use zkm_verifier::Groth16Verifier; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES}; pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOutput { + let current_part_stark_vk = Groth16Verifier::get_part_stark_vk(&input.zkm_version).to_vec(); let mut chain_state = match input.prev_proof { StateChainPrevProofType::GenesisBlock => { let block_hash: [u8; 32] = input.blocks[0].evm_block.current_block.hash_slow().into(); @@ -15,13 +16,14 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu } StateChainPrevProofType::PrevProof(prev_proof) => { println!("verify state chain of prev proof"); - let groth16_vk = *zkm_verifier::GROTH16_VK_BYTES; + let groth16_vk = *IMM_GROTH16_VK_BYTES; let zkm_vk_hash = String::from_utf8(input.zkm_vk_hash.to_vec()).unwrap(); - Groth16Verifier::verify( + Groth16Verifier::verify_by_imm_groth16_vk( &input.zkm_proof, &input.zkm_public_values, &zkm_vk_hash, groth16_vk, + ¤t_part_stark_vk, ) .unwrap(); prev_proof.chain_state @@ -29,5 +31,5 @@ pub fn state_chain_circuit(input: StateChainCircuitInput) -> StateChainCircuitOu }; chain_state.apply_blocks(input.blocks); - StateChainCircuitOutput { chain_state } + StateChainCircuitOutput { chain_state, part_stark_vk: current_part_stark_vk } } diff --git a/crates/state-chain/src/state_chain.rs b/crates/state-chain/src/state_chain.rs index b5b8b5f9..ce735638 100644 --- a/crates/state-chain/src/state_chain.rs +++ b/crates/state-chain/src/state_chain.rs @@ -42,6 +42,7 @@ pub struct StateChainState { #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] pub struct StateChainCircuitOutput { pub chain_state: StateChainState, + pub part_stark_vk: Vec, } #[derive(Serialize, Deserialize, PartialEq, Clone, Debug)] @@ -49,6 +50,7 @@ pub struct StateChainCircuitInput { pub zkm_proof: Vec, pub zkm_public_values: Vec, pub zkm_vk_hash: Vec, + pub zkm_version: String, pub prev_proof: StateChainPrevProofType, pub blocks: Vec, } diff --git a/crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json b/crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json similarity index 68% rename from crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json rename to crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json index 2e02efd9..a5cebc2d 100644 --- a/crates/store/.sqlx/query-0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e.json +++ b/crates/store/.sqlx/query-a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc.json @@ -1,12 +1,12 @@ { "db_name": "SQLite", - "query": "INSERT OR\n REPLACE INTO graph (graph_id, instance_id, kickoff_index, from_addr, to_addr, amount, challenge_amount,\n status, sub_status, operator_pubkey, cur_prekickoff_txid, next_prekickoff, force_skip_kickoff_txid,\n quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid,\n challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids,\n blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash,\n bridge_out_start_at, zkm_version, status_updated_at, proceed_withdraw_height, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "query": "INSERT OR\n REPLACE INTO graph (graph_id, instance_id, kickoff_index, from_addr, to_addr, amount, challenge_amount,\n status, sub_status, operator_pubkey, cur_prekickoff_txid, next_prekickoff, force_skip_kickoff_txid,\n quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid,\n challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids,\n blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash,\n bridge_out_start_at, status_updated_at, proceed_withdraw_height, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", "describe": { "columns": [], "parameters": { - "Right": 34 + "Right": 33 }, "nullable": [] }, - "hash": "0d2299e1894169e179a5716f3a9e5cc2bce15d8facaf649e25d9919fb26f103e" + "hash": "a574aa126ca49083135ef445cb213379bf8df51054958887f27081ff7f8f47cc" } diff --git a/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql b/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql new file mode 100644 index 00000000..3938b9ba --- /dev/null +++ b/crates/store/migrations/20260406120000_drop_graph_zkm_version.sql @@ -0,0 +1,2 @@ +-- Drop graph-level zkm_version because version semantics now live on proofs only +ALTER TABLE graph DROP COLUMN `zkm_version`; diff --git a/crates/store/src/localdb.rs b/crates/store/src/localdb.rs index 5acc76ab..d80ad4b0 100644 --- a/crates/store/src/localdb.rs +++ b/crates/store/src/localdb.rs @@ -1107,8 +1107,8 @@ impl<'a> StorageProcessor<'a> { quick_challenge_txid, challenge_incomplete_kickoff_txid, pegin_txid, kickoff_txid, take1_txid, challenge_txid, take2_txid, disprove_txid, watchtower_challenge_init_txid, watchtower_challenge_timeout_txids, nack_txids, blockhash_commit_timeout_txid, assert_init_txid, assert_commit_timeout_txids, init_withdraw_tx_hash, - bridge_out_start_at, zkm_version, status_updated_at, proceed_withdraw_height, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + bridge_out_start_at, status_updated_at, proceed_withdraw_height, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", graph.graph_id, graph.instance_id, graph.kickoff_index, @@ -1138,7 +1138,6 @@ impl<'a> StorageProcessor<'a> { assert_commit_timeout_txids_json, graph.init_withdraw_tx_hash, graph.bridge_out_start_at, - graph.zkm_version, graph.status_updated_at, graph.proceed_withdraw_height, graph.created_at, @@ -1222,7 +1221,6 @@ impl<'a> StorageProcessor<'a> { assert_commit_timeout_txids, init_withdraw_tx_hash, bridge_out_start_at, - zkm_version, status_updated_at, proceed_withdraw_height, CASE diff --git a/crates/store/src/schema.rs b/crates/store/src/schema.rs index 9d94029f..c40da0cd 100644 --- a/crates/store/src/schema.rs +++ b/crates/store/src/schema.rs @@ -408,7 +408,6 @@ pub struct Graph { pub assert_commit_timeout_txids: Vec, pub init_withdraw_tx_hash: Option, pub bridge_out_start_at: i64, - pub zkm_version: String, pub status_updated_at: i64, pub proceed_withdraw_height: i64, pub created_at: i64, diff --git a/docs/part-stark-vk-attest-cli.md b/docs/part-stark-vk-attest-cli.md new file mode 100644 index 00000000..73cb0bf9 --- /dev/null +++ b/docs/part-stark-vk-attest-cli.md @@ -0,0 +1,281 @@ +# `part-stark-vk-attest` CLI Guide + +This document explains how to use `part-stark-vk-attest` to build the latest `part_stark_vk` attestation snapshot and add publisher signatures to that snapshot. + +## Overview + +The CLI currently provides two subcommands: + +- `build-tree` +- `sign-root` + +The workflow is fixed: + +1. Run `build-tree` first to generate the latest snapshot from the full active version set +2. Let each publisher signer run `sign-root` once +3. After the number of signatures in `manifest.json` reaches the threshold from `commit_info`, the proof side can load the attestation snapshot + +## Binary Entry + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- ... +``` + +The binary is defined in: + +- [`node/Cargo.toml`](../node/Cargo.toml) +- [`node/src/bin/part_stark_vk_attest.rs`](../node/src/bin/part_stark_vk_attest.rs) + +## Directory Model + +The attestation directory stores only one latest snapshot. Historical snapshots are not kept. + +Default output directory: + +```text +data/psv-attestations +``` + +Latest snapshot layout: + +```text +data/psv-attestations/ + manifest.json + proofs/ + v1.2.4.json + v1.2.5.json +``` + +Where: + +- `manifest.json` stores the current Merkle root, ordered versions, publisher metadata, and aggregated signatures +- `proofs/.json` stores the `part_stark_vk`, `leaf_index`, and `merkle_path` for each version + +## Version Rules + +All `--versions` inputs represent the full active version set, not incremental additions. + +The CLI will: + +1. Sort versions by semver +2. Load `part_stark_vk` for each sorted version +3. Build the Merkle tree using that sorted order + +Example: + +```text +Input: v1.2.10,v1.2.4,v1.2.5 +Sorted: v1.2.4,v1.2.5,v1.2.10 +``` + +If versions are duplicated, the command fails. + +## `build-tree` + +### Purpose + +- Build the latest Merkle tree from the full version set +- Generate Merkle proofs for every version +- Overwrite the attestation directory +- Do not write signatures + +### Command Format + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions \ + --attestation-dir +``` + +### Parameters + +- `--versions` + Comma-separated version list +- `--attestation-dir` + Output attestation directory; defaults to `data/psv-attestations` + +### Example + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions v1.2.4,v1.2.5 \ + --attestation-dir circuits/data/psv-attestations +``` + +### Output + +On success, the command prints output similar to: + +```text +built latest part_stark_vk snapshot in circuits/data/psv-attestations for versions v1.2.4,v1.2.5 +``` + +Note: + +- `build-tree` creates an unsigned snapshot +- Running only `build-tree` is not enough for the proof side to consume the attestation + +## `sign-root` + +### Purpose + +- Rebuild the Merkle tree from the same version set +- Load the current publisher set and threshold from `commit_info.active_publisher_set()` +- Sign the current root with a single publisher private key +- Merge the signature into the latest `manifest.json` + +### Command Format + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions \ + --commit-info-file \ + --publisher-secret-key-wif \ + --attestation-dir +``` + +### Parameters + +- `--versions` + Full active version set; must match the snapshot being signed +- `--commit-info-file` + Path to `commit_info.json` +- `--publisher-secret-key-wif` + Bitcoin WIF private key for a single publisher signer +- `--attestation-dir` + Attestation directory; defaults to `data/psv-attestations` + +### Signer Matching Rule + +The command does not require a manual signer index. + +`--publisher-secret-key-wif` is parsed as WIF, following the same Bitcoin private key format used in `sequencer-set-publish.rs`. + +The CLI will: + +1. Derive the compressed public key from the private key +2. Read the current active publisher set from `commit_info.active_publisher_set()` +3. Find that public key inside the active publisher set +4. Use the matching position as `signer_pubkey_index` + +If the private key does not belong to the current active publisher set, the command fails. + +### Your Current `commit_info` + +If you are using: + +- [`circuits/data/commit-chain/commit_info.json.0`](../circuits/data/commit-chain/commit_info.json.0) + +Then the command looks like: + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +### Multi-Signer Aggregation + +`sign-root` handles only one signer per invocation. + +If multiple signers exist, run it once per signer: + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations + +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations + +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +Signatures are aggregated into the same `manifest.json`. + +## Signature Invalidation Rules + +Existing signatures are cleared if any of the following changes: + +- Version list changes +- Version ordering changes +- Any resolved `part_stark_vk` bytes change +- `root` changes +- `publisher_set_id` changes + +Notes: + +- `publisher_set_id` already includes `threshold` +- A threshold change therefore appears as a `publisher_set_id` change + +## How the Proof Side Uses It + +The proof side accepts only the latest snapshot format. + +Requirements: + +- `manifest.json` must exist in the attestation directory +- Matching `proofs/.json` files must exist +- `manifest.json` must already contain enough valid signatures + +If the directory contains only the old `bundles/` files and no `manifest.json`, the proof side fails immediately. + +## Recommended Procedure + +### Step 1: Build the Latest Snapshot + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + build-tree \ + --versions v1.2.4,v1.2.5 \ + --attestation-dir circuits/data/psv-attestations +``` + +### Step 2: Let Each Signer Add One Signature + +```bash +cargo run -p bitvm2-noded --bin part-stark-vk-attest -- \ + sign-root \ + --versions v1.2.4,v1.2.5 \ + --commit-info-file circuits/data/commit-chain/commit_info.json.0 \ + --publisher-secret-key-wif \ + --attestation-dir circuits/data/psv-attestations +``` + +Repeat until the number of signatures reaches the threshold from `commit_info`. + +## Common Errors + +- `versions is empty` + No version list was provided +- `duplicate version '...'` + Duplicate version after normalization +- `failed to load part_stark_vk for version '...'` + The local verifier cannot resolve that version +- `publisher_secret_key_wif does not belong to active publisher set` + The provided WIF key does not belong to the current active publisher set +- `missing latest attestation manifest '.../manifest.json'` + The proof side is loading an attestation directory without a latest snapshot + +## Relevant Implementation Files + +- [`node/src/bin/part_stark_vk_attest.rs`](../node/src/bin/part_stark_vk_attest.rs) +- [`crates/bitcoin-light-client-circuit/src/attestation.rs`](../crates/bitcoin-light-client-circuit/src/attestation.rs) diff --git a/node/Cargo.toml b/node/Cargo.toml index c9bd33e0..9395478f 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -35,6 +35,10 @@ path = "src/bin/send_bridge_out.rs" name = "update-db" path = "src/bin/db_inject.rs" +[[bin]] +name = "part-stark-vk-attest" +path = "src/bin/part_stark_vk_attest.rs" + [dependencies] libp2p = { workspace = true, features = [ "autonat", @@ -106,8 +110,9 @@ indicatif = "0.17.8" dirs = "5.0.1" zkm-sdk = { workspace = true } -zkm-verifier = { workspace = true } +zkm-verifier = { workspace = true, features = ["ark"] } borsh = {version = "1.5.3", features = ["derive"] } +semver = "1.0" proof-builder = { workspace = true } util = { workspace = true } diff --git a/node/src/bin/part_stark_vk_attest.rs b/node/src/bin/part_stark_vk_attest.rs new file mode 100644 index 00000000..411fec7e --- /dev/null +++ b/node/src/bin/part_stark_vk_attest.rs @@ -0,0 +1,246 @@ +use anyhow::{Context, Result, bail}; +use bitcoin::PrivateKey; +use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey}; +use bitcoin_light_client_circuit::{ + part_stark_vk_attestation_dir, save_latest_part_stark_vk_attestation_snapshot, + sign_latest_part_stark_vk_snapshot, +}; +use clap::{Parser, Subcommand}; +use commit_chain::CommitInfo; +use semver::Version; +use std::path::PathBuf; +use std::str::FromStr; +use zkm_verifier::Groth16Verifier; + +#[derive(Debug, Parser)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + BuildTree { + #[arg(long, value_delimiter = ',')] + versions: Vec, + #[arg(long)] + attestation_dir: Option, + }, + SignRoot { + #[arg(long, value_delimiter = ',')] + versions: Vec, + #[arg(long)] + commit_info_file: PathBuf, + #[arg(long, value_parser = decode_publisher_secret_key_wif)] + publisher_secret_key_wif: SecretKey, + #[arg(long)] + attestation_dir: Option, + }, +} + +fn resolve_attestation_dir(attestation_dir: Option) -> PathBuf { + attestation_dir.unwrap_or_else(part_stark_vk_attestation_dir) +} + +fn normalize_version(version: &str) -> Result { + let raw_version = version.trim(); + if raw_version.is_empty() { + bail!("version cannot be empty"); + } + let normalized = raw_version + .strip_prefix('v') + .or_else(|| raw_version.strip_prefix('V')) + .unwrap_or(raw_version); + Version::parse(normalized).with_context(|| format!("invalid semver version '{version}'")) +} + +/// Sort versions by semantic version while rejecting duplicate normalized versions. +fn order_versions(versions: &[String]) -> Result> { + if versions.is_empty() { + bail!("versions is empty"); + } + + let mut keyed_versions = versions + .iter() + .map(|version| Ok((normalize_version(version)?, version.clone()))) + .collect::>>()?; + keyed_versions.sort_by(|left, right| left.0.cmp(&right.0).then(left.1.cmp(&right.1))); + + let mut ordered_versions = Vec::with_capacity(keyed_versions.len()); + let mut previous: Option = None; + for (normalized, original) in keyed_versions { + if previous.as_ref() == Some(&normalized) { + bail!("duplicate version '{original}'"); + } + previous = Some(normalized); + ordered_versions.push(original); + } + Ok(ordered_versions) +} + +fn load_publisher_set(commit_info_file: &PathBuf) -> Result<(Vec, u16)> { + let bytes = std::fs::read(commit_info_file).with_context(|| { + format!("failed to read commit_info file '{}'", commit_info_file.display()) + })?; + let commit_info: CommitInfo = serde_json::from_slice(&bytes).with_context(|| { + format!("failed to decode commit_info file '{}'", commit_info_file.display()) + })?; + let (encoded_public_keys, threshold) = commit_info.active_publisher_set(); + if encoded_public_keys.is_empty() { + bail!("commit_info publisher_public_keys is empty"); + } + if threshold == 0 { + bail!("commit_info threshold must be greater than 0"); + } + let publisher_public_keys = encoded_public_keys + .iter() + .map(|compressed_pk| { + PublicKey::from_str(compressed_pk) + .with_context(|| format!("invalid publisher public key '{}'", compressed_pk)) + }) + .collect::>>()?; + if usize::from(threshold) > publisher_public_keys.len() { + bail!( + "commit_info threshold {} exceeds publisher_public_keys length {}", + threshold, + publisher_public_keys.len() + ); + } + Ok((publisher_public_keys, threshold)) +} + +fn load_part_stark_vk_for_version(zkm_version: &str) -> Result> { + std::panic::catch_unwind(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec()) + .map_err(|_| anyhow::anyhow!("failed to load part_stark_vk for version '{zkm_version}'")) +} + +fn load_part_stark_vks_for_versions(ordered_versions: &[String]) -> Result>> { + ordered_versions.iter().map(|version| load_part_stark_vk_for_version(version)).collect() +} + +fn decode_publisher_secret_key_wif(value: &str) -> Result { + let private_key = + PrivateKey::from_wif(value).map_err(|err| format!("invalid publisher WIF key: {err}"))?; + Ok(private_key.inner) +} + +/// Resolve the signer index by matching the secret key derived public key against the active set. +fn resolve_signer_index( + secret_key: &SecretKey, + publisher_public_keys: &[PublicKey], +) -> Result { + let signer_public_key = PublicKey::from_secret_key(&Secp256k1::new(), secret_key); + publisher_public_keys.iter().position(|public_key| *public_key == signer_public_key).ok_or_else( + || anyhow::anyhow!("publisher_secret_key_wif does not belong to active publisher set"), + ) +} + +fn main() -> Result<()> { + dotenv::dotenv().ok(); + let cli = Cli::parse(); + + match cli.command { + Command::BuildTree { versions, attestation_dir } => { + let attestation_dir = resolve_attestation_dir(attestation_dir); + let ordered_versions = order_versions(&versions)?; + let part_stark_vks = load_part_stark_vks_for_versions(&ordered_versions)?; + save_latest_part_stark_vk_attestation_snapshot( + &attestation_dir, + &ordered_versions, + &part_stark_vks, + None, + None, + None, + vec![], + ) + .map_err(anyhow::Error::msg)?; + println!( + "built latest part_stark_vk snapshot in {} for versions {}", + attestation_dir.display(), + ordered_versions.join(",") + ); + } + Command::SignRoot { + versions, + commit_info_file, + publisher_secret_key_wif, + attestation_dir, + } => { + let attestation_dir = resolve_attestation_dir(attestation_dir); + let ordered_versions = order_versions(&versions)?; + let part_stark_vks = load_part_stark_vks_for_versions(&ordered_versions)?; + let (publisher_public_keys, threshold) = load_publisher_set(&commit_info_file)?; + let signer_pubkey_index = + resolve_signer_index(&publisher_secret_key_wif, &publisher_public_keys)?; + let manifest = sign_latest_part_stark_vk_snapshot( + &attestation_dir, + &ordered_versions, + &part_stark_vks, + &publisher_public_keys, + threshold, + signer_pubkey_index, + &publisher_secret_key_wif, + ) + .map_err(anyhow::Error::msg)?; + println!("{}", serde_json::to_string_pretty(&manifest)?); + } + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use bitcoin::Network; + use bitcoin::secp256k1::Secp256k1; + + #[test] + fn test_decode_publisher_secret_key_wif_accepts_wif() { + let secret_key = + SecretKey::from_str("0101010101010101010101010101010101010101010101010101010101010101") + .unwrap(); + let private_key = PrivateKey::new(secret_key, Network::Regtest); + + let decoded = decode_publisher_secret_key_wif(&private_key.to_wif()).unwrap(); + + assert_eq!(decoded, secret_key); + } + + #[test] + fn test_order_versions_sorts_semver_with_v_prefix() { + let ordered = + order_versions(&["v1.2.10".to_string(), "v1.2.4".to_string(), "v1.2.5".to_string()]) + .unwrap(); + assert_eq!(ordered, vec!["v1.2.4", "v1.2.5", "v1.2.10"]); + } + + #[test] + fn test_order_versions_rejects_duplicate_versions() { + let err = order_versions(&["v1.2.5".to_string(), "v1.2.5".to_string()]).unwrap_err(); + assert!(err.to_string().contains("duplicate")); + } + + #[test] + fn test_resolve_signer_index_matches_active_publisher_set_order() { + let secp = Secp256k1::new(); + let secret_key_0 = + SecretKey::from_str("0101010101010101010101010101010101010101010101010101010101010101") + .unwrap(); + let secret_key_1 = + SecretKey::from_str("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); + let secret_key_2 = + SecretKey::from_str("0303030303030303030303030303030303030303030303030303030303030303") + .unwrap(); + let publisher_public_keys = vec![ + PublicKey::from_secret_key(&secp, &secret_key_2), + PublicKey::from_secret_key(&secp, &secret_key_0), + PublicKey::from_secret_key(&secp, &secret_key_1), + ]; + + let signer_index = resolve_signer_index(&secret_key_0, &publisher_public_keys).unwrap(); + + assert_eq!(signer_index, 1); + } +} diff --git a/node/src/bin/sequencer-set-publish.rs b/node/src/bin/sequencer-set-publish.rs index d3900eb7..c6fe4f6c 100644 --- a/node/src/bin/sequencer-set-publish.rs +++ b/node/src/bin/sequencer-set-publish.rs @@ -111,6 +111,7 @@ impl OutputData { async fn save_commit_info( output_file: &str, btc_public_keys: &[secp256k1::PublicKey], + next_btc_public_keys: &[secp256k1::PublicKey], sequencers: Vec, init_genesis: bool, commit_info_file: &str, @@ -129,6 +130,10 @@ async fn save_commit_info( txid: txid.clone(), threshold: (btc_public_keys.len() * 2).div_ceil(3) as u16, publisher_public_keys: btc_public_keys.iter().map(|pubkey| pubkey.to_string()).collect(), + next_threshold: Some((next_btc_public_keys.len() * 2).div_ceil(3) as u16), + next_publisher_public_keys: Some( + next_btc_public_keys.iter().map(|pubkey| pubkey.to_string()).collect(), + ), genesis_txid, sequencers: sequencers.iter().cloned().map(|v| v.into()).collect(), }; @@ -361,7 +366,7 @@ async fn main() -> Result<(), Box> { &goat_client, owner_btc_key_wif, publisher_btc_pubkeys.clone(), - next_publisher_btc_pubkeys, + next_publisher_btc_pubkeys.clone(), fee_tx, update_connector, goat_block_number, @@ -373,6 +378,7 @@ async fn main() -> Result<(), Box> { match save_commit_info( &args.output_file, &publisher_btc_pubkeys, + &next_publisher_btc_pubkeys, sequencers, init_genesis, &commit_info, diff --git a/node/src/handle.rs b/node/src/handle.rs index de1f1860..25f644b7 100644 --- a/node/src/handle.rs +++ b/node/src/handle.rs @@ -3226,7 +3226,7 @@ async fn handle_disprove_ready_challenger( txins }; // 2. check assertions committed by Operator, if any assertion is invalid, sign & broadcast disprove txn - let vk = crate::vk::get_vk(&graph.parameters.zkm_version).await?; + let vk = crate::vk::get_vk().await?; let disprove_scripts = get_disprove_scripts(&graph.parameters).await?; let disprove_scripts = disprove_scripts.try_into().map_err(|_| anyhow!("Mismatch disprove scripts num"))?; diff --git a/node/src/lib.rs b/node/src/lib.rs index 3042c519..9ecafd89 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -39,7 +39,6 @@ mod dbg { use serde::Deserialize; use serde::Serialize; use uuid::Uuid; - use zkm_sdk::ZKM_CIRCUIT_VERSION; fn dbg_network() -> Network { Network::Testnet4 @@ -140,7 +139,6 @@ mod dbg { watchtower_pubkeys, hashlocks, guest_constant_value: [3u8; 32], - zkm_version: ZKM_CIRCUIT_VERSION.to_string(), } } fn build_dbg_simplified_graph() -> SimplifiedBitvm2Graph { @@ -171,6 +169,21 @@ mod dbg { ); } + #[test] + fn dbg_serde_ignores_legacy_graph_zkm_version() { + let graph = build_dbg_simplified_graph(); + let mut value = serde_json::to_value(&graph).unwrap(); + value + .get_mut("parameters") + .and_then(serde_json::Value::as_object_mut) + .unwrap() + .insert("zkm_version".to_string(), serde_json::Value::String("v1.2.5".to_string())); + + let decoded: SimplifiedBitvm2Graph = serde_json::from_value(value).unwrap(); + assert_eq!(decoded.parameters.graph_id, graph.parameters.graph_id); + assert_eq!(decoded.parameters.graph_nonce, graph.parameters.graph_nonce); + } + #[tokio::test] #[ignore = "requires local db"] async fn dbg_serde_from_db() { diff --git a/node/src/rpc_service/handler/bitvm2_handler.rs b/node/src/rpc_service/handler/bitvm2_handler.rs index 50b83a97..86448b72 100644 --- a/node/src/rpc_service/handler/bitvm2_handler.rs +++ b/node/src/rpc_service/handler/bitvm2_handler.rs @@ -838,7 +838,6 @@ pub async fn get_instances_overview( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 1699123456, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 @@ -931,7 +930,6 @@ pub async fn get_graph( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 1699123456, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 @@ -1034,7 +1032,6 @@ pub async fn get_graphs( /// "assert_commit_timeout_txids": [], /// "init_withdraw_tx_hash": null, /// "bridge_out_start_at": 0, -/// "zkm_version": "zkm1.0.0", /// "status_updated_at": 1699123456, /// "created_at": 1699123456, /// "updated_at": 1699123456 diff --git a/node/src/rpc_service/mod.rs b/node/src/rpc_service/mod.rs index 8e261b0d..b2a67541 100644 --- a/node/src/rpc_service/mod.rs +++ b/node/src/rpc_service/mod.rs @@ -581,7 +581,6 @@ mod tests { assert_commit_timeout_txids: vec![], init_withdraw_tx_hash: Some(format!("0x{}", hex::encode(generate_random_bytes(32)))), bridge_out_start_at: current_time_secs() + 100, - zkm_version: "zkm_0.1.0".to_string(), status_updated_at: current_time_secs(), proceed_withdraw_height: 0, created_at: current_time_secs(), @@ -617,7 +616,6 @@ mod tests { assert_commit_timeout_txids: vec![], init_withdraw_tx_hash: None, bridge_out_start_at: 0, - zkm_version: "zkm_0.1.0".to_string(), status_updated_at: current_time_secs(), proceed_withdraw_height: 0, created_at: current_time_secs(), diff --git a/node/src/utils.rs b/node/src/utils.rs index 5968d535..33dd76eb 100644 --- a/node/src/utils.rs +++ b/node/src/utils.rs @@ -56,6 +56,7 @@ use serde::{Deserialize, Serialize}; use std::fs::{self, File}; use std::io::{BufReader, BufWriter}; use std::net::SocketAddr; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -70,8 +71,8 @@ use store::{ PeginInstanceProcessData, SerializableTxid, UInt64Array3, }; use stun_client::{Attribute, Class, Client}; -use zkm_sdk::{ZKM_CIRCUIT_VERSION, ZKMProofWithPublicValues}; -use zkm_verifier::{GROTH16_VK_BYTES, convert_ark}; +use zkm_sdk::ZKMProofWithPublicValues; +use zkm_verifier::{Groth16Verifier, IMM_GROTH16_VK_BYTES, convert_ark_imm_wrap_vk}; use crate::env; use crate::rpc_service::routes::v1::{ @@ -1614,15 +1615,15 @@ pub async fn is_take2_timelock_expired( /// Loads partial scripts from a local cache file. /// If cache file does not exist, generate partial scripts by vk an cache it -pub async fn get_partial_scripts(version: String) -> Result> { - let scripts_cache_path = format!("{SCRIPT_CACHE_FILE_NAME}_{version}.bin"); +pub async fn get_partial_scripts() -> Result> { + let scripts_cache_path = format!("{SCRIPT_CACHE_FILE_NAME}.bin"); if Path::new(&scripts_cache_path).exists() { let file = File::open(scripts_cache_path)?; let reader = BufReader::new(file); let scripts_bytes: Vec = bincode::deserialize_from(reader)?; Ok(scripts_bytes) } else { - let partial_scripts = generate_partial_scripts(&get_vk(&version).await?); + let partial_scripts = generate_partial_scripts(&get_vk().await?); if let Some(parent) = Path::new(&scripts_cache_path).parent() { fs::create_dir_all(parent)?; }; @@ -1634,7 +1635,7 @@ pub async fn get_partial_scripts(version: String) -> Result> { } pub async fn get_disprove_scripts(graph_params: &Bitvm2GraphParameters) -> Result> { - let partial_scripts = get_partial_scripts(graph_params.zkm_version.clone()).await?; + let partial_scripts = get_partial_scripts().await?; let (mut disprove_scripts, disprove_scripts_1) = generate_disprove_scripts( &partial_scripts, graph_params.operator_wots_pubkeys.clone(), @@ -1751,17 +1752,27 @@ pub async fn broadcast_package( fn gen_watchtower_commitment(graph_id: Uuid, proof_data: ProofData) -> Result> { let graph_id = graph_id.as_bytes(); - let proof = - proof_data.proof.as_slice().try_into().map_err(|_| anyhow!("invalid proof length"))?; - let public_inputs = proof_data - .public_inputs - .as_slice() - .try_into() - .map_err(|_| anyhow!("invalid public inputs length"))?; + let proof = proof_data.proof.as_slice(); if proof_data.vk.len() != VK_HASH_SIZE { bail!("invalid vk_hash length"); } - Ok(build_watchtower_commitment(graph_id, proof, public_inputs, &proof_data.vk)) + if proof_data.proof_part_stark_vk.is_empty() { + bail!("missing proof_part_stark_vk"); + } + + build_watchtower_commitment( + graph_id, + proof, + &proof_data.public_inputs, + &proof_data.vk, + &proof_data.proof_part_stark_vk, + ) + .map_err(|e| anyhow!("failed to build watchtower commitment: {e}")) +} + +fn load_part_stark_vk_for_zkm_version(zkm_version: &str) -> Result> { + catch_unwind(AssertUnwindSafe(|| Groth16Verifier::get_part_stark_vk(zkm_version).to_vec())) + .map_err(|_| anyhow!("failed to load part_stark_vk for zkm_version {zkm_version}")) } // proof network @@ -1932,28 +1943,24 @@ pub async fn get_operator_proof( info!("get_operator_proof get proof successfully"); let proof: ZKMProofWithPublicValues = bincode::deserialize(proof_data.proof.as_slice()).unwrap(); - if proof.zkm_version != bitvm_graph.parameters.zkm_version { - bail!( - "zkm_version mismatch, expected {}, got {}", - bitvm_graph.parameters.zkm_version, - proof.zkm_version - ); - } - let (_best_btc_block_hash, constant, included_watchtower): ( - [u8; 32], - [u8; 32], - [u8; 32], - ) = proof.public_values.clone().read(); + let proof_part_stark_vk = load_part_stark_vk_for_zkm_version(&proof.zkm_version)?; + let output: bitcoin_light_client_circuit::OperatorPublicOutputs = + proof.public_values.clone().read(); // TODO: additionally check constant and included_watchtower with included_watchtowers. //proof.public_values.head(); info!("get_operator_proof parse proof successfully"); - let groth16_vk = &GROTH16_VK_BYTES; - let ark_proof = convert_ark(&proof, &proof_data.vk, groth16_vk).unwrap(); + let ark_proof = convert_ark_imm_wrap_vk( + &proof, + &proof_data.vk, + &IMM_GROTH16_VK_BYTES, + &proof_part_stark_vk, + ) + .map_err(|e| anyhow!("failed to convert operator proof to ark format: {e}"))?; info!("get_operator_proof parse proof successfully"); Ok(( Some(( - [constant, included_watchtower], + [output.constant, output.included_watchtowers], ark_proof.proof.clone(), ark_proof.public_inputs.into(), ark_proof.groth16_vk.into(), @@ -2692,7 +2699,6 @@ pub async fn build_graph_params( watchtower_pubkeys, hashlocks, guest_constant_value, - zkm_version: ZKM_CIRCUIT_VERSION.to_string(), // use the latest version }) } @@ -3856,7 +3862,6 @@ fn convert_graph(bitvm2_graph: &Bitvm2Graph, current_time: i64) -> Graph { .collect(), init_withdraw_tx_hash: None, bridge_out_start_at: 0, - zkm_version: bitvm2_graph.parameters.zkm_version.clone(), status_updated_at: current_time, proceed_withdraw_height: 0, created_at: current_time, @@ -4830,4 +4835,16 @@ mod tests { assert_eq!(url.as_str(), "http://127.0.0.1:8900/v1/proofs/operator_proofs"); } + + #[test] + fn test_load_part_stark_vk_for_zkm_version_accepts_known_version() { + let part_stark_vk = load_part_stark_vk_for_zkm_version("v1.2.4").unwrap(); + assert!(!part_stark_vk.is_empty()); + } + + #[test] + fn test_load_part_stark_vk_for_zkm_version_rejects_unknown_version_without_panic() { + let err = load_part_stark_vk_for_zkm_version("v0.0.0-test").unwrap_err(); + assert!(err.to_string().contains("failed to load part_stark_vk")); + } } diff --git a/node/src/vk.rs b/node/src/vk.rs index b202275f..708b3b6b 100644 --- a/node/src/vk.rs +++ b/node/src/vk.rs @@ -24,23 +24,23 @@ pub(crate) fn block_on(fut: impl std::future::Future) -> T { } } -pub async fn get_vk(zkm_version: &str) -> Result { - let build_dir = try_install_circuit_artifacts(zkm_version); +pub async fn get_vk() -> Result { + let build_dir = try_install_circuit_artifacts(); let vk_file = build_dir.join("groth16_vk.bin"); let content = fs::read(&vk_file)?; Ok(load_ark_groth16_verifying_key_from_bytes(&content)?) } #[must_use] -pub fn groth16_circuit_artifacts_dir(zkm_version: &str) -> PathBuf { - dirs::home_dir().unwrap().join(".zkm").join("circuits/groth16").join(zkm_version) +pub fn groth16_circuit_artifacts_dir() -> PathBuf { + dirs::home_dir().unwrap().join(".zkm").join("circuits/groth16/imm-wrap-vk") } /// Tries to install the groth16 circuit artifacts if they are not already installed. #[must_use] -pub fn try_install_circuit_artifacts(zkm_version: &str) -> PathBuf { +pub fn try_install_circuit_artifacts() -> PathBuf { let artifacts_type = "groth16"; - let build_dir = groth16_circuit_artifacts_dir(zkm_version); + let build_dir = groth16_circuit_artifacts_dir(); if build_dir.exists() { println!( @@ -49,19 +49,18 @@ pub fn try_install_circuit_artifacts(zkm_version: &str) -> PathBuf { build_dir.display() ); } else { - install_circuit_artifacts(build_dir.clone(), artifacts_type, zkm_version); + install_circuit_artifacts(build_dir.clone(), artifacts_type); } build_dir } #[allow(clippy::needless_pass_by_value)] -pub fn install_circuit_artifacts(build_dir: PathBuf, artifacts_type: &str, zkm_version: &str) { +pub fn install_circuit_artifacts(build_dir: PathBuf, artifacts_type: &str) { // Create the build directory. - std::fs::create_dir_all(&build_dir).expect("failed to create build directory"); + fs::create_dir_all(&build_dir).expect("failed to create build directory"); // Download the artifacts. - let download_url = - format!("{CIRCUIT_ARTIFACTS_URL_BASE}/{zkm_version}-{artifacts_type}.tar.gz"); + let download_url = format!("{CIRCUIT_ARTIFACTS_URL_BASE}/{artifacts_type}-imm-wrap-vk.tar.gz"); let mut artifacts_tar_gz_file = tempfile::NamedTempFile::new().expect("failed to create tempfile"); let client = reqwest::Client::builder().build().expect("failed to create reqwest client"); @@ -119,10 +118,10 @@ mod tests { #[tokio::test] #[ignore] async fn test_get_vk() { - let latest = zkm_sdk::ZKM_CIRCUIT_VERSION; - get_vk(latest).await.unwrap(); + let vk = get_vk().await.unwrap(); + let imm_v = + load_ark_groth16_verifying_key_from_bytes(&zkm_verifier::IMM_GROTH16_VK_BYTES).unwrap(); - let older = "v1.2.2"; - get_vk(older).await.unwrap(); + assert_eq!(vk, imm_v); } } diff --git a/proof-builder-rpc/src/api/proof_handler.rs b/proof-builder-rpc/src/api/proof_handler.rs index 09e935e6..37e72da4 100644 --- a/proof-builder-rpc/src/api/proof_handler.rs +++ b/proof-builder-rpc/src/api/proof_handler.rs @@ -226,6 +226,14 @@ pub(super) async fn post_watchtower_proof_task( let challenge_init_txid = InputValidator::validate_btc_txid(&payload.challenge_init_txid, "challenge_init_txid")? .to_string(); + let mut storage_process = + api_state.local_db.acquire().await.api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")?; + storage_process + .find_graph(&graph_id) + .await + .api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")? + .ok_or_else(|| anyhow::anyhow!("graph {graph_id} not found")) + .api_error("POST_WATCHTOWER_PROOF_TASK_ERROR")?; let watchtower_proof = find_watchtower_task(&api_state.local_db, instance_id, graph_id, &payload.public_key) diff --git a/proof-builder-rpc/src/task/mod.rs b/proof-builder-rpc/src/task/mod.rs index 09eb425a..e58fcb03 100644 --- a/proof-builder-rpc/src/task/mod.rs +++ b/proof-builder-rpc/src/task/mod.rs @@ -14,7 +14,6 @@ use ::header_chain_proof::HeaderChainProofBuilder; use ::state_chain_proof::StateChainProofBuilder; use bitcoin::{BlockHash, Network, Txid}; use client::btc_chain::BTCClient; -use commit_chain::CircuitCommit; use std::str::FromStr; use std::time::UNIX_EPOCH; use uuid::Uuid; @@ -276,7 +275,7 @@ async fn read_watchtower_challenge_details<'a>( if let Some(first) = challenge_init_txids.first() { if !challenge_init_txids.iter().all(|x| first == x) { anyhow::bail!( - "Inconsistant watchtower challenge info from instance {} and graph_id {}", + "Inconsistent watchtower challenge info from instance {} and graph_id {}", task.instance_id, task.graph_id ); @@ -477,17 +476,22 @@ pub(crate) async fn fetch_on_demand_task( }; tracing::info!("commit_chain_input_proof: {commit_chain_input_proof:?}"); let commit_chain_input_proof = commit_chain_input_proof.path_to_proof.unwrap(); - let file = format!("{commit_chain_input_proof}.commits"); - let content = match std::fs::read_to_string(&file) { - Ok(d) => d, - Err(e) => { - tracing::error!("read {file:?} error, {e}"); + let commits_file = format!("{commit_chain_input_proof}.commits"); + let commits: Vec = + match serde_json::from_str(&std::fs::read_to_string(&commits_file)?) { + Ok(commits) => commits, + Err(err) => { + tracing::warn!("Failed to read commit-chain commits, error: {err}"); + return Ok(None); + } + }; + let latest_sequencer_commit_txid = match commits.first() { + Some(commit) => commit.commit_txn.compute_txid().to_string(), + None => { + tracing::warn!("Commit-chain proof does not contain any commits yet"); return Ok(None); } }; - let commits: Vec = serde_json::from_str(&content)?; - let latest_sequencer_commit_txid = commits[0].commit_txn.compute_txid().to_string(); - Ok(Some(OnDemandTask { task_index, latest_sequencer_commit_txid,