From 72378dec448ac4570be4df64e1bfc79f28afea14 Mon Sep 17 00:00:00 2001 From: clabby Date: Tue, 4 Jun 2024 16:07:36 -0400 Subject: [PATCH] feat(client): `StatelessL2BlockExecutor` Implements the `StatelessL2BlockExecutor`, capable of executing `L2ExecutionPayloadEnvelope`s and returning the block header + receipts. The `StatelessL2BlockExecutor` is backed by the `TrieDB` in the `kona-mpt` crate, fetching necessary data from the initial state root as well as the starting parent block hash. --- Cargo.lock | 98 ++- bin/programs/client/Cargo.toml | 13 +- bin/programs/client/src/executor/mod.rs | 3 - bin/programs/client/src/l2/executor/canyon.rs | 53 ++ .../client/src/l2/executor/eip4788.rs | 169 +++++ .../client/src/l2/executor/fetcher.rs | 58 ++ bin/programs/client/src/l2/executor/mod.rs | 612 ++++++++++++++++++ bin/programs/client/src/l2/executor/util.rs | 30 + bin/programs/client/src/l2/mod.rs | 5 + bin/programs/client/src/lib.rs | 2 +- ...21ed4da5aaff39d9670da80741d5e574cba420.bin | Bin 0 -> 107 bytes ...33f0840f1547508eef2a4d52f8d69a544ac4c9.bin | Bin 0 -> 532 bytes ...6ada075122b884e91f329137c9e391d9dc1048.bin | Bin 0 -> 532 bytes ...be03b27cf42b3266607d7c2999c30d56a84877.bin | Bin 0 -> 48 bytes ...e195b466ffac16bfffed0ecaaddf6f55b9395a.bin | Bin 0 -> 532 bytes ...1280fb2f8e62e78529d271d56149b89c1fcf07.bin | Bin 0 -> 532 bytes ...9386dd2923276b6b61d6e9bb330a985859c3e1.bin | 1 + ...21b1e874ef08d29d2cf7752eec126edf941b37.bin | Bin 0 -> 532 bytes ...999f1fe3e85a6a994ed13630b80dad4b76fe11.bin | 4 + ...dbd0a9da2dc3ea638ae2e45e64ab10fb6fc568.bin | Bin 0 -> 532 bytes ...515bf9edc4374c5ed54b5e4f02442158c28e34.bin | Bin 0 -> 532 bytes ...b6dbb0d4b19265cc9337b8789fe1353bd9dc35.bin | Bin 0 -> 2055 bytes ...aecc5592a2036c4872d8dd9f6aca5efa638322.bin | 5 + ...48c2032668072f70a96f392955c659139bde84.bin | Bin 0 -> 83 bytes ...1141bb607e29e71815eacddaf53951b939a103.bin | Bin 0 -> 532 bytes ...282be0345b49d7b6ae99eead54f48ace81429f.bin | Bin 0 -> 532 bytes ...6e99e509a0f248680842519fe482101d5f8ae8.bin | Bin 0 -> 532 bytes ...7b90065f487eb6f2cd322e12b6c5f259f48331.bin | Bin 0 -> 532 bytes ...4b344cd5f9ae4ed7b64a53bf7d9299a455e294.bin | Bin 0 -> 532 bytes ...335f4c5ebba6ae74ffcba29096bbcd41cfd309.bin | 1 + ...6b513f8757798448a88cafb724b69afb46cacb.bin | Bin 0 -> 532 bytes ...9e0be494cefa9abecb78672efe84b10d712486.bin | Bin 0 -> 532 bytes ...4e163f3f6ad7c248ca5be17c3fb5d6bade741c.bin | 2 + ...4090e9507f4816b809698d2646574756a13055.bin | Bin 0 -> 532 bytes ...6a360932cea7111ce49194d74ce9247fdd91a4.bin | Bin 0 -> 532 bytes ...dd798d1558e6140fe562bc45c183adcf719bbd.bin | 2 + ...acafbfd7c68ca8b0ccb680a978c6baf9d405f1.bin | 1 + ...3323dd9e8079300ca7244b66d2f1bb81369232.bin | Bin 0 -> 532 bytes ...71a13832136334df872de0de199ca078bc6b59.bin | Bin 0 -> 532 bytes ...7937e579f30f9774d640b98e755b9e765f38d3.bin | Bin 0 -> 340 bytes ...0254fb6421a563fb0e4de659d96406fd8e13b0.bin | Bin 0 -> 243 bytes ...cbb7959d7cdde7b327edcea6df6530a73df9d4.bin | Bin 0 -> 532 bytes ...cf21610f828cf12b27e9b2729967b635a5e626.bin | Bin 0 -> 50 bytes ...ae630ef0cc8213af81f0f9997aaf5e80c42ecc.bin | Bin 0 -> 532 bytes ...a86882570fe18d42fb8f74b47951d56d6cef7a.bin | 1 + ...79e5859580442531fc987343ba45015e33e62a.bin | 3 + ...5de8775cf0a7ec3158873c36ba8daaa8bd3741.bin | 1 + ...517971bb8d213de1e23225e2b20d36a5b6427c.bin | Bin 0 -> 532 bytes ...d6ee93a74f878325dfcee0d4ffc1f1fdeaf48b.bin | Bin 0 -> 532 bytes ...63bdf6a3e1de9a038e9925238338b7e9aa3991.bin | 1 + ...69497890c31426e6470fe6b031ce3f325c215d.bin | Bin 0 -> 532 bytes ...2143936b5eec73a11e55b6b5ac4b50773e74eb.bin | Bin 0 -> 532 bytes ...980549697169300bc98bd7eeb73a67587ccab2.bin | 2 + ...9ba07843dd931d60fbf9dbf8e2eb20ddd89ae5.bin | Bin 0 -> 179 bytes ...8f96378066946d80e89f06cac1e9ffbe68fb26.bin | Bin 0 -> 56 bytes ...608f9fe8c48ed2072fad4abb382693703966a0.bin | Bin 0 -> 532 bytes ...bbeff2fe5e9b902da35a14f8fb52ea3eb2d983.bin | Bin 0 -> 532 bytes ...141e778f9b674d1d322962eed900f02c29990a.bin | 1 + ...34c9d3eeb459516f0b8b6a4258b51ee331547e.bin | Bin 0 -> 179 bytes ...9ae41e04243b7008cf3eadb29256d4a71c1dfd.bin | Bin 0 -> 1342 bytes ...526fff934018f736ac9f54f960a93c05d58bb6.bin | Bin 0 -> 276 bytes ...9841035e7f680b194632c6476a73e7bf8d1a15.bin | Bin 0 -> 532 bytes ...04c5d3ae209d2c8f17b89d8e4efb05feec8f47.bin | 2 + ...c5be0cdb279310f8b5fd8e5e570ddc859f762f.bin | Bin 0 -> 115 bytes ...777299115b0d82dc29cbf3ff675479d84a27be.bin | 1 + ...95f2a338ba985b163c11d9baf809b800cf84e5.bin | Bin 0 -> 532 bytes ...1f3954bf05cc09100bc7a4ae61bc6211f758e1.bin | 1 + ...2d78b266c212c1faf9256b5d8f65bcd691caea.bin | Bin 0 -> 532 bytes ...3fc6c613e9e31d085be80a811400fa39c36b29.bin | Bin 0 -> 532 bytes ...2ffcd32eb1769fde2bf351899eea45d90f2f7d.bin | 2 + ...f724b22ab7819aea4e3d67f5d5281869309c91.bin | Bin 0 -> 276 bytes ...6466e22f7eb3b698ed91095cdfa9c0961a7170.bin | Bin 0 -> 532 bytes ...eedd580b152fda82bb5652d76b6cb4dcbf0802.bin | Bin 0 -> 532 bytes ...52f3d35588dadf919ee1f0e3cb9b62d3f4b02c.bin | Bin 0 -> 97 bytes ...23638298b5dda2fff1b5edf224ce88d14e3e4b.bin | Bin 0 -> 39 bytes crates/derive/Cargo.toml | 2 +- crates/mpt/src/db/mod.rs | 96 +-- crates/mpt/src/fetcher.rs | 63 ++ crates/mpt/src/lib.rs | 3 + crates/mpt/src/list_walker.rs | 48 +- crates/mpt/src/node.rs | 63 +- crates/mpt/src/test_util.rs | 33 +- crates/primitives/src/payload.rs | 41 +- 83 files changed, 1197 insertions(+), 226 deletions(-) delete mode 100644 bin/programs/client/src/executor/mod.rs create mode 100644 bin/programs/client/src/l2/executor/canyon.rs create mode 100644 bin/programs/client/src/l2/executor/eip4788.rs create mode 100644 bin/programs/client/src/l2/executor/fetcher.rs create mode 100644 bin/programs/client/src/l2/executor/mod.rs create mode 100644 bin/programs/client/src/l2/executor/util.rs create mode 100644 bin/programs/client/src/l2/mod.rs create mode 100644 bin/programs/client/testdata/block_120794432_exec/01c9e411b33995639dce57799621ed4da5aaff39d9670da80741d5e574cba420.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/024f07c1de57fb4709c0485fe433f0840f1547508eef2a4d52f8d69a544ac4c9.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/029298bf41ace28a77846e89856ada075122b884e91f329137c9e391d9dc1048.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/0a966e78d9a8026bdb70032888be03b27cf42b3266607d7c2999c30d56a84877.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/11625c9d4e7bb3fe3c4a7a221fe195b466ffac16bfffed0ecaaddf6f55b9395a.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/13df272d502299b4847ed747ad1280fb2f8e62e78529d271d56149b89c1fcf07.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/14a0646914bb81f97bab254df79386dd2923276b6b61d6e9bb330a985859c3e1.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/16cecc8df1727ea4d64fe5d64021b1e874ef08d29d2cf7752eec126edf941b37.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/16f30348a3650a8dda66cd4233999f1fe3e85a6a994ed13630b80dad4b76fe11.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/19ff14f7c4e836a32b0b814cf6dbd0a9da2dc3ea638ae2e45e64ab10fb6fc568.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/1b2eacdf6bd937041d50d520b1515bf9edc4374c5ed54b5e4f02442158c28e34.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/23867707929adfff9c3e99737caecc5592a2036c4872d8dd9f6aca5efa638322.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/2699a8471589af386d86059a5a48c2032668072f70a96f392955c659139bde84.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/26aaaadb0bfeecf65b1ba917d31141bb607e29e71815eacddaf53951b939a103.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/3b6b8e909eb7507402c051aff6282be0345b49d7b6ae99eead54f48ace81429f.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/40368bab3a53e76940958bc92c6e99e509a0f248680842519fe482101d5f8ae8.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/48fff8f1fd80c81eaa3c6184627b90065f487eb6f2cd322e12b6c5f259f48331.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4974e12df5974fdbd2f9988aed4b344cd5f9ae4ed7b64a53bf7d9299a455e294.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4c95cf2cb1d0d7b2548c4b6a16335f4c5ebba6ae74ffcba29096bbcd41cfd309.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4e03be42805687850c90ebc9086b513f8757798448a88cafb724b69afb46cacb.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4e1b08d0262bfdfd06ac3d950f9e0be494cefa9abecb78672efe84b10d712486.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4e209eafb77d208ff7dc6601124e163f3f6ad7c248ca5be17c3fb5d6bade741c.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4e3ea077078e2400e198de0edb4090e9507f4816b809698d2646574756a13055.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/4f170a13fab02b6a6c41a61a3a6a360932cea7111ce49194d74ce9247fdd91a4.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/52a58c59207755dde82f58a514dd798d1558e6140fe562bc45c183adcf719bbd.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/52ac577eff8e570d3553a41f94acafbfd7c68ca8b0ccb680a978c6baf9d405f1.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/530152cfb9990c122ab1693f3d3323dd9e8079300ca7244b66d2f1bb81369232.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/5c1518b897b616053778ecd26c71a13832136334df872de0de199ca078bc6b59.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/6ef4fb49c50e658b8e5f5d03197937e579f30f9774d640b98e755b9e765f38d3.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/773afa9eb6d04bb86ffb3ddd850254fb6421a563fb0e4de659d96406fd8e13b0.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/78b3719e6377f9e9e185d60714cbb7959d7cdde7b327edcea6df6530a73df9d4.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/8007b5cf62bed7907f876f97c1cf21610f828cf12b27e9b2729967b635a5e626.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/85a02af3629156a9c1a7da0434ae630ef0cc8213af81f0f9997aaf5e80c42ecc.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/8c6ffe2ed314659019111c3e6ea86882570fe18d42fb8f74b47951d56d6cef7a.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/96bee8bd2cdf004aaa65ebb41579e5859580442531fc987343ba45015e33e62a.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/9dfe90e2c2b8bef643fde8a4415de8775cf0a7ec3158873c36ba8daaa8bd3741.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/a0b24abb13d6149947247a8817517971bb8d213de1e23225e2b20d36a5b6427c.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/a38158f9a821924e38eab475e0d6ee93a74f878325dfcee0d4ffc1f1fdeaf48b.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/a4739db65ed82b002d1501b15e63bdf6a3e1de9a038e9925238338b7e9aa3991.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/a5e9953f800a99d4bc8dde35fa69497890c31426e6470fe6b031ce3f325c215d.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/ac6481216c3ec3a3bba356cf022143936b5eec73a11e55b6b5ac4b50773e74eb.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/b567c54f0bc7034c18e906e583980549697169300bc98bd7eeb73a67587ccab2.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/b7a27b4f2673d087c9a6bd9a989ba07843dd931d60fbf9dbf8e2eb20ddd89ae5.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/b95180726e05e0a34e4ac7a2f88f96378066946d80e89f06cac1e9ffbe68fb26.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/bb1f3a144706c1e341edd2ca22608f9fe8c48ed2072fad4abb382693703966a0.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/c4c73aa63f92bfdd5e1c760f9bbbeff2fe5e9b902da35a14f8fb52ea3eb2d983.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990a.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/c88974f0129bb5e31fcf9ee30734c9d3eeb459516f0b8b6a4258b51ee331547e.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/c88a313aa75dc4fbf0b6850d9f9ae41e04243b7008cf3eadb29256d4a71c1dfd.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/c96741e51de476969656bfa630526fff934018f736ac9f54f960a93c05d58bb6.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/cadbb3ac372d814135a40809fa9841035e7f680b194632c6476a73e7bf8d1a15.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/ccf9e7c516f45cfe7d4e6ff62704c5d3ae209d2c8f17b89d8e4efb05feec8f47.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/d1ec58cd69ee695261b81e8263c5be0cdb279310f8b5fd8e5e570ddc859f762f.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/d1f04aeacdaf9febee874d8ed7777299115b0d82dc29cbf3ff675479d84a27be.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/d6f5eea5b42f36238f9787bb4c95f2a338ba985b163c11d9baf809b800cf84e5.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/de08b8f9278b9f92d19c79eca21f3954bf05cc09100bc7a4ae61bc6211f758e1.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/e13022cf22b02f4168185a84172d78b266c212c1faf9256b5d8f65bcd691caea.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/e8950c5620c8c3e797ab0c74fb3fc6c613e9e31d085be80a811400fa39c36b29.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/e9ad57c7ea3d3e54221946c77f2ffcd32eb1769fde2bf351899eea45d90f2f7d.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/eab3f67aad27e7e1b2d534a1b5f724b22ab7819aea4e3d67f5d5281869309c91.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/eac162a574d5e95b1c1466f5136466e22f7eb3b698ed91095cdfa9c0961a7170.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/ee5d62827673b76fae02f5114feedd580b152fda82bb5652d76b6cb4dcbf0802.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c.bin create mode 100644 bin/programs/client/testdata/block_120794432_exec/fac225c9ebe9ba4a3762f4031223638298b5dda2fff1b5edf224ce88d14e3e4b.bin create mode 100644 crates/mpt/src/fetcher.rs diff --git a/Cargo.lock b/Cargo.lock index fd6d73642..34aaa0ac3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,9 +141,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8aa973e647ec336810a9356af8aea787249c9d00b1525359f3db29a68d231b" +checksum = "5277af0cbcc483ee6ad2c1e818090b5928d27f04fd6580680f31c1cf8068bcc2" dependencies = [ "alloy-rlp", "bytes", @@ -294,9 +294,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dbd17d67f3e89478c8a634416358e539e577899666c927bc3d2b1328ee9b6ca" +checksum = "30708a79919b082f2692423c8cc72fc250477e4a2ecb0d4a7244cd3cdb299965" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -308,13 +308,13 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6da95adcf4760bb4b108fefa51d50096c5e5fdd29ee72fed3e86ee414f2e34" +checksum = "1c7a679ac01774ab7e00a567a918d4231ae692c5c8cedaf4e16956c3116d7896" dependencies = [ "alloy-sol-macro-input", "const-hex", - "heck 0.4.1", + "heck", "indexmap", "proc-macro-error", "proc-macro2", @@ -326,13 +326,13 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c8da04c1343871fb6ce5a489218f9c85323c8340a36e9106b5fc98d4dd59d5" +checksum = "356da0c2228aa6675a5faaa08a3e4061b967f924753983d72b9a18d9a3fad44e" dependencies = [ "const-hex", "dunce", - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.66", @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a64d2d2395c1ac636b62419a7b17ec39031d6b2367e66e9acbf566e6055e9c" +checksum = "6eb5e6234c0b62514992589fe1578f64d418dbc8ef5cd1ab2d7f2f568f599698" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -428,9 +428,9 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] @@ -734,9 +734,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" dependencies = [ "cc", "glob", @@ -825,7 +825,7 @@ version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "syn 2.0.66", @@ -1332,12 +1332,6 @@ dependencies = [ "serde", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1582,14 +1576,21 @@ dependencies = [ name = "kona-client" version = "0.1.0" 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=cb95183)", "alloy-primitives", + "alloy-rlp", "anyhow", "async-trait", "cfg-if", "kona-common", "kona-common-proc", + "kona-derive", + "kona-mpt", "kona-preimage", "lru", + "op-alloy-consensus", + "revm", "spin 0.9.8", ] @@ -1637,7 +1638,7 @@ dependencies = [ "op-alloy-consensus", "proptest", "reqwest", - "revm-primitives 3.1.1", + "revm-primitives", "serde", "serde_json", "sha2", @@ -2228,9 +2229,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -2393,7 +2394,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a58182c7454179826f9dad2ca577661963092ce9d0fd0c9d682c1e9215a72e70" dependencies = [ - "revm-primitives 4.0.0", + "revm-primitives", "serde", ] @@ -2408,34 +2409,13 @@ dependencies = [ "c-kzg", "k256", "once_cell", - "revm-primitives 4.0.0", + "revm-primitives", "ripemd", "secp256k1", "sha2", "substrate-bn", ] -[[package]] -name = "revm-primitives" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbbc9640790cebcb731289afb7a7d96d16ad94afeb64b5d0b66443bd151e79d6" -dependencies = [ - "alloy-primitives", - "auto_impl", - "bitflags 2.5.0", - "bitvec", - "c-kzg", - "cfg-if", - "derive_more", - "dyn-clone", - "enumn", - "hashbrown", - "hex", - "once_cell", - "serde", -] - [[package]] name = "revm-primitives" version = "4.0.0" @@ -2488,9 +2468,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -2512,9 +2492,9 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" @@ -2907,9 +2887,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8db114c44cf843a8bacd37a146e37987a0b823a0e8bc4fdc610c9c72ab397a5" +checksum = "e6fe08d08d84f2c0a77f1e7c46518789d745c2e87a2721791ed7c3c9bc78df28" dependencies = [ "paste", "proc-macro2", @@ -3027,9 +3007,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3046,9 +3026,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/bin/programs/client/Cargo.toml b/bin/programs/client/Cargo.toml index 31a48b0ea..7bf55cec9 100644 --- a/bin/programs/client/Cargo.toml +++ b/bin/programs/client/Cargo.toml @@ -11,14 +11,21 @@ homepage.workspace = true # workspace cfg-if.workspace = true alloy-primitives.workspace = true +alloy-consensus.workspace = true +alloy-rlp.workspace = true anyhow.workspace = true +revm = { workspace = true, features = ["optimism"] } # local -kona-common = { path = "../../../crates/common" } -kona-common-proc = { path = "../../../crates/common-proc" } -kona-preimage = { path = "../../../crates/preimage" } +kona-common = { path = "../../../crates/common", version = "0.0.1" } +kona-common-proc = { path = "../../../crates/common-proc", version = "0.0.1" } +kona-preimage = { path = "../../../crates/preimage", version = "0.0.1" } +kona-mpt = { path = "../../../crates/mpt", version = "0.0.1" } +kona-derive = { path = "../../../crates/derive", version = "0.0.1" } # external +op-alloy-consensus = { git = "https://github.com/clabby/op-alloy", branch = "refcell/consensus-port", default-features = false } +alloy-eips = { git = "https://github.com/alloy-rs/alloy", rev = "cb95183", default-features = false } lru = "0.12.3" async-trait = "0.1.80" spin = "0.9.8" diff --git a/bin/programs/client/src/executor/mod.rs b/bin/programs/client/src/executor/mod.rs deleted file mode 100644 index b32f646f1..000000000 --- a/bin/programs/client/src/executor/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Contains the EVM executor and its associated types. - -// TODO diff --git a/bin/programs/client/src/l2/executor/canyon.rs b/bin/programs/client/src/l2/executor/canyon.rs new file mode 100644 index 000000000..207351b9a --- /dev/null +++ b/bin/programs/client/src/l2/executor/canyon.rs @@ -0,0 +1,53 @@ +//! Contains logic specific to Canyon hardfork activation. + +use alloy_primitives::{address, b256, hex, Address, Bytes, B256}; +use kona_derive::types::RollupConfig; +use revm::{ + primitives::{Account, Bytecode, HashMap}, + DatabaseCommit, State, +}; + +/// The address of the create2 deployer +const CREATE_2_DEPLOYER_ADDR: Address = address!("13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2"); + +/// The codehash of the create2 deployer contract. +const CREATE_2_DEPLOYER_CODEHASH: B256 = + b256!("b0550b5b431e30d38000efb7107aaa0ade03d48a7198a140edda9d27134468b2"); + +/// The raw bytecode of the create2 deployer contract. +const CREATE_2_DEPLOYER_BYTECODE: [u8; 1584] = hex!("6080604052600436106100435760003560e01c8063076c37b21461004f578063481286e61461007157806356299481146100ba57806366cfa057146100da57600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b5061006f61006a366004610327565b6100fa565b005b34801561007d57600080fd5b5061009161008c366004610327565b61014a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100c657600080fd5b506100916100d5366004610349565b61015d565b3480156100e657600080fd5b5061006f6100f53660046103ca565b610172565b61014582826040518060200161010f9061031a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052610183565b505050565b600061015683836102e7565b9392505050565b600061016a8484846102f0565b949350505050565b61017d838383610183565b50505050565b6000834710156101f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064015b60405180910390fd5b815160000361025f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016101eb565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff8116610156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f790000000000000060448201526064016101eb565b60006101568383305b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b61014e806104ad83390190565b6000806040838503121561033a57600080fd5b50508035926020909101359150565b60008060006060848603121561035e57600080fd5b8335925060208401359150604084013573ffffffffffffffffffffffffffffffffffffffff8116811461039057600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000606084860312156103df57600080fd5b8335925060208401359150604084013567ffffffffffffffff8082111561040557600080fd5b818601915086601f83011261041957600080fd5b81358181111561042b5761042b61039b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156104715761047161039b565b8160405282815289602084870101111561048a57600080fd5b826020860160208301376000602084830101528095505050505050925092509256fe608060405234801561001057600080fd5b5061012e806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063249cb3fa14602d575b600080fd5b603c603836600460b1565b604e565b60405190815260200160405180910390f35b60008281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff16608857600060aa565b7fa2ef4600d742022d532d4747cb3547474667d6f13804902513b2ec01c848f4b45b9392505050565b6000806040838503121560c357600080fd5b82359150602083013573ffffffffffffffffffffffffffffffffffffffff8116811460ed57600080fd5b80915050925092905056fea26469706673582212205ffd4e6cede7d06a5daf93d48d0541fc68189eeb16608c1999a82063b666eb1164736f6c63430008130033a2646970667358221220fdc4a0fe96e3b21c108ca155438d37c9143fb01278a3c1d274948bad89c564ba64736f6c63430008130033"); + +/// The Canyon hardfork issues an irregular state transition that force-deploys the create2 +/// deployer contract. This is done by directly setting the code of the create2 deployer account +/// prior to executing any transactions on the timestamp activation of the fork. +pub(crate) fn ensure_create2_deployer_canyon( + config: &RollupConfig, + timestamp: u64, + db: &mut State, +) -> Result<(), DB::Error> +where + DB: revm::Database, +{ + // If the canyon hardfork is active at the current timestamp, and it was not active at the + // previous block timestamp (heuristically, block time is not perfectly constant at 2s), and the + // chain is an optimism chain, then we need to force-deploy the create2 deployer contract. + if config.is_canyon_active(timestamp) && !config.is_canyon_active(timestamp.saturating_sub(2)) { + // Load the create2 deployer account from the cache. + let acc = db.load_cache_account(CREATE_2_DEPLOYER_ADDR)?; + + // Update the account info with the create2 deployer codehash and bytecode. + let mut acc_info = acc.account_info().unwrap_or_default(); + acc_info.code_hash = CREATE_2_DEPLOYER_CODEHASH; + acc_info.code = Some(Bytecode::new_raw(Bytes::from_static(&CREATE_2_DEPLOYER_BYTECODE))); + + // Convert the cache account back into a revm account and mark it as touched. + let mut revm_acc: Account = acc_info.into(); + revm_acc.mark_touch(); + + // Commit the create2 deployer account to the database. + db.commit(HashMap::from([(CREATE_2_DEPLOYER_ADDR, revm_acc)])); + return Ok(()); + } + + Ok(()) +} diff --git a/bin/programs/client/src/l2/executor/eip4788.rs b/bin/programs/client/src/l2/executor/eip4788.rs new file mode 100644 index 000000000..cc15a7a0b --- /dev/null +++ b/bin/programs/client/src/l2/executor/eip4788.rs @@ -0,0 +1,169 @@ +//! Contains the logic for executing the pre-block beacon root call. + +use alloc::{boxed::Box, vec::Vec}; +use alloy_consensus::constants::BEACON_ROOTS_ADDRESS; +use alloy_primitives::{Address, Bytes, B256, U256}; +use anyhow::{anyhow, Result}; +use kona_derive::types::{L2ExecutionPayloadEnvelope, RollupConfig}; +use revm::{ + primitives::{ + BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg, OptimismFields, TransactTo, TxEnv, + }, + Database, DatabaseCommit, Evm, +}; + +/// Execute the EIP-4788 pre-block beacon root contract call. +pub(crate) fn pre_block_beacon_root_contract_call( + db: &mut DB, + config: &RollupConfig, + block_number: u64, + initialized_cfg: &CfgEnvWithHandlerCfg, + initialized_block_env: &BlockEnv, + payload: &L2ExecutionPayloadEnvelope, +) -> Result<()> +where + DB::Error: core::fmt::Display, +{ + // apply pre-block EIP-4788 contract call + let mut evm_pre_block = Evm::builder() + .with_db(db) + .with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env( + initialized_cfg.clone(), + initialized_block_env.clone(), + Default::default(), + )) + .build(); + + // initialize a block from the env, because the pre block call needs the block itself + apply_beacon_root_contract_call( + config, + payload.execution_payload.timestamp, + block_number, + payload.parent_beacon_block_root, + &mut evm_pre_block, + ) +} + +/// Apply the EIP-4788 pre-block beacon root contract call to a given EVM instance. +fn apply_beacon_root_contract_call( + config: &RollupConfig, + timestamp: u64, + block_number: u64, + parent_beacon_block_root: Option, + evm: &mut Evm<'_, EXT, DB>, +) -> Result<()> +where + DB::Error: core::fmt::Display, +{ + if !config.is_ecotone_active(timestamp) { + return Ok(()); + } + + let parent_beacon_block_root = + parent_beacon_block_root.ok_or(anyhow!("missing parent beacon block root"))?; + + // if the block number is zero (genesis block) then the parent beacon block root must + // be 0x0 and no system transaction may occur as per EIP-4788 + if block_number == 0 { + if parent_beacon_block_root != B256::ZERO { + anyhow::bail!("Cancun genesis block parent beacon block root must be 0x0"); + } + return Ok(()); + } + + // Get the previous environment + let previous_env = Box::new(evm.context.evm.env().clone()); + + // modify env for pre block call + fill_tx_env_with_beacon_root_contract_call(&mut evm.context.evm.env, parent_beacon_block_root); + + let mut state = match evm.transact() { + Ok(res) => res.state, + Err(e) => { + evm.context.evm.env = previous_env; + anyhow::bail!("Failed to execute pre block call: {}", e); + } + }; + + state.remove(&alloy_eips::eip4788::SYSTEM_ADDRESS); + state.remove(&evm.block().coinbase); + + evm.context.evm.db.commit(state); + + // re-set the previous env + evm.context.evm.env = previous_env; + + Ok(()) +} + +/// Fill transaction environment with the EIP-4788 system contract message data. +/// +/// This requirements for the beacon root contract call defined by +/// [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) are: +/// +/// At the start of processing any execution block where `block.timestamp >= FORK_TIMESTAMP` (i.e. +/// before processing any transactions), call [`BEACON_ROOTS_ADDRESS`] as +/// [`SYSTEM_ADDRESS`](alloy_eips::eip4788::SYSTEM_ADDRESS) with the 32-byte input of +/// `header.parent_beacon_block_root`. This will trigger the `set()` routine of the beacon roots +/// contract. +fn fill_tx_env_with_beacon_root_contract_call(env: &mut Env, parent_beacon_block_root: B256) { + fill_tx_env_with_system_contract_call( + env, + alloy_eips::eip4788::SYSTEM_ADDRESS, + BEACON_ROOTS_ADDRESS, + parent_beacon_block_root.0.into(), + ); +} + +/// Fill transaction environment with the system caller and the system contract address and message +/// data. +/// +/// This is a system operation and therefore: +/// * the call must execute to completion +/// * the call does not count against the block’s gas limit +/// * the call does not follow the EIP-1559 burn semantics - no value should be transferred as part +/// of the call +/// * if no code exists at the provided address, the call will fail silently +fn fill_tx_env_with_system_contract_call( + env: &mut Env, + caller: Address, + contract: Address, + data: Bytes, +) { + env.tx = TxEnv { + caller, + transact_to: TransactTo::Call(contract), + // Explicitly set nonce to None so revm does not do any nonce checks + nonce: None, + gas_limit: 30_000_000, + value: U256::ZERO, + data, + // Setting the gas price to zero enforces that no value is transferred as part of the call, + // and that the call will not count against the block's gas limit + gas_price: U256::ZERO, + // The chain ID check is not relevant here and is disabled if set to None + chain_id: None, + // Setting the gas priority fee to None ensures the effective gas price is derived from the + // `gas_price` field, which we need to be zero + gas_priority_fee: None, + access_list: Vec::new(), + // blob fields can be None for this tx + blob_hashes: Vec::new(), + max_fee_per_blob_gas: None, + optimism: OptimismFields { + source_hash: None, + mint: None, + is_system_transaction: Some(false), + // The L1 fee is not charged for the EIP-4788 transaction, submit zero bytes for the + // enveloped tx size. + enveloped_tx: Some(Bytes::default()), + }, + ..Default::default() + }; + + // ensure the block gas limit is >= the tx + env.block.gas_limit = U256::from(env.tx.gas_limit); + + // disable the base fee check for this call by setting the base fee to zero + env.block.basefee = U256::ZERO; +} diff --git a/bin/programs/client/src/l2/executor/fetcher.rs b/bin/programs/client/src/l2/executor/fetcher.rs new file mode 100644 index 000000000..c68ac55c8 --- /dev/null +++ b/bin/programs/client/src/l2/executor/fetcher.rs @@ -0,0 +1,58 @@ +//! Contains the fetcher construction functions for the block executor's [TrieDB]. +//! +//! [TrieDB]: kona_mpt::TrieDB + +use crate::CachingOracle; +use alloy_consensus::Header; +use alloy_primitives::{Bytes, B256}; +use alloy_rlp::Decodable; +use anyhow::{anyhow, Result}; +use kona_mpt::TrieDBFetcher; +use kona_preimage::{PreimageKey, PreimageKeyType, PreimageOracleClient}; + +/// The [TrieDBFetcher] implementation for the block executor's [TrieDB]. +/// +/// TODO: Move this into the higher-level L2 chain fetcher, and also implement the [TrieDBFetcher] +/// trait. +/// +/// [TrieDB]: kona_mpt::TrieDB +#[derive(Debug)] +pub struct TrieDBProvider<'a, const N: usize> { + /// The inner caching oracle to fetch trie node preimages from. + caching_oracle: &'a CachingOracle, +} + +impl<'a, const N: usize> TrieDBProvider<'a, N> { + /// Constructs a new [TrieDBProvider] with the given [CachingOracle]. + pub fn new(caching_oracle: &'a CachingOracle) -> Self { + Self { caching_oracle } + } +} + +impl<'a, const N: usize> TrieDBFetcher for TrieDBProvider<'a, N> { + fn trie_node_preimage(&self, key: B256) -> Result { + // Fetch the trie preimage from the caching oracle. + kona_common::block_on(async move { + self.caching_oracle + .get(PreimageKey::new(*key, PreimageKeyType::Keccak256)) + .await + .map(Into::into) + }) + } + + fn bytecode_by_hash(&self, _: B256) -> Result { + todo!() + } + + fn header_by_hash(&self, hash: B256) -> Result
{ + // Fetch the header from the caching oracle. + kona_common::block_on(async move { + let header_bytes = self + .caching_oracle + .get(PreimageKey::new(*hash, PreimageKeyType::Keccak256)) + .await?; + Header::decode(&mut header_bytes.as_slice()) + .map_err(|e| anyhow!("Failed to RLP decode Header: {e}")) + }) + } +} diff --git a/bin/programs/client/src/l2/executor/mod.rs b/bin/programs/client/src/l2/executor/mod.rs new file mode 100644 index 000000000..e5127f98e --- /dev/null +++ b/bin/programs/client/src/l2/executor/mod.rs @@ -0,0 +1,612 @@ +//! The block executor for the L2 client program. Operates off of a [TrieDB] backed [State], +//! allowing for stateless block execution of OP Stack blocks. + +use alloc::{sync::Arc, vec::Vec}; +use alloy_consensus::{Header, Sealable, Sealed, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; +use alloy_eips::eip2718::Encodable2718; +use alloy_primitives::{Bytes, TxKind, B256, U256}; +use anyhow::{anyhow, Result}; +use kona_derive::types::{L2ExecutionPayload, L2ExecutionPayloadEnvelope, RollupConfig}; +use kona_mpt::{ordered_trie_with_encoder, TrieDB, TrieDBFetcher}; +use op_alloy_consensus::{OpReceipt, OpReceiptEnvelope, OpReceiptWithBloom, OpTxEnvelope}; +use revm::{ + db::{states::bundle_state::BundleRetention, State}, + primitives::{ + calc_excess_blob_gas, BlobExcessGasAndPrice, BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, + EVMError, EnvWithHandlerCfg, OptimismFields, SpecId, TransactTo, TxEnv, + }, + DatabaseCommit, Evm, StateBuilder, +}; + +mod fetcher; +pub use fetcher::TrieDBProvider; + +mod eip4788; +pub(crate) use eip4788::pre_block_beacon_root_contract_call; + +mod canyon; +pub(crate) use canyon::ensure_create2_deployer_canyon; + +mod util; +pub(crate) use util::{logs_bloom, wrap_receipt_with_bloom}; + +/// The block executor for the L2 client program. Operates off of a [TrieDB] backed [State], +/// allowing for stateless block execution of OP Stack blocks. +#[derive(Debug)] +pub struct StatelessL2BlockExecutor +where + F: TrieDBFetcher, +{ + /// The [RollupConfig]. + config: Arc, + /// The parent header + parent_header: Sealed
, + /// The inner state database component. + state: State>, +} + +impl StatelessL2BlockExecutor +where + F: TrieDBFetcher, +{ + /// Constructs a new [StatelessL2BlockExecutor] with the given starting state root, parent hash, + /// and [CachingOracle]. + pub fn new( + config: Arc, + starting_state_root: B256, + parent_header: Sealed
, + fetcher: F, + ) -> Self { + let trie_db = TrieDB::new(starting_state_root, parent_header.seal(), fetcher); + let state = StateBuilder::new_with_database(trie_db).with_bundle_update().build(); + Self { config, parent_header, state } + } +} + +impl StatelessL2BlockExecutor +where + F: TrieDBFetcher, +{ + /// Executes the given block, returning the resulting state root. + /// + /// ## Steps + /// 1. Prepare the block environment. + /// 2. Apply the pre-block EIP-4788 contract call. + /// 3. Prepare the EVM with the given L2 execution payload in the block environment. 3.i) Reject + /// any EIP-4844 transactions, as they are not supported on the OP Stack. 3.ii) If the + /// transaction is a deposit, cache the depositor account prior to execution. 3.iii) + /// Construct the EVM with the given configuration. 3.iv) Execute the transaction. 3.v) + /// Accumulate the gas used by the transaction to the block-scoped cumulative gas used + /// counter. 3.vi) Create a receipt envelope for the transaction. + /// 4. Merge all state transitions into the cache state. + /// 5. Compute the [state root, transactions root, receipts root, logs bloom] for the processed + /// block. + pub fn execute_payload(&mut self, payload: L2ExecutionPayloadEnvelope) -> Result<&Header> { + let payload_envelope @ L2ExecutionPayloadEnvelope { + execution_payload: payload, + parent_beacon_block_root, + } = &payload; + + // Prepare the `revm` environment. + let mut initialized_block_env = BlockEnv::default(); + Self::prepare_block_env(payload, &mut initialized_block_env); + let initialized_cfg = self.evm_cfg_env(payload.timestamp); + + // Prepare the EVM with the given L2 execution payload in the block environment. + let block_number = self.parent_header.number + 1; + + // Apply the pre-block EIP-4788 contract call. + pre_block_beacon_root_contract_call( + &mut self.state, + self.config.as_ref(), + block_number, + &initialized_cfg, + &initialized_block_env, + payload_envelope, + )?; + + // Ensure that the create2 contract is deployed upon transition to the Canyon hardfork. + ensure_create2_deployer_canyon(self.config.as_ref(), payload.timestamp, &mut self.state)?; + + // Construct the EVM with the given configuration. + // TODO(clabby): Accelerate precompiles w/ custom precompile handler. + let mut evm = Evm::builder() + .with_db(&mut self.state) + .with_env_with_handler_cfg(EnvWithHandlerCfg::new_with_cfg_env( + initialized_cfg.clone(), + initialized_block_env.clone(), + Default::default(), + )) + .build(); + let mut cumulative_gas_used = 0u64; + let mut receipts: Vec = Vec::with_capacity(payload.transactions.len()); + + // Execute the transactions in the payload. + for (i, transaction) in payload.deserialized_transactions.iter().enumerate() { + // Reject any EIP-4844 transactions. + if matches!(transaction, OpTxEnvelope::Eip4844(_)) { + anyhow::bail!("EIP-4844 transactions are not supported"); + } + + // If the transaction is a deposit, cache the depositor account. + // + // This only needs to be done post-Regolith, as deposit nonces were not included in + // Bedrock. In addition, non-deposit transactions do not have deposit + // nonces. + let depositor = self + .config + .is_regolith_active(payload.timestamp) + .then(|| { + if let OpTxEnvelope::Deposit(deposit) = transaction { + evm.db_mut().load_cache_account(deposit.from).ok().cloned() + } else { + None + } + }) + .flatten(); + + // Modify the transaction environment with the transaction data. + evm = evm + .modify() + .modify_tx_env(|tx| { + Self::prepare_tx_env(transaction, payload.transactions[i].as_ref(), tx) + .expect("Failed to prepare tx env") + }) + .build(); + + // TODO(clabby): Get pre-execution verification working for deposits, use + // `transact_commit`. + let revm::primitives::ResultAndState { result, state } = + match evm.transact_preverified() { + Ok(res) => res, + Err(err) => match err { + EVMError::Transaction(e) => { + anyhow::bail!("Transaction error: {e}") + } + err => { + anyhow::bail!("Fatal EVM error: {err}") + } + }, + }; + evm.db_mut().commit(state); + + // Accumulate the gas used by the transaction. + cumulative_gas_used += result.gas_used(); + + // Create receipt envelope. + let receipt_envelope = wrap_receipt_with_bloom( + OpReceiptWithBloom { + receipt: OpReceipt { + status: result.is_success(), + cumulative_gas_used: cumulative_gas_used as u128, + logs: result.into_logs(), + deposit_nonce: depositor + .map(|depositor| depositor.account_info().unwrap_or_default().nonce), + // The deposit receipt version was introduced in Canyon to indicate an + // update to how receipt hashes should be computed + // when set. The state transition process + // ensures this is only set for post-Canyon deposit transactions. + deposit_receipt_version: self + .config + .is_canyon_active(payload.timestamp) + .then_some(1), + }, + logs_bloom: Default::default(), + }, + transaction.tx_type(), + ); + receipts.push(receipt_envelope); + } + + // Drop the exclusive reference to the state in the EVM so that it may be mutated again. + drop(evm); + + // Merge all state transitions into the cache state. + self.state.merge_transitions(BundleRetention::PlainState); + + // Take the bundle state. + let bundle = self.state.take_bundle(); + + // Recompute the header roots. + let state_root = self.state.database.state_root(&bundle)?; + let transactions_root = Self::compute_transactions_root(&payload.transactions); + let receipts_root = + Self::compute_receipts_root(&receipts, self.config.as_ref(), payload.timestamp); + + // The withdrawals root on OP Stack chains, after Canyon activation, is always the empty + // root hash. + let withdrawals_root = + self.config.is_canyon_active(payload.timestamp).then_some(EMPTY_ROOT_HASH); + + // Compute logs bloom filter for the block. + let logs_bloom = logs_bloom(receipts.iter().flat_map(|receipt| receipt.logs())); + + // Compute Cancun fields, if active. + let (blob_gas_used, excess_blob_gas) = self + .config + .is_ecotone_active(payload.timestamp) + .then(|| { + let excess_blob_gas = if self.config.is_ecotone_active(self.parent_header.timestamp) + { + let parent_excess_blob_gas = + self.parent_header.excess_blob_gas.unwrap_or_default(); + let parent_blob_gas_used = self.parent_header.blob_gas_used.unwrap_or_default(); + calc_excess_blob_gas(parent_excess_blob_gas, parent_blob_gas_used) + } else { + // For the first post-fork block, both blob gas fields are evaluated to 0. + calc_excess_blob_gas(0, 0) + }; + + (Some(0), Some(excess_blob_gas)) + }) + .unwrap_or_default(); + + // Construct the new header. + let header = Header { + parent_hash: self.parent_header.seal(), + ommers_hash: EMPTY_OMMER_ROOT_HASH, + beneficiary: payload.fee_recipient, + state_root, + transactions_root, + receipts_root, + withdrawals_root, + logs_bloom, + difficulty: U256::ZERO, + number: block_number, + gas_limit: payload.gas_limit, + gas_used: cumulative_gas_used, + timestamp: payload.timestamp, + mix_hash: payload.prev_randao, + nonce: 0, + base_fee_per_gas: payload.base_fee_per_gas, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root: *parent_beacon_block_root, + // Provide no extra data on OP Stack chains + extra_data: Bytes::default(), + } + .seal_slow(); + + // Update the parent block hash in the state database. + self.state.database.set_parent_block_hash(header.seal()); + + // Update the parent header in the executor. + self.parent_header = header; + + Ok(&self.parent_header) + } + + /// Returns the active [CfgEnvWithHandlerCfg] for the executor. + fn evm_cfg_env(&self, timestamp: u64) -> CfgEnvWithHandlerCfg { + let cfg_env = CfgEnv::default().with_chain_id(self.config.l2_chain_id); + if self.config.is_fjord_active(timestamp) { + // TODO(clabby): Replace w/ Fjord Spec ID, once in a revm release. + CfgEnvWithHandlerCfg::new_with_spec_id(cfg_env, SpecId::ECOTONE) + } else if self.config.is_ecotone_active(timestamp) { + CfgEnvWithHandlerCfg::new_with_spec_id(cfg_env, SpecId::ECOTONE) + } else if self.config.is_canyon_active(timestamp) { + CfgEnvWithHandlerCfg::new_with_spec_id(cfg_env, SpecId::CANYON) + } else if self.config.is_regolith_active(timestamp) { + CfgEnvWithHandlerCfg::new_with_spec_id(cfg_env, SpecId::REGOLITH) + } else { + CfgEnvWithHandlerCfg::new_with_spec_id(cfg_env, SpecId::BEDROCK) + } + } + + /// Computes the receipts root from the given set of receipts. + /// + /// ## Takes + /// - `receipts`: The receipts to compute the root for. + /// - `config`: The rollup config to use for the computation. + /// - `timestamp`: The timestamp to use for the computation. + /// + /// ## Returns + /// The computed receipts root. + fn compute_receipts_root( + receipts: &[OpReceiptEnvelope], + config: &RollupConfig, + timestamp: u64, + ) -> B256 { + // There is a minor bug in op-geth and op-erigon where in the Regolith hardfork, + // the receipt root calculation does not inclide the deposit nonce in the + // receipt encoding. In the Regolith hardfork, we must strip the deposit nonce + // from the receipt encoding to match the receipt root calculation. + if config.is_regolith_active(timestamp) && !config.is_canyon_active(timestamp) { + let receipts = receipts + .iter() + .cloned() + .map(|receipt| match receipt { + OpReceiptEnvelope::Deposit(mut deposit_receipt) => { + deposit_receipt.receipt.deposit_nonce = None; + OpReceiptEnvelope::Deposit(deposit_receipt) + } + _ => receipt, + }) + .collect::>(); + + ordered_trie_with_encoder(receipts.as_ref(), |receipt, mut buf| { + receipt.encode_2718(&mut buf) + }) + .root() + } else { + ordered_trie_with_encoder(receipts, |receipt, mut buf| receipt.encode_2718(&mut buf)) + .root() + } + } + + /// Computes the transactions root from the given set of encoded transactions. + /// + /// ## Takes + /// - `transactions`: The transactions to compute the root for. + /// + /// ## Returns + /// The computed transactions root. + fn compute_transactions_root(transactions: &[Bytes]) -> B256 { + ordered_trie_with_encoder(transactions, |tx, buf| buf.put_slice(tx.as_ref())).root() + } + + /// Prepares a [BlockEnv] with the given [L2ExecutionPayloadEnvelope]. + /// + /// ## Takes + /// - `payload`: The payload to prepare the environment for. + /// - `env`: The block environment to prepare. + fn prepare_block_env(payload: &L2ExecutionPayload, env: &mut BlockEnv) { + env.number = U256::from(payload.block_number); + env.coinbase = payload.fee_recipient; + env.timestamp = U256::from(payload.timestamp); + env.gas_limit = U256::from(payload.gas_limit); + env.basefee = U256::from(payload.base_fee_per_gas.unwrap_or_default()); + env.difficulty = payload.prev_randao.into(); + env.prevrandao = Some(payload.prev_randao); + env.blob_excess_gas_and_price = + payload.excess_blob_gas.map(|excess_blob_gas| BlobExcessGasAndPrice { + excess_blob_gas, + blob_gasprice: payload.blob_gas_used.unwrap_or_default() as u128, + }); + } + + /// Prepares a [TxEnv] with the given [OpTxEnvelope]. + /// + /// ## Takes + /// - `transaction`: The transaction to prepare the environment for. + /// - `env`: The transaction environment to prepare. + /// + /// ## Returns + /// - `Ok(())` if the environment was successfully prepared. + /// - `Err(_)` if an error occurred while preparing the environment. + fn prepare_tx_env( + transaction: &OpTxEnvelope, + encoded_transaction: &[u8], + env: &mut TxEnv, + ) -> Result<()> { + match transaction { + OpTxEnvelope::Legacy(signed_tx) => { + let tx = signed_tx.tx(); + env.caller = signed_tx + .recover_signer() + .map_err(|e| anyhow!("Failed to recover signer: {}", e))?; + env.gas_limit = tx.gas_limit as u64; + env.gas_price = U256::from(tx.gas_price); + env.gas_priority_fee = None; + env.transact_to = match tx.to { + TxKind::Call(to) => TransactTo::Call(to), + TxKind::Create => TransactTo::create(), + }; + env.value = tx.value; + env.data = tx.input.clone(); + env.chain_id = tx.chain_id; + env.nonce = Some(tx.nonce); + env.access_list.clear(); + env.blob_hashes.clear(); + env.max_fee_per_blob_gas.take(); + env.optimism = OptimismFields { + source_hash: None, + mint: None, + is_system_transaction: Some(false), + enveloped_tx: Some(encoded_transaction.to_vec().into()), + }; + Ok(()) + } + OpTxEnvelope::Eip2930(signed_tx) => { + let tx = signed_tx.tx(); + env.caller = signed_tx + .recover_signer() + .map_err(|e| anyhow!("Failed to recover signer: {}", e))?; + env.gas_limit = tx.gas_limit as u64; + env.gas_price = U256::from(tx.gas_price); + env.gas_priority_fee = None; + env.transact_to = match tx.to { + TxKind::Call(to) => TransactTo::Call(to), + TxKind::Create => TransactTo::create(), + }; + env.value = tx.value; + env.data = tx.input.clone(); + env.chain_id = Some(tx.chain_id); + env.nonce = Some(tx.nonce); + env.access_list = tx + .access_list + .0 + .iter() + .map(|l| { + ( + l.address, + l.storage_keys.iter().map(|k| U256::from_be_bytes(k.0)).collect(), + ) + }) + .collect(); + env.blob_hashes.clear(); + env.max_fee_per_blob_gas.take(); + env.optimism = OptimismFields { + source_hash: None, + mint: None, + is_system_transaction: Some(false), + enveloped_tx: Some(encoded_transaction.to_vec().into()), + }; + Ok(()) + } + OpTxEnvelope::Eip1559(signed_tx) => { + let tx = signed_tx.tx(); + env.caller = signed_tx + .recover_signer() + .map_err(|e| anyhow!("Failed to recover signer: {}", e))?; + env.gas_limit = tx.gas_limit as u64; + env.gas_price = U256::from(tx.max_fee_per_gas); + env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); + env.transact_to = match tx.to { + TxKind::Call(to) => TransactTo::Call(to), + TxKind::Create => TransactTo::create(), + }; + env.value = tx.value; + env.data = tx.input.clone(); + env.chain_id = Some(tx.chain_id); + env.nonce = Some(tx.nonce); + env.access_list = tx + .access_list + .0 + .iter() + .map(|l| { + ( + l.address, + l.storage_keys.iter().map(|k| U256::from_be_bytes(k.0)).collect(), + ) + }) + .collect(); + env.blob_hashes.clear(); + env.max_fee_per_blob_gas.take(); + env.optimism = OptimismFields { + source_hash: None, + mint: None, + is_system_transaction: Some(false), + enveloped_tx: Some(encoded_transaction.to_vec().into()), + }; + Ok(()) + } + OpTxEnvelope::Deposit(tx) => { + env.caller = tx.from; + env.access_list.clear(); + env.gas_limit = tx.gas_limit as u64; + env.gas_price = U256::ZERO; + env.gas_priority_fee = None; + match tx.to { + TxKind::Call(to) => env.transact_to = TransactTo::Call(to), + TxKind::Create => env.transact_to = TransactTo::create(), + } + env.value = tx.value; + env.data = tx.input.clone(); + env.chain_id = None; + env.nonce = None; + env.optimism = OptimismFields { + source_hash: Some(tx.source_hash), + mint: tx.mint, + is_system_transaction: Some(tx.is_system_transaction), + enveloped_tx: Some(encoded_transaction.to_vec().into()), + }; + Ok(()) + } + _ => anyhow::bail!("Unexpected tx type"), + } + } +} + +#[cfg(test)] +mod test { + extern crate std; + use std::format; + + use super::*; + use alloc::string::{String, ToString}; + use alloy_eips::eip2718::Decodable2718; + use alloy_primitives::{address, b256, bloom, hex}; + use alloy_rlp::Decodable; + + /// A [TrieDBFetcher] implementation that fetches trie nodes and bytecode from the local + /// testdata folder. + struct TestdataTrieDBFetcher { + testdata_folder: String, + } + + impl TrieDBFetcher for TestdataTrieDBFetcher { + fn trie_node_preimage(&self, key: B256) -> Result { + let file_name = format!("testdata/{}/{}.bin", self.testdata_folder, hex::encode(key)); + std::fs::read(&file_name) + .map_err(|e| anyhow!("Failed to read {file_name}: {}", e)) + .map(Into::into) + } + + fn bytecode_by_hash(&self, code_hash: B256) -> Result { + let file_name = + format!("testdata/{}/{}.bin", self.testdata_folder, hex::encode(code_hash)); + std::fs::read(&file_name) + .map_err(|e| anyhow!("Failed to read {file_name}: {}", e)) + .map(Into::into) + } + + fn header_by_hash(&self, hash: B256) -> Result
{ + let file_name = format!("testdata/{}/{}.bin", self.testdata_folder, hex::encode(hash)); + let encoded_header = std::fs::read(&file_name) + .map_err(|e| anyhow!("Failed to read {file_name}: {}", e))?; + Header::decode(&mut encoded_header.as_slice()).map_err(|e| anyhow!(e)) + } + } + + #[test] + fn test_l2_block_executor() { + // Static for the execution of block #120794432 on OP mainnet. + // https://optimistic.etherscan.io/block/120794432 + + // Make a mock rollup config, with Ecotone activated at timestamp = 0. + let rollup_config = RollupConfig { + l2_chain_id: 10, + regolith_time: Some(0), + canyon_time: Some(0), + delta_time: Some(0), + ecotone_time: Some(0), + ..Default::default() + }; + + // Decode the headers. + let raw_header = hex!("f90244a0ff7c6abc94edcaddd02c12ec7d85ffbb3ba293f3b76897e4adece57e692bcc39a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0a0b24abb13d6149947247a8817517971bb8d213de1e23225e2b20d36a5b6427ca0c31e4a2ada52ac698643357ca89ef2740d384076ef0e17b653bcb6ea7dd8902ea09f4fcf34e78afc216240e3faa72c822f8eea4757932eb9e0fd42839d192bb903b901000440000210068007000000940000000220000006000820048404800002000004040100001b2000008800001040000018280000400001200004000101086000000802800080004008010001080000200100a00000204840000118042080000400804001000a0400080200111000000800050000020200064000000012000800048000000000101800200002000000080008001581402002200210341089000080c2d004106000000018000000804285800800000020000180008000020000000000020103410400000000200400008000280400000100020000002002000021000811000920808000010000000200210400000020008000400000000000211008808407332d3f8401c9c3808327c44d84665a343780a0edba75784acf3165bffd96df8b78ffdb3781db91f886f22b4bee0a6f722df93988000000000000000083202ef8a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a0917693152c4a041efbc196e9d169087093336da96a8bb3af1e55fce447a7b8a9"); + let header = Header::decode(&mut &raw_header[..]).unwrap(); + let raw_expected_header = hex!("f90243a09506905902f5c3613c5441a8697c09e7aafdb64082924d8bd2857f9e34a47a9aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0a1e9207c3c68cd4854074f08226a3643debed27e45bf1b22ab528f8de16245eda0121e8765953af84974b845fd9b01f5ff9b0f7d2886a2464535e8e9976a1c8daba092c6a5e34d7296d63d1698258c40539a20080c668fc9d63332363cfbdfa37976b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000808407332d408401c9c38082ab4b84665a343980a0edba75784acf3165bffd96df8b78ffdb3781db91f886f22b4bee0a6f722df93988000000000000000083201f31a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a0917693152c4a041efbc196e9d169087093336da96a8bb3af1e55fce447a7b8a9"); + let expected_header = Header::decode(&mut &raw_expected_header[..]).unwrap(); + + // Initialize the block executor on block #120794431's post-state. + let mut l2_block_executor = StatelessL2BlockExecutor::new( + Arc::new(rollup_config), + b256!("a0b24abb13d6149947247a8817517971bb8d213de1e23225e2b20d36a5b6427c"), + header.seal_slow(), + TestdataTrieDBFetcher { testdata_folder: "block_120794432_exec".to_string() }, + ); + + let raw_tx = hex!("7ef8f8a003b511b9b71520cd62cad3b5fd5b1b8eaebd658447723c31c7f1eba87cfe98c894deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e2000000558000c5fc5000000000000000300000000665a33a70000000001310e960000000000000000000000000000000000000000000000000000000214d2697300000000000000000000000000000000000000000000000000000000000000015346d208a396843018a2e666c8e7832067358433fb87ca421273c6a4e69f78d50000000000000000000000006887246668a3b87f54deb3b94ba47a6f63f32985"); + let payload = L2ExecutionPayloadEnvelope { + parent_beacon_block_root: Some(b256!( + "917693152c4a041efbc196e9d169087093336da96a8bb3af1e55fce447a7b8a9" + )), + execution_payload: L2ExecutionPayload { + parent_hash: b256!("9506905902f5c3613c5441a8697c09e7aafdb64082924d8bd2857f9e34a47a9a"), + fee_recipient: address!("4200000000000000000000000000000000000011"), + state_root: b256!("a1e9207c3c68cd4854074f08226a3643debed27e45bf1b22ab528f8de16245ed"), + receipts_root: b256!("92c6a5e34d7296d63d1698258c40539a20080c668fc9d63332363cfbdfa37976"), + logs_bloom: bloom!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + prev_randao: b256!("edba75784acf3165bffd96df8b78ffdb3781db91f886f22b4bee0a6f722df939"), + block_number: 0x7332d40, + gas_limit: 0x1c9c380, + gas_used: 0xab4b, + timestamp: 0x665a3439, + extra_data: Default::default(), + base_fee_per_gas: Some(0x201f31), + block_hash: Default::default(), + transactions: alloc::vec![raw_tx.into()], + deserialized_transactions: alloc::vec![OpTxEnvelope::decode_2718(&mut &raw_tx[..]).unwrap()], + withdrawals: Default::default(), + blob_gas_used: Some(0), + excess_blob_gas: Some(0), + }, + }; + let produced_header = l2_block_executor.execute_payload(payload).unwrap(); + + assert_eq!(produced_header, &expected_header); + assert_eq!(l2_block_executor.parent_header.seal(), expected_header.hash_slow()); + } +} diff --git a/bin/programs/client/src/l2/executor/util.rs b/bin/programs/client/src/l2/executor/util.rs new file mode 100644 index 000000000..c2eff0f08 --- /dev/null +++ b/bin/programs/client/src/l2/executor/util.rs @@ -0,0 +1,30 @@ +//! Contains utilities for the L2 executor. + +use alloy_primitives::{Bloom, Log}; +use op_alloy_consensus::{OpReceiptEnvelope, OpReceiptWithBloom, OpTxType}; + +/// Compute the logs bloom filter for the given logs. +pub(crate) fn logs_bloom<'a>(logs: impl IntoIterator) -> Bloom { + let mut bloom = Bloom::ZERO; + for log in logs { + bloom.m3_2048(log.address.as_slice()); + for topic in log.topics() { + bloom.m3_2048(topic.as_slice()); + } + } + bloom +} + +/// Wrap an [OpReceiptWithBloom] in an [OpReceiptEnvelope], provided the receipt and a [TxType]. +pub(crate) fn wrap_receipt_with_bloom( + receipt: OpReceiptWithBloom, + tx_type: OpTxType, +) -> OpReceiptEnvelope { + match tx_type { + OpTxType::Legacy => OpReceiptEnvelope::Legacy(receipt), + OpTxType::Eip2930 => OpReceiptEnvelope::Eip2930(receipt), + OpTxType::Eip1559 => OpReceiptEnvelope::Eip1559(receipt), + OpTxType::Eip4844 => OpReceiptEnvelope::Eip4844(receipt), + OpTxType::Deposit => OpReceiptEnvelope::Deposit(receipt), + } +} diff --git a/bin/programs/client/src/l2/mod.rs b/bin/programs/client/src/l2/mod.rs new file mode 100644 index 000000000..f4b12dbe5 --- /dev/null +++ b/bin/programs/client/src/l2/mod.rs @@ -0,0 +1,5 @@ +//! Contains the L2-specifc contstructs of the client program, such as the +//! [StatelessL2BlockExecutor] + +mod executor; +pub use executor::{StatelessL2BlockExecutor, TrieDBProvider}; diff --git a/bin/programs/client/src/lib.rs b/bin/programs/client/src/lib.rs index df8075340..3110a0d79 100644 --- a/bin/programs/client/src/lib.rs +++ b/bin/programs/client/src/lib.rs @@ -6,7 +6,7 @@ extern crate alloc; -mod executor; +pub mod l2; mod comms; pub use comms::{CachingOracle, HINT_WRITER, ORACLE_READER}; diff --git a/bin/programs/client/testdata/block_120794432_exec/01c9e411b33995639dce57799621ed4da5aaff39d9670da80741d5e574cba420.bin b/bin/programs/client/testdata/block_120794432_exec/01c9e411b33995639dce57799621ed4da5aaff39d9670da80741d5e574cba420.bin new file mode 100644 index 0000000000000000000000000000000000000000..6a30e25b8dff3c5aeea5ffabc1c4e112b023903b GIT binary patch literal 107 zcmV-x0F?juX`L{*m+gD_35XX4U?)~>M$t1{j+$)XJ?TDcTa*E~N%%*D?P|$@pjPM~ z7aPn~rvHOQ=90kpZd*v;8<}jazyV?}wc}&7A)v+5MgfNRBRrCReX`ug1Hk0~wo}T2 NCp&xk*aTgLq;NcxHNXG> literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/024f07c1de57fb4709c0485fe433f0840f1547508eef2a4d52f8d69a544ac4c9.bin b/bin/programs/client/testdata/block_120794432_exec/024f07c1de57fb4709c0485fe433f0840f1547508eef2a4d52f8d69a544ac4c9.bin new file mode 100644 index 0000000000000000000000000000000000000000..0a0dd827ac4c15e8ac19c2c07f42b739870bc7fd GIT binary patch literal 532 zcmV+v0_*+x0ui8O@y{G);-wsIlKpg7$V}~Q9fJ{D_T5wc(~PeNNHPVW?keKeOi6E8 zEEPO#SrWg4FFz1`HpbormW{w}J>A1=U7!6ZNu@_+oA0Y^lZ&ItQ zVe_Z6rl2crnT2DF^7;}BcfFl>S$TXox)5bk*p^*8)W^Ri&6A*d9}Tbz$ZLb1#9sZe z?8L-b`jEl5jvNfhk1w#xHO)Jqbt{ki*BqXHKzqt2ncrqwTK2vQmN05P-=uRiNXa~M zpg;l#BTOL$Q@g1q=A{9sS!!kOQ%l!0(CzHDl1j3+0HAK&)3j8lP)7`Z+bCXQ$B2Ps z1o3vRNQ#uj{U*&?Xr-Vh9znz^AZt0AVD{>j@=E~plg29)8bx9#)e^^Zv^Ke*`+8yM z`-9HSdK~g_0>WRQAiCmcWUKs>0AQve*Ujr=pz8Qjwl)6^tc-^Z%=y|_yCDW-pMkO+ z16FUB@4^o+AEuDZ1D+*8m literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/029298bf41ace28a77846e89856ada075122b884e91f329137c9e391d9dc1048.bin b/bin/programs/client/testdata/block_120794432_exec/029298bf41ace28a77846e89856ada075122b884e91f329137c9e391d9dc1048.bin new file mode 100644 index 0000000000000000000000000000000000000000..64e5873417e51caccb6464870fc16a248b67c470 GIT binary patch literal 532 zcmV+v0_*+x0ui7_OwnDD^Hm`hS}}lf+cV3qsdmlxz9`lt2AU3vgN4PQcRKo>w$Mws zZ~Hyng#uLjWFe(v`wmU!S=nR;{f-l`ppDz-W*YtpAZ0v?gHI}7JlzA+JakA2wl%3v zvrh9VrJ&sOcFZ41R6!7R_7s8?V6GWTkF6!kRA5DNA5U_E@ExEnA6D;K)%PpiwFU$F zxU!0&IaxzTzvp*KFE*&FSD65yuKd90R?GXS0A_z<`En>c$gUVl-|UJro`a`rYJfHn zp!pgjQS}wD0Gm;)y-05~;6d@7FCTYxWpJH_*L`Kn|DaQrg~*`k0_Q^&=OVQ`4-GIf5H$~;Ip8veG9BQ|W6x&VDDH>|rGHU+{6^e8_E3InTAA4ilxd z7)EeNpPB|&$5z4Ipr;tfY3l@_VdjV5qdgj*SDf#yuY?0tuZH1s$8~pgD)$fx+ zVw%26_twM|k^KWoP@%epChcX;Pp~eaO+|A$5j1cuJ`<;4rF(6=FF6HU7Xn(GG|%0S z0hb|Ipomb=y-|po!f`0YP-0w^m5jv-C%B3;WArWT1)fQ7W1x$2nl}$F+>()T2}Ado WBzz#N%GrgO@=ZS%zkM?u{2YKaG6nSj literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/0a966e78d9a8026bdb70032888be03b27cf42b3266607d7c2999c30d56a84877.bin b/bin/programs/client/testdata/block_120794432_exec/0a966e78d9a8026bdb70032888be03b27cf42b3266607d7c2999c30d56a84877.bin new file mode 100644 index 0000000000000000000000000000000000000000..dc6d7018d84562fb9d818df63023828818dbd972 GIT binary patch literal 48 zcmaFAz>@dP&5-V-71x+uS9VzBpYUF`XR3z-$2T+m$zpt;pCZ@;bc0^SIp=9Fgggq2jFMOz5(hN%18mN~OCC!|S5v2^t8QV{Mh-)Se3@`-S6 zpaHzbg4+rL{}yDELS3Df=}>MgubkUuloROeBm7I4n_1(+X zVoO=Kn|{HC7hx&{QlC*6kT|z3SYbDy7Ej}L5JwpQp_qU4Sdt}_B;vt^!*>>rt+!^RN)&iYG~ z^EC=r6AUVf^0j+NMTZZNh>xZi>1K48phqeWm~iYIe=X18nx#oi7K)*k1?SiwR6I9-h(!|$Lwvt{KYqVln%+O(ipTG;$wxHh>@*?qpTF0~xNRqW-wjhIO zn|7nni!HfPLh=`1h!UWbH^YF(Bj45vc)#cC>Y>^^h=EMF*)!_NIhOB8iLN`K=9&XC zcn8VI-#XRvt8n8QsJ8Jb+ZkOJ!V|c)GXn>epa7OIe5hM|&`)-BpP${u+R9|HAKbJA zop&R6cFq2PiJ;*yBF`eQFF|M+T7(xZc(P`~62bcUC2L)eWxUpr%IcuYmOwdi_uI{F z3wDTa*ArOZ2Gw!%Io#p=FM+&GETxE`CMytc7j)w0ySpiU08C0yaX$szU}!<097_WF zxRi#epgX6%ipX{z0=56rd9>-P75g8|m)P2c)IQ WyhN~eZN&e$`T3xXvY^TE+Q5M6$P-xr literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/14a0646914bb81f97bab254df79386dd2923276b6b61d6e9bb330a985859c3e1.bin b/bin/programs/client/testdata/block_120794432_exec/14a0646914bb81f97bab254df79386dd2923276b6b61d6e9bb330a985859c3e1.bin new file mode 100644 index 000000000..3f8d0de8e --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/14a0646914bb81f97bab254df79386dd2923276b6b61d6e9bb330a985859c3e1.bin @@ -0,0 +1 @@ +5ޙ_ 3mu+MPőх+vMZ0 \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/16cecc8df1727ea4d64fe5d64021b1e874ef08d29d2cf7752eec126edf941b37.bin b/bin/programs/client/testdata/block_120794432_exec/16cecc8df1727ea4d64fe5d64021b1e874ef08d29d2cf7752eec126edf941b37.bin new file mode 100644 index 0000000000000000000000000000000000000000..12092918e0bd3dd8b13054181f116c62b5c24ebb GIT binary patch literal 532 zcmV+v0_*+x0ui8XNx2GEXMwz=`wJ1Ll@1R#PO3EA!(Rd_Dj17=0Hq6{%^F+H2c@Ne zfWcH>6PMX?62b#B_7K$JZ47gE#L*m=pjg7tGjf^iFPYS2isSG`Cd63;(l_L8xevE% zQ$of>$DlT-tq;GroeP53vuQMgxkQM!BCN%rQ~f1A=XX2fW~QLiWs7JR0I9Ge0C94h zOir_3wYM8{Z5(RB_9P|gyX9)2d;G^{={&axzqk}bq! zrdSV2450hQSxE7bVS}L5=`5E;$W;0xmeWqXM(-XN5O&aO7=V`(cS1wUM$7J?r}y1u zryzvFn9}g6H>%*YqT$DH7xSnbAyq4BCWEhy zv|&;a&}$2z7zlE2+v z9CiyYve|>6ltXlD(N}Tc^D}XIiX7p)XP0PI?Y7F}(8S6s z#<91cpg)4!ZaCpF_VBYeQR^=m|8HIfQOJ!+0uyJ$C$ygdBB11A5iaa6pKNZPkTw$@ W+lVC~i`;j~|AdyALKR98m5P8G0R-a! literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/16f30348a3650a8dda66cd4233999f1fe3e85a6a994ed13630b80dad4b76fe11.bin b/bin/programs/client/testdata/block_120794432_exec/16f30348a3650a8dda66cd4233999f1fe3e85a6a994ed13630b80dad4b76fe11.bin new file mode 100644 index 000000000..1e4f5d230 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/16f30348a3650a8dda66cd4233999f1fe3e85a6a994ed13630b80dad4b76fe11.bin @@ -0,0 +1,4 @@ +񀀀?D }_.U֢`돸5]|fzȅDŽ+U)LC7ht3w45GmJ#lkf zQuRrmk*(7nghRuZm%1H9^%t>A6I-90pfv?3Ho8Za0zK}J=?}Pw&?TQ(RZhNr$XjWH zwUC=nWT1!}BStw^#8v$rnHgM;YG6otH7{2rZ$^C)zE}O3gj%34w(sd4{{fhvm?>Mi zTyY4eM)K5&X}f5Ezu4U(@Hix(iHs2dZT+l2Q6YhH^OkoseG;GoPY1!?SNlf^z(`-@Gw_5D6-Q8x?mnsJn>_sw6;H!EAGd?J znj(K+7XQBwQJ^w24HQs&SyYdZ9h8hLBrEvtpQ);`?d&t4*Q>zplIoPi zNDvN2lpnj+R7}14 zZwwF6pP;L&vu59Jg^ES=5+ds_SzrRa0i&2~tM~?E%%C=MpabToE zpo(in|B86CBm$ntgAkRwAP0{F=BQH)9pPc*T>8pT$Dkwyo(6=gHma?Jlj{(Wyng|# z23Tz~skUy;!f(>zM@^v0+q0}UErCHbqzDQ6m_Y+xe`pICMl!}nYIEnmjT#l8q(9LF zo;%bark{K?n)Sjvb7$yVI*}>Tg7AWgqpLY`peWrg?V5vz5al!bz)~tDyc`Y9E@;XG zp+q|rpTt~r!=PhZY-yw^GRB(^Zu7!93T(RHhUDdbaYL`+%P+k^wI`r$6yWEFP{_<} z8L=sIp*8Vn4&r_UInXdaR;4kWv+0tcSI%!Hc7U(&a+VJoq*tEV_Jaw+#OE&Ipja{f z!K%1dppS~s#h{AB5}f@V06+}Wi=DE8%NC+s9V2GyqVe4x|Dev@w;z#Z{;-$~?)mqZ WC{X4zO`LE?nf_1d(seJpsq28ajSUI_ literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35.bin b/bin/programs/client/testdata/block_120794432_exec/1f958654ab06a152993e7a0ae7b6dbb0d4b19265cc9337b8789fe1353bd9dc35.bin new file mode 100644 index 0000000000000000000000000000000000000000..7269251eef3d948a4f514ea1f48c8963ed8f586c GIT binary patch literal 2055 zcmcIlU1%It6rQ^~yPLLxO`2>hN;;KD0}?~1yJ;*Nw~Y@f6mN!h1~aYP!|oc_Zgxwv z+N7vEKf7rmXlJ(32Oq>V^`{S(f}~Ih5)eUy;6p^Q57H+Q3w^MW1|imSXLi>grr9bu z!_GbToO93bckVKsC1obYw}SAT%7hrZ_JE!`%&y+w3c|4Jk?kOSisYG|!DC3SA-Ohk zKG_cBJ{5#5)ATFCMfN&8EH~7*Pli6>}-Id^Yv2u))J4Wui%B_7LmFr9_VxCZ`^g zvg5~cnej}%2*qq6FXanGDVxt0v%sFI;Kj^G%IRe3hzR5;+ z`?K58{;Mk8-Jx|r;0+Z5GX{j_6^-&%&$v)w3<68d-D08rU2Nd_R?V}xS%qMz?0Uwe zEB=Nm6%M>$UzH>8XN~|~I4fvWMpqq56FL)&b_l-6d+JcOV>^31L82zXsY;kKR*y+# zG6cZ_9%T;IsDrNo;=cvK;NL)y&g3#Cmt-t-l zCm&1uZXMcrVDaef3->HNs106yI^|{vqk*s3}*XOv0PU zsnXJG=>t>y`#P7po}67+{q^)p|MlN`GKu{ct=`Yy+4JSp83%{Sy{qOpEcKXgo<8$?`OpMmE)?k+!lctx`U-v9bC;h;Fu` zR-dP3OcRGrvmF*`gUE1=7c&g5B756Y=(j=$=cGLjlPoez^|Lrvw8~#EI^B}35gm19 zCTNDS6%U+OD+aO1NQK`ZL^cUTPAe$m#xA2Vmb6Y0B5QclkWxLsJFM5DRlCZ~)CStH a%mF4i#5QDJpx@`x6NOxASZKLd*!%}7BBS;I literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/23867707929adfff9c3e99737caecc5592a2036c4872d8dd9f6aca5efa638322.bin b/bin/programs/client/testdata/block_120794432_exec/23867707929adfff9c3e99737caecc5592a2036c4872d8dd9f6aca5efa638322.bin new file mode 100644 index 000000000..cdf79e716 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/23867707929adfff9c3e99737caecc5592a2036c4872d8dd9f6aca5efa638322.bin @@ -0,0 +1,5 @@ +gpˇ` TfETmuO;\ղVVݑ-x;VZ-25)^ə_c+yuh2%`?˼ywWL\&TͥYRw08.wD^ff p#K3 uCf628Ux@/myJׂZ?4{xKSjd,?tj 4"W L@ ٠He +fB3ZjN60 Kv; +t8PgUQY`!&(N[9t +Jk# :߆3<7o )?*YEFrbi P\EUBqK/e'̢x&)y5 \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/2699a8471589af386d86059a5a48c2032668072f70a96f392955c659139bde84.bin b/bin/programs/client/testdata/block_120794432_exec/2699a8471589af386d86059a5a48c2032668072f70a96f392955c659139bde84.bin new file mode 100644 index 0000000000000000000000000000000000000000..7b4dc4ae991619ea0ae9bcb82c0ba5beea17b84e GIT binary patch literal 83 zcmewn*Z>0yKE(aMq2tjtwbJPD4COT)3lGJr@HJZYE4Tzqp7Y_{ji0%oAjO9Bw446tUtHh6@H zbv2=iq7s+-BnpAqiQ5axYBj{5Woy?_71i{6<}&B*LMOq=1pgPS3l5!F^5-4ur>ZYQ zpzcW?-@9c2!Aj+;c_K7I0jyenJR*)T6nH+fjx|slOQ7ovz23BE^3c%a$elob>yvjp z-VkI(>f4&tNwI!7bN-+~A0uprUxWp+oyHC+2CPVA_0)HcV&u-EL5|IW!r9-T!-&?u zZNRrO9XQJzV+zfpuY2+Y?Mt;sA6b*=A)C?vphlj^w)2!gCaSavcJFcelHVM)v&&oO z61u)(!y|y=6rgF}WXNo~gXq|{P#WZliAcALz%9GiaaQq=B5l3G{o1_LGw&6w zvlg=)PAQJ)rX+hxZgy2EgXf<6qt?WrBbekE zXM4hJpk!MY+c1RdaN-!1(fIy{BarR6MXdfVpspXTseXPd9hIAKwkK=8tHI(?D+*%g z!?8av(e0h81)#O_qdyqH&nt(Br5m&uh>Zjj_J;dN4*c+T%b?@sL~@|DDS>x>d}b!r ztp`Pb_5#1u*mc6BRrw!vA`ED)X z@UWW1p!=W2XU?}L5t2SGS@Reqb W``$JE5+aJpmLcDcHF^ugPlbS*+6sXH literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/40368bab3a53e76940958bc92c6e99e509a0f248680842519fe482101d5f8ae8.bin b/bin/programs/client/testdata/block_120794432_exec/40368bab3a53e76940958bc92c6e99e509a0f248680842519fe482101d5f8ae8.bin new file mode 100644 index 0000000000000000000000000000000000000000..22de0eb98965a477e11d0a062ee6b75440912dd0 GIT binary patch literal 532 zcmV+v0_*+x0ui8D_o5&4W4;Z!1}iy}=GTeH0+;Ssxf~+c4Fe&+Yj?Y#_qrpBgFokP z%|m_v_7t%X2dO!n2&$QMJe+1*HqR2kp!{XPH56|fvdR<{v5@m9Y^Us$ENmEO-WEw* z)*UXIkD&evAzmTvhjb91qe1^J_*AnGWf|oFU4mPJ+Rbm`Gx?wy#3cWktYq9MnGOB^ zFG$$Q8`;iDjDwEwAy#=92f*f_(d<~wY3^xKVYnWGW5vD<+b5F{__h6xURMp=g`ajW zpno*kmIH@TJEc@iWH|w{-BvOQ*p|X)}hlRjr zzC-+|ZAoOIBI%SuYG-0|*O>|wmEKdJMB`IXLz0X+T=i?pbj=DcRD`ic}=U;Y0c#3%!tX2Qa(pVWk{0GPUzu_E1*&$1jA;HN&wr3Ex-FU Wcc9#vy$Ld=mc7}i=`2#!v literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/48fff8f1fd80c81eaa3c6184627b90065f487eb6f2cd322e12b6c5f259f48331.bin b/bin/programs/client/testdata/block_120794432_exec/48fff8f1fd80c81eaa3c6184627b90065f487eb6f2cd322e12b6c5f259f48331.bin new file mode 100644 index 0000000000000000000000000000000000000000..85fb2c98243b7742628497b51d1f5783d86c4cf1 GIT binary patch literal 532 zcmV+v0_*+x0ui8l@2SaI_o3{Jl-eX#*K#FwxG8Pao&~;N_~}>u9{%m1=-V+8d(P3x zYZSmi!X{#+!m2YF*$!oM`hie)XqGocpoKv@bKx;w>VzkCQnH~CHEhs%TS&aVCuA$L zQrvfg44{*cX-KZ#De9It9%8%29FmQgqtsakRrTY~auHW;nP`0Bc#Ymina% z#V8|XMqlPzRwYs=SD&B(V7EW9{K}+te0tM{aq)W{z{vzMI#f)AeF^&H0LA8@19$iJ z(~fScX!Bze$E!_-#bjANNc?j7aWVx6IV!hXpq6DoH%rZHl1Q`T9KbxdVf_0hjwTRL zzH(j3B}-LB=b#(5^c$=AW_Z@K5T;3{?qF_?VGTn+9MLX1pZGHn3G$#7N(PofZ-$0B z%I=Ow-W6EsJVTPur4j|vIE*>#ik5Mpv>RqdClRG+yWAIW%NM*BEv?5B>8|?{VFI7B z)zLcApj(|*iwgufX~BsP2l-!(A>oU93G*a@WPxcx*JiH)dY~Eq6!*mFHlr&GflT(> W(5c!j!|G#-;^bars}TEd#b|()sRR}P literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/4974e12df5974fdbd2f9988aed4b344cd5f9ae4ed7b64a53bf7d9299a455e294.bin b/bin/programs/client/testdata/block_120794432_exec/4974e12df5974fdbd2f9988aed4b344cd5f9ae4ed7b64a53bf7d9299a455e294.bin new file mode 100644 index 0000000000000000000000000000000000000000..858dbee6e9fbcdeb95e4525fe5683a93734af5f7 GIT binary patch literal 532 zcmV+v0_*+x0uiA0$}?0dImxU7Xl}>p|8~h;!sPOy4CrKxbQY4)UU(^>u+xP^c%!ie z3bS0!cs|K7ahEN)o|kQFI+mE&)B7Yvph-6~4wK&RqX5PzrxQWtBS2~!aP#pm$L z+IUV>N1&ekn)@2}7K7ekzMyekl&!e~)$9nu({m!BRS48HTX&#yxW``#NRy3dR{?bB zlLOdscQXOZhM**EuV{~>vF}KrpH`kQ-G_!9XVm*W8@qViWf>n(f;D+Ex8563hr!%z zpm#r*R2T~H{7tYT7H87|6M!_OZ0Gsh)y_H=UM=;6k)S)BGxwoN&-t=owwkTSa1$O= z4><8VWF+v|ixXqg6kDL+0wghY$OJN!QxCz6Z^Z*?Drd}Yyh*d2)^1B*9IEJ`@LYnl z{Jv?Ok>l5%vxM+-G-OKL$vYtma#Z1de~tc#3O#|263MtJd`j z+0D`qdN)FIl%TX-(m_n!R0O{I85@2SzCH4rG0gN~^{w=56Yj_Df?1&AOE}mF#14bs z*Q{6U5MOT3r!Lben`<&v5@+)vG9vzBr047hJC@7|hD?#W WKb^vB;@|>pQuZP2V^|I$D#C#6=?BvQ literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/4c95cf2cb1d0d7b2548c4b6a16335f4c5ebba6ae74ffcba29096bbcd41cfd309.bin b/bin/programs/client/testdata/block_120794432_exec/4c95cf2cb1d0d7b2548c4b6a16335f4c5ebba6ae74ffcba29096bbcd41cfd309.bin new file mode 100644 index 000000000..912a17ed8 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/4c95cf2cb1d0d7b2548c4b6a16335f4c5ebba6ae74ffcba29096bbcd41cfd309.bin @@ -0,0 +1 @@ +QKw~vp< ؿ<"U萱8Z'ќy9T  ǤabXက \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/4e03be42805687850c90ebc9086b513f8757798448a88cafb724b69afb46cacb.bin b/bin/programs/client/testdata/block_120794432_exec/4e03be42805687850c90ebc9086b513f8757798448a88cafb724b69afb46cacb.bin new file mode 100644 index 0000000000000000000000000000000000000000..4531429abc8b72b20220fcc3a42001ef1689ad16 GIT binary patch literal 532 zcmV+v0_*+x0ui8j3M$<0D+j79zP9op)CbyB<4qfg!z*tZKfseiTRVlI5j%`inK+CG zPxef=)A(7?oqCvb6~X$=0hZRi7h`ADpkve~s$u;qf8|oE(giJOGZ6(D3r{g6apnho z1rv)P;xcJ^XLK6LA#9x;fh6UhB?Il0$L7Q4dzfnAAy(~Jc7Id(V^9@K7n zptL}w?WnyQaJ9Bj@FRc1I^oVb9W}9^(-WGqfC*RLcc5t?nrq^MdE6oVgPG8s+LB^+UkzWu+j2rI|LF*M3WSAY*eS9kIYcI z7TEoc!9<>i`-cb-qtJxOui4f{gu?VOA}<$$pnE`FNc!xo&Bfv|G zr*t89I WQgnDV@3~$+^DP3r^3&Pw75RXf&H}Rl literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/4e1b08d0262bfdfd06ac3d950f9e0be494cefa9abecb78672efe84b10d712486.bin b/bin/programs/client/testdata/block_120794432_exec/4e1b08d0262bfdfd06ac3d950f9e0be494cefa9abecb78672efe84b10d712486.bin new file mode 100644 index 0000000000000000000000000000000000000000..28b8963b30b85d66b0a1787c3dd8e2ae28c8906d GIT binary patch literal 532 zcmV+v0_*+x0ui8fp6>CkOd`rjQaEw9nb}%?qwS+raiMzaG5%gnbeGcWph*At@%@0v9;!THgkpP;246^iw(`v~E)urI z@>%qQF`!x3A#s(QZa-0nsnkiMAy#npVf{r^^^>LT>&}6HrrDqjL?SV7z+blB+^z(A zbvqVP>kXbdbebh+o)eYE_pMW)i2FSHi_Dxtn>S$eL!8m$yw2aa@Zy>3k~WYl1>}ij zpr;3lYr&Gy<40T6-)Q?(%D*5^a{?I7Oqm<)HA}LB_!xR^8qwZXG>&ur&xP zP5&U)hXu0)g@~j~%Dtd-@%+jTDOBsvQi;A-43q>nA*oZtqXv{o3*#UIV|f#x%p3n^ zM0b3$`dY07V{wASI%ix^6AZUvq-XEEtU?c-pmE2U!@iC7gD?tDNUnIZ*#$ZX_ZlNC z#w|#}$|#_Dy`Y)!doblJaXnuL7S~9s(3bXTx@5(mC=@y!)yBb)2Gt4v*(HT;7(@5z=o$*{^fX|b zM WD3w1u#vP_I;F(*${;RLa^2C5#W)~v> literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/4e209eafb77d208ff7dc6601124e163f3f6ad7c248ca5be17c3fb5d6bade741c.bin b/bin/programs/client/testdata/block_120794432_exec/4e209eafb77d208ff7dc6601124e163f3f6ad7c248ca5be17c3fb5d6bade741c.bin new file mode 100644 index 000000000..b5820b3ac --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/4e209eafb77d208ff7dc6601124e163f3f6ad7c248ca5be17c3fb5d6bade741c.bin @@ -0,0 +1,2 @@ +KNO/^ɲ"nYt@HҙKJc攲Ci<6Z'!qC<8-N7D赡0TM&C|+D6!~`w<3zaugO)_>VF0.s`SDfU}&L!};SRϹ *i?=3#ݞy0 $Kf62&|H8ņ5bQ`Y2(?xk,BW?=N*"mx,ILP6k +X(<7{pHvuMu4Hҍ4$ԌgO`R{{_z9"gB}, 6tPQuD=%ktc_-Js>-3v`I7Sc@E;Ad[ \c8,[Ja)H-_0uÌ(+< ɬA;f:5gU5Q%^d%:9_O*oRHŘF{Eۿ> OTbR + \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/4e3ea077078e2400e198de0edb4090e9507f4816b809698d2646574756a13055.bin b/bin/programs/client/testdata/block_120794432_exec/4e3ea077078e2400e198de0edb4090e9507f4816b809698d2646574756a13055.bin new file mode 100644 index 0000000000000000000000000000000000000000..46e9d763f9d0a1a2b807725ede66aa37e99e37f9 GIT binary patch literal 532 zcmV+v0_*+x0ui7c=&!@M>9;*`;Ql+z?da=NkQ11v$!O{p8qeXxXp1|bBEb_Djk4uU zf6jb2ms%^sFM9#!Z2>;XZdw;P0>eX7pp1OtwHCIgbu~ z(qp?ofuK1G2X(rzMx|fyC@JC7jR@+{=lkkKnw-^}*VVWaAPJy4Jqbw%^VA4NT=ZVd zj_hDv1N>A1Q@NIG7n*E_wj=GJKpbDtHWK5t3AzKcdo5qIZ?Sep#z}j0Yu|5=ILmO2X7tg;zR5~;|MQ(??IETfLaL-~cKeebqCZ^ecxRRXQ|S~aBS_J`psS^Lh9w8Y+419W|2)H_O404_a^%DZ zBJ%E{a)MdvVxWB8z+vI=O0ZU>yq6JhcfFM&@Stz>thdlJxT4R7(${WZ WuaR~1fdOi%O(qkRJx{x%H>!Z_BM-{} literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/4f170a13fab02b6a6c41a61a3a6a360932cea7111ce49194d74ce9247fdd91a4.bin b/bin/programs/client/testdata/block_120794432_exec/4f170a13fab02b6a6c41a61a3a6a360932cea7111ce49194d74ce9247fdd91a4.bin new file mode 100644 index 0000000000000000000000000000000000000000..62759b596a57b7945b2e659f8ca7b1399ca3fb14 GIT binary patch literal 532 zcmV+v0_*+x0ui9DUtTPMDJMcZt0BG~{7sgO7#8+(ioQI7d)Vn+wabB^*nO9qGENsSiW}mV z_?oubqsM-zru*L2p-%4}bqW)pj&QB!6V7(C76BIcsNIA(vefjU&|Tt@i9k1^NGdnV zpfvw+fJsn5C3R|)wtS!_F_#SNjxliEAcb>ez9EmZv!F?I;Vt!-PutS@n2PO7G)&d` zu1?psN>jgml9{Ac;*_9NapiW>^;2s0G|jb$<+U6t?Hpkm1Oo^yejW0+v!RxtIixd~ zRDc9vSj(pHMv#YJ@3Sv_sHDtQrqk4=f||5|pll(fI6Rka<)%x|`QG8Epf3L1NF}DA zte`Y)x^v7X6rjZ2a+FK(kpCv=W7CxFoYzCQZ8?*dLHH5%(OGrbd~2Y^?Nf;`FL#d@ zI<#^9;}&FL{TyGc1ixQWXN~xrmk`vT@JKNtEKNbm#GsI5|5@&Q&p+#IxPX0YMO-WE zMHSK+paBF#b{=AN_(_yA0XZI$M?TT!Vt*!Nl8RqXL?tlwuAs7mmUvhF^~>$7;3_V- Wy~x{Kcrg9cCtp(b? +'wN&ZA\Gc?<D\ \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/52ac577eff8e570d3553a41f94acafbfd7c68ca8b0ccb680a978c6baf9d405f1.bin b/bin/programs/client/testdata/block_120794432_exec/52ac577eff8e570d3553a41f94acafbfd7c68ca8b0ccb680a978c6baf9d405f1.bin new file mode 100644 index 000000000..bebc1f6e4 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/52ac577eff8e570d3553a41f94acafbfd7c68ca8b0ccb680a978c6baf9d405f1.bin @@ -0,0 +1 @@ +1-Rv;&q~j2 KJ°s- is \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/530152cfb9990c122ab1693f3d3323dd9e8079300ca7244b66d2f1bb81369232.bin b/bin/programs/client/testdata/block_120794432_exec/530152cfb9990c122ab1693f3d3323dd9e8079300ca7244b66d2f1bb81369232.bin new file mode 100644 index 0000000000000000000000000000000000000000..886ec522df71cab241b17e5eaca9eba116ba3297 GIT binary patch literal 532 zcmV+v0_*+x0ui8i+t0&f%JCB(iVEo~JV%X0&?JwE>Fgbu@&e|%^VU|NJP!QCf5R1^#i%1*t)c+fW(EeB?3M`OVnBU2pu_(1#B}XJ&XH)=%onGnm0;|*`ybB0$cXHP zCu94tlb|}5LB_xrZ{tkNqItqBr92u0ZwC;WxG|pdaqv}dcsHOv0sE1JG38+XNLuho ztGb|XMlzh23hYYBWoxwWpXWvz6ugKtk zpyJOPielc@t0uB`mMA70y0g;gKU{{zbFBUc-8B=EjG$BTcPfZSEaK z%ghvXvWzZk!FxMWGm_cf<0mPEli1iSgdbg}puF~&{E9=0T8i#hyLAeR#i*aOBw(XH z)NqR!2vo!E8K8)La1==cGgUEd-gK`JS}SE?E=X`{;*X#Pqpq@Od9VR` z_8H!+7WaP75ppdtwWdVMKzRwVg$UxHG|!%66@gZXyGn@%lElOgmaqF(-u>*BiIvLC8T-aCW(10$7W!+{OIMM| zBhsIwa&HPh9wM_ac&xJvuyIRH!Q8F1prlsMWE(HX8{iPV4r*C~y_D;Aty%2NvS#2W z9a))Ikf76HU%9T$TlyWTcsxb^0XVZa+?F8@|F|ivjJzNqvD2Vc?vo{%dQzP?c;HZ~ za0sFCBa*-rki^a8dS1KBW+&31s;eJOSA*2cM+i+BhPjI-NTi}@-^r;5fHAn|X(1+q zpo5b8x7}J>LEZSZ^m|#J?k&XMO#g-wPQOQA&kN(!Lr!D6L!)#+Ot z6lV1kWM<+oezUfi?U4yw->JZs8gX!-ExnVrei)s9n7+!QnA>Zal}=?xD|bYC{i73w zV*Yp5ptUVNeCLYDef_SiLGAvxM}mRlnZ0b(MGDxe0dsA9bj-GjniHDOQe Wj=cc3W-B#VD11a5fkA$>a?OA=R}l*U literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/6ef4fb49c50e658b8e5f5d03197937e579f30f9774d640b98e755b9e765f38d3.bin b/bin/programs/client/testdata/block_120794432_exec/6ef4fb49c50e658b8e5f5d03197937e579f30f9774d640b98e755b9e765f38d3.bin new file mode 100644 index 0000000000000000000000000000000000000000..a264927c03fea365e712cdfb4d1b9ebb972c1994 GIT binary patch literal 340 zcmV-a0jvJ`0a2i6X_(9dIf`lqWZmDjO2?x3kCr!pW|VD!=${74!Ri0L zX!|CBpvBcoky}=%i0)zSod{hi{j`&mmzCf{gJiC+V_snP;{&rRFAp mfS}B|d)3Z@M> literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/773afa9eb6d04bb86ffb3ddd850254fb6421a563fb0e4de659d96406fd8e13b0.bin b/bin/programs/client/testdata/block_120794432_exec/773afa9eb6d04bb86ffb3ddd850254fb6421a563fb0e4de659d96406fd8e13b0.bin new file mode 100644 index 0000000000000000000000000000000000000000..59b094cc17d8d617be924c6f1650940741ed29ad GIT binary patch literal 243 zcmVx^afS_wMp-=tnbPml5wQzQOx6BdPsAst6xuBGib*0)>^RR%R5P1Ixv(Esz;5E;V z4UZlsHq5#I;P4*rlK-w8XhuO?fS@c{XeQ?nkQW;fJgt3Fl3Lr780tMm()6!(a;r;k tNrixbfPjF2pbYzGm$EWHWX0YRm&0km<@cc)8*MhV7y2h+jVFQxiGVf3dj9|b literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/78b3719e6377f9e9e185d60714cbb7959d7cdde7b327edcea6df6530a73df9d4.bin b/bin/programs/client/testdata/block_120794432_exec/78b3719e6377f9e9e185d60714cbb7959d7cdde7b327edcea6df6530a73df9d4.bin new file mode 100644 index 0000000000000000000000000000000000000000..0f0ee9ea54f5a51c8a763e503b910ee65656770c GIT binary patch literal 532 zcmV+v0_*+x0ui8LNN`TXj7q&^dbq<{xqx^>c{mvZ%SSUJB2mF&2Hx_ZtF)F2RR_)x z$2Xud9~+^M(;;-oTY3ttpXFj{n3oHsphOzci1$$)N;l{k)<|Khaz{6wkOKK}*(}9} zKjAyQ)S&Jw=1n|xZJ#Y*`VMX4HtSt!PifJp?07qu*$Z1KBY*C@ouV* z!l7tn-#GgH+B|v-x({CLxo3-@B}@clC;Vimb{FmS1wgO=4q3?@m2ook&VWe7^ zpuULySKyuF@MrKMHhGB=kcbn1Bt1P2Y3qXOI_os+lAx3QDDYKHt!q4kJfLzrS@Pbp zWNEFIV={4kdqy{R@D`vp(v~t`JmpP`P{z$zb}<7`x->5bSL4i4f&aXd0xz)`fsytY)GIWS{6-ej;LAo z?`-ZDsDwCCtdpdQrM5GT(>HAFZ86WFktc>y_HYs)?+TiKWXFCZ$sOJmgh$`h&Gr;T zt$3Y5pxvNpWtxm6b6@73l@VRl&GsBK45y10AcLo{zamMH6`+|tuTcyF2q9$m%5jAn WcZP8fc#VLQ$v$OzwW(Grz>gDdZ}uky#nY}Joh*+RxSftp`vv~&k4K<4@5;32+BjR8!8P!} zuYDN%jvQW$3hDi3UeS?Js|CK)gVQNk${=>r&GQ%FS8~w+XFn-Mm`>}0bD%gd)f%y)pRxbg9CfMf$^S}t zsc{gMN33EUbBPXD+RC8D=*9^{_RJ#GBp9E{SS4j(oom9>3#WhOs|UlHrݟj^c"S>k86'26 G&|oQ0#٠Hr yH%GqISrtîyVB\v_ _U7i1,7MUr$?_-dn$e%𯾠3M<@@eV~PX Ȑ^JaJc19Ӈ4s9Ǯcvw3$}%^aJ4PCm}SCL_:5va sԇ̢NˣluOuEӑ){Sߖd &xN 5I:^>i56R.!00X,:LLEX;-a?7V;dLU eNTӴD/ӌ@\j:Z+^Ga(/>1un DRNeXnhe@TS-T޾qJn/o"f$*lH%XCڍA[X;@u*зA[ `88::39ݸ \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/96bee8bd2cdf004aaa65ebb41579e5859580442531fc987343ba45015e33e62a.bin b/bin/programs/client/testdata/block_120794432_exec/96bee8bd2cdf004aaa65ebb41579e5859580442531fc987343ba45015e33e62a.bin new file mode 100644 index 000000000..c6f30c104 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/96bee8bd2cdf004aaa65ebb41579e5859580442531fc987343ba45015e33e62a.bin @@ -0,0 +1,3 @@ +"Q}F MBniǪjY(@]>)[qde%x€'gh'Tc$jйLp׸W/lh8A֝ޝP{tT:_FiUV싶 _Pi|Ѱcͺ'6G`N|Ie #tA%B;ωshet]Q4>_f&~s I. +7E ߖ lHih} +< \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/9dfe90e2c2b8bef643fde8a4415de8775cf0a7ec3158873c36ba8daaa8bd3741.bin b/bin/programs/client/testdata/block_120794432_exec/9dfe90e2c2b8bef643fde8a4415de8775cf0a7ec3158873c36ba8daaa8bd3741.bin new file mode 100644 index 000000000..7a60defee --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/9dfe90e2c2b8bef643fde8a4415de8775cf0a7ec3158873c36ba8daaa8bd3741.bin @@ -0,0 +1 @@ +Q8`ե9^D,M'Y>7JW=>T"F/.v+QE/} \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/a0b24abb13d6149947247a8817517971bb8d213de1e23225e2b20d36a5b6427c.bin b/bin/programs/client/testdata/block_120794432_exec/a0b24abb13d6149947247a8817517971bb8d213de1e23225e2b20d36a5b6427c.bin new file mode 100644 index 0000000000000000000000000000000000000000..344a51987293788d5e2b3367e87e9d9b98a02e30 GIT binary patch literal 532 zcmV+v0_*+x0ui9dXi4FaSzSG^&4qk!o+`+2L1#jDjhW*x$0H`v^EWA=IaTx*^0XRF z;x+E(6(rW!hGHVHD$rx6_Fk(Ad==_G&Mk))tb8wk)QEB*ZjtUZ+v zo(trZ&ib0Z%Xnul{)Dj&aU_PI;?-~cyiyG|C$dqwbF$-_phhGRvXET682#tal>znf zpzd<;;!0{aiemb91?D+>D01E$B-OD=JTIbgz-vXErJ&MaJwe=H^o`X|t4hjQA#BG` zjOcfG1-{?XM(b<-AaI}?F09{c**63oP}Lx@QCs=##5YV{)k|Ja0z@HL!j3ec?p1SU(1uME*PvNzod%lS4#F}EIHv_Z_hFBb&o~;tkit@mxGtB4ON5}rP!FDPuP!8$ z?gV4kiA~v_Yle%N`*}(=`Z>dEDWJO_Iuu6+!Q(;g(#j%W WkDutoj?xD&txCH%CX;YEW}tv_I|wuY literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/a38158f9a821924e38eab475e0d6ee93a74f878325dfcee0d4ffc1f1fdeaf48b.bin b/bin/programs/client/testdata/block_120794432_exec/a38158f9a821924e38eab475e0d6ee93a74f878325dfcee0d4ffc1f1fdeaf48b.bin new file mode 100644 index 0000000000000000000000000000000000000000..edec2e684dcfdceca7412c105ee515d608dc8172 GIT binary patch literal 532 zcmV+v0_*+x0ui7CttmSPH`9c-{b5OZrY;~CGp|94N40+jLi}<=-UJVzzs$URzYt?p zs2JJXv#b&xQ`e#eWGB>`{da#JJq=FIpqik?qp$8b@;m`RAS`jUmfV>PU0$abuTF%b z=7_8IBA_%uWcXtfh1sV=04Gs^adtHuRQ3Fj-5?6gYTQLe7NMYsZ?e4ZD~;eYe0dEn zp1BJm)W6>b#%*rrH+JcD&PunSsEK)A<=eczdTwa_5!GC)MPMjfGyHtC9miO_3H8%B zpp_5MEf`M;K@YpEHUw#`+7F(;K0I_0ty~~h#fjprlb}^{b!#&u1VwE@1G)<1P+jI>gLpfy<-e^Y)E`@NJ-WpnoMQH0l8x**Iz zScT;?_4DfY>ICXGAR4ye6IsSruc=RKsJl3I#cIqK$VNhEN+?Q383;wXb3`4pX7oN z9bby*pkM3l1Ko7KF84lfq!GZ%irSqO2R)A<4zxJ_INFQ<=b#aLN{Z##O9-N;wf8H} WH0tm_yYv&Vԧ \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/a5e9953f800a99d4bc8dde35fa69497890c31426e6470fe6b031ce3f325c215d.bin b/bin/programs/client/testdata/block_120794432_exec/a5e9953f800a99d4bc8dde35fa69497890c31426e6470fe6b031ce3f325c215d.bin new file mode 100644 index 0000000000000000000000000000000000000000..8b8081f6921cb3f0694de15f0e2d9e0f7c4569df GIT binary patch literal 532 zcmV+v0_*+x0ui7-@!IL?R>$BtXbXXom%=O4GJXgMbf{&2o~PalPi8AP-i$g&)=Z@x{NuZU1uY@_>Dhj zX1WoYl;2@!)G0J#$*p4H=}beQ6Tu$ADPF0wr)=C(CM3K&i8fz*D+XH!Ld44f&M4@(*~R7z>4z3T7eA z6lp!Ev;lo{Tx{BN2fhEC#5HyM(zYKRpkX=JB@x&(_k8197L1FSHN75Z|07ix^E1zG zk3BtYSfH``NO`pgo%e+IExB-rHLk;T@kUbeSeZl}ZQUnfgczW77q}1p!z|FRT(k^BLJ@X@sEvj&uX{!Y#4t zM5pM2zV|fzYx?|si0gVPva-PaYR8qJm!L?6`FU0zycCxV35wnV=3xrtR-4jh-uP2x zh+w0GpuZq17F;jq=I$~t23>SWznP~q1_}5x^CM5|uGY$gQlN+D5@qRc{ZtXmNiCif W?HnzJqWU;E#K7h@+T|2&k1&AZ2^56@ literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/b567c54f0bc7034c18e906e583980549697169300bc98bd7eeb73a67587ccab2.bin b/bin/programs/client/testdata/block_120794432_exec/b567c54f0bc7034c18e906e583980549697169300bc98bd7eeb73a67587ccab2.bin new file mode 100644 index 000000000..dc6334718 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/b567c54f0bc7034c18e906e583980549697169300bc98bd7eeb73a67587ccab2.bin @@ -0,0 +1,2 @@ +f;&e*x$~[FDnIe_]y7yt@u[v_8ӠTR>z +۰Աe̓7x5;5 \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/b7a27b4f2673d087c9a6bd9a989ba07843dd931d60fbf9dbf8e2eb20ddd89ae5.bin b/bin/programs/client/testdata/block_120794432_exec/b7a27b4f2673d087c9a6bd9a989ba07843dd931d60fbf9dbf8e2eb20ddd89ae5.bin new file mode 100644 index 0000000000000000000000000000000000000000..b13ec9f00d00abff48f3b480708b5b3e9888e57c GIT binary patch literal 179 zcmV;k08Ib*v4DVpph)EDsqsYS)wk});Yn2KDwN9i5Q(*@q7d8dD$6YH`hb9dpcLPV z*YhL>TxM1gfF>uhv7X$ngg@Ayd0?((L hv(S7QCCh`G$6YG-0OyUek@beCT28t^HjG_yfPmL@VY>hT literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/b95180726e05e0a34e4ac7a2f88f96378066946d80e89f06cac1e9ffbe68fb26.bin b/bin/programs/client/testdata/block_120794432_exec/b95180726e05e0a34e4ac7a2f88f96378066946d80e89f06cac1e9ffbe68fb26.bin new file mode 100644 index 0000000000000000000000000000000000000000..8c42d54bce2e32627cfb21a499678c9235278261 GIT binary patch literal 56 zcmV-80LTCLpgJ|I`@vuM8ab|gG*8zF@{Wc8w5p6{#o0XJkha_fbqqu)m O-m|$&qwlGN=*!tsLAxg<50o-!n2JaE80XolWu{R>{8S;3fm5>Z4f zKJP9%+N=Ptm^Ke?T{c{Sv?SUbM*USppsIT3zR+iUFN-dh%c-_F*A~2SE{%9HV()iP zv?3GJ0-#ZO)3wf5FpvkHFcZcz;PiRWnj0lIS9wAtCg{1SCHSBLk;Z<d$Mqztw{q%}#%o#IA1hj&oIM9Y5mAsyZLb@C zpuKQs`3+jLQpT@6$&ZPA7h~VlLDb_dG_d3D_H!Vw51_j1==nd%JuiiuOPL2IgIeiF zI8VCIFHc$>R68EndA*?WG8LvDK@468)_b`LtbrS$P9rgDjkx>dF!z#a?0h_+Eq}u^ zI=SY;9smg_b^g?wf4v_Mt$GVTI2u1n_he@JpyB;Jy;2Dn2K5uQ_It#5`g#f&7c^6b`KfIzK$eHc`p?~ WHSO-)jfj|av#l~+!&P2v!+U^PoCJvg literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/c4c73aa63f92bfdd5e1c760f9bbbeff2fe5e9b902da35a14f8fb52ea3eb2d983.bin b/bin/programs/client/testdata/block_120794432_exec/c4c73aa63f92bfdd5e1c760f9bbbeff2fe5e9b902da35a14f8fb52ea3eb2d983.bin new file mode 100644 index 0000000000000000000000000000000000000000..d1eaab5fff2915fa59b650d602c56c83b6a0245b GIT binary patch literal 532 zcmV+v0_*+x0ui7ShJY*l0}A(C@SpjIZl=c$`0VQa=V~MxFQOB%h7q2iB=627ZA$6K zh<9fksb!=VSxaa69?RS_Bb53HD)t*Zpm7bhu*e4!EAS4Hdr7a6pt;CcqkNsG0EiA` z(|NLh%b=z0nMlY%dOBCah1$&3!J{qdT$c}4laZy212XnE_Z*-D(K3#j3s#-RDKWsu zT3U^a+!R*hGudPkt2Dlg&vwM1H#$xC>;HkkrMnQkGFNx_g^z;vGJ4wJN{Dsed!D1G zphuG8kWKh(VV^=GQ$c=K1db?Yv!Hmhah_v$`RU<>)&~^Jx0RiI z-RH9>?arp(WiY2b`P85~Fm+>+_p!I+VqVqB-i%)E*q5v$>Zv zF%5=FTHkz9FpSRXyWiDJ4%B5N30q-H18=KipmO=`{^@a7lN}6I zwRecMpa`Ted)^*Wm0>BAo~M){sN7{FNsp8?v|Q#LCOVn8_Mjy%z@~#|ri0=|mA~1o WL9&FgLjy8#UF4~fsFU`P@Hc?PyAa9% literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990a.bin b/bin/programs/client/testdata/block_120794432_exec/c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990a.bin new file mode 100644 index 000000000..b3b16a678 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/c5d54b915b56a888eee4e6eeb3141e778f9b674d1d322962eed900f02c29990a.bin @@ -0,0 +1 @@ +6l(*I)TZ&Df6ƈ \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/c88974f0129bb5e31fcf9ee30734c9d3eeb459516f0b8b6a4258b51ee331547e.bin b/bin/programs/client/testdata/block_120794432_exec/c88974f0129bb5e31fcf9ee30734c9d3eeb459516f0b8b6a4258b51ee331547e.bin new file mode 100644 index 0000000000000000000000000000000000000000..000748693587d162a7e09e920bba4b67adff9b70 GIT binary patch literal 179 zcmV;k08Ib*v4EgbrHol1cU9f!FIc4%-Fb}_SmqQDOahtt>pw7oxX9Lxe z@h!^5k(|;BTsJ6{G`E_MAWLu}uNQ@ac7UKpPDYh7BSF5+6FtX_2(u7s45-#W<$ahN zqTYhGoBH5@piAn=Kvd3%y#WP8)ur_?Zv0i|Kff5E93jLZZ~*BX{eYlM$e?~4>LjPc h<>E3UH*o?RN%okTMR1?Ess#9pft5XgfPjF2fPhSbSaJXW literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/c88a313aa75dc4fbf0b6850d9f9ae41e04243b7008cf3eadb29256d4a71c1dfd.bin b/bin/programs/client/testdata/block_120794432_exec/c88a313aa75dc4fbf0b6850d9f9ae41e04243b7008cf3eadb29256d4a71c1dfd.bin new file mode 100644 index 0000000000000000000000000000000000000000..7dbebc3f258b370f4dfd414916fe122721416d71 GIT binary patch literal 1342 zcmZ{kO=uHA6vt8F&olBNXLJvM6e?^(HbJBE#!YLBv5}@#3PN|2 z21zTjNz*1#(R%Ubr6)Zog7o4+58_2c3L=Oe1f?iK)i=9IOusgP`EA~N|Nomey8#_M z-ottmCk+80`dUx{*4@C#D&EPk(yD85V|AvHlWaiOmUE|D5Qhrr;*PzDpHfRP#6HB& zyY^p3Od|f0xCb$9tJ*RyPCsI3w(Wit@h9TFn|(u=MGzlXUHgJqQ!MbUol?;34Tc0_ zK^NlL?|mbP*AYW6+rA+t5QpEse~7qLtfl8}J#lgJ8$&fu&j5z%5qoRTONjddL2IX+ z)^S?h4UDsXe~>%w_=6(5Q)xu}1|EvD)1ksj zo9gU1)Nzn(e;HoImgRI$%H-^s5NZKxnK^x&=FN+L3zyr@EZv(aw`GE**qKOvWe(G# zm&r6yS17W0eF535F03nrwSY>i2Ro}=w&ZU~+qU77t*|e%=8jPG!=sHKLhY?Yi(4yS z*L5ixVa1NB1axhw=i<(u0M37^`o-j8aRghfVq(Bz)C)(U9ha&8&Yo~YyL3c~jD{zr z@!>%!G~nfOvsHD{g?vptpik1(yXxg?1UJ3cWH^sSuLE zp~AEb3`KRhv{l1xxHvm$zjG;5!6%dGr7x!>IqTfn#My|Q!P!`nvjhHMR^dzsX@**N z3krCWRGwD=aLHioF6f0=_Vz+v$z9*4?OnJqPXCY+f(h6Gs Qc@T<5!rF0CT~BKN0os}rsQ>@~ literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/c96741e51de476969656bfa630526fff934018f736ac9f54f960a93c05d58bb6.bin b/bin/programs/client/testdata/block_120794432_exec/c96741e51de476969656bfa630526fff934018f736ac9f54f960a93c05d58bb6.bin new file mode 100644 index 0000000000000000000000000000000000000000..1169e1a7ed47905bc9324f038f2f34b02838c418 GIT binary patch literal 276 zcmV+v0qg$x0TG}9$>b5UIhA9b&R2PsA?;12s{c9JXAP(aLDl7S%cLNnaYI|9?#g@m zObSoemK7NExIK-)j*BnL;v?tn?YC=ffS_IE^waK={c83(9+N4{o&V+l82u*y%In~$ z$2|NpN%Vk#fS}RpN{|%Kp({bCzi#o&0+z{j#9O{aN|ang0F~RMocMsCQ^-)1rMMP= zAFr6FT)TLflYy$(S%K3TNT}6zC;Xe~fS|TzStsMIZwt=W$MLXUM3|BjTYM&Ma$6R( z;hVB6%)FqU%P&^F$pNt*nC~$TY?2%M8Iz680RjEi@@bh_5Np(cpc;vC4;Gf4ZoQ>6 aJ7`6X{oa53jvNrg6ST4H)07|;vh_6pgP?QWHlKf#7=KB3Pg|{Lj2XKJl(UHt7{)# z#RK5ez@SJ1_jL;0yW^aJp&1$_?#HnqWvhCooou>z)3H*uYaO6MildprCZ)rb>Iqv! zguFkCl0nkwA65jG2M*!ilaisJMhXDJ?W@kudw1QaqeIX>idc`XHXTHOl}J$L1&X{*e^RF{?&>yy`WG^tvF^uCDjcTnxL589^qR- zCd@2Ee?x9YjZ+ignVO*98+OAo%TM+Sq698>IO)|=y{V}L#$C%8-oNFg2;b?TFu~kc zeYMnzXv}7v|jL_I!DG&D+yYz z2X<#tk%0p>VxSfw#6RVgTZ3tz?o4Qw6s=6Jlc-GQz;xNAXG;xK8bYAQECPr6B zR-rIepbM@U^B9Da%iC)asfXckdbrϟmb[,(sȈ!s[36 R6ߦ]>;L=qeV@Yh0{4ɛL5"ۡ]2Q %[+IUyF<Y6(ށ>ta}ʜPL\ haRTτ@K=Έݠo.e>nhWBtyQmlzj`fY +\Cxް&,5naJa7ʾZ͔B傴Ƣ$L*G⏍7nc5 &Z2/ \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/d1ec58cd69ee695261b81e8263c5be0cdb279310f8b5fd8e5e570ddc859f762f.bin b/bin/programs/client/testdata/block_120794432_exec/d1ec58cd69ee695261b81e8263c5be0cdb279310f8b5fd8e5e570ddc859f762f.bin new file mode 100644 index 0000000000000000000000000000000000000000..c0dc02dfd97c058da607011f9392a5b6a33878a5 GIT binary patch literal 115 zcmexSxL{AX^MQBDZWdeSzkR)8lL14e?Wea=SKdD2{=9hEZ|jPJ1-}ldo_zgsmzR0c z7iJ;lZt)?5R82-xF$Zul?NY96(XQJR|vdxS!AP?BWhy4|B|d{-+#ZsasX zpdj!f*rnVS{s4-0)fl$NA;ZLEp~vw(ZAnR$neW6X>!2}L)YJlrMt60KkRmQ7B#*s? zJfn|>z)vBktOjUV@Zg}3-Gpaf5aqS{CQ!ZsTT=LpmG$m+n@-uHuSeKw-m{5B-;m1AD zP|h`RDB=V_Da%7teRk3-IxnG<4n57FM@IG=GejjPtetIDLo3Y?&i&?V&nx!Tt2AU) z#tWi5pg+dZBxVk0sBdZolHPp{^XjHbVlkE#v4dVF3pZkD@1V;f)cpPw^5X-adVBa1 WSy>Y)xR4Md5#orj95F*81;0^3a zd)8>$BjWkb+fN}}`ow(f;b&jDKHsi?pldGXyA4JMK=ku4E!#C6wYrDh8BY`J(rG$; zPpjnN510#Kmi>%mUVYl~?5AN9`- z&?>E$#>HAr>_#<%;%aNu+9Xz>Uuhf*e6gG+d9ur>3ryOzYOECj)(X7`-o9xDWgC%@ zpu;%TIQqTs+%QvORck$vGh9y?`R5ttI~f`#@Vltir=YRfU38xhsVY~pAg7r;B@m%1 zc=0$iG}JEANN_uaH2I*NWx5nI^ZuoX;`@In{e$es_s%@=JtGKNgIW;xX`O_iTmV>P z<}x}Bkn_nC8G@0z`0SjWq4tjhjGUM}sgT}Kp!7kY2vT6rwKo^^gL4d&S=-u_@{n0o zh~ce#-|Kk*qo94wWjR%r7Np92))x}@ziE2_;e1FgF)Zc W_yXqWAPCHByVCgN371>dBh`RtLk`XW literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/e8950c5620c8c3e797ab0c74fb3fc6c613e9e31d085be80a811400fa39c36b29.bin b/bin/programs/client/testdata/block_120794432_exec/e8950c5620c8c3e797ab0c74fb3fc6c613e9e31d085be80a811400fa39c36b29.bin new file mode 100644 index 0000000000000000000000000000000000000000..999e7375f7ca2137027990050b43657c12f022b4 GIT binary patch literal 532 zcmV+v0_*+x0ui92Qh)_~J@@n(DC0~vJaeo#@usBVQ32A1_pc}SIfRIywiD@&yz?ft zDD%$4&!<_UxNML^INw1H6Xf9gmau1)pscbz%pT|-O>2lj_7@mb*RRx(b)Syu(vajW zDC0tOq@d;8CBA+Tdh1CHo9k|gY3F{xFr+w%-UHak4ysK3Y5Abw!QrX95q0lSa-WX&*M0F+lM4>FXG{^! WZ7nUO$(2T-WS_hex|+a@V|aju-50q4 literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/e9ad57c7ea3d3e54221946c77f2ffcd32eb1769fde2bf351899eea45d90f2f7d.bin b/bin/programs/client/testdata/block_120794432_exec/e9ad57c7ea3d3e54221946c77f2ffcd32eb1769fde2bf351899eea45d90f2f7d.bin new file mode 100644 index 000000000..c9771a516 --- /dev/null +++ b/bin/programs/client/testdata/block_120794432_exec/e9ad57c7ea3d3e54221946c77f2ffcd32eb1769fde2bf351899eea45d90f2f7d.bin @@ -0,0 +1,2 @@ +o 1\%ȃmNly:eAiOM.hH|5VFBe%MVmb{j TR>z +۰Աe̓7x5;5 \ No newline at end of file diff --git a/bin/programs/client/testdata/block_120794432_exec/eab3f67aad27e7e1b2d534a1b5f724b22ab7819aea4e3d67f5d5281869309c91.bin b/bin/programs/client/testdata/block_120794432_exec/eab3f67aad27e7e1b2d534a1b5f724b22ab7819aea4e3d67f5d5281869309c91.bin new file mode 100644 index 0000000000000000000000000000000000000000..42a9bd4931b44c4deeada120af4219928b356d5e GIT binary patch literal 276 zcmV+v0qg$x0TH11O`^LO8)$u5LGJrZG;>{6=;-rqA0HI!0J#NysKdpeQ>Xy~5kGSR zQ(=I*X@)G@HL4mq06mujfti+74LfcLptWbkPYcHbOc?0~<%5_7NojFuFbm0x*Y3AE zXIOm7vVfq7&+@f02>4&9u6F$ceUB_SnLW9fVIzE^rr243K$HuBfS{@tjlo6|P@^mT%$#A+nL#uN%eF;+P6oJ5-u zhey_?U!aZReI(4YXU-G#1l5-1I@^?))EPqz^?*~ici^oKR;C%;tK?zBZ`Hx3x6A7os$Z&qLZ?28Xvq7uzBho#Trs>vP&9I zpgU`hke;_tbOOLpul6V_;51uF*S4;i?yXexiq3&TpP=fazBY#p<_BA`lB7a-hO>NNW32L1oCP7Eq~y!= zRJB+f7aWIB3X4ETTb~QTJN-H4;wtihc+rS@plPjLU9PGj?fw!~uN&*A+%T)GuIN78 zG>W+GUBH1%ZlLcT;^=5VV*rEBIy0X*vh%mvNu8zP7#w%IeSAchha{lcxN$K&cH-Ea zk6o2y7XzUX5gb=?HzvD@yF`tv7!jYKJ^ZppCFdE>Yc%JEhuvW7 WU}0)Dl;RabDfZYY_&GW*;2?m_Nehku literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/ee5d62827673b76fae02f5114feedd580b152fda82bb5652d76b6cb4dcbf0802.bin b/bin/programs/client/testdata/block_120794432_exec/ee5d62827673b76fae02f5114feedd580b152fda82bb5652d76b6cb4dcbf0802.bin new file mode 100644 index 0000000000000000000000000000000000000000..e63d83a8d9142e685340d7565f7b4e73258c8d1d GIT binary patch literal 532 zcmV+v0_*+x0ui9rth%PGmp#FI{5qJiVgM9DkvCjgk18``S|hL+z+a-E-6HGx7%M{E zLrGrCmi{!ZAvd^?1SfDtEg@9(EBIaNux=wi>x6$;p&`< zAXj|DPN1rkQeVy#S+BOYOP7l~IKa|F-74VPV*I-w;_8=mX^5a;cB$bs5*};Nw|4el zGu2MITu(yy{mv8u^Yc+fh*S%p|8cpUWqofLQ+SJ)rrW*Ti3m$~rIb^=ZMlaVyMuH#d5prGW-kTQ{^aIAC{Jo!`@hZf>~ zfQ(FQ%^pthyp8L9+##UGO&Gm=&r^;H(mx&Hui7PqBS{7TH}|fzg);88UU>wd@83EH z!$gbK1TR-$2XXUZXBpX`aKV61#k?wysaTTlpzU;qU_*RQ+jMS}8e{tC4$l)}+y$fD zM?jVZO38)S;GlWieXjUF8zbWRQ=&(%zojSP-fj=Y!|{UP(}%o)QiGsB6y@@cnYlI@cg1X=F;J~}MC&$134MSxJLzB~F z#@B1ppiC>$}F3f-ddl0Sw literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c.bin b/bin/programs/client/testdata/block_120794432_exec/f57acd40259872606d76197ef052f3d35588dadf919ee1f0e3cb9b62d3f4b02c.bin new file mode 100644 index 0000000000000000000000000000000000000000..c527f90d44d9f74b221eff48110ef851583120ba GIT binary patch literal 97 zcmXpm{*MX%i6r=jCn%VSB&dYP$N!CvH*FA2@C;94kpJJvHlZ;@B*6wO4iaDti4RIp Yi2oc7QV0@oVsmN?jW?YDmJDS80JpI&x&QzG literal 0 HcmV?d00001 diff --git a/bin/programs/client/testdata/block_120794432_exec/fac225c9ebe9ba4a3762f4031223638298b5dda2fff1b5edf224ce88d14e3e4b.bin b/bin/programs/client/testdata/block_120794432_exec/fac225c9ebe9ba4a3762f4031223638298b5dda2fff1b5edf224ce88d14e3e4b.bin new file mode 100644 index 0000000000000000000000000000000000000000..acd7cd5c699bb4cdec26d1465ce50883092f2188 GIT binary patch literal 39 xcmV+?0NDTLpCF>tDO&*Dhw?x}cjf}2_}~fqN;wxbD Result { Ok(Default::default()) }; -/// let mock_header_fetcher = |hash: B256| -> Result
{ Ok(Default::default()) }; /// let mock_starting_root = B256::default(); /// let mock_parent_block_hash = B256::default(); /// -/// let trie_db = TrieDB::new( -/// mock_starting_root, -/// mock_parent_block_hash, -/// mock_fetcher, -/// mock_fetcher, -/// mock_header_fetcher, -/// ); +/// let trie_db = TrieDB::new(mock_starting_root, mock_parent_block_hash, NoopTrieDBFetcher); /// let mut state = StateBuilder::new_with_database(trie_db).with_bundle_update().build(); /// let evm = EvmBuilder::default().with_db(&mut state).build(); /// @@ -77,11 +68,9 @@ pub use account::TrieAccount; /// /// [State]: revm::State #[derive(Debug, Clone)] -pub struct TrieDB +pub struct TrieDB where - PF: Fn(B256) -> Result + Copy, - CHF: Fn(B256) -> Result + Copy, - HF: Fn(B256) -> Result
+ Copy, + F: TrieDBFetcher, { /// The [TrieNode] representation of the root node. root_node: TrieNode, @@ -89,35 +78,21 @@ where storage_roots: HashMap, /// The parent block hash of the current block. parent_block_hash: B256, - /// The preimage fetching function - trie_preimage_fetcher: PF, - /// The code hash fetching function - code_by_hash_fetcher: CHF, - /// The [Header] fetching function - header_by_hash_fetcher: HF, + /// The [TrieDBFetcher] + fetcher: F, } -impl TrieDB +impl TrieDB where - PF: Fn(B256) -> Result + Copy, - CHF: Fn(B256) -> Result + Copy, - HF: Fn(B256) -> Result
+ Copy, + F: TrieDBFetcher, { /// Creates a new [TrieDB] with the given root node. - pub fn new( - root: B256, - parent_block_hash: B256, - trie_preimage_fetcher: PF, - code_by_hash_fetcher: CHF, - header_by_hash_fetcher: HF, - ) -> Self { + pub fn new(root: B256, parent_block_hash: B256, fetcher: F) -> Self { Self { root_node: TrieNode::new_blinded(root), storage_roots: Default::default(), parent_block_hash, - trie_preimage_fetcher, - code_by_hash_fetcher, - header_by_hash_fetcher, + fetcher, } } @@ -211,12 +186,7 @@ where .get_mut(address) .ok_or(anyhow!("Storage root not found for account"))?; bundle_account.storage.iter().try_for_each(|(index, value)| { - Self::change_storage( - acc_storage_root, - *index, - value.present_value, - self.trie_preimage_fetcher, - ) + Self::change_storage(acc_storage_root, *index, value.present_value, &self.fetcher) })?; // Recompute the account storage root. @@ -233,18 +203,12 @@ where // Insert or update the account in the trie. let account_path = Nibbles::unpack(keccak256(address.as_slice())); - if let Ok(account_rlp_ref) = - self.root_node.open(&account_path, self.trie_preimage_fetcher) - { + if let Ok(account_rlp_ref) = self.root_node.open(&account_path, &self.fetcher) { // Update the existing account in the trie. *account_rlp_ref = account_buf.into(); } else { // Insert the new account into the trie. - self.root_node.insert( - &account_path, - account_buf.into(), - self.trie_preimage_fetcher, - )?; + self.root_node.insert(&account_path, account_buf.into(), &self.fetcher)?; } } @@ -265,7 +229,7 @@ where storage_root: &mut TrieNode, index: U256, value: U256, - preimage_fetcher: PF, + fetcher: &F, ) -> Result<()> { // RLP encode the storage slot value. let mut rlp_buf = Vec::with_capacity(value.length()); @@ -273,37 +237,29 @@ where // Insert or update the storage slot in the trie. let hashed_slot_key = keccak256(index.to_be_bytes::<32>().as_slice()); - if let Ok(storage_slot_rlp) = - storage_root.open(&Nibbles::unpack(hashed_slot_key), preimage_fetcher) + if let Ok(storage_slot_rlp) = storage_root.open(&Nibbles::unpack(hashed_slot_key), fetcher) { // If the storage slot already exists, update it. *storage_slot_rlp = rlp_buf.into(); } else { // If the storage slot does not exist, insert it. - storage_root.insert( - &Nibbles::unpack(hashed_slot_key), - rlp_buf.into(), - preimage_fetcher, - )?; + storage_root.insert(&Nibbles::unpack(hashed_slot_key), rlp_buf.into(), fetcher)?; } Ok(()) } } -impl Database for TrieDB +impl Database for TrieDB where - PF: Fn(B256) -> Result + Copy, - CHF: Fn(B256) -> Result + Copy, - HF: Fn(B256) -> Result
+ Copy, + F: TrieDBFetcher, { type Error = anyhow::Error; fn basic(&mut self, address: Address) -> Result, Self::Error> { // Fetch the account from the trie. let hashed_address_nibbles = Nibbles::unpack(keccak256(address.as_slice())); - let Ok(trie_account_rlp) = - self.root_node.open(&hashed_address_nibbles, self.trie_preimage_fetcher) + let Ok(trie_account_rlp) = self.root_node.open(&hashed_address_nibbles, &self.fetcher) else { // If the account does not exist in the trie, return `Ok(None)`. return Ok(None); @@ -327,7 +283,8 @@ where } fn code_by_hash(&mut self, code_hash: B256) -> Result { - (self.code_by_hash_fetcher)(code_hash) + self.fetcher + .bytecode_by_hash(code_hash) .map(Bytecode::new_raw) .map_err(|e| anyhow!("Failed to fetch code by hash: {e}")) } @@ -342,8 +299,7 @@ where // Fetch the storage slot from the trie. let hashed_slot_key = keccak256(index.to_be_bytes::<32>().as_slice()); - let slot_value = - storage_root.open(&Nibbles::unpack(hashed_slot_key), self.trie_preimage_fetcher)?; + let slot_value = storage_root.open(&Nibbles::unpack(hashed_slot_key), &self.fetcher)?; // Decode the storage slot value. let int_slot = U256::decode(&mut slot_value.as_ref()) @@ -358,7 +314,7 @@ where // Fetch the block header from the preimage fetcher. let mut block_hash = self.parent_block_hash; - let mut header = (self.header_by_hash_fetcher)(block_hash)?; + let mut header = self.fetcher.header_by_hash(block_hash)?; // Check if the block number is in range. If not, we can fail early. if u64_block_number > header.number || @@ -370,7 +326,7 @@ where // Walk back the block headers to the desired block number. while header.number > u64_block_number { block_hash = header.parent_hash; - header = (self.header_by_hash_fetcher)(block_hash)?; + header = self.fetcher.header_by_hash(block_hash)?; } Ok(block_hash) diff --git a/crates/mpt/src/fetcher.rs b/crates/mpt/src/fetcher.rs new file mode 100644 index 000000000..0693570f9 --- /dev/null +++ b/crates/mpt/src/fetcher.rs @@ -0,0 +1,63 @@ +//! Contains the [Fetcher] trait for fetching trie node preimages, contract bytecode, and headers. + +use alloy_consensus::Header; +use alloy_primitives::{Bytes, B256}; +use anyhow::Result; + +/// The [TrieDBFetcher] trait defines the synchronous interface for fetching trie node preimages and +/// headers. +pub trait TrieDBFetcher { + /// Fetches the preimage for the given trie node hash. + /// + /// ## Takes + /// - `key`: The key of the trie node to fetch. + /// + /// ## Returns + /// - Ok(Bytes): The trie node preimage. + /// - Err(anyhow::Error): If the trie node preimage could not be fetched. + /// + /// [TrieDB]: crate::TrieDB + fn trie_node_preimage(&self, key: B256) -> Result; + + /// Fetches the preimage of the bytecode hash provided. + /// + /// ## Takes + /// - `hash`: The hash of the bytecode. + /// + /// ## Returns + /// - Ok(Bytes): The bytecode of the contract. + /// - Err(anyhow::Error): If the bytecode hash could not be fetched. + /// + /// [TrieDB]: crate::TrieDB + fn bytecode_by_hash(&self, code_hash: B256) -> Result; + + /// Fetches the preimage of [Header] hash provided. + /// + /// ## Takes + /// - `hash`: The hash of the RLP-encoded [Header]. + /// + /// ## Returns + /// - Ok(Bytes): The [Header]. + /// - Err(anyhow::Error): If the [Header] could not be fetched. + /// + /// [TrieDB]: crate::TrieDB + fn header_by_hash(&self, hash: B256) -> Result
; +} + +/// The default, no-op implementation of the [TrieDBFetcher] trait, used for testing. +#[derive(Debug, Clone, Copy)] +pub struct NoopTrieDBFetcher; + +impl TrieDBFetcher for NoopTrieDBFetcher { + fn trie_node_preimage(&self, _key: B256) -> Result { + Ok(Bytes::new()) + } + + fn bytecode_by_hash(&self, _code_hash: B256) -> Result { + Ok(Bytes::new()) + } + + fn header_by_hash(&self, _hash: B256) -> Result
{ + Ok(Header::default()) + } +} diff --git a/crates/mpt/src/lib.rs b/crates/mpt/src/lib.rs index b942c5942..dddf2c1ab 100644 --- a/crates/mpt/src/lib.rs +++ b/crates/mpt/src/lib.rs @@ -9,6 +9,9 @@ extern crate alloc; mod db; pub use db::{TrieAccount, TrieDB}; +mod fetcher; +pub use fetcher::{NoopTrieDBFetcher, TrieDBFetcher}; + mod node; pub use node::TrieNode; diff --git a/crates/mpt/src/list_walker.rs b/crates/mpt/src/list_walker.rs index 5794f452c..d7ccafee3 100644 --- a/crates/mpt/src/list_walker.rs +++ b/crates/mpt/src/list_walker.rs @@ -1,7 +1,7 @@ //! This module contains the [OrderedListWalker] struct, which allows for traversing an MPT root of //! a derivable ordered list. -use crate::TrieNode; +use crate::{TrieDBFetcher, TrieNode}; use alloc::{collections::VecDeque, vec}; use alloy_primitives::{Bytes, B256}; use alloy_rlp::{Decodable, EMPTY_STRING_CODE}; @@ -14,19 +14,19 @@ use core::marker::PhantomData; /// 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 { +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, + _phantom: PhantomData, } -impl OrderedListWalker +impl OrderedListWalker where - PreimageFetcher: Fn(B256) -> Result + Copy, + F: TrieDBFetcher, { /// Creates a new [OrderedListWalker], yet to be hydrated. pub fn new(root: B256) -> Self { @@ -35,7 +35,7 @@ where /// 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 { + pub fn try_new_hydrated(root: B256, fetcher: &F) -> Result { let mut walker = Self { root, inner: None, _phantom: PhantomData }; walker.hydrate(fetcher)?; Ok(walker) @@ -43,7 +43,7 @@ where /// 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<()> { + pub fn hydrate(&mut self, fetcher: &F) -> 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.") @@ -81,10 +81,7 @@ where } /// Traverses a [TrieNode], returning all values of child [TrieNode::Leaf] variants. - fn fetch_leaves( - trie_node: &TrieNode, - fetcher: PreimageFetcher, - ) -> Result> { + fn fetch_leaves(trie_node: &TrieNode, fetcher: &F) -> Result> { match trie_node { TrieNode::Branch { stack } => { let mut leaf_values = VecDeque::with_capacity(stack.len()); @@ -126,16 +123,19 @@ where /// 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 + fn get_trie_node(hash: T, fetcher: &F) -> Result where T: Into, { - let preimage = fetcher(hash.into())?; + let preimage = fetcher.trie_node_preimage(hash.into())?; TrieNode::decode(&mut preimage.as_ref()).map_err(|e| anyhow!(e)) } } -impl Iterator for OrderedListWalker { +impl Iterator for OrderedListWalker +where + F: TrieDBFetcher, +{ type Item = (Bytes, Bytes); fn next(&mut self) -> Option { @@ -151,7 +151,10 @@ mod test { use super::*; use crate::{ ordered_trie_with_encoder, - test_util::{get_live_derivable_receipts_list, get_live_derivable_transactions_list}, + test_util::{ + get_live_derivable_receipts_list, get_live_derivable_transactions_list, + TrieNodeProvider, + }, }; use alloc::{collections::BTreeMap, string::String, vec::Vec}; use alloy_consensus::{ReceiptEnvelope, TxEnvelope}; @@ -162,9 +165,8 @@ mod test { #[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(); + let fetcher = TrieNodeProvider::new(preimages, BTreeMap::default(), BTreeMap::default()); + let list = OrderedListWalker::try_new_hydrated(root, &fetcher).unwrap(); assert_eq!( list.into_iter() @@ -177,9 +179,8 @@ mod test { #[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(); + let fetcher = TrieNodeProvider::new(preimages, BTreeMap::default(), BTreeMap::default()); + let list = OrderedListWalker::try_new_hydrated(root, &fetcher).unwrap(); assert_eq!( list.into_iter() @@ -202,9 +203,8 @@ mod test { acc }); - let list = - OrderedListWalker::try_new_hydrated(root, |f| Ok(preimages.get(&f).unwrap().clone())) - .unwrap(); + let fetcher = TrieNodeProvider::new(preimages, BTreeMap::default(), BTreeMap::default()); + let list = OrderedListWalker::try_new_hydrated(root, &fetcher).unwrap(); assert_eq!( list.inner diff --git a/crates/mpt/src/node.rs b/crates/mpt/src/node.rs index fcb6974f3..5237c14c7 100644 --- a/crates/mpt/src/node.rs +++ b/crates/mpt/src/node.rs @@ -1,6 +1,7 @@ //! This module contains the [TrieNode] type, which represents a node within a standard Merkle //! Patricia Trie. +use crate::TrieDBFetcher; use alloc::{boxed::Box, vec, vec::Vec}; use alloy_primitives::{keccak256, Bytes, B256}; use alloy_rlp::{Buf, BufMut, Decodable, Encodable, Header, EMPTY_STRING_CODE}; @@ -128,20 +129,20 @@ impl TrieNode { /// ## Returns /// - `Err(_)` - Could not retrieve the node with the given key from the trie. /// - `Ok((_, _))` - The key and value of the node - pub fn open<'a>( + pub fn open<'a, F: TrieDBFetcher>( &'a mut self, path: &Nibbles, - fetcher: impl Fn(B256) -> Result + Copy, + fetcher: &F, ) -> Result<&'a mut Bytes> { self.open_inner(path, 0, fetcher) } /// Inner alias for `open` that keeps track of the nibble offset. - fn open_inner<'a>( + fn open_inner<'a, F: TrieDBFetcher>( &'a mut self, path: &Nibbles, mut nibble_offset: usize, - fetcher: impl Fn(B256) -> Result + Copy, + fetcher: &F, ) -> Result<&'a mut Bytes> { match self { TrieNode::Branch { ref mut stack } => { @@ -158,8 +159,10 @@ impl TrieNode { TrieNode::Blinded { commitment } => { // If the string is a hash, we need to grab the preimage for it and // continue recursing. - let trie_node = TrieNode::decode(&mut fetcher(*commitment)?.as_ref()) - .map_err(|e| anyhow!(e))?; + let trie_node = TrieNode::decode( + &mut fetcher.trie_node_preimage(*commitment)?.as_ref(), + ) + .map_err(|e| anyhow!(e))?; *branch_node = trie_node; // If the value was found in the blinded node, return it. @@ -195,8 +198,10 @@ impl TrieNode { // Follow extension branch if let TrieNode::Blinded { commitment } = node.as_ref() { *node = Box::new( - TrieNode::decode(&mut fetcher(*commitment)?.as_ref()) - .map_err(|e| anyhow!(e))?, + TrieNode::decode( + &mut fetcher.trie_node_preimage(*commitment)?.as_ref(), + ) + .map_err(|e| anyhow!(e))?, ); } node.open_inner(path, nibble_offset, fetcher) @@ -205,8 +210,9 @@ impl TrieNode { } } TrieNode::Blinded { commitment } => { - let trie_node = TrieNode::decode(&mut fetcher(*commitment)?.as_ref()) - .map_err(|e| anyhow!(e))?; + let trie_node = + TrieNode::decode(&mut fetcher.trie_node_preimage(*commitment)?.as_ref()) + .map_err(|e| anyhow!(e))?; *self = trie_node; self.open_inner(path, nibble_offset, fetcher) } @@ -225,22 +231,22 @@ impl TrieNode { /// ## Returns /// - `Err(_)` - Could not insert the node at the given path in the trie. /// - `Ok(())` - The node was successfully inserted at the given path. - pub fn insert( + pub fn insert( &mut self, path: &Nibbles, value: Bytes, - fetcher: impl Fn(B256) -> Result + Copy, + fetcher: &F, ) -> Result<()> { self.insert_inner(path, value, 0, fetcher) } /// Inner alias for `insert` that keeps track of the nibble offset. - fn insert_inner( + fn insert_inner( &mut self, path: &Nibbles, value: Bytes, mut nibble_offset: usize, - fetcher: impl Fn(B256) -> Result + Copy, + fetcher: &F, ) -> Result<()> { let remaining_nibbles = path.slice(nibble_offset..); match self { @@ -328,8 +334,9 @@ impl TrieNode { TrieNode::Blinded { commitment } => { // If a blinded node is approached, reveal the node and continue the insertion // recursion. - let trie_node = TrieNode::decode(&mut fetcher(*commitment)?.as_ref()) - .map_err(|e| anyhow!(e))?; + let trie_node = + TrieNode::decode(&mut fetcher.trie_node_preimage(*commitment)?.as_ref()) + .map_err(|e| anyhow!(e))?; *self = trie_node; self.insert_inner(path, value, nibble_offset, fetcher) } @@ -574,12 +581,14 @@ fn unpack_path_to_nibbles(first: Option, rest: &[u8]) -> Nibbles { #[cfg(test)] mod test { use super::*; - use crate::{ordered_trie_with_encoder, TrieNode}; + use crate::{ + fetcher::NoopTrieDBFetcher, ordered_trie_with_encoder, test_util::TrieNodeProvider, + TrieNode, + }; use alloc::{collections::BTreeMap, vec, vec::Vec}; - use alloy_primitives::{b256, bytes, hex, keccak256, Bytes, B256}; + use alloy_primitives::{b256, bytes, hex, keccak256}; use alloy_rlp::{Decodable, Encodable, EMPTY_STRING_CODE}; use alloy_trie::Nibbles; - use anyhow::{anyhow, Result}; #[test] fn test_decode_branch() { @@ -680,14 +689,13 @@ mod test { acc.insert(keccak256(value.as_ref()), value); acc }); - let fetcher = |h: B256| -> Result { - preimages.get(&h).cloned().ok_or(anyhow!("Failed to find preimage")) - }; + let fetcher = TrieNodeProvider::new(preimages, Default::default(), Default::default()); - let mut root_node = TrieNode::decode(&mut fetcher(root).unwrap().as_ref()).unwrap(); + let mut root_node = + TrieNode::decode(&mut fetcher.trie_node_preimage(root).unwrap().as_ref()).unwrap(); for (i, value) in VALUES.iter().enumerate() { let path_nibbles = Nibbles::unpack([if i == 0 { EMPTY_STRING_CODE } else { i as u8 }]); - let v = root_node.open(&path_nibbles, fetcher).unwrap(); + let v = root_node.open(&path_nibbles, &fetcher).unwrap(); let mut encoded_value = Vec::with_capacity(value.length()); value.encode(&mut encoded_value); @@ -704,10 +712,9 @@ mod test { fn test_insert_static() { let mut node = TrieNode::Leaf { prefix: Nibbles::unpack(hex!("01")), value: Default::default() }; - node.insert(&Nibbles::unpack(hex!("012345")), bytes!("01"), |_| Ok(Default::default())) - .unwrap(); - node.insert(&Nibbles::unpack(hex!("012346")), bytes!("02"), |_| Ok(Default::default())) - .unwrap(); + let noop_fetcher = NoopTrieDBFetcher; + node.insert(&Nibbles::unpack(hex!("012345")), bytes!("01"), &noop_fetcher).unwrap(); + node.insert(&Nibbles::unpack(hex!("012346")), bytes!("02"), &noop_fetcher).unwrap(); let expected = TrieNode::Extension { prefix: Nibbles::unpack(hex!("01")), diff --git a/crates/mpt/src/test_util.rs b/crates/mpt/src/test_util.rs index 9b6812478..90082505f 100644 --- a/crates/mpt/src/test_util.rs +++ b/crates/mpt/src/test_util.rs @@ -2,7 +2,7 @@ extern crate std; -use crate::ordered_trie_with_encoder; +use crate::{ordered_trie_with_encoder, TrieDBFetcher}; use alloc::{collections::BTreeMap, vec::Vec}; use alloy_consensus::{Receipt, ReceiptEnvelope, ReceiptWithBloom, TxEnvelope, TxType}; use alloy_primitives::{keccak256, Bytes, Log, B256}; @@ -118,3 +118,34 @@ pub(crate) async fn get_live_derivable_transactions_list( Ok((root, preimages, consensus_txs)) } + +/// A mock [TrieDBFetcher] for testing that only serves trie node preimages. +pub(crate) struct TrieNodeProvider { + preimages: BTreeMap, + bytecode: BTreeMap, + headers: BTreeMap, +} + +impl TrieNodeProvider { + pub(crate) fn new( + preimages: BTreeMap, + bytecode: BTreeMap, + headers: BTreeMap, + ) -> Self { + Self { preimages, bytecode, headers } + } +} + +impl TrieDBFetcher for TrieNodeProvider { + fn trie_node_preimage(&self, key: B256) -> Result { + self.preimages.get(&key).cloned().ok_or_else(|| anyhow!("Key not found")) + } + + fn bytecode_by_hash(&self, hash: B256) -> Result { + self.bytecode.get(&hash).cloned().ok_or_else(|| anyhow!("Key not found")) + } + + fn header_by_hash(&self, hash: B256) -> Result { + self.headers.get(&hash).cloned().ok_or_else(|| anyhow!("Key not found")) + } +} diff --git a/crates/primitives/src/payload.rs b/crates/primitives/src/payload.rs index a2c42830d..b66d446b5 100644 --- a/crates/primitives/src/payload.rs +++ b/crates/primitives/src/payload.rs @@ -15,7 +15,7 @@ pub const PAYLOAD_MEM_FIXED_COST: u64 = 1000; pub const PAYLOAD_TX_MEM_OVERHEAD: u64 = 24; use super::{ - Block, BlockInfo, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx, L2BlockInfo, OpBlock, + BlockInfo, L1BlockInfoBedrock, L1BlockInfoEcotone, L1BlockInfoTx, L2BlockInfo, OpBlock, RollupConfig, SystemConfig, Withdrawal, }; use alloy_rlp::Encodable; @@ -95,6 +95,9 @@ pub struct L2ExecutionPayload { /// The transactions. #[cfg_attr(feature = "serde", serde(rename = "transactions"))] pub transactions: Vec, + /// The deserialized transactions. + #[cfg_attr(feature = "serde", serde(skip))] + pub deserialized_transactions: Vec, /// The withdrawals. #[cfg_attr( feature = "serde", @@ -219,41 +222,6 @@ impl L2ExecutionPayloadEnvelope { } } -impl From for L2ExecutionPayloadEnvelope { - fn from(block: Block) -> Self { - let Block { header, body, withdrawals, .. } = block; - Self { - execution_payload: L2ExecutionPayload { - parent_hash: header.parent_hash, - fee_recipient: header.beneficiary, - state_root: header.state_root, - receipts_root: header.receipts_root, - logs_bloom: header.logs_bloom, - prev_randao: header.difficulty.into(), - block_number: header.number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: header.extra_data.clone(), - base_fee_per_gas: header.base_fee_per_gas, - block_hash: header.hash_slow(), - transactions: body - .into_iter() - .map(|tx| { - let mut buf = Vec::with_capacity(tx.length()); - tx.encode(&mut buf); - buf.into() - }) - .collect(), - withdrawals, - blob_gas_used: header.blob_gas_used, - excess_blob_gas: header.excess_blob_gas, - }, - parent_beacon_block_root: header.parent_beacon_block_root, - } - } -} - impl From for L2ExecutionPayloadEnvelope { fn from(block: OpBlock) -> Self { let OpBlock { header, body, withdrawals, .. } = block; @@ -272,6 +240,7 @@ impl From for L2ExecutionPayloadEnvelope { extra_data: header.extra_data.clone(), base_fee_per_gas: header.base_fee_per_gas, block_hash: header.hash_slow(), + deserialized_transactions: body.clone(), transactions: body .into_iter() .map(|tx| {