diff --git a/Cargo.lock b/Cargo.lock index d30d20e48..c12c73c8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,12 +38,12 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding#1956325c245f48e3828ff79cc66cb8c5c54ffcda" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" dependencies = [ - "alloy-eips 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "serde", "sha2", ] @@ -62,14 +62,28 @@ dependencies = [ "sha2", ] +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "c-kzg", + "serde", + "sha2", +] + [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding#1956325c245f48e3828ff79cc66cb8c5c54ffcda" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" dependencies = [ "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "c-kzg", "serde", ] @@ -87,6 +101,19 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "c-kzg", + "once_cell", + "serde", +] + [[package]] name = "alloy-genesis" version = "0.1.0" @@ -97,6 +124,16 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "serde", +] + [[package]] name = "alloy-json-rpc" version = "0.1.0" @@ -108,6 +145,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "alloy-network" version = "0.1.0" @@ -115,10 +164,26 @@ source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a2 dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", - "alloy-json-rpc", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-primitives", - "alloy-rpc-types", - "alloy-signer", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "async-trait", + "futures-utils-wasm", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-primitives", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy)", "async-trait", "futures-utils-wasm", "thiserror", @@ -129,7 +194,7 @@ name = "alloy-node-bindings" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-primitives", "k256", "serde_json", @@ -166,19 +231,47 @@ name = "alloy-provider" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-json-rpc", - "alloy-network", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-primitives", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "lru", + "reqwest", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-provider" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-primitives", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-rpc-types-trace", - "alloy-transport", - "alloy-transport-http", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy)", "async-stream", "async-trait", "auto_impl", "dashmap", "futures", + "futures-utils-wasm", "lru", "reqwest", "serde_json", @@ -206,7 +299,7 @@ checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -214,9 +307,29 @@ name = "alloy-rpc-client" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "alloy-transport-http", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy)", "futures", "pin-project", "reqwest", @@ -236,7 +349,7 @@ source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a2 dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", - "alloy-genesis", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-primitives", "alloy-rlp", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", @@ -247,22 +360,52 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-sol-types", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "alloy-rpc-types-trace" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ "alloy-primitives", - "alloy-rpc-types", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "serde", "serde_json", ] +[[package]] +name = "alloy-rpc-types-trace" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "serde", + "serde_json", +] + [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding#1956325c245f48e3828ff79cc66cb8c5c54ffcda" +source = "git+https://github.com/alloy-rs/alloy?rev=cb95183#cb95183d477024b57b27336035d10403e8ba55b8" dependencies = [ "alloy-primitives", "serde", @@ -279,6 +422,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + [[package]] name = "alloy-signer" version = "0.1.0" @@ -292,6 +445,19 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" version = "0.7.0" @@ -305,7 +471,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "syn-solidity", "tiny-keccak", ] @@ -321,7 +487,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "syn-solidity", ] @@ -341,7 +507,25 @@ name = "alloy-transport" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "base64", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", + "wasm-bindgen-futures", +] + +[[package]] +name = "alloy-transport" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy)", "base64", "futures-util", "futures-utils-wasm", @@ -359,14 +543,42 @@ name = "alloy-transport-http" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=e3f2f07#e3f2f075a9e7ad9753a255dbe71dbad6a91ba96d" dependencies = [ - "alloy-json-rpc", - "alloy-transport", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "reqwest", "serde_json", "tower", "url", ] +[[package]] +name = "alloy-transport-http" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy#eb0d564f0105254b9fc29be6dde301d4a2b74ebc" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "reqwest", + "serde_json", + "tower", + "url", +] + +[[package]] +name = "alloy-trie" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb28aa4ecd32fdfa1b1bdd111ff7357dd562c6b2372694cf9e613434fcba659" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "hashbrown", + "nybbles", + "smallvec", + "tracing", +] + [[package]] name = "anyhow" version = "1.0.82" @@ -522,7 +734,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -533,7 +745,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -544,7 +756,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -693,9 +905,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -900,6 +1112,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "enumn" version = "0.1.13" @@ -908,7 +1129,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1058,7 +1279,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1142,6 +1363,25 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -1237,13 +1477,14 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http", "http-body", "httparse", @@ -1409,11 +1650,11 @@ dependencies = [ "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-node-bindings", "alloy-primitives", - "alloy-provider", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-rlp", - "alloy-rpc-client", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "alloy-sol-types", - "alloy-transport-http", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=e3f2f07)", "anyhow", "async-trait", "c-kzg", @@ -1434,6 +1675,25 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "kona-mpt" +version = "0.0.1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-primitives", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-rlp", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy)", + "alloy-trie", + "anyhow", + "reqwest", + "smallvec", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "kona-preimage" version = "0.0.1" @@ -1605,6 +1865,16 @@ dependencies = [ "libc", ] +[[package]] +name = "nybbles" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" +dependencies = [ + "const-hex", + "smallvec", +] + [[package]] name = "object" version = "0.32.2" @@ -1623,13 +1893,13 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "op-alloy-consensus" version = "0.1.0" -source = "git+https://github.com/clabby/op-alloy?branch=refcell/consensus-port#2d72c8ee077360ae0358e9c61f1bb37ac27be3b0" +source = "git+https://github.com/clabby/op-alloy?branch=refcell/consensus-port#74ed6337b600a7f77fa10568be0f054042f70400" dependencies = [ - "alloy-consensus 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", - "alloy-eips 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "alloy-primitives", "alloy-rlp", - "alloy-serde 0.1.0 (git+https://github.com/clabby/alloy?branch=cl/consensus-expose-encoding)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=cb95183)", "serde", ] @@ -1656,7 +1926,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1772,7 +2042,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -1856,9 +2126,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -1960,14 +2230,16 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "reqwest" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e6cc1e89e689536eb5aeede61520e874df5a4707df811cd5da4aa5fbb2aae19" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64", "bytes", + "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", @@ -1987,6 +2259,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -2100,9 +2373,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad" dependencies = [ "bitflags 2.5.0", "errno", @@ -2223,29 +2496,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2296,9 +2569,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2391,9 +2664,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2409,7 +2682,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2418,6 +2691,27 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tap" version = "1.0.1" @@ -2438,22 +2732,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2526,7 +2820,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2562,6 +2856,7 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -2629,7 +2924,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -2804,7 +3099,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-shared", ] @@ -2838,7 +3133,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3065,7 +3360,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] [[package]] @@ -3085,5 +3380,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.60", ] diff --git a/README.md b/README.md index fe54f5a84..cda866472 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ verify an [L2 output root][g-output-root] from the L1 inputs it was [derived fro - [`common`](./crates/common): A suite of utilities for developing `client` programs to be ran on top of Fault Proof VMs. - [`preimage`](./crates/preimage): High level interfaces to the [`PreimageOracle`][fpp-specs] ABI +- [`mpt`](./crrates/mpt): Utilities for interacting with the Merkle Patricia Trie in the client program. - [`derive`](./crates/derive): `no_std` compatible implementation of the [derivation pipeline][g-derivation-pipeline]. ## Book diff --git a/crates/mpt/Cargo.toml b/crates/mpt/Cargo.toml new file mode 100644 index 000000000..bdc70a6a1 --- /dev/null +++ b/crates/mpt/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "kona-mpt" +description = "Utilities for interacting with and iterating through a merkle patricia trie" +version = "0.0.1" +edition.workspace = true +authors.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true + +[dependencies] +# workspace +anyhow.workspace = true +tracing.workspace = true +alloy-primitives = { workspace = true, features = ["rlp"] } + +# External +alloy-trie = { version = "0.3.1", default-features = false } +alloy-rlp = { version = "0.3.4", default-features = false } +smallvec = "1.13" + +[dev-dependencies] +tokio = { version = "1.36.0", features = ["full"] } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0" } +alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0" } +alloy-consensus = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0" } +alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", version = "0.1.0" } +reqwest = "0.12" +tracing-subscriber = "0.3.18" diff --git a/crates/mpt/README.md b/crates/mpt/README.md new file mode 100644 index 000000000..44e4889ec --- /dev/null +++ b/crates/mpt/README.md @@ -0,0 +1,3 @@ +# `kona-mpt` + +Utilities for interacting with and iterating through a merkle patricia trie diff --git a/crates/mpt/src/lib.rs b/crates/mpt/src/lib.rs new file mode 100644 index 000000000..a0b59ff1a --- /dev/null +++ b/crates/mpt/src/lib.rs @@ -0,0 +1,16 @@ +#![doc = include_str!("../README.md")] +#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)] +#![deny(unused_must_use, rust_2018_idioms)] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#![no_std] + +extern crate alloc; + +mod node; +pub use node::{NodeElement, TrieNode}; + +mod list_walker; +pub use list_walker::OrderedListWalker; + +#[cfg(test)] +mod test_util; diff --git a/crates/mpt/src/list_walker.rs b/crates/mpt/src/list_walker.rs new file mode 100644 index 000000000..3aa0f8cbf --- /dev/null +++ b/crates/mpt/src/list_walker.rs @@ -0,0 +1,202 @@ +//! This module contains the [OrderedListWalker] struct, which allows for traversing an MPT root of +//! a derivable ordered list. + +use crate::{NodeElement, TrieNode}; +use alloc::{collections::VecDeque, vec}; +use alloy_primitives::{Bytes, B256}; +use alloy_rlp::{Decodable, EMPTY_STRING_CODE}; +use anyhow::{anyhow, Result}; +use core::{fmt::Display, marker::PhantomData}; + +/// A [OrderedListWalker] allows for traversing over a Merkle Patricia Trie containing a derivable +/// ordered list. +/// +/// Once it has ben hydrated with [Self::hydrate], the elements in the derivable list can be +/// iterated over using the [Iterator] implementation. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct OrderedListWalker { + /// The Merkle Patricia Trie root. + root: B256, + /// The leaf nodes of the derived list, in order. [None] if the tree has yet to be fully + /// traversed with [Self::hydrate]. + inner: Option>, + /// Phantom data + _phantom: PhantomData, +} + +impl OrderedListWalker +where + PreimageFetcher: Fn(B256) -> Result + Copy, +{ + /// Creates a new [OrderedListWalker], yet to be hydrated. + pub fn new(root: B256) -> Self { + Self { root, inner: None, _phantom: PhantomData } + } + + /// Creates a new [OrderedListWalker] and hydrates it with [Self::hydrate] and the given fetcher + /// immediately. + pub fn try_new_hydrated(root: B256, fetcher: PreimageFetcher) -> Result { + let mut walker = Self { root, inner: None, _phantom: PhantomData }; + walker.hydrate(fetcher)?; + Ok(walker) + } + + /// Hydrates the [OrderedListWalker]'s iterator with the leaves of the derivable list. If + /// `Self::inner` is [Some], this function will fail fast. + pub fn hydrate(&mut self, fetcher: PreimageFetcher) -> Result<()> { + // Do not allow for re-hydration if `inner` is `Some` and still contains elements. + if self.inner.is_some() && self.inner.as_ref().map(|s| s.len()).unwrap_or_default() > 0 { + anyhow::bail!("Iterator is already hydrated, and has not been consumed entirely.") + } + + // Get the preimage to the root node. + let root_trie_node = Self::get_trie_node(self.root, fetcher)?; + + // With small lists the iterator seems to use 0x80 (RLP empty string, unlike the others) + // as key for item 0, causing it to come last. We need to account for this, pulling the + // first element into its proper position. + let mut ordered_list = Self::fetch_leaves(root_trie_node, fetcher)?; + if !ordered_list.is_empty() { + if ordered_list.len() <= EMPTY_STRING_CODE as usize { + // If the list length is < 0x80, the final element is the first element. + let first = ordered_list.pop_back().ok_or(anyhow!("Empty list fetched"))?; + ordered_list.push_front(first); + } else { + // If the list length is > 0x80, the element at index 0x80-1 is the first element. + let first = ordered_list + .remove((EMPTY_STRING_CODE - 1) as usize) + .ok_or(anyhow!("Empty list fetched"))?; + ordered_list.push_front(first); + } + } + + self.inner = Some(ordered_list); + Ok(()) + } + + /// Traverses a [TrieNode], returning all values of child [TrieNode::Leaf] variants. + fn fetch_leaves(trie_node: TrieNode, fetcher: PreimageFetcher) -> Result> { + match trie_node { + TrieNode::Branch { stack } => { + let mut leaf_values = VecDeque::with_capacity(stack.len()); + for item in stack.into_iter() { + match item { + NodeElement::String(s) => { + // If the string is a hash, we need to grab the preimage for it and + // continue recursing. + let trie_node = Self::get_trie_node(s.as_ref(), fetcher)?; + leaf_values.append(&mut Self::fetch_leaves(trie_node, fetcher)?); + } + list @ NodeElement::List(_) => { + let trie_node = list.try_list_into_node()?; + leaf_values.append(&mut Self::fetch_leaves(trie_node, fetcher)?); + } + _ => { /* Skip over empty lists and strings; We're looking for leaves */ } + } + } + Ok(leaf_values) + } + TrieNode::Leaf { value, .. } => Ok(vec![value].into()), + TrieNode::Extension { node, .. } => { + // If the node is a hash, we need to grab the preimage for it and continue + // recursing. + let trie_node = Self::get_trie_node(node.as_ref(), fetcher)?; + Ok(Self::fetch_leaves(trie_node, fetcher)?) + } + } + } + + /// Grabs the preimage of `hash` using `fetcher`, and attempts to decode the preimage data into + /// a [TrieNode]. Will error if the conversion of `T` into [B256] fails. + fn get_trie_node(hash: T, fetcher: PreimageFetcher) -> Result + where + T: TryInto, + >::Error: Display, + { + let hash = hash.try_into().map_err(|e| anyhow!("Error in conversion: {e}"))?; + let preimage = fetcher(hash)?; + TrieNode::decode(&mut preimage.as_ref()).map_err(|e| anyhow!(e)) + } +} + +impl Iterator for OrderedListWalker { + type Item = Bytes; + + fn next(&mut self) -> Option { + match self.inner { + Some(ref mut leaves) => leaves.pop_front(), + _ => None, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test_util::{ + get_live_derivable_receipts_list, get_live_derivable_transactions_list, + ordered_trie_with_encoder, + }; + use alloc::{collections::BTreeMap, string::String, vec::Vec}; + use alloy_consensus::{ReceiptEnvelope, TxEnvelope}; + use alloy_primitives::keccak256; + use alloy_provider::network::eip2718::Decodable2718; + use alloy_rlp::Encodable; + + #[tokio::test] + async fn test_list_walker_online_receipts() { + let (root, preimages, envelopes) = get_live_derivable_receipts_list().await.unwrap(); + let list = + OrderedListWalker::try_new_hydrated(root, |f| Ok(preimages.get(&f).unwrap().clone())) + .unwrap(); + + assert_eq!( + list.into_iter() + .map(|rlp| ReceiptEnvelope::decode_2718(&mut rlp.as_ref()).unwrap()) + .collect::>(), + envelopes + ); + } + + #[tokio::test] + async fn test_list_walker_online_transactions() { + let (root, preimages, envelopes) = get_live_derivable_transactions_list().await.unwrap(); + let list = + OrderedListWalker::try_new_hydrated(root, |f| Ok(preimages.get(&f).unwrap().clone())) + .unwrap(); + + assert_eq!( + list.into_iter() + .map(|rlp| TxEnvelope::decode(&mut rlp.as_ref()).unwrap()) + .collect::>(), + envelopes + ); + } + + #[test] + fn test_list_walker() { + const VALUES: [&str; 3] = ["test one", "test two", "test three"]; + + let mut trie = ordered_trie_with_encoder(&VALUES, |v, buf| v.encode(buf)); + let root = trie.root(); + + let preimages = + trie.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + acc.insert(keccak256(value.as_ref()), value); + acc + }); + + let list = + OrderedListWalker::try_new_hydrated(root, |f| Ok(preimages.get(&f).unwrap().clone())) + .unwrap(); + + assert_eq!( + list.inner + .unwrap() + .iter() + .map(|v| String::decode(&mut v.as_ref()).unwrap()) + .collect::>(), + VALUES + ); + } +} diff --git a/crates/mpt/src/node.rs b/crates/mpt/src/node.rs new file mode 100644 index 000000000..105ae1fc8 --- /dev/null +++ b/crates/mpt/src/node.rs @@ -0,0 +1,191 @@ +//! This module contains the [TrieNode] type, which allows for decoding the RLP + +use alloc::{collections::VecDeque, vec::Vec}; +use alloy_primitives::Bytes; +use alloy_rlp::{Buf, Decodable, EMPTY_LIST_CODE, EMPTY_STRING_CODE}; +use anyhow::{anyhow, Result}; + +/// The length of the branch list when RLP encoded +const BRANCH_LIST_LENGTH: usize = 17; + +/// The length of a leaf or extension node's RLP encoded list +const LEAF_OR_EXTENSION_LIST_LENGTH: usize = 2; + +/// Prefix for even-nibbled extension node paths. +const PREFIX_EXTENSION_EVEN: u8 = 0; + +/// Prefix for odd-nibbled extension node paths. +const PREFIX_EXTENSION_ODD: u8 = 1; + +/// Prefix for even-nibbled leaf node paths. +const PREFIX_LEAF_EVEN: u8 = 2; + +/// Prefix for odd-nibbled leaf node paths. +const PREFIX_LEAF_ODD: u8 = 3; + +/// A [TrieNode] is a node within a standard Merkle Patricia Trie. +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum TrieNode { + /// A branch node refers to up to 16 child nodes with the encoding `rlp([ v0, ..., v15, value + /// ])` + Branch { + /// The 16 child nodes and value of the branch. + stack: VecDeque, + }, + /// A leaf node is a 2-item node with the encoding `rlp([encoded_path, value])` + Leaf { + /// The key of the leaf node + key: Bytes, + /// The value of the leaf node + value: Bytes, + }, + /// An extension node is a 2-item pointer node with the encoding `rlp([encoded_path, key])` + Extension { + /// The path prefix of the extension + prefix: Bytes, + /// The pointer to the child node + node: Bytes, + }, +} + +impl TrieNode { + /// Attempts to convert a `path` and `value` into a [TrieNode], if they correspond to a + /// [TrieNode::Leaf] or [TrieNode::Extension]. + pub fn try_from_path_and_value(path: Bytes, value: Bytes) -> Result { + match path[0] >> 4 { + PREFIX_EXTENSION_EVEN | PREFIX_EXTENSION_ODD => { + // extension node + Ok(TrieNode::Extension { prefix: path, node: value }) + } + PREFIX_LEAF_EVEN | PREFIX_LEAF_ODD => { + // leaf node + Ok(TrieNode::Leaf { key: path, value }) + } + _ => { + anyhow::bail!("Unexpected path identifier in high-order nibble") + } + } + } +} + +impl Decodable for TrieNode { + /// Attempts to decode the [TrieNode]. + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + let mut list: VecDeque<_> = Vec::::decode(buf)?.into(); + + match list.len() { + BRANCH_LIST_LENGTH => Ok(Self::Branch { stack: list }), + LEAF_OR_EXTENSION_LIST_LENGTH => { + let Some(NodeElement::String(path)) = list.pop_front() else { + return Err(alloy_rlp::Error::UnexpectedList); + }; + let Some(NodeElement::String(value)) = list.pop_front() else { + return Err(alloy_rlp::Error::UnexpectedList); + }; + + Self::try_from_path_and_value(path, value) + .map_err(|_| alloy_rlp::Error::UnexpectedList) + } + _ => Err(alloy_rlp::Error::UnexpectedLength), + } + } +} + +/// A [NodeElement] is an element within a MPT node's RLP array +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum NodeElement { + /// An RLP String + String(Bytes), + /// An empty RLP string (0x80) + EmptyString, + /// An RLP List + List(VecDeque), + /// An empty RLP list (0xC0) + EmptyList, +} + +impl NodeElement { + /// Attempts to convert `Self` into a [TrieNode::Leaf] or [TrieNode::Extension], if `Self` is a + /// [NodeElement::List] variant. + pub fn try_list_into_node(self) -> Result { + if let NodeElement::List(mut list) = self { + if list.len() != LEAF_OR_EXTENSION_LIST_LENGTH { + anyhow::bail!("Invalid length"); + } + + let path = list.pop_front().ok_or(anyhow!("List is empty; Impossible case"))?; + let value = list.pop_front().ok_or(anyhow!("List is empty; Impossible case"))?; + TrieNode::try_from_path_and_value(path, value) + } else { + anyhow::bail!("Self is not a list") + } + } +} + +impl Decodable for NodeElement { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + match buf[0] { + EMPTY_STRING_CODE => { + buf.advance(1); + Ok(Self::EmptyString) + } + EMPTY_LIST_CODE => { + buf.advance(1); + Ok(Self::EmptyList) + } + EMPTY_LIST_CODE.. => Ok(Self::List(Vec::::decode(buf)?.into())), + _ => Ok(Self::String(Bytes::decode(buf)?)), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use alloc::vec; + use alloy_primitives::{bytes, hex}; + + #[test] + fn test_decode_branch() { + const BRANCH_RLP: [u8; 64] = hex!("f83ea0eb08a66a94882454bec899d3e82952dcc918ba4b35a09a84acd98019aef4345080808080808080cd308b8a746573742074687265658080808080808080"); + let expected = TrieNode::Branch { + stack: vec![ + NodeElement::String(bytes!( + "eb08a66a94882454bec899d3e82952dcc918ba4b35a09a84acd98019aef43450" + )), + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::List(vec![bytes!("30"), bytes!("8a74657374207468726565")].into()), + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + NodeElement::EmptyString, + ] + .into(), + }; + assert_eq!(expected, TrieNode::decode(&mut BRANCH_RLP.as_slice()).unwrap()); + } + + #[test] + fn test_decode_extension() { + const EXTENSION_RLP: [u8; 10] = hex!("c98300646f8476657262"); + let expected = TrieNode::Extension { prefix: bytes!("00646f"), node: bytes!("76657262") }; + assert_eq!(expected, TrieNode::decode(&mut EXTENSION_RLP.as_slice()).unwrap()); + } + + #[test] + fn test_decode_leaf() { + const LEAF_RLP: [u8; 11] = hex!("ca8320646f8576657262FF"); + let expected = TrieNode::Leaf { key: bytes!("20646f"), value: bytes!("76657262FF") }; + assert_eq!(expected, TrieNode::decode(&mut LEAF_RLP.as_slice()).unwrap()); + } +} diff --git a/crates/mpt/src/test_util.rs b/crates/mpt/src/test_util.rs new file mode 100644 index 000000000..49194d0e8 --- /dev/null +++ b/crates/mpt/src/test_util.rs @@ -0,0 +1,167 @@ +//! Testing utilities for `kona-mpt` + +extern crate std; + +use alloc::{collections::BTreeMap, vec::Vec}; +use alloy_consensus::{Receipt, ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType}; +use alloy_primitives::{keccak256, Bytes, Log, B256}; +use alloy_provider::{network::eip2718::Encodable2718, Provider, ProviderBuilder}; +use alloy_rlp::{BufMut, Encodable}; +use alloy_rpc_types::BlockTransactions; +use alloy_trie::{HashBuilder, Nibbles}; +use anyhow::{anyhow, Result}; +use reqwest::Url; + +const RPC_URL: &str = "https://docs-demo.quiknode.pro/"; + +/// Grabs a live merkleized receipts list within a block header. +pub(crate) async fn get_live_derivable_receipts_list( +) -> Result<(B256, BTreeMap, Vec)> { + // Initialize the provider. + let provider = ProviderBuilder::new() + .on_http(Url::parse(RPC_URL).expect("invalid rpc url")) + .map_err(|e| anyhow!(e))?; + + let block_number = 19005266; + let block = provider + .get_block(block_number.into(), true) + .await + .map_err(|e| anyhow!(e))? + .ok_or(anyhow!("Missing block"))?; + let receipts = provider + .get_block_receipts(block_number.into()) + .await + .map_err(|e| anyhow!(e))? + .ok_or(anyhow!("Missing receipts"))?; + + let consensus_receipts = receipts + .into_iter() + .map(|r| { + let rpc_receipt = r.inner.as_receipt_with_bloom().expect("Infalliable"); + let consensus_receipt = ReceiptWithBloom::new( + Receipt { + status: rpc_receipt.receipt.status, + cumulative_gas_used: rpc_receipt.receipt.cumulative_gas_used, + logs: rpc_receipt + .receipt + .logs + .iter() + .map(|l| Log { address: l.address(), data: l.data().clone() }) + .collect(), + }, + rpc_receipt.logs_bloom, + ); + + match r.transaction_type() { + TxType::Legacy => ReceiptEnvelope::Legacy(consensus_receipt), + TxType::Eip2930 => ReceiptEnvelope::Eip2930(consensus_receipt), + TxType::Eip1559 => ReceiptEnvelope::Eip1559(consensus_receipt), + TxType::Eip4844 => ReceiptEnvelope::Eip4844(consensus_receipt), + } + }) + .collect::>(); + + // Compute the derivable list + let mut list = + ordered_trie_with_encoder(consensus_receipts.as_ref(), |rlp, buf| rlp.encode_2718(buf)); + let root = list.root(); + + // Sanity check receipts root is correct + assert_eq!(block.header.receipts_root, root); + + // Construct the mapping of hashed intermediates -> raw intermediates + let preimages = + list.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + acc.insert(keccak256(value.as_ref()), value); + acc + }); + + Ok((root, preimages, consensus_receipts)) +} + +/// Grabs a live merkleized transactions list within a block header. +pub(crate) async fn get_live_derivable_transactions_list( +) -> Result<(B256, BTreeMap, Vec)> { + // Initialize the provider. + let provider = ProviderBuilder::new() + .on_http(Url::parse(RPC_URL).expect("invalid rpc url")) + .map_err(|e| anyhow!(e))?; + + let block_number = 19005266; + let block = provider + .get_block(block_number.into(), true) + .await + .map_err(|e| anyhow!(e))? + .ok_or(anyhow!("Missing block"))?; + + let BlockTransactions::Full(txs) = block.transactions else { + anyhow::bail!("Did not fetch full block"); + }; + let consensus_txs = txs + .into_iter() + .map(|tx| TxEnvelope::try_from(tx).map_err(|e| anyhow!(e))) + .collect::>>()?; + + // Compute the derivable list + let mut list = + ordered_trie_with_encoder(consensus_txs.as_ref(), |rlp, buf| rlp.encode_2718(buf)); + let root = list.root(); + + // Sanity check transaction root is correct + assert_eq!(block.header.transactions_root, root); + + // Construct the mapping of hashed intermediates -> raw intermediates + let preimages = + list.take_proofs().into_iter().fold(BTreeMap::default(), |mut acc, (_, value)| { + acc.insert(keccak256(value.as_ref()), value); + acc + }); + + Ok((root, preimages, consensus_txs)) +} + +/// Compute a trie root of the collection of items with a custom encoder. +pub(crate) fn ordered_trie_with_encoder(items: &[T], mut encode: F) -> HashBuilder +where + F: FnMut(&T, &mut dyn BufMut), +{ + let mut index_buffer = Vec::new(); + let mut value_buffer = Vec::new(); + let items_len = items.len(); + + // Store preimages for all intermediates + let path_nibbles = (0..items_len) + .map(|i| { + let i = adjust_index_for_rlp(i, items_len); + index_buffer.clear(); + i.encode(&mut index_buffer); + Nibbles::unpack(&index_buffer) + }) + .collect::>(); + + let mut hb = HashBuilder::default().with_proof_retainer(path_nibbles); + for i in 0..items_len { + let index = adjust_index_for_rlp(i, items_len); + + index_buffer.clear(); + index.encode(&mut index_buffer); + + value_buffer.clear(); + encode(&items[index], &mut value_buffer); + + hb.add_leaf(Nibbles::unpack(&index_buffer), &value_buffer); + } + + hb +} + +/// Adjust the index of an item for rlp encoding. +pub(crate) const fn adjust_index_for_rlp(i: usize, len: usize) -> usize { + if i > 0x7f { + i + } else if i == 0x7f || i + 1 == len { + 0 + } else { + i + 1 + } +}