diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6b82262..bd9b5308 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,8 @@ jobs: fail-fast: false matrix: rust: ["stable", "beta", "nightly"] - flags: ["--no-default-features", "", "--all-features"] +# flags: ["--no-default-features", "", "--all-features"] + flags: ["--no-default-features", "", "--features bsc", "--features optimism,opbnb"] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master @@ -31,16 +32,16 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo test --workspace ${{ matrix.flags }} - # test-no-std: - # name: test no_std - # runs-on: ubuntu-latest - # timeout-minutes: 30 - # steps: - # - uses: actions/checkout@v4 - # - uses: dtolnay/rust-toolchain@stable - # with: - # targets: riscv32imac-unknown-none-elf - # - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features +# test-no-std: +# name: test no_std +# runs-on: ubuntu-latest +# timeout-minutes: 30 +# steps: +# - uses: actions/checkout@v4 +# - uses: dtolnay/rust-toolchain@stable +# with: +# targets: riscv32imac-unknown-none-elf +# - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features check-no-default-features: name: check no-default-features @@ -73,26 +74,40 @@ jobs: cargo check --no-default-features --features std clippy: - name: clippy + name: clippy / ${{ matrix.network }} runs-on: ubuntu-latest timeout-minutes: 30 + strategy: + matrix: + include: + - network: optimism + extra-features: "opbnb" + - network: bsc + extra-features: "" steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - run: cargo clippy --workspace --all-targets --all-features + - run: cargo clippy --workspace --all-targets --features "${{ matrix.network }} ${{ matrix.extra-features }}" env: RUSTFLAGS: -Dwarnings docs: - name: docs + name: docs / ${{ matrix.network }} runs-on: ubuntu-latest timeout-minutes: 30 + strategy: + matrix: + include: + - network: optimism + extra-features: "opbnb" + - network: bsc + extra-features: "" steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: components: rust-docs - - run: cargo doc --workspace --all-features --no-deps --document-private-items + - run: cargo doc --workspace --no-deps --document-private-items --features "${{ matrix.network }} ${{ matrix.extra-features }}" env: RUSTDOCFLAGS: "--cfg docsrs -D warnings" diff --git a/Cargo.lock b/Cargo.lock index d4d59295..bfa4a9d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,20 +119,20 @@ checksum = "db8aa973e647ec336810a9356af8aea787249c9d00b1525359f3db29a68d231b" dependencies = [ "alloy-rlp", "arbitrary", - "bytes", + "bytes 1.6.0", "cfg-if", "const-hex", "derive_arbitrary", "derive_more", "ethereum_ssz", - "getrandom", + "getrandom 0.2.15", "hex-literal", "itoa", - "k256", + "k256 0.13.3", "keccak-asm", "proptest", "proptest-derive", - "rand", + "rand 0.8.5", "ruint", "serde", "tiny-keccak", @@ -174,7 +174,7 @@ checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" dependencies = [ "alloy-rlp-derive", "arrayvec", - "bytes", + "bytes 1.6.0", ] [[package]] @@ -256,8 +256,8 @@ dependencies = [ "alloy-primitives", "async-trait", "auto_impl", - "elliptic-curve", - "k256", + "elliptic-curve 0.13.8", + "k256 0.13.3", "thiserror", ] @@ -351,12 +351,36 @@ dependencies = [ "url", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anomaly" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "550632e31568ae1a5f47998c3aa48563030fc49b9ec91913ca337cf64fbc5ccb" +dependencies = [ + "backtrace", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -549,7 +573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -559,7 +583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -635,7 +659,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0aef7712851e524f35fbbb74fa6599c5cd8692056a1c36f9ca0d2001b670e7e5" dependencies = [ - "hex", + "hex 0.4.3", "num", ] @@ -741,17 +765,40 @@ dependencies = [ "serde", ] +[[package]] +name = "bitvec" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" +dependencies = [ + "funty 1.1.0", + "radium 0.3.0", + "wyz 0.2.0", +] + [[package]] name = "bitvec" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "funty", - "radium", + "funty 2.0.0", + "radium 0.7.0", "serde", "tap", - "wyz", + "wyz 0.5.1", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", ] [[package]] @@ -760,7 +807,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -769,7 +816,16 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -784,7 +840,7 @@ dependencies = [ "ark-serialize 0.4.2", "ark-std 0.4.0", "hkdf", - "hmac", + "hmac 0.12.1", "libm", "sha2 0.10.8", ] @@ -801,6 +857,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata 0.1.10", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -813,12 +880,24 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + [[package]] name = "bytes" version = "1.6.0" @@ -837,7 +916,7 @@ dependencies = [ "blst", "cc", "glob", - "hex", + "hex 0.4.3", "libc", "serde", ] @@ -866,7 +945,13 @@ version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.5", ] [[package]] @@ -941,23 +1026,23 @@ name = "cometbft" version = "0.1.0-alpha.2" source = "git+https://github.com/bnb-chain/greenfield-cometbft-rs.git?rev=1282547#12825470f8b2df8e960e39a84ad4c9921492f512" dependencies = [ - "bytes", + "bytes 1.6.0", "cometbft-proto", "digest 0.10.7", - "ed25519", + "ed25519 2.2.3", "ed25519-consensus", "flex-error", "futures", "num-traits", "once_cell", - "prost", - "prost-types", + "prost 0.12.6", + "prost-types 0.12.6", "serde", "serde_bytes", "serde_json", "serde_repr", "sha2 0.10.8", - "signature", + "signature 2.2.0", "subtle", "subtle-encoding", "time", @@ -973,7 +1058,7 @@ dependencies = [ "flex-error", "serde", "serde_json", - "toml", + "toml 0.8.14", "url", ] @@ -1018,12 +1103,12 @@ name = "cometbft-proto" version = "0.1.0-alpha.2" source = "git+https://github.com/bnb-chain/greenfield-cometbft-rs.git?rev=1282547#12825470f8b2df8e960e39a84ad4c9921492f512" dependencies = [ - "bytes", + "bytes 1.6.0", "flex-error", - "num-derive", + "num-derive 0.4.2", "num-traits", - "prost", - "prost-types", + "prost 0.12.6", + "prost-types 0.12.6", "serde", "serde_bytes", "subtle-encoding", @@ -1036,16 +1121,16 @@ version = "0.1.0-alpha.2" source = "git+https://github.com/bnb-chain/greenfield-cometbft-rs.git?rev=1282547#12825470f8b2df8e960e39a84ad4c9921492f512" dependencies = [ "async-trait", - "bytes", + "bytes 1.6.0", "cometbft", "cometbft-config", "cometbft-proto", "flex-error", "futures", - "getrandom", + "getrandom 0.2.15", "peg", "pin-project", - "rand", + "rand 0.8.5", "reqwest 0.11.27", "semver 1.0.23", "serde", @@ -1083,11 +1168,17 @@ checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" dependencies = [ "cfg-if", "cpufeatures", - "hex", + "hex 0.4.3", "proptest", "serde", ] +[[package]] +name = "const-oid" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6b64db6932c7e49332728e3a6bd82c6b7e16016607d20923b537c3bc4c0d5f" + [[package]] name = "const-oid" version = "0.9.6" @@ -1218,8 +1309,8 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", - "rand_core", + "generic-array 0.14.7", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -1230,10 +1321,33 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] +[[package]] +name = "crypto-mac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + [[package]] name = "curve25519-dalek-ng" version = "4.1.1" @@ -1242,7 +1356,7 @@ checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" dependencies = [ "byteorder", "digest 0.9.0", - "rand_core", + "rand_core 0.6.4", "subtle-ng", "zeroize", ] @@ -1266,13 +1380,22 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "der" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f59c66c30bb7445c8320a5f9233e437e3572368099f25532a59054328899b4" +dependencies = [ + "const-oid 0.4.5", +] + [[package]] name = "der" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "const-oid", + "const-oid 0.9.6", "zeroize", ] @@ -1320,13 +1443,22 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1336,7 +1468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", + "const-oid 0.9.6", "crypto-common", "subtle", ] @@ -1353,28 +1485,49 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ecdsa" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fbdb4ff710acb4db8ca29f93b897529ea6d6a45626d5183b47e012aa6ae7e4" +dependencies = [ + "elliptic-curve 0.8.5", + "hmac 0.10.1", + "signature 1.2.2", +] + [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der", + "der 0.7.9", "digest 0.10.7", - "elliptic-curve", + "elliptic-curve 0.13.8", "rfc6979", - "signature", + "signature 2.2.0", "spki", ] +[[package]] +name = "ed25519" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +dependencies = [ + "serde", + "signature 1.2.2", +] + [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8", - "signature", + "pkcs8 0.10.2", + "signature 2.2.0", ] [[package]] @@ -1384,8 +1537,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c8465edc8ee7436ffea81d21a019b16676ee3db267aa8d5a8d729581ecf998b" dependencies = [ "curve25519-dalek-ng", - "hex", - "rand_core", + "hex 0.4.3", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519 1.2.0", + "rand 0.7.3", + "serde", + "serde_bytes", "sha2 0.9.9", "zeroize", ] @@ -1396,6 +1564,24 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +[[package]] +name = "elliptic-curve" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2db227e61a43a34915680bdda462ec0e212095518020a88a1f91acd16092c39" +dependencies = [ + "bitvec 0.18.5", + "digest 0.9.0", + "ff 0.8.0", + "funty 1.1.0", + "generic-array 0.14.7", + "group 0.8.0", + "pkcs8 0.3.3", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -1405,11 +1591,11 @@ dependencies = [ "base16ct", "crypto-bigint", "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1437,14 +1623,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" dependencies = [ "base64 0.21.7", - "bytes", - "hex", - "k256", + "bytes 1.6.0", + "hex 0.4.3", + "k256 0.13.3", "log", - "rand", + "rand 0.8.5", "rlp", "serde", - "sha3", + "sha3 0.10.8", "zeroize", ] @@ -1482,12 +1668,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" dependencies = [ "ethereum-types", - "hex", + "hex 0.4.3", "once_cell", "regex", "serde", "serde_json", - "sha3", + "sha3 0.10.8", "thiserror", "uint", ] @@ -1557,16 +1743,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" dependencies = [ "arrayvec", - "bytes", + "bytes 1.6.0", "chrono", "const-hex", - "elliptic-curve", + "elliptic-curve 0.13.8", "ethabi", - "generic-array", - "k256", + "generic-array 0.14.7", + "k256 0.13.3", "num_enum", "open-fastrlp", - "rand", + "rand 0.8.5", "rlp", "serde", "serde_json", @@ -1586,7 +1772,7 @@ dependencies = [ "async-trait", "auto_impl", "base64 0.21.7", - "bytes", + "bytes 1.6.0", "const-hex", "enr", "ethers-core", @@ -1625,6 +1811,34 @@ dependencies = [ "once_cell", ] +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "fastrand" version = "2.1.0" @@ -1639,7 +1853,18 @@ checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" dependencies = [ "arrayvec", "auto_impl", - "bytes", + "bytes 1.6.0", +] + +[[package]] +name = "ff" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +dependencies = [ + "bitvec 0.18.5", + "rand_core 0.5.1", + "subtle", ] [[package]] @@ -1648,7 +1873,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1660,7 +1885,7 @@ checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "arbitrary", "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -1704,6 +1929,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "funty" version = "2.0.0" @@ -1824,6 +2055,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1835,6 +2075,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1844,7 +2095,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1872,14 +2123,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "group" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +dependencies = [ + "ff 0.8.0", + "rand_core 0.5.1", + "subtle", +] + [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", - "rand_core", + "ff 0.13.0", + "rand_core 0.6.4", "subtle", ] @@ -1889,7 +2151,7 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "futures-core", "futures-sink", @@ -1909,7 +2171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ "atomic-waker", - "bytes", + "bytes 1.6.0", "fnv", "futures-core", "futures-sink", @@ -2008,6 +2270,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" + [[package]] name = "hex" version = "0.4.3" @@ -2029,7 +2297,17 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac", + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac", + "digest 0.9.0", ] [[package]] @@ -2047,7 +2325,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "itoa", ] @@ -2058,7 +2336,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes", + "bytes 1.6.0", "fnv", "itoa", ] @@ -2069,7 +2347,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ - "bytes", + "bytes 1.6.0", "http 0.2.12", "pin-project-lite", ] @@ -2080,18 +2358,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "bytes", + "bytes 1.6.0", "http 1.1.0", ] [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "bytes", - "futures-core", + "bytes 1.6.0", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -2115,7 +2393,7 @@ version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-channel", "futures-core", "futures-util", @@ -2139,7 +2417,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-channel", "futures-util", "h2 0.4.5", @@ -2173,7 +2451,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "bytes", + "bytes 1.6.0", "http-body-util", "hyper 1.3.1", "hyper-util", @@ -2185,11 +2463,11 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-channel", "futures-util", "http 1.1.0", @@ -2203,6 +2481,44 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ics23" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d020eb9116abc920452cb63aec8ff662483bf2b75199680046057389b1128988" +dependencies = [ + "bytes 0.5.6", + "failure", + "hex 0.4.3", + "prost 0.6.1", + "ripemd160 0.8.0", + "sha2 0.8.2", + "sha3 0.8.2", +] + [[package]] name = "idna" version = "0.5.0" @@ -2306,6 +2622,24 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "itertools" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.10.5" @@ -2353,6 +2687,18 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "k256" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4476a0808212a9e81ce802eb1a0cfc60e73aea296553bacc0fac7e1268bc572a" +dependencies = [ + "cfg-if", + "ecdsa 0.10.2", + "elliptic-curve 0.8.5", + "sha2 0.9.9", +] + [[package]] name = "k256" version = "0.13.3" @@ -2360,11 +2706,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "once_cell", "sha2 0.10.8", - "signature", + "signature 2.2.0", ] [[package]] @@ -2472,17 +2818,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2533,6 +2878,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "num-derive" version = "0.4.2" @@ -2643,6 +2999,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2657,7 +3019,7 @@ checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ "arrayvec", "auto_impl", - "bytes", + "bytes 1.6.0", "ethereum-types", "open-fastrlp-derive", ] @@ -2668,7 +3030,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" dependencies = [ - "bytes", + "bytes 1.6.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2724,12 +3086,18 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "primeorder", "sha2 0.10.8", ] +[[package]] +name = "parity-bytes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -2737,7 +3105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", - "bitvec", + "bitvec 1.0.1", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", @@ -2855,7 +3223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -2912,13 +3280,22 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4839a901843f3942576e65857f0ebf2e190ef7024d3c62a94099ba3f819ad1d" +dependencies = [ + "der 0.1.0", +] + [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der", + "der 0.7.9", "spki", ] @@ -2989,7 +3366,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", ] [[package]] @@ -3059,8 +3436,8 @@ dependencies = [ "bitflags 2.5.0", "lazy_static", "num-traits", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -3079,14 +3456,61 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce49aefe0a6144a45de32927c77bd2859a5f7677b55f220ae5b744e87389c212" +dependencies = [ + "bytes 0.5.6", + "prost-derive 0.6.1", +] + [[package]] name = "prost" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ - "bytes", - "prost-derive", + "bytes 1.6.0", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost-amino" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dda006a6c21ae45e261a5a756f2a3e5299722eedae2405f4747dd6a5b47556e" +dependencies = [ + "byteorder", + "bytes 0.5.6", +] + +[[package]] +name = "prost-amino-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bbb97577964b9ff334506e319a7628af460f59a6be1da592b5bdccb6a78e921" +dependencies = [ + "failure", + "itertools 0.7.11", + "proc-macro2", + "quote", + "sha2 0.9.9", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" +dependencies = [ + "anyhow", + "itertools 0.8.2", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -3102,13 +3526,23 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "prost-types" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1834f67c0697c001304b75be76f67add9c89742eda3a085ad8ee0bb38c3417aa" +dependencies = [ + "bytes 0.5.6", + "prost 0.6.1", +] + [[package]] name = "prost-types" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost", + "prost 0.12.6", ] [[package]] @@ -3126,12 +3560,31 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + [[package]] name = "radium" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -3139,8 +3592,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -3150,7 +3613,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -3159,7 +3631,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -3168,7 +3649,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -3208,10 +3689,16 @@ checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata", + "regex-automata 0.4.6", "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-automata" version = "0.4.6" @@ -3242,7 +3729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", - "bytes", + "bytes 1.6.0", "encoding_rs", "futures-core", "futures-util", @@ -3284,7 +3771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64 0.22.1", - "bytes", + "bytes 1.6.0", "encoding_rs", "futures-core", "futures-util", @@ -3361,6 +3848,8 @@ dependencies = [ name = "revm-precompile" version = "7.0.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", "aurora-engine-modexp", "bls_on_arkworks", "blst", @@ -3371,11 +3860,12 @@ dependencies = [ "cometbft-proto", "criterion", "eyre", - "k256", + "k256 0.13.3", "once_cell", "p256", - "prost", - "rand", + "parity-bytes", + "prost 0.12.6", + "rand 0.8.5", "revm-primitives", "ripemd", "rstest", @@ -3385,6 +3875,7 @@ dependencies = [ "serde_json", "sha2 0.10.8", "substrate-bn", + "tendermint", ] [[package]] @@ -3394,14 +3885,14 @@ dependencies = [ "alloy-primitives", "auto_impl", "bitflags 2.5.0", - "bitvec", + "bitvec 1.0.1", "c-kzg", "cfg-if", "derive_more", "dyn-clone", "enumn", "hashbrown 0.14.5", - "hex", + "hex 0.4.3", "once_cell", "serde", ] @@ -3412,9 +3903,9 @@ version = "0.1.0" dependencies = [ "alloy-sol-macro", "alloy-sol-types", - "bytes", + "bytes 1.6.0", "eyre", - "hex", + "hex 0.4.3", "microbench", "regex", "revm", @@ -3427,9 +3918,9 @@ dependencies = [ "alloy-rlp", "hash-db", "hashbrown 0.14.5", - "hex", + "hex 0.4.3", "indicatif", - "k256", + "k256 0.13.3", "microbench", "plain_hasher", "revm", @@ -3447,7 +3938,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "hmac", + "hmac 0.12.1", "subtle", ] @@ -3474,7 +3965,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin 0.9.8", "untrusted 0.9.0", @@ -3490,13 +3981,35 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "ripemd160" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "opaque-debug 0.2.3", +] + +[[package]] +name = "ripemd160" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.1", +] + [[package]] name = "rlp" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "bytes", + "bytes 1.6.0", "rlp-derive", "rustc-hex", ] @@ -3551,14 +4064,14 @@ dependencies = [ "arbitrary", "ark-ff 0.3.0", "ark-ff 0.4.2", - "bytes", + "bytes 1.6.0", "fastrlp", "num-bigint", "num-traits", "parity-scale-codec", "primitive-types", "proptest", - "rand", + "rand 0.8.5", "rlp", "ruint-macro", "serde", @@ -3763,9 +4276,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", - "generic-array", - "pkcs8", + "der 0.7.9", + "generic-array 0.14.7", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -3776,7 +4289,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ - "rand", + "rand 0.8.5", "secp256k1-sys", ] @@ -3942,6 +4455,18 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3952,7 +4477,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest 0.9.0", - "opaque-debug", + "opaque-debug 0.3.1", ] [[package]] @@ -3966,6 +4491,19 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" +dependencies = [ + "block-buffer 0.7.3", + "byte-tools", + "digest 0.8.1", + "keccak", + "opaque-debug 0.2.3", +] + [[package]] name = "sha3" version = "0.10.8" @@ -3986,6 +4524,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "signature" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +dependencies = [ + "digest 0.9.0", + "rand_core 0.5.1", +] + [[package]] name = "signature" version = "2.2.0" @@ -3993,7 +4541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4058,7 +4606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der", + "der 0.7.9", ] [[package]] @@ -4128,15 +4676,15 @@ dependencies = [ "byteorder", "crunchy", "lazy_static", - "rand", + "rand 0.8.5", "rustc-hex", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "subtle-encoding" @@ -4193,6 +4741,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -4232,6 +4792,65 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendermint" +version = "0.17.0" +source = "git+https://github.com/bnb-chain/tendermint-rs-parlia?tag=v0.1.0-beta.1#5c5cccaaf6fb0459c433e6312bed2a24386159db" +dependencies = [ + "anomaly", + "async-trait", + "bstr", + "byteorder", + "bytes 0.5.6", + "chrono", + "ed25519 1.2.0", + "ed25519-dalek", + "futures", + "hex 0.3.2", + "ics23", + "k256 0.7.3", + "num-traits", + "once_cell", + "parity-bytes", + "prost 0.6.1", + "prost-amino", + "prost-amino-derive", + "prost-types 0.6.1", + "ripemd160 0.9.1", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.9.9", + "signature 1.2.2", + "subtle", + "subtle-encoding", + "tendermint-proto", + "thiserror", + "toml 0.5.11", + "zeroize", +] + +[[package]] +name = "tendermint-proto" +version = "0.17.0" +source = "git+https://github.com/bnb-chain/tendermint-rs-parlia?tag=v0.1.0-beta.1#5c5cccaaf6fb0459c433e6312bed2a24386159db" +dependencies = [ + "anomaly", + "bytes 0.5.6", + "chrono", + "num-derive 0.3.3", + "num-traits", + "prost 0.6.1", + "prost-amino", + "prost-amino-derive", + "prost-types 0.6.1", + "serde", + "serde_bytes", + "subtle-encoding", + "thiserror", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -4342,7 +4961,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", - "bytes", + "bytes 1.6.0", "libc", "mio", "num_cpus", @@ -4416,13 +5035,22 @@ version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ - "bytes", + "bytes 1.6.0", "futures-core", "futures-sink", "pin-project-lite", "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.14" @@ -4561,12 +5189,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" dependencies = [ "byteorder", - "bytes", + "bytes 1.6.0", "data-encoding", "http 0.2.12", "httparse", "log", - "rand", + "rand 0.8.5", "rustls", "sha1", "thiserror", @@ -4595,7 +5223,7 @@ dependencies = [ "arbitrary", "byteorder", "crunchy", - "hex", + "hex 0.4.3", "static_assertions", ] @@ -4731,6 +5359,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4850,6 +5484,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5046,6 +5689,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "wyz" version = "0.5.1" diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 87ecceb7..94d35693 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -55,6 +55,7 @@ asm-keccak = ["revm-primitives/asm-keccak"] portable = ["revm-primitives/portable"] parse = ["dep:paste", "dep:phf"] +bsc = ["revm-primitives/bsc"] optimism = ["revm-primitives/optimism"] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = [ diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 158f4c94..5f066031 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -46,6 +46,13 @@ cometbft-proto = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.g cometbft-light-client = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.git", rev = "1282547" } prost = { version = "0.12.3" } bls_on_arkworks = "0.3.0" +tendermint = { git = "https://github.com/bnb-chain/tendermint-rs-parlia", tag = "v0.1.0-beta.1", features = ["secp256k1"] } +parity-bytes = { version = "0.1.2", default-features = false } +alloy-rlp = { version = "0.3", default-features = false, features = [ + "arrayvec", + "derive", +] } +alloy-primitives = {version = "0.7.0"} # p256verify precompile p256 = { version = "0.13.2", optional = true, default-features = false, features = ["ecdsa"] } @@ -76,6 +83,7 @@ std = [ hashbrown = ["revm-primitives/hashbrown"] asm-keccak = ["revm-primitives/asm-keccak"] +bsc = ["revm-primitives/bsc", "secp256k1", "secp256r1"] optimism = ["revm-primitives/optimism", "secp256r1"] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = [ diff --git a/crates/precompile/src/bls.rs b/crates/precompile/src/bls.rs index b0a87513..0f73bb3b 100644 --- a/crates/precompile/src/bls.rs +++ b/crates/precompile/src/bls.rs @@ -29,7 +29,7 @@ fn bls_signature_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResu if (input_length <= msg_and_sig_length) || ((input_length - msg_and_sig_length) % BLS_SINGLE_PUBKEY_LENGTH != 0) { - return Err(Error::BLSInvalidInputLength); + return Err(Error::Reverted(cost)); } let msg_hash: &Vec = &input[..BLS_MSG_HASH_LENGTH as usize].to_vec(); @@ -37,7 +37,9 @@ fn bls_signature_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResu let pub_keys_data = &input[msg_and_sig_length as usize..].to_vec(); // check signature format - let _ = bls::signature_to_point(&signature.to_vec()).map_err(|_| Error::BLSInvalidSignature)?; + if bls::signature_to_point(&signature.to_vec()).is_err() { + return Err(Error::Reverted(cost)); + } let pub_key_count = (input_length - msg_and_sig_length) / BLS_SINGLE_PUBKEY_LENGTH; let mut pub_keys = Vec::with_capacity(pub_key_count as usize); @@ -48,13 +50,13 @@ fn bls_signature_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResu let pub_key = &pub_keys_data[i as usize * BLS_SINGLE_PUBKEY_LENGTH as usize ..(i + 1) as usize * BLS_SINGLE_PUBKEY_LENGTH as usize]; if !bls::key_validate(&pub_key.to_vec()) { - return Err(Error::BLSInvalidPublicKey); + return Err(Error::Reverted(cost)); } pub_keys.push(pub_key.to_vec()); msg_hashes.push(msg_hash.clone().to_vec()); } if pub_keys.is_empty() { - return Err(Error::BLSInvalidPublicKey); + return Err(Error::Reverted(cost)); } // verify signature @@ -134,7 +136,7 @@ mod tests { match bls_signature_validation_run(&Bytes::from(input.clone()), 100_000_000) { Ok(_) => panic!("BLS signature validation failed, expect error"), - Err(e) => assert_eq!(e, Error::BLSInvalidSignature), + Err(e) => assert_eq!(e, Error::Reverted(4500)), } // wrong pubkey @@ -148,7 +150,7 @@ mod tests { match bls_signature_validation_run(&Bytes::from(input.clone()), 100_000_000) { Ok(_) => panic!("BLS signature validation failed, expect error"), - Err(e) => assert_eq!(e, Error::BLSInvalidSignature), + Err(e) => assert_eq!(e, Error::Reverted(4500)), } } @@ -206,7 +208,7 @@ mod tests { match bls_signature_validation_run(&Bytes::from(input.clone()), 100_000_000) { Ok(_) => panic!("BLS signature validation failed, expect error"), - Err(e) => assert_eq!(e, Error::BLSInvalidSignature), + Err(e) => assert_eq!(e, Error::Reverted(11500)), } // invalid pubkey @@ -224,7 +226,7 @@ mod tests { match bls_signature_validation_run(&Bytes::from(input.clone()), 100_000_000) { Ok(_) => panic!("BLS signature validation failed, expect error"), - Err(e) => assert_eq!(e, Error::BLSInvalidSignature), + Err(e) => assert_eq!(e, Error::Reverted(11500)), } // duplicate pubkey diff --git a/crates/precompile/src/cometbft.rs b/crates/precompile/src/cometbft.rs index 2df72ec9..f3f0df6e 100644 --- a/crates/precompile/src/cometbft.rs +++ b/crates/precompile/src/cometbft.rs @@ -1,7 +1,5 @@ use crate::{Error, Precompile, PrecompileError, PrecompileResult, PrecompileWithAddress}; -use cometbft::vote::Power; -use cometbft::PublicKey; -use cometbft::{block::signed_header::SignedHeader, validator::Set}; +use cometbft::{block::signed_header::SignedHeader, validator::Set, vote::Power, PublicKey}; use cometbft_light_client::{ predicates::VerificationPredicates, types::{LightBlock, TrustThreshold}, @@ -14,15 +12,19 @@ use cometbft_light_client_verifier::{ use cometbft_proto::types::v1::LightBlock as TmLightBlock; use prost::Message; use revm_primitives::Bytes; -use std::borrow::ToOwned; -use std::string::String; -use std::vec::Vec; +use std::{borrow::ToOwned, string::String, vec::Vec}; pub(crate) const COMETBFT_LIGHT_BLOCK_VALIDATION: PrecompileWithAddress = PrecompileWithAddress( crate::u64_to_address(103), Precompile::Standard(cometbft_light_block_validation_run), ); +pub(crate) const COMETBFT_LIGHT_BLOCK_VALIDATION_BEFORE_HERTZ: PrecompileWithAddress = + PrecompileWithAddress( + crate::u64_to_address(103), + Precompile::Standard(cometbft_light_block_validation_run_before_hertz), + ); + const UINT64_TYPE_LENGTH: u64 = 8; const CONSENSUS_STATE_LENGTH_BYTES_LENGTH: u64 = 32; const VALIDATE_RESULT_METADATA_LENGTH: u64 = 32; @@ -46,6 +48,21 @@ const MAX_CONSENSUS_STATE_LENGTH: u64 = CHAIN_ID_LENGTH + 99 * SINGLE_VALIDATOR_BYTES_LENGTH; fn cometbft_light_block_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + cometbft_light_block_validation_run_inner(input, gas_limit, true) +} + +fn cometbft_light_block_validation_run_before_hertz( + input: &Bytes, + gas_limit: u64, +) -> PrecompileResult { + cometbft_light_block_validation_run_inner(input, gas_limit, false) +} + +fn cometbft_light_block_validation_run_inner( + input: &Bytes, + gas_limit: u64, + is_hertz: bool, +) -> PrecompileResult { const COMETBFT_LIGHT_BLOCK_VALIDATION_BASE: u64 = 3_000; if COMETBFT_LIGHT_BLOCK_VALIDATION_BASE > gas_limit { @@ -62,10 +79,13 @@ fn cometbft_light_block_validation_run(input: &Bytes, gas_limit: u64) -> Precomp Err(e) => return Err(e), }; - let validator_set_changed = match consensus_state.apply_light_block(&light_block) { + let mut validator_set_changed = match consensus_state.apply_light_block(&light_block) { Ok(validator_set_changed) => validator_set_changed, Err(e) => return Err(e), }; + if !is_hertz { + validator_set_changed = false; + } let consensus_state_bytes = match consensus_state.encode() { Ok(cs) => cs, @@ -304,7 +324,7 @@ impl ConsensusState { type DecodeConsensusStateResult = Result; /// input: /// | chainID | height | nextValidatorSetHash | [{validator pubkey, voting power, relayer address, relayer bls pubkey}] | -/// | 32 bytes | 8 bytes | 32 bytes | [{32 bytes, 8 bytes, 20 bytes, 48 bytes}] +/// | 32 bytes | 8 bytes | 32 bytes | [{32 bytes, 8 bytes, 20 bytes, 48 bytes}] fn decode_consensus_state(input: &Bytes) -> DecodeConsensusStateResult { let minimum_length = CHAIN_ID_LENGTH + HEIGHT_LENGTH + VALIDATOR_SET_HASH_LENGTH; let input_length = input.len() as u64; @@ -701,4 +721,22 @@ mod tests { } } } + + #[test] + fn test_cometbft_light_block_validate_before_hertz() { + let input = Bytes::from(hex!( + "000000000000000000000000000000000000000000000000000000000000018c677265656e6669656c645f393030302d3132310000000000000000000000000000000000000000013c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb40e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e8423000000000098968015154514f68ce65a0d9eecc578c0ab12da0a2a28a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b0000000000989680432f6c4908a9aa5f3444421f466b11645235c99b831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b0a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a0000000000989680864cb9828254d712f8e59b164fc6a9402dc4e6c59065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca0aeb060adb030a02080b1213677265656e6669656c645f393030302d3132311802220c08b2d7f3a10610e8d2adb3032a480a20ec6ecb5db4ffb17fabe40c60ca7b8441e9c5d77585d0831186f3c37aa16e9c15122408011220a2ab9e1eb9ea52812f413526e424b326aff2f258a56e00d690db9f805b60fe7e32200f40aeff672e8309b7b0aefbb9a1ae3d4299b5c445b7d54e8ff398488467f0053a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85542203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb404a203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb405220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f935a20bc50557c12d7392b0d07d75df0b61232d48f86a74fdea6d1485d9be6317d268c6220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8556a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85572146699336aa109d1beab3946198c8e59f3b2cbd92f7a4065e3cd89e315ca39d87dee92835b98f8b8ec0861d6d9bb2c60156df5d375b3ceb1fbe71af6a244907d62548a694165caa660fec7a9b4e7b9198191361c71be0b128a0308021a480a20726abd0fdbfb6f779b0483e6e4b4b6f12241f6ea2bf374233ab1a316692b6415122408011220159f10ff15a8b58fc67a92ffd7f33c8cd407d4ce81b04ca79177dfd00ca19a67226808021214050cff76cc632760ba9db796c046004c900967361a0c08b3d7f3a10610808cadba03224080713027ffb776a702d78fd0406205c629ba473e1f8d6af646190f6eb9262cd67d69be90d10e597b91e06d7298eb6fa4b8f1eb7752ebf352a1f51560294548042268080212146699336aa109d1beab3946198c8e59f3b2cbd92f1a0c08b3d7f3a10610b087c1c00322405e2ddb70acfe4904438be3d9f4206c0ace905ac4fc306a42cfc9e86268950a0fbfd6ec5f526d3e41a3ef52bf9f9f358e3cb4c3feac76c762fa3651c1244fe004226808021214c55765fd2d0570e869f6ac22e7f2916a35ea300d1a0c08b3d7f3a10610f0b3d492032240ca17898bd22232fc9374e1188636ee321a396444a5b1a79f7628e4a11f265734b2ab50caf21e8092c55d701248e82b2f011426cb35ba22043b497a6b4661930612a0050aa8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da880aa2010a146699336aa109d1beab3946198c8e59f3b2cbd92f12220a20451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b1880ade2042080ade2042a30831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b3214432f6c4908a9aa5f3444421f466b11645235c99b3a14a0a7769429468054e19059af4867da0a495567e50aa2010a14c55765fd2d0570e869f6ac22e7f2916a35ea300d12220a200a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a1880ade2042080ade2042a309065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca3214864cb9828254d712f8e59b164fc6a9402dc4e6c53a143139916d97df0c589312b89950b6ab9795f34d1a12a8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da88" + )); + let except_output_after_hertz = Bytes::from(hex!( + "000000000000000000000000000000000000000000000000000000000000018c677265656e6669656c645f393030302d3132310000000000000000000000000000000000000000023c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb40e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e8423000000000098968015154514f68ce65a0d9eecc578c0ab12da0a2a28a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b0000000000989680432f6c4908a9aa5f3444421f466b11645235c99b831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b0a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a0000000000989680864cb9828254d712f8e59b164fc6a9402dc4e6c59065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca" + )); + + let result = cometbft_light_block_validation_run_before_hertz(&input, 100_000); + let (gas_used, output) = match result { + Ok(result) => result, + Err(_) => panic!("cometbft_light_block_validation_run failed"), + }; + assert_eq!(gas_used, 3_000); + assert_eq!(output, except_output_after_hertz); + } } diff --git a/crates/precompile/src/double_sign.rs b/crates/precompile/src/double_sign.rs new file mode 100644 index 00000000..f7ad52d4 --- /dev/null +++ b/crates/precompile/src/double_sign.rs @@ -0,0 +1,202 @@ +use crate::secp256k1; +use crate::{Bytes, Error, Precompile, PrecompileResult, PrecompileWithAddress}; +use alloy_primitives::{BlockNumber, ChainId, U256}; +use alloy_rlp::{Decodable, RlpDecodable, RlpEncodable}; +use core::cmp::Ordering; +use revm_primitives::alloy_primitives::B512; +use revm_primitives::{keccak256, B256}; + +/// Double sign evidence validation precompile for BSC. +pub(crate) const DOUBLE_SIGN_EVIDENCE_VALIDATION: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(104), + Precompile::Standard(double_sign_evidence_validation_run), +); + +const EXTRA_SEAL_LENGTH: usize = 65; + +/// Double sign evidence with two different headers. +#[derive(Debug, RlpDecodable, PartialEq)] +pub(crate) struct DoubleSignEvidence { + pub(crate) chain_id: ChainId, + pub(crate) header_bytes1: Bytes, + pub(crate) header_bytes2: Bytes, +} + +/// Header of a block. +#[derive(Debug, RlpDecodable, PartialEq)] +pub(crate) struct Header { + pub(crate) parent_hash: [u8; 32], + pub(crate) uncle_hash: [u8; 32], + pub(crate) coinbase: [u8; 20], + pub(crate) root: [u8; 32], + pub(crate) tx_hash: [u8; 32], + pub(crate) receipt_hash: [u8; 32], + pub(crate) bloom: [u8; 256], + pub(crate) difficulty: U256, + pub(crate) number: BlockNumber, + pub(crate) gas_limit: u64, + pub(crate) gas_used: u64, + pub(crate) time: u64, + pub(crate) extra: Bytes, + pub(crate) mix_digest: [u8; 32], + pub(crate) nonce: [u8; 8], +} + +/// The fields to generate the seal hash. +#[derive(Debug, RlpEncodable, RlpDecodable, PartialEq)] +pub(crate) struct SealContent { + pub(crate) chain_id: ChainId, + pub(crate) parent_hash: [u8; 32], + pub(crate) uncle_hash: [u8; 32], + pub(crate) coinbase: [u8; 20], + pub(crate) root: [u8; 32], + pub(crate) tx_hash: [u8; 32], + pub(crate) receipt_hash: [u8; 32], + pub(crate) bloom: [u8; 256], + pub(crate) difficulty: U256, + pub(crate) number: BlockNumber, + pub(crate) gas_limit: u64, + pub(crate) gas_used: u64, + pub(crate) time: u64, + pub(crate) extra: Bytes, + pub(crate) mix_digest: [u8; 32], + pub(crate) nonce: [u8; 8], +} + +/// Run the double sign evidence validation precompile. +/// +/// input: rlp encoded DoubleSignEvidence +/// +/// return: +/// +/// signer address| evidence height| +/// +/// 20 bytes | 32 bytes | +fn double_sign_evidence_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + const DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE: u64 = 10_000; + + if DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let evidence = match DoubleSignEvidence::decode(&mut input.iter().as_ref()) { + Ok(e) => e, + Err(_) => return Err(Error::Reverted(DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE)), + }; + + let header1 = match Header::decode(&mut evidence.header_bytes1.as_ref()) { + Ok(e) => e, + Err(_) => return Err(Error::Reverted(DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE)), + }; + let header2 = match Header::decode(&mut evidence.header_bytes2.as_ref()) { + Ok(e) => e, + Err(_) => return Err(Error::Reverted(DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE)), + }; + + // basic check + if header1.number.to_be_bytes().len() > 32 || header2.number.to_be_bytes().len() > 32 { + return Err(Error::other("invalid evidence")); + } + if header1.number != header2.number { + return Err(Error::other("invalid evidence")); + } + if header1.parent_hash.cmp(&header2.parent_hash) != Ordering::Equal { + return Err(Error::other("invalid evidence")); + } + + if header1.extra.len() < EXTRA_SEAL_LENGTH || header1.extra.len() < EXTRA_SEAL_LENGTH { + return Err(Error::other("invalid evidence")); + } + let sig1 = &header1.extra[header1.extra.len() - EXTRA_SEAL_LENGTH..]; + let sig2 = &header2.extra[header2.extra.len() - EXTRA_SEAL_LENGTH..]; + if sig1.eq(sig2) { + return Err(Error::other("invalid evidence")); + } + + // check signature + let msg_hash1 = seal_hash(&header1, evidence.chain_id); + let msg_hash2 = seal_hash(&header2, evidence.chain_id); + + if msg_hash1.eq(&msg_hash2) { + return Err(Error::other("invalid evidence")); + } + + let recid1 = sig1[64]; + let sig1 = <&B512>::try_from(&sig1[..64]).unwrap(); + let addr1 = match secp256k1::ecrecover(sig1, recid1, &msg_hash1) { + Ok(pk) => pk, + Err(_) => return Err(Error::Reverted(DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE)), + }; + + let recid2 = sig2[64]; + let sig2 = <&B512>::try_from(&sig2[..64]).unwrap(); + let addr2 = match secp256k1::ecrecover(sig2, recid2, &msg_hash2) { + Ok(pk) => pk, + Err(_) => return Err(Error::Reverted(DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE)), + }; + + if !addr1.eq(&addr2) { + return Err(Error::other("invalid evidence")); + } + + let mut res = [0; 52]; + let signer = &addr1[12..]; + res[..20].clone_from_slice(signer); + res[52 - header1.number.to_be_bytes().len()..].clone_from_slice(&header1.number.to_be_bytes()); + + Ok(( + DOUBLE_SIGN_EVIDENCE_VALIDATION_BASE, + Bytes::copy_from_slice(&res), + )) +} + +fn seal_hash(header: &Header, chain_id: ChainId) -> B256 { + let seal_content = SealContent { + chain_id, + parent_hash: header.parent_hash, + uncle_hash: header.uncle_hash, + coinbase: header.coinbase, + root: header.root, + tx_hash: header.tx_hash, + receipt_hash: header.receipt_hash, + bloom: header.bloom, + difficulty: header.difficulty, + number: header.number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + time: header.time, + extra: header.extra.slice(..header.extra.len() - EXTRA_SEAL_LENGTH), + mix_digest: header.mix_digest, + nonce: header.nonce, + }; + let encoded = alloy_rlp::encode(seal_content); + + keccak256(encoded) +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_primitives::hex; + + #[test] + fn test_double_sign_evidence_validation_run() { + let input = hex::decode("f906278202cab9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494976ea74026e726554db657fa54763abd0c3a0aa9a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a804ae755e0fe64b59753f4db6308a1f679747bce186aa2c62b95fa6eeff3fbd08f3b0667e45428a54ade15bad19f49641c499b431b36f65803ea71b379e6b61de501a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b9030ff9030ca01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094976ea74026e726554db657fa54763abd0c3a0aa9a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001820cdf830f4240830f4240846555fa64b90111d983010301846765746888676f312e32302e378664617277696e00007abd731ef8ae07b86091cb8836d58f5444b883422a18825d899035d3e6ea39ad1a50069bf0b86da8b5573dde1cb4a0a34f19ce94e0ef78ff7518c80265b8a3ca56e3c60167523590d4e8dcc324900559465fc0fa403774096614e135de280949b58a45cc96f2ba9e17f848820d41a08429d0d8b33ee72a84f750fefea846cbca54e487129c7961c680bb72309ca888820d42a08c9db14d938b19f9e2261bbeca2679945462be2b58103dfff73665d0d150fb8a80c0b17bfe88534296ff064cb7156548f6deba2d6310d5044ed6485f087dc6ef232e051c28e1909c2b50a3b4f29345d66681c319bef653e52e5d746480d5a3983b00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000").unwrap(); + + let res = double_sign_evidence_validation_run(&Bytes::from(input), 10_000).unwrap(); + + let gas = res.0; + assert_eq!(gas, 10_000u64); + + let res = hex::encode(res.1); + assert_eq!(res, "15d34aaf54267db7d7c367839aaf71a00a2c6a650000000000000000000000000000000000000000000000000000000000000cdf") + } + + #[test] + fn test_double_sign_evidence_validation_run_invalid_evidence() { + let input = hex::decode("f9066b38b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0fae1a05fcb14bfd9b8a9f2b65007a9b6c2000de0627a73be644dd993d32342c494df87f0e2b8519ea2dd4abd8b639cdd628497ed25a0f385cc58ed297ff0d66eb5580b02853d3478ba418b1819ac659ee05df49b9794a0bf88464af369ed6b8cf02db00f0b9556ffa8d49cd491b00952a7f83431446638a00a6d0870e586a76278fbfdcedf76ef6679af18fc1f9137cfad495f434974ea81b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b980988e1b9d0beb91dab063e04879a24c43d33baae3759dee41fd62ffa83c77fd202bea27a829b49e8025bdd198393526dd12b223ab16052fd26a43f3aabf63e76901a0232c9ba2d41b40d36ed794c306747bcbc49bf61a0f37409c18bfe2b5bef26a2d880000000000000000b90332f9032fa01062d3d5015b9242bc193a9b0769f3d3780ecb55f97f40a752ae26d0b68cd0d8a0b2789a5357827ed838335283e15c4dcc42b9bebcbf2919a18613246787e2f96094df87f0e2b8519ea2dd4abd8b639cdd628497ed25a071ce4c09ee275206013f0063761bc19c93c13990582f918cc57333634c94ce89a00e095703e5c9b149f253fe89697230029e32484a410b4b1f2c61442d73c3095aa0d317ae19ede7c8a2d3ac9ef98735b049bcb7278d12f48c42b924538b60a25e12b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a1010000000000000000000000000000000000000000000000000000000000000000830f4240830f42408465bc6996b90115d983010306846765746889676f312e32302e3131856c696e7578000053474aa9f8b25fb860b0844a5082bfaa2299d2a23f076e2f6b17b15f839cc3e7d5a875656f6733fd4b87ba3401f906d15f3dea263cd9a6076107c7db620a4630dd3832c4a4b57eb8f497e28a3d69e5c03b30205c4b45675747d513e1accd66329770f3c35b18c9d023f84c84023a5ad6a086a28d985d9a6c8e7f9a4feadd5ace0adba9818e1e1727edca755fcc0bd8344684023a5ad7a0bc3492196b2e68b8e6ceea87cfa7588b4d590089eb885c4f2c1e9d9fb450f7b9804c71ed015dd0c5c2d7393b68c2927f83f0a5da4c66f761f09e2f950cc610832c7876144599368404096ddef0eadacfde57717e2c7d23982b927285b797d41bfa00a0b56228685be711834d0f154292d07826dea42a0fad3e4f56c31470b7fbfbea26880000000000000000").unwrap(); + + let res = double_sign_evidence_validation_run(&Bytes::from(input), 10_000); + assert_eq!(res.err(), Some(Error::Reverted(10000))); + } +} diff --git a/crates/precompile/src/iavl.rs b/crates/precompile/src/iavl.rs new file mode 100644 index 00000000..6ad3fecc --- /dev/null +++ b/crates/precompile/src/iavl.rs @@ -0,0 +1,208 @@ +#![allow(dead_code)] + +use crate::{Bytes, Error, Precompile, PrecompileError, PrecompileResult, PrecompileWithAddress}; +use parity_bytes::BytesRef; +use tendermint::lite::iavl_proof; + +/// Iavl proof validation precompile for BSC. +pub(crate) const IAVL_PROOF_VALIDATION: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(101), + Precompile::Standard(iavl_proof_validation_run), +); + +/// Iavl proof validation precompile for BSC after Nano hardfork. +pub(crate) const IAVL_PROOF_VALIDATION_NANO: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(101), + Precompile::Standard(iavl_proof_validation_run_nano), +); + +/// Iavl proof validation precompile for BSC after Moran hardfork. +pub(crate) const IAVL_PROOF_VALIDATION_MORAN: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(101), + Precompile::Standard(iavl_proof_validation_run_moran), +); + +/// Iavl proof validation precompile for BSC after Planck hardfork. +pub(crate) const IAVL_PROOF_VALIDATION_PLANCK: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(101), + Precompile::Standard(iavl_proof_validation_run_planck), +); + +/// Iavl proof validation precompile for BSC after Plato hardfork. +pub(crate) const IAVL_PROOF_VALIDATION_PLATO: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(101), + Precompile::Standard(iavl_proof_validation_run_plato), +); + +/// Run Iavl proof validation. +fn iavl_proof_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + iavl_proof_validation_run_inner(input, gas_limit, false, false, false) +} + +/// Run Iavl proof validation with Nano hardfork. +fn iavl_proof_validation_run_nano(_input: &Bytes, _gas_limit: u64) -> PrecompileResult { + Err(PrecompileError::other("suspended")) +} + +/// Run Iavl proof validation with Moran hardfork. +fn iavl_proof_validation_run_moran(input: &Bytes, gas_limit: u64) -> PrecompileResult { + iavl_proof_validation_run_inner(input, gas_limit, true, false, false) +} + +/// Run Iavl proof validation with Planck hardfork. +fn iavl_proof_validation_run_planck(input: &Bytes, gas_limit: u64) -> PrecompileResult { + iavl_proof_validation_run_inner(input, gas_limit, false, true, false) +} + +/// Run Iavl proof validation with Plato hardfork. +fn iavl_proof_validation_run_plato(input: &Bytes, gas_limit: u64) -> PrecompileResult { + iavl_proof_validation_run_inner(input, gas_limit, false, false, true) +} + +/// Run Iavl proof validation with given hardfork toggles. +fn iavl_proof_validation_run_inner( + input: &Bytes, + gas_limit: u64, + is_moran: bool, + is_planck: bool, + is_plato: bool, +) -> PrecompileResult { + const IAVL_PROOF_VALIDATION_BASE: u64 = 3_000; + + if IAVL_PROOF_VALIDATION_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let mut output = [0u8; 32]; + let mut bytes = BytesRef::Fixed(&mut output); + let res = iavl_proof::execute(input.as_ref(), &mut bytes, is_moran, is_planck, is_plato); + match res { + Ok(()) => Ok(( + IAVL_PROOF_VALIDATION_BASE, + Bytes::copy_from_slice(&output[..]), + )), + Err(str) => Err(PrecompileError::other(str)), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_primitives::hex; + + #[test] + fn test_iavl_proof_validation_run() { + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000007306163630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d000000000000000000000000000000000000000000000000000000000000007b4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b28152c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae20add070a066961766c3a76121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9").unwrap(); + let res = iavl_proof_validation_run(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = hex::encode(res.1); + assert_eq!( + res, + "0000000000000000000000000000000000000000000000000000000000000001" + ) + } + + #[test] + fn test_iavl_proof_validation_run_moran() { + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000007306163630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d000000000000000000000000000000000000000000000000000000000000007b4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b28152c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae20add070a066961766c3a76121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9").unwrap(); + let res = iavl_proof_validation_run_moran(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = hex::encode(res.1); + assert_eq!( + res, + "0000000000000000000000000000000000000000000000000000000000000001" + ) + } + + #[test] + fn test_iavl_proof_validation_run_absence_proof_moran() { + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000007306163630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d000000000000000000000000000000000000000000000000000000000000007b4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b28152c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae20add070a066961766c3a61121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9").unwrap(); + let res = iavl_proof_validation_run_moran(&Bytes::from(input), 3_000u64); + + assert_eq!( + res.err(), + Some(PrecompileError::other("invalid merkle proof")) + ); + } + + #[test] + fn test_iavl_proof_validation_run_before_after_moran() { + // Bytest1 is the inputs of exploit tx 0x05356fd06ce56a9ec5b4eaf9c075abd740cae4c21eab1676440ab5cd2fe5c57a + let bytest1 = hex::decode("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd9ac0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd9ac1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20121a1f9c4eca726c725796c5375fc4158986ced08e498dc8268ef94d8ed1891612001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd9ac12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143").unwrap(); + // Bytest1 is the inputs of exploit tx 0xebf83628ba893d35b496121fb8201666b8e09f3cbadf0e269162baa72efe3b8b + let bytest2 = hex::decode("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd85c0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd85c1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20da657c1ffb86c684eb3e265361ef0fa4f9dfa670b45f9f91c5eb6ad84b21a4d112001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd85c12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143").unwrap(); + + let testcases = vec![bytest1, bytest2]; + + testcases.into_iter().for_each(|t| { + let res = iavl_proof_validation_run(&Bytes::from(t.clone()), 3_000u64); + assert_eq!(res.err(), None); + + let res = iavl_proof_validation_run_moran(&Bytes::from(t.clone()), 3_000u64); + + assert_eq!( + res.err(), + Some(PrecompileError::other("invalid merkle proof")) + ); + }); + + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000007306163630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d000000000000000000000000000000000000000000000000000000000000007b4bdc4c270a750a148a4e2eb018bdf98a8f53ec755740ffc728637a1d12110a0941544348412d3733301080f69bf321120b0a03424e4210e8baeb8d44120f0a075050432d303041108094ebdc031a26eb5ae98721031c199c92e5b0080967da99be27cf2da53317441b4a663e6d9c6caf02be1fdbdc20d7962b28152c69c314b4de5c8035253c8bc0771d9ca17b1b23a57c0c6d068b57579791cae20add070a066961766c3a61121c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d1ab407b2070aaf070a2d081810cdfd2b188096a82222209f223f804e2d94ac51c4321b0687397012e6d95eb9783b03bc790da631004c7c0a2d081710adb31a18f395a8222a20d2a38865de82383ccce0140513b65cec1bf2ae6cd7dfeb22eb6faadb4e26b26f0a2d081510b2990b18f395a82222208a02bbd5a695dfc772627ac8744aa9cf30ae26575bdce8c96a9a0d0999175b430a2d081410e6ff0418f395a8222a20d39619c779be909e67f23499fb74eb2c19afd7f21523401d4ccf7e917db5cd600a2d081210e3fe0118f395a8222a20a10cc73843f889d9e03a463eb135e928bb980e19734344cba0fbf4e8a4c5258b0a2c081010dd6518f395a8222a2007fd15843a2fd3f58d021b0e072a6c70742d7a3d993a922445e3491e1c14ee8e0a2c080f10cc2a18eda6a7222a20088942d7b30abd021d8e9505cc41313fad87c8c10a799f3b51018b7b2cfe4ad90a2c080d10b70d18eda6a7222a2091a37bc44d0c61e3752ddc59eb390355ab65e8a9fb453be4f0acec537f1ca14f0a2c080c10890818eda6a72222201cfc317855a06667c45812fe36efe33af05671dfe0d9b56b02662011af2e79e30a2c080b10ac0318c4b0ee212220aeb454a4b3243b6269a2fd8841dca9a951c53b30f1e27da91063dae7224402c70a2c080910e40118c4b0ee212a20441340a4de6498f861b97b3f3ad9603af055e5af51a0d96fff2ae28e3c5c6c9a0a2c0808108d0118c4b0ee212220ae32ea4b9ab7b53571da320e2815fd8b2c278124961cca4a1849a799842424450a2b0807104d18c4b0ee212220e2804c9b7f045ec0b4ab20920a937b82fda8b7a9ddd12b21637335b915cfda550a2b0806102418a5f4c7192a20ec85f22addedfc82c771af5b4c77544b7c1d7c5bbac33f2712dfba1045ebdbd00a2b0805101118a5f4c7192a2071ade34dcc447a0ba8adc603080633d15c06f3525830c86ebce35eca0a4921fc0a2b0804100c18a5f4c7192a205190bce93993e65b266a3417ed511df8897a812cb4b62569e5afcfbec10b69cd0a2b0803100618a5f4c7192220b76c6884f1d412ac10bfb3987fb7d26f0330b2a85539509ebc5c6bdec2f95d520a2b0802100418a5f4c71922206a285b4a4f9d1c687bbafa1f3649b6a6e32b1a85dd0402421210683e846cf0020a2b0801100218a5f4c7192220033b3f7c6dcb258b6e55545e7a4f51539447cd595eb8a2e373ba0015502da1051a450a1c6163636f756e743a8a4e2eb018bdf98a8f53ec755740ffc728637a1d12201a272295e94cf1d8090bdb019dde48e9dab026ad2c3e43aaa7e61cc954a9245d18a5f4c7190ab6040a0a6d756c746973746f726512036163631aa204a0040a9d040a300a0364657812290a27088496a822122038fc49f49648fec62acc434151a51eaa378c1b20a730a749548e36f1529422500a300a03676f7612290a27088496a8221220a78ce489bdf08b9ee869c184876e1623dc38b3e64a5cf1a0005f97976c64deac0a380a0b61746f6d69635f7377617012290a27088496a8221220544c2fa38f61e10a39ec00b3e724d5834761268bb455cdbf5843bcf1531f8fbc0a300a0376616c12290a27088496a82212201f71082c9f6f45fb456b2c00b41e50d2f662f2dfec3cb6965f19d214bf02f3980a0f0a046d61696e12070a05088496a8220a320a057374616b6512290a27088496a82212200dd467343c718f240e50b4feac42970fc8c1c69a018be955f9c27913ac1f8b3c0a300a0361636312290a27088496a8221220270c19ccc9c40c5176b3dfbd8af734c97a307e0dbd8df9e286dcd5d709f973ed0a330a06746f6b656e7312290a27088496a8221220c4f96eedf50c83964de9df013afec2e545012d92528b643a5166c828774187b60a320a05706169727312290a27088496a8221220351c55cfda84596ecd22ebc77013662aba97f81f19d9ef3d150213bb07c823060a360a0974696d655f6c6f636b12290a27088496a8221220e7adf5bd30ce022decf0e9341bf05c464ed70cdbc97423bd2bab8f3571e5179b0a330a06706172616d7312290a27088496a822122042a9dfc356ca435db131eb41fb1975c8482f2434537918665e530b0b4633b5f9").unwrap(); + let res = iavl_proof_validation_run_moran(&Bytes::from(input), 3_000u64); + + assert_eq!( + res.err(), + Some(PrecompileError::other("invalid merkle proof")) + ); + } + + #[test] + fn test_iavl_proof_validation_run_valid_proof_moran() { + let input = hex::decode("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd9ac0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd9ac1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20121a1f9c4eca726c725796c5375fc4158986ced08e498dc8268ef94d8ed1891612001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd9ac12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143").unwrap(); + let res = iavl_proof_validation_run(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = hex::encode(res.1); + assert_eq!( + res, + "0000000000000000000000000000000000000000000000000000000000000001" + ) + } + + #[test] + fn test_iavl_proof_validation_run_valid_proof_plank() { + let input = hex::decode("000000000000000000000000000000000000000000000000000000000000015b6962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000477696e640000000000000000000000000000000000000000000000000000000000000005626c6f7773ae6d1123fc362b3297bfb19c9f9fabbcbd1e2555b923dead261905b8a2ff6db60a300a0a69637332333a6961766c120477696e641a1c0a1a0a0477696e641205626c6f77731a0b0801180120012a030002040a9d010a0c69637332333a73696d706c6512036962631a87010a84010a036962631220141acb8632cfb808f293f2649cb9aabaca74fc18640900ffd0d48e2994b2a1521a090801180120012a0100222708011201011a205f0ba08283de309300409486e978a3ea59d82bccc838b07c7d39bd87c16a5034222708011201011a20455b81ef5591150bd24d3e57a769f65518b16de93487f0fab02271b3d69e2852").unwrap(); + let res = iavl_proof_validation_run_planck(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = hex::encode(res.1); + assert_eq!( + res, + "0000000000000000000000000000000000000000000000000000000000000001" + ) + } + + #[test] + fn test_iavl_proof_validation_run_valid_proof_plato() { + let input = hex::decode("000000000000000000000000000000000000000000000000000000000000015b6962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000477696e640000000000000000000000000000000000000000000000000000000000000005626c6f7773ae6d1123fc362b3297bfb19c9f9fabbcbd1e2555b923dead261905b8a2ff6db60a300a0a69637332333a6961766c120477696e641a1c0a1a0a0477696e641205626c6f77731a0b0801180120012a030002040a9d010a0c69637332333a73696d706c6512036962631a87010a84010a036962631220141acb8632cfb808f293f2649cb9aabaca74fc18640900ffd0d48e2994b2a1521a090801180120012a0100222708011201011a205f0ba08283de309300409486e978a3ea59d82bccc838b07c7d39bd87c16a5034222708011201011a20455b81ef5591150bd24d3e57a769f65518b16de93487f0fab02271b3d69e2852").unwrap(); + let res = iavl_proof_validation_run_plato(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = hex::encode(res.1); + assert_eq!( + res, + "0000000000000000000000000000000000000000000000000000000000000001" + ) + } +} diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 347d3a62..a63d84c2 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -14,7 +14,9 @@ mod bls; pub mod bls12_381; pub mod bn128; mod cometbft; +mod double_sign; pub mod hash; +mod iavl; pub mod identity; #[cfg(feature = "c-kzg")] pub mod kzg_point_evaluation; @@ -22,6 +24,9 @@ pub mod modexp; pub mod secp256k1; #[cfg(feature = "secp256r1")] pub mod secp256r1; +mod tendermint; +#[cfg(feature = "secp256k1")] +mod tm_secp256k1; pub mod utilities; use core::hash::Hash; @@ -54,6 +59,7 @@ impl PrecompileOutput { } } } + #[derive(Clone, Default, Debug)] pub struct Precompiles { /// Precompiles. @@ -69,8 +75,16 @@ impl Precompiles { PrecompileSpecId::ISTANBUL => Self::istanbul(), PrecompileSpecId::BERLIN => Self::berlin(), PrecompileSpecId::FERMAT => Self::fermat(), + PrecompileSpecId::NANO => Self::nano(), + PrecompileSpecId::MORAN => Self::moran(), + PrecompileSpecId::PLANCK => Self::planck(), + PrecompileSpecId::LUBAN => Self::luban(), + PrecompileSpecId::PLATO => Self::plato(), + PrecompileSpecId::HERTZ => Self::hertz(), + PrecompileSpecId::FEYNMAN => Self::feynman(), PrecompileSpecId::CANCUN => Self::cancun(), PrecompileSpecId::PRAGUE => Self::prague(), + PrecompileSpecId::HABER => Self::haber(), PrecompileSpecId::LATEST => Self::latest(), } } @@ -121,6 +135,13 @@ impl Precompiles { bn128::mul::ISTANBUL, bn128::pair::ISTANBUL, ]); + + #[cfg(feature = "bsc")] + precompiles.extend([ + tendermint::TENDERMINT_HEADER_VALIDATION, + iavl::IAVL_PROOF_VALIDATION, + ]); + Box::new(precompiles) }) } @@ -129,6 +150,9 @@ impl Precompiles { pub fn berlin() -> &'static Self { static INSTANCE: OnceBox = OnceBox::new(); INSTANCE.get_or_init(|| { + #[cfg(feature = "bsc")] + let mut precompiles = Self::plato().clone(); + #[cfg(not(feature = "bsc"))] let mut precompiles = Self::istanbul().clone(); precompiles.extend([ // EIP-2565: ModExp Gas Cost. @@ -144,15 +168,104 @@ impl Precompiles { pub fn fermat() -> &'static Self { static INSTANCE: OnceBox = OnceBox::new(); INSTANCE.get_or_init(|| { - let precompiles = Self::berlin().clone(); - let precompiles = { - let mut precompiles = precompiles; - precompiles.extend([ - bls::BLS_SIGNATURE_VALIDATION, - cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION, - ]); - precompiles - }; + let mut precompiles = Self::berlin().clone(); + precompiles.extend([ + bls::BLS_SIGNATURE_VALIDATION, + cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION, + ]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Nano sepc. + pub fn nano() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::istanbul().clone(); + precompiles.extend([ + tendermint::TENDERMINT_HEADER_VALIDATION_NANO, + iavl::IAVL_PROOF_VALIDATION_NANO, + ]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Moran sepc. + pub fn moran() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::istanbul().clone(); + precompiles.extend([ + tendermint::TENDERMINT_HEADER_VALIDATION, + iavl::IAVL_PROOF_VALIDATION_MORAN, + ]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Planck sepc. + pub fn planck() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::istanbul().clone(); + precompiles.extend([ + tendermint::TENDERMINT_HEADER_VALIDATION, + iavl::IAVL_PROOF_VALIDATION_PLANCK, + ]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Luban sepc. + pub fn luban() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::planck().clone(); + precompiles.extend([ + bls::BLS_SIGNATURE_VALIDATION, + cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION_BEFORE_HERTZ, + ]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Plato sepc. + pub fn plato() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::luban().clone(); + precompiles.extend([iavl::IAVL_PROOF_VALIDATION_PLATO]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Hertz sepc. + pub fn hertz() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::berlin().clone(); + precompiles.extend([cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION]); + + Box::new(precompiles) + }) + } + + /// Returns precompiles for Feynman sepc. + pub fn feynman() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Self::hertz().clone(); + precompiles.extend([double_sign::DOUBLE_SIGN_EVIDENCE_VALIDATION]); + + // this feature is enabled with bsc + #[cfg(feature = "secp256k1")] + precompiles.extend([tm_secp256k1::TM_SECP256K1_SIGNATURE_RECOVER]); Box::new(precompiles) }) @@ -165,6 +278,9 @@ impl Precompiles { pub fn cancun() -> &'static Self { static INSTANCE: OnceBox = OnceBox::new(); INSTANCE.get_or_init(|| { + #[cfg(feature = "bsc")] + let precompiles = Self::feynman().clone(); + #[cfg(not(feature = "bsc"))] let precompiles = Self::berlin().clone(); // Don't include KZG point evaluation precompile in no_std builds. @@ -204,9 +320,30 @@ impl Precompiles { }) } + /// Returns precompiles for Haber spec. + pub fn haber() -> &'static Self { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let precompiles = Self::cancun().clone(); + + #[cfg(feature = "secp256r1")] + let precompiles = { + let mut precompiles = precompiles; + precompiles.extend([secp256r1::P256VERIFY]); + precompiles + }; + + Box::new(precompiles) + }) + } + /// Returns the precompiles for the latest spec. pub fn latest() -> &'static Self { - Self::prague() + if cfg!(feature = "bsc") { + Self::haber() + } else { + Self::prague() + } } /// Returns an iterator over the precompiles addresses. @@ -279,6 +416,16 @@ pub enum PrecompileSpecId { ISTANBUL, BERLIN, FERMAT, + + NANO, // BSC NANO HARDFORK + MORAN, // BSC MORAN HARDFORK + PLANCK, // BSC PLANCK HARDFORK + LUBAN, // BSC LUBAN HARDFORK + PLATO, // BSC PLATO HARDFORK + HERTZ, // BSC HERTZ HARDFORK + FEYNMAN, // BSC FEYNMAN HARDFORK + HABER, // BSC HABER HARDFORK + CANCUN, PRAGUE, LATEST, @@ -294,18 +441,34 @@ impl PrecompileSpecId { } BYZANTIUM | CONSTANTINOPLE | PETERSBURG => Self::BYZANTIUM, ISTANBUL | MUIR_GLACIER => Self::ISTANBUL, + #[cfg(feature = "bsc")] + RAMANUJAN | NIELS | MIRROR_SYNC | BRUNO | EULER => Self::ISTANBUL, + #[cfg(feature = "bsc")] + NANO => Self::NANO, + #[cfg(feature = "bsc")] + MORAN | GIBBS => Self::MORAN, + #[cfg(feature = "bsc")] + PLANCK => Self::PLANCK, + #[cfg(feature = "bsc")] + LUBAN => Self::LUBAN, + #[cfg(feature = "bsc")] + PLATO => Self::PLATO, BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN, + #[cfg(feature = "bsc")] + HERTZ | HERTZ_FIX | KEPLER => Self::HERTZ, + #[cfg(feature = "bsc")] + FEYNMAN | FEYNMAN_FIX => Self::FEYNMAN, CANCUN => Self::CANCUN, PRAGUE => Self::PRAGUE, - LATEST => Self::LATEST, #[cfg(feature = "optimism")] BEDROCK | REGOLITH | CANYON => Self::BERLIN, #[cfg(feature = "optimism")] ECOTONE | FJORD => Self::CANCUN, #[cfg(feature = "opbnb")] FERMAT => Self::FERMAT, - #[cfg(feature = "opbnb")] - HABER => Self::CANCUN, + #[cfg(any(feature = "bsc", feature = "opbnb"))] + HABER => Self::HABER, + LATEST => Self::LATEST, } } } diff --git a/crates/precompile/src/tendermint.rs b/crates/precompile/src/tendermint.rs new file mode 100644 index 00000000..ef06c96e --- /dev/null +++ b/crates/precompile/src/tendermint.rs @@ -0,0 +1,55 @@ +use crate::{Bytes, Error, Precompile, PrecompileError, PrecompileResult, PrecompileWithAddress}; +use parity_bytes::BytesRef; +use tendermint::lite::light_client; + +/// Tendermint precompile for BSC. +pub(crate) const TENDERMINT_HEADER_VALIDATION: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(100), + Precompile::Standard(crate::tendermint::tendermint_header_validation_run), +); + +/// Tendermint precompile for BSC after Nano hardfork. +pub(crate) const TENDERMINT_HEADER_VALIDATION_NANO: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(100), + Precompile::Standard(crate::tendermint::tendermint_header_validation_run_nano), +); + +/// Run the Tendermint header validation precompile after Nano hardfork. +fn tendermint_header_validation_run_nano(_input: &Bytes, _gas_limit: u64) -> PrecompileResult { + Err(PrecompileError::other("suspended")) +} + +/// Run the Tendermint header validation precompile. +fn tendermint_header_validation_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + const TENDERMINT_HEADER_VALIDATION_BASE: u64 = 3_000; + + if TENDERMINT_HEADER_VALIDATION_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let mut output = vec![0u8, 0, 0]; + let mut bytes = BytesRef::Flexible(&mut output); + let res = light_client::TmHeaderVerifier::execute(input.as_ref(), &mut bytes); + match res { + Ok(()) => Ok((TENDERMINT_HEADER_VALIDATION_BASE, Bytes::from(output))), + Err(str) => Err(PrecompileError::other(str)), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_primitives::hex; + + #[test] + fn test_tendermint_header_validation_run() { + let input = hex::decode("0000000000000000000000000000000000000000000000000000000000001325000000000000000000000000000000000000000000000000000000000000022042696e616e63652d436861696e2d4e696c6500000000000000000000000000000000000003fc05e2b7029751d2a6581efc2f79712ec44d8b4981850325a7feadaa58ef4ddaa18a9380d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27ae17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f000000174876e800184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c9000000174876e8004d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b74000000174876e800bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed6000000174876e8008f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d53000000174876e8004a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b5000000174876e800c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a000000174876e8009142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc000000174876e80049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e000000174876e80004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b6000000174876e8004034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e8000000174876e800e3210a92130abb020a02080a121242696e616e63652d436861696e2d4e696c6518e38bf01f220c08e191aef20510f5f4e4c70230dae0c7173a480a20102b54820dd8fb5bc2c4e875ee573fa294d9b7b7ceb362aa8fd21b33dee41b1c12240801122082f341511f3e6b89d6177fd31f8a106013ba09d6e12ef40a7dec885d81b687634220b1b77e6977e0cd0177e3102a78833c9e152aa646ed4fb5a77e8af58c9867eec0522080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a5a2080d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27a6220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f936a20a3e248bc209955054d880e4d89ff3c0419c0cd77681f4b4c6649ead5545054b982011462633d9db7ed78e951f79913fdc8231aa77ec12b12d1100a480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be212b601080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510cebfe23e321406fd60078eb4c2356137dd50036597db267cf61642409276f20ad4b152f91c344bd63ac691bad66e04e228a8b58dca293ff0bd10f8aef6dfbcecae49e32b09d89e10b771a6c01628628596a95e126b04763560c66c0f12b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510a4caa532321418e69cc672973992bb5f76d049a5b2c5ddf77436380142409ed2b74fa835296d552e68c439dd4ee3fa94fb197282edcc1cc815c863ca42a2c9a73475ff6be9064371a61655a3c31d2f0acc89c3a4489ad4c2671aef52360512b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510a69eca2f3214344c39bb8f4512d6cab1f6aafac1811ef9d8afdf38024240de2768ead90011bcbb1914abc1572749ab7b81382eb81cff3b41c56edc12470a7b8a4d61f8b4ca7b2cb7e24706edd219455796b4db74cd36965859f91dc8910312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510dcdd833b321437ef19af29679b368d2b9e9de3f8769b357866763803424072ddfe0aeb13616b3f17eb60b19a923ec51fcc726625094aa069255c829c8cdd9e242080a1e559b0030fe9a0db19fd34e392bd78df12a9caff9f2b811bc1ac0a12b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510e9f2f859321462633d9db7ed78e951f79913fdc8231aa77ec12b38044240f5f61c640ab2402b44936de0d24e7b439df78bc3ef15467ecb29b92ece4aa0550790d5ce80761f2ac4b0e3283969725c42343749d9b44b179b2d4fced66c5d0412b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510ff90f55532147b343e041ca130000a8bc00c35152bd7e774003738054240df6e298b3efd42eb536e68a0210bc921e8b5dc145fe965f63f4d3490064f239f2a54a6db16c96086e4ae52280c04ad8b32b44f5ff3d41f0c364949ccb628c50312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510cad7c931321491844d296bd8e591448efc65fd6ad51a888d58fa3806424030298627da1afd28229aac150f553724b594989e59136d6a175d84e45a4dee344ff9e0eeb69fdf29abb6d833adc3e1ccdc87b2a65019ef5fb627c44d9d132c0012b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510c8c296323214b3727172ce6473bc780298a2d66c12f1a14f5b2a38074240918491100730b4523f0c85409f6d1cca9ebc4b8ca6df8d55fe3d85158fa43286608693c50332953e1d3b93e3e78b24e158d6a2275ce8c6c7c07a7a646a19200312b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef2051086f1a2403214b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba338084240ca59c9fc7f6ab660e9970fc03e5ed588ccb8be43fe5a3e8450287b726f29d039e53fe888438f178ac63c3d2ca969cd8c2fbc8606f067634339b6a94a7382960212b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef2051080efbb543214e0dd72609cc106210d1aa13936cb67b93a0aee2138094240e787a21f5cb7052624160759a9d379dd9db144f2b498bca026375c9ce8ecdc2a0936af1c309b3a0f686c92bf5578b595a4ca99036a19c9fc50d3718fd454b30012b801080210e38bf01f22480a207eaabf7df1081377e06e08efe7ad17974049380bdd65a9b053c099ef80ff6e6f122408011220d153cc308d9cb96ca43ffeceaae1ee85794c83d17408ff76cfee92f5e91d0be22a0b08e291aef20510ddf8d85a3214fc3108dc3814888f4187452182bc1baf83b71bc9380a4240d51ea31f6449eed71de22339722af1edbb0b21401037d85882b32a2ed8ae9127f2df4d1da2092729e582812856227ed6cdf98a3f60203d1ff80bd635fb03bb0912a4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff011aa4070a4f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff010a4b0a1418e69cc672973992bb5f76d049a5b2c5ddf7743612251624de6420184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c91880d0dbc3f4022080d0dbc3f4020a4b0a14344c39bb8f4512d6cab1f6aafac1811ef9d8afdf12251624de64204d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b741880d0dbc3f4022080d0dbc3f4020a4b0a1437ef19af29679b368d2b9e9de3f8769b3578667612251624de6420bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed61880d0dbc3f4022080d0dbc3f4020a4b0a1462633d9db7ed78e951f79913fdc8231aa77ec12b12251624de64208f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d531880d0dbc3f4022080d0dbc3f4020a4b0a147b343e041ca130000a8bc00c35152bd7e774003712251624de64204a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b51880d0dbc3f4022080d0dbc3f4020a4b0a1491844d296bd8e591448efc65fd6ad51a888d58fa12251624de6420c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a1880d0dbc3f4022080d0dbc3f4020a4b0a14b3727172ce6473bc780298a2d66c12f1a14f5b2a12251624de64209142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc1880d0dbc3f4022080d0dbc3f4020a4b0a14b6f20c7faa2b2f6f24518fa02b71cb5f4a09fba312251624de642049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e1880d0dbc3f4022080d0dbc3f4020a4b0a14e0dd72609cc106210d1aa13936cb67b93a0aee2112251624de642004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b61880d0dbc3f4022080d0dbc3f4020a4b0a14fc3108dc3814888f4187452182bc1baf83b71bc912251624de64204034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e81880d0dbc3f4022080d0dbc3f402124f0a1406fd60078eb4c2356137dd50036597db267cf61612251624de6420e17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f1880d0dbc3f4022080e0ebdaf2e2ffffff01").unwrap(); + let res = tendermint_header_validation_run(&Bytes::from(input), 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let output = hex::encode(res.1); + assert_eq!(output, "000000000000000000000000000000000000000000000000000000000000022042696e616e63652d436861696e2d4e696c6500000000000000000000000000000000000003fc05e3a3e248bc209955054d880e4d89ff3c0419c0cd77681f4b4c6649ead5545054b980d9ab0fc10d18ca0e0832d5f4c063c5489ec1443dfb738252d038a82131b27ae17cbe9c20cdcfdf876b3b12978d3264a007fcaaa71c4cdb701d9ebc0323f44f000000174876e800184e7b103d34c41003f9b864d5f8c1adda9bd0436b253bb3c844bc739c1e77c9000000174876e8004d420aea843e92a0cfe69d89696dff6827769f9cb52a249af537ce89bf2a4b74000000174876e800bd03de9f8ab29e2800094e153fac6f696cfa512536c9c2f804dcb2c2c4e4aed6000000174876e8008f4a74a07351895ddf373057b98fae6dfaf2cd21f37a063e19601078fe470d53000000174876e8004a5d4753eb79f92e80efe22df7aca4f666a4f44bf81c536c4a09d4b9c5b654b5000000174876e800c80e9abef7ff439c10c68fe8f1303deddfc527718c3b37d8ba6807446e3c827a000000174876e8009142afcc691b7cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc000000174876e80049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb787a5b314a298e000000174876e80004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b6000000174876e8004034b37ceda8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e8000000174876e800"); + } +} diff --git a/crates/precompile/src/tm_secp256k1.rs b/crates/precompile/src/tm_secp256k1.rs new file mode 100644 index 00000000..7dacc9e2 --- /dev/null +++ b/crates/precompile/src/tm_secp256k1.rs @@ -0,0 +1,130 @@ +use crate::{Bytes, Error, Precompile, PrecompileError, PrecompileResult, PrecompileWithAddress}; +use secp256k1::{ecdsa, Message, PublicKey}; +use tendermint::{account, public_key}; + +/// Tendermint SECP256K1 signature recover precompile for BSC. +pub(crate) const TM_SECP256K1_SIGNATURE_RECOVER: PrecompileWithAddress = PrecompileWithAddress( + crate::u64_to_address(105), + Precompile::Standard(tm_secp256k1_signature_recover_run), +); + +const SECP256K1_PUBKEY_LENGTH: usize = 33; +const SECP256K1_SIGNATURE_LENGTH: usize = 64; +const SECP256K1_SIGNATURE_MSGHASH_LENGTH: usize = 32; + +/// Runs the Tendermint SECP256K1 signature recover precompile. +/// +/// input: +/// +/// | PubKey | Signature | SignatureMsgHash | +/// +/// | 33 bytes | 64 bytes | 32 bytes | +fn tm_secp256k1_signature_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { + const TM_SECP256K1_SIGNATURE_RECOVER_BASE: u64 = 3_000; + + if TM_SECP256K1_SIGNATURE_RECOVER_BASE > gas_limit { + return Err(Error::OutOfGas); + } + + let input_length = input.len(); + if input_length + != SECP256K1_PUBKEY_LENGTH + SECP256K1_SIGNATURE_LENGTH + SECP256K1_SIGNATURE_MSGHASH_LENGTH + { + return Err(PrecompileError::other("invalid input")); + } + + let public_key = match PublicKey::from_slice(&input[..SECP256K1_PUBKEY_LENGTH]) { + Ok(pk) => pk, + Err(_) => return Err(PrecompileError::other("invalid pubkey")), + }; + + let message = Message::from_digest( + input[SECP256K1_PUBKEY_LENGTH + SECP256K1_SIGNATURE_LENGTH..] + .try_into() + .unwrap(), + ); + + let sig = match ecdsa::Signature::from_compact( + &input[SECP256K1_PUBKEY_LENGTH..SECP256K1_PUBKEY_LENGTH + SECP256K1_SIGNATURE_LENGTH], + ) { + Ok(s) => s, + Err(_) => return Err(PrecompileError::other("invalid signature")), + }; + + let res = sig.verify(&message, &public_key).is_ok(); + + if !res { + return Err(PrecompileError::other("invalid signature")); + } + + let tm_pub_key = + match public_key::PublicKey::from_raw_secp256k1(&input[..SECP256K1_PUBKEY_LENGTH]) { + Some(pk) => pk, + None => return Err(PrecompileError::other("invalid pubkey")), + }; + + return Ok(( + TM_SECP256K1_SIGNATURE_RECOVER_BASE, + Bytes::copy_from_slice(account::Id::from(tm_pub_key).as_bytes()), + )); +} + +#[cfg(test)] +mod tests { + use super::*; + use revm_primitives::hex; + + #[test] + fn test_tm_secp256k1_signature_recover_run_local_key() { + let pub_key = + hex::decode("0278caa4d6321aa856d6341dd3e8bcdfe0b55901548871c63c3f5cec43c2ae88a9") + .unwrap(); + let sig = hex::decode("0cb78be0d8eaeab991907b06c61240c04f4ca83f54b7799ce77cf029b837988038c4b3b7f5df231695b0d14499b716e1fd6504860eb3c9244ecb4e569d44c062").unwrap(); + let msg_hash = + hex::decode("b6ac827edff4bbbf23579720782dbef40b65780af292cc66849e7e5944f1230f") + .unwrap(); + + let expect_address = hex::decode("fa3B227adFf8EA1706098928715076D76959Ae6c").unwrap(); + + let mut input = vec![]; + input.extend(pub_key); + input.extend(sig); + input.extend(msg_hash); + + let input = revm_primitives::Bytes::copy_from_slice(&input); + let res = tm_secp256k1_signature_recover_run(&input, 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = res.1; + assert_eq!(res, Bytes::from(expect_address)); + } + + #[test] + fn test_tm_secp256k1_signature_recover_run_ledger_key() { + let pub_key = + hex::decode("02d63ee39adb1779353b4393dd5ea9d6d2b6df63b71d168571803cc7b9a0a20e98") + .unwrap(); + let sig = hex::decode("66bdb5d381b2773c0f569858c7ee143959522d7c1f46dc656c325cb7353ec40c28ec22dff3650b34c096c5b12e702d7237d409f1ebaaa6dd1128a8f2d401fd5b").unwrap(); + let msg_hash = + hex::decode("c45e8f0dc7c054c31912beeffd6f10f1c585606d61e252e97968cd66661c2571") + .unwrap(); + + let expect_address = hex::decode("65a284146b84210a01add088954bb52d88b230af").unwrap(); + + let mut input = vec![]; + input.extend(pub_key); + input.extend(sig); + input.extend(msg_hash); + + let input = revm_primitives::Bytes::copy_from_slice(&input); + let res = tm_secp256k1_signature_recover_run(&input, 3_000u64).unwrap(); + + let gas = res.0; + assert_eq!(gas, 3_000u64); + + let res = res.1; + assert_eq!(res, Bytes::from(expect_address)); + } +} diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index ee77dd34..bb6b57c1 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -72,6 +72,7 @@ arbitrary = ["std", "alloy-primitives/arbitrary", "bitflags/arbitrary"] asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] +bsc = [] optimism = [] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = ["optimism"] diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 44b07369..19d0fc50 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -553,6 +553,10 @@ pub struct TxEnv { #[cfg(feature = "optimism")] /// Optimism fields. pub optimism: OptimismFields, + + #[cfg_attr(feature = "serde", serde(flatten))] + #[cfg(feature = "bsc")] + pub bsc: BscFields, } pub enum TxType { @@ -595,6 +599,8 @@ impl Default for TxEnv { max_fee_per_blob_gas: None, #[cfg(feature = "optimism")] optimism: OptimismFields::default(), + #[cfg(feature = "bsc")] + bsc: BscFields::default(), } } } @@ -658,6 +664,15 @@ pub struct OptimismFields { pub enveloped_tx: Option, } +/// Additional [TxEnv] fields for bsc. +#[cfg(feature = "bsc")] +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BscFields { + /// Whether the transaction is a system transaction. + pub is_system_transaction: Option, +} + /// Transaction destination. #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/primitives/src/env/handler_cfg.rs b/crates/primitives/src/env/handler_cfg.rs index f57a3e8c..ed166e15 100644 --- a/crates/primitives/src/env/handler_cfg.rs +++ b/crates/primitives/src/env/handler_cfg.rs @@ -12,6 +12,9 @@ pub struct HandlerCfg { /// Optimism related field, it will append the Optimism handle register to the EVM. #[cfg(feature = "optimism")] pub is_optimism: bool, + /// Bsc related field, it will append the Bsc handle register to the EVM. + #[cfg(feature = "bsc")] + pub is_bsc: bool, } impl Default for HandlerCfg { @@ -35,6 +38,8 @@ impl HandlerCfg { spec_id, #[cfg(feature = "optimism")] is_optimism, + #[cfg(feature = "bsc")] + is_bsc: true, } } @@ -47,6 +52,12 @@ impl HandlerCfg { } } + /// Creates new `HandlerCfg` instance with the bsc feature. + #[cfg(feature = "bsc")] + pub fn new_with_bsc(spec_id: SpecId, is_bsc: bool) -> Self { + Self { spec_id, is_bsc } + } + /// Returns `true` if the optimism feature is enabled and flag is set to `true`. pub fn is_optimism(&self) -> bool { cfg_if::cfg_if! { @@ -57,6 +68,17 @@ impl HandlerCfg { } } } + + /// Returns `true` if the bsc feature is enabled and flag is set to `true`. + pub fn is_bsc(&self) -> bool { + cfg_if::cfg_if! { + if #[cfg(feature = "bsc")] { + self.is_bsc + } else { + false + } + } + } } /// Configuration environment with the chain spec id. @@ -89,6 +111,12 @@ impl CfgEnvWithHandlerCfg { pub fn enable_optimism(&mut self) { self.handler_cfg.is_optimism = true; } + + /// Enables the bsc feature. + #[cfg(feature = "bsc")] + pub fn enable_bsc(&mut self) { + self.handler_cfg.is_bsc = true; + } } impl DerefMut for CfgEnvWithHandlerCfg { @@ -142,6 +170,12 @@ impl EnvWithHandlerCfg { pub fn enable_optimism(&mut self) { self.handler_cfg.is_optimism = true; } + + /// Enables the bsc handle register. + #[cfg(feature = "bsc")] + pub fn enable_bsc(&mut self) { + self.handler_cfg.is_bsc = true; + } } impl DerefMut for EnvWithHandlerCfg { diff --git a/crates/primitives/src/precompile.rs b/crates/primitives/src/precompile.rs index 5fd5845d..903013ff 100644 --- a/crates/primitives/src/precompile.rs +++ b/crates/primitives/src/precompile.rs @@ -125,12 +125,6 @@ pub enum PrecompileError { BlobMismatchedVersion, /// The proof verification failed. BlobVerifyKzgProofFailed, - /// The input length is not matching the expected length. - BLSInvalidInputLength, - /// The bls signature is invalid. - BLSInvalidSignature, - /// The bls public key is invalid. - BLSInvalidPublicKey, /// The cometbft validation input is invalid. CometBftInvalidInput, /// The cometbft apply block failed. @@ -139,6 +133,10 @@ pub enum PrecompileError { CometBftEncodeConsensusStateFailed, /// Catch-all variant for other errors. Other(String), + /// Reverted error + /// This is for BSC EVM compatibility specially. + /// This error will not consume all gas but only the returned amount. + Reverted(u64), } impl PrecompileError { @@ -165,13 +163,11 @@ impl fmt::Display for PrecompileError { Self::BlobInvalidInputLength => "invalid blob input length", Self::BlobMismatchedVersion => "mismatched blob version", Self::BlobVerifyKzgProofFailed => "verifying blob kzg proof failed", - Self::BLSInvalidInputLength => "invalid input length for BLS", - Self::BLSInvalidSignature => "invalid BLS signature", - Self::BLSInvalidPublicKey => "invalid BLS public key", Self::CometBftInvalidInput => "invalid cometbft light block validation input", Self::CometBftApplyBlockFailed => "failed to apply cometbft block", Self::CometBftEncodeConsensusStateFailed => "failed to encode cometbft consensus state", Self::Other(s) => s, + Self::Reverted(_) => "execution reverted", }; f.write_str(s) } diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index fce209ef..918b9039 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -1,11 +1,14 @@ #![allow(non_camel_case_types)] +#[cfg(all(feature = "optimism", feature = "bsc"))] +compile_error!("Features 'optimism' and 'bsc' cannot be enabled together."); + pub use SpecId::*; /// Specification IDs and their activation block. /// /// Information was obtained from the [Ethereum Execution Specifications](https://github.com/ethereum/execution-specs) -#[cfg(not(feature = "optimism"))] +#[cfg(all(not(feature = "optimism"), not(feature = "bsc")))] #[repr(u8)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -71,6 +74,56 @@ pub enum SpecId { LATEST = u8::MAX, } +/// Specification IDs and their activation block of BSC. +#[cfg(feature = "bsc")] +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, enumn::N)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum SpecId { + FRONTIER = 0, + FRONTIER_THAWING = 1, + HOMESTEAD = 2, // Homestead 0 + TANGERINE = 3, // Tangerine Whistle(EIP150) 0 + SPURIOUS_DRAGON = 4, // Spurious Dragon(EIP155, EIP158) 0 + BYZANTIUM = 5, // Byzantium 0 + CONSTANTINOPLE = 6, // Constantinople 0 + PETERSBURG = 7, // Petersburg 0 + ISTANBUL = 8, // Istanbul 0 + MUIR_GLACIER = 9, // Muir Glacier 0 + RAMANUJAN = 10, // Ramanujan 0 + NIELS = 11, // Niels 0 + MIRROR_SYNC = 12, // Mirror Sync 5184000 + BRUNO = 13, // Bruno 13082000 + EULER = 14, // Euler 18907621 + NANO = 15, // Nano 21962149 + MORAN = 16, // Moran 22107423 + GIBBS = 17, // Gibbs 23846001 + PLANCK = 18, // Planck 27281024 + LUBAN = 19, // Luban 29020050 + PLATO = 20, // Plato 30720096 + BERLIN = 21, // Berlin 31302048 + LONDON = 22, // London 31302048 + HERTZ = 23, // Hertz 31302048 + HERTZ_FIX = 24, // HertzFix 34140700 + SHANGHAI = 25, // Shanghai timestamp(1705996800) + KEPLER = 26, // Kepler timestamp(1705996800) + FEYNMAN = 27, // Feynman timestamp(1713419340) + FEYNMAN_FIX = 28, // FeynmanFix timestamp(1713419340) + CANCUN = 29, // Cancun timestamp(1718863500) + HABER = 30, // Haber timestamp(1718863500) + + // TODO: or u8::MAX - n? + /// Not enabled in bsc + DAO_FORK = 31, + ARROW_GLACIER = 32, + GRAY_GLACIER = 33, + MERGE = 34, + PRAGUE = 35, + + #[default] + LATEST = u8::MAX, +} + impl SpecId { /// Returns the `SpecId` for the given `u8`. #[inline] @@ -121,7 +174,39 @@ impl From<&str> for SpecId { "Ecotone" => SpecId::ECOTONE, #[cfg(feature = "optimism")] "Fjord" => SpecId::FJORD, - #[cfg(feature = "opbnb")] + #[cfg(feature = "bsc")] + "Ramanujan" => SpecId::RAMANUJAN, + #[cfg(feature = "bsc")] + "Niels" => SpecId::NIELS, + #[cfg(feature = "bsc")] + "MirrorSync" => SpecId::MIRROR_SYNC, + #[cfg(feature = "bsc")] + "Bruno" => SpecId::BRUNO, + #[cfg(feature = "bsc")] + "Euler" => SpecId::EULER, + #[cfg(feature = "bsc")] + "Nano" => SpecId::NANO, + #[cfg(feature = "bsc")] + "Moran" => SpecId::MORAN, + #[cfg(feature = "bsc")] + "Gibbs" => SpecId::GIBBS, + #[cfg(feature = "bsc")] + "Planck" => SpecId::PLANCK, + #[cfg(feature = "bsc")] + "Luban" => SpecId::LUBAN, + #[cfg(feature = "bsc")] + "Plato" => SpecId::PLATO, + #[cfg(feature = "bsc")] + "Hertz" => SpecId::HERTZ, + #[cfg(feature = "bsc")] + "HertzFix" => SpecId::HERTZ_FIX, + #[cfg(feature = "bsc")] + "Kepler" => SpecId::KEPLER, + #[cfg(feature = "bsc")] + "Feynman" => SpecId::FEYNMAN, + #[cfg(feature = "bsc")] + "FeynmanFix" => SpecId::FEYNMAN_FIX, + #[cfg(any(feature = "opbnb", feature = "bsc"))] "Haber" => SpecId::HABER, _ => Self::LATEST, } @@ -156,14 +241,46 @@ impl From for &'static str { SpecId::REGOLITH => "Regolith", #[cfg(feature = "opbnb")] SpecId::FERMAT => "Fermat", - #[cfg(feature = "opbnb")] - SpecId::HABER => "Haber", #[cfg(feature = "optimism")] SpecId::CANYON => "Canyon", #[cfg(feature = "optimism")] SpecId::ECOTONE => "Ecotone", #[cfg(feature = "optimism")] SpecId::FJORD => "Fjord", + #[cfg(feature = "bsc")] + SpecId::RAMANUJAN => "Ramanujan", + #[cfg(feature = "bsc")] + SpecId::NIELS => "Niels", + #[cfg(feature = "bsc")] + SpecId::MIRROR_SYNC => "MirrorSync", + #[cfg(feature = "bsc")] + SpecId::BRUNO => "Bruno", + #[cfg(feature = "bsc")] + SpecId::EULER => "Euler", + #[cfg(feature = "bsc")] + SpecId::NANO => "Nano", + #[cfg(feature = "bsc")] + SpecId::MORAN => "Moran", + #[cfg(feature = "bsc")] + SpecId::GIBBS => "Gibbs", + #[cfg(feature = "bsc")] + SpecId::PLANCK => "Planck", + #[cfg(feature = "bsc")] + SpecId::LUBAN => "Luban", + #[cfg(feature = "bsc")] + SpecId::PLATO => "Plato", + #[cfg(feature = "bsc")] + SpecId::HERTZ => "Hertz", + #[cfg(feature = "bsc")] + SpecId::HERTZ_FIX => "HertzFix", + #[cfg(feature = "bsc")] + SpecId::KEPLER => "Kepler", + #[cfg(feature = "bsc")] + SpecId::FEYNMAN => "Feynman", + #[cfg(feature = "bsc")] + SpecId::FEYNMAN_FIX => "FeynmanFix", + #[cfg(any(feature = "opbnb", feature = "bsc"))] + SpecId::HABER => "Haber", SpecId::LATEST => "Latest", } } @@ -213,6 +330,26 @@ spec!(PRAGUE, PragueSpec); spec!(LATEST, LatestSpec); +// BSC Hardforks +#[cfg(feature = "bsc")] +spec!(NANO, NanoSpec); +#[cfg(feature = "bsc")] +spec!(MORAN, MoranSpec); +#[cfg(feature = "bsc")] +spec!(PLANCK, PlanckSpec); +#[cfg(feature = "bsc")] +spec!(LUBAN, LubanSpec); +#[cfg(feature = "bsc")] +spec!(PLATO, PlatoSpec); +#[cfg(feature = "bsc")] +spec!(HERTZ, HertzSpec); +#[cfg(feature = "bsc")] +spec!(KEPLER, KeplerSpec); +#[cfg(feature = "bsc")] +spec!(FEYNMAN, FeynmanSpec); +#[cfg(any(feature = "bsc", feature = "opbnb"))] +spec!(HABER, HaberSpec); + // Optimism Hardforks #[cfg(feature = "optimism")] spec!(BEDROCK, BedrockSpec); @@ -226,10 +363,8 @@ spec!(ECOTONE, EcotoneSpec); spec!(FJORD, FjordSpec); #[cfg(feature = "opbnb")] spec!(FERMAT, FermatSpec); -#[cfg(feature = "opbnb")] -spec!(HABER, HaberSpec); -#[cfg(not(feature = "optimism"))] +#[cfg(all(not(feature = "optimism"), not(feature = "bsc")))] #[macro_export] macro_rules! spec_to_generic { ($spec_id:expr, $e:expr) => {{ @@ -393,6 +528,115 @@ macro_rules! spec_to_generic { }}; } +#[cfg(feature = "bsc")] +#[macro_export] +macro_rules! spec_to_generic { + ($spec_id:expr, $e:expr) => {{ + match $spec_id { + $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { + use $crate::FrontierSpec as SPEC; + $e + } + $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => { + use $crate::HomesteadSpec as SPEC; + $e + } + $crate::SpecId::TANGERINE => { + use $crate::TangerineSpec as SPEC; + $e + } + $crate::SpecId::SPURIOUS_DRAGON => { + use $crate::SpuriousDragonSpec as SPEC; + $e + } + $crate::SpecId::BYZANTIUM => { + use $crate::ByzantiumSpec as SPEC; + $e + } + $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => { + use $crate::PetersburgSpec as SPEC; + $e + } + $crate::SpecId::ISTANBUL + | $crate::SpecId::MUIR_GLACIER + | $crate::SpecId::RAMANUJAN + | $crate::SpecId::NIELS + | $crate::SpecId::MIRROR_SYNC + | $crate::SpecId::BRUNO + | $crate::SpecId::EULER => { + use $crate::IstanbulSpec as SPEC; + $e + } + $crate::SpecId::NANO => { + use $crate::NanoSpec as SPEC; + $e + } + $crate::SpecId::MORAN | $crate::SpecId::GIBBS => { + use $crate::MoranSpec as SPEC; + $e + } + $crate::SpecId::PLANCK => { + use $crate::PlanckSpec as SPEC; + $e + } + $crate::SpecId::LUBAN => { + use $crate::LubanSpec as SPEC; + $e + } + $crate::SpecId::PLATO => { + use $crate::PlatoSpec as SPEC; + $e + } + $crate::SpecId::BERLIN => { + use $crate::BerlinSpec as SPEC; + $e + } + $crate::SpecId::LONDON + | $crate::SpecId::ARROW_GLACIER + | $crate::SpecId::GRAY_GLACIER => { + use $crate::LondonSpec as SPEC; + $e + } + $crate::SpecId::MERGE => { + use $crate::MergeSpec as SPEC; + $e + } + $crate::SpecId::HERTZ | $crate::SpecId::HERTZ_FIX => { + use $crate::HertzSpec as SPEC; + $e + } + $crate::SpecId::SHANGHAI => { + use $crate::ShanghaiSpec as SPEC; + $e + } + $crate::SpecId::KEPLER => { + use $crate::KeplerSpec as SPEC; + $e + } + $crate::SpecId::FEYNMAN | $crate::SpecId::FEYNMAN_FIX => { + use $crate::FeynmanSpec as SPEC; + $e + } + $crate::SpecId::CANCUN => { + use $crate::CancunSpec as SPEC; + $e + } + $crate::SpecId::PRAGUE => { + use $crate::PragueSpec as SPEC; + $e + } + $crate::SpecId::HABER => { + use $crate::HaberSpec as SPEC; + $e + } + $crate::SpecId::LATEST => { + use $crate::LatestSpec as SPEC; + $e + } + } + }}; +} + #[cfg(test)] mod tests { use super::*; @@ -404,6 +648,7 @@ mod tests { spec_to_generic!(FRONTIER, assert_eq!(SPEC::SPEC_ID, FRONTIER)); spec_to_generic!(FRONTIER_THAWING, assert_eq!(SPEC::SPEC_ID, FRONTIER)); spec_to_generic!(HOMESTEAD, assert_eq!(SPEC::SPEC_ID, HOMESTEAD)); + #[cfg(not(feature = "bsc"))] spec_to_generic!(DAO_FORK, assert_eq!(SPEC::SPEC_ID, HOMESTEAD)); spec_to_generic!(TANGERINE, assert_eq!(SPEC::SPEC_ID, TANGERINE)); spec_to_generic!(SPURIOUS_DRAGON, assert_eq!(SPEC::SPEC_ID, SPURIOUS_DRAGON)); @@ -414,23 +659,68 @@ mod tests { spec_to_generic!(MUIR_GLACIER, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); spec_to_generic!(BERLIN, assert_eq!(SPEC::SPEC_ID, BERLIN)); spec_to_generic!(LONDON, assert_eq!(SPEC::SPEC_ID, LONDON)); + #[cfg(not(feature = "bsc"))] spec_to_generic!(ARROW_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); + #[cfg(not(feature = "bsc"))] spec_to_generic!(GRAY_GLACIER, assert_eq!(SPEC::SPEC_ID, LONDON)); + #[cfg(not(feature = "bsc"))] spec_to_generic!(MERGE, assert_eq!(SPEC::SPEC_ID, MERGE)); #[cfg(feature = "optimism")] spec_to_generic!(BEDROCK, assert_eq!(SPEC::SPEC_ID, BEDROCK)); #[cfg(feature = "optimism")] spec_to_generic!(REGOLITH, assert_eq!(SPEC::SPEC_ID, REGOLITH)); + #[cfg(feature = "opbnb")] + spec_to_generic!(FERMAT, assert_eq!(SPEC::SPEC_ID, FERMAT)); spec_to_generic!(SHANGHAI, assert_eq!(SPEC::SPEC_ID, SHANGHAI)); #[cfg(feature = "optimism")] spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON)); + #[cfg(feature = "optimism")] + spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE)); spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN)); #[cfg(feature = "optimism")] spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE)); #[cfg(feature = "optimism")] spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD)); + #[cfg(not(feature = "bsc"))] spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); + #[cfg(any(feature = "bsc", feature = "opbnb"))] + spec_to_generic!(HABER, assert_eq!(SPEC::SPEC_ID, HABER)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); + + #[cfg(feature = "bsc")] + spec_to_generic!(RAMANUJAN, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + #[cfg(feature = "bsc")] + spec_to_generic!(NIELS, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + #[cfg(feature = "bsc")] + spec_to_generic!(MIRROR_SYNC, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + #[cfg(feature = "bsc")] + spec_to_generic!(BRUNO, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + #[cfg(feature = "bsc")] + spec_to_generic!(EULER, assert_eq!(SPEC::SPEC_ID, ISTANBUL)); + #[cfg(feature = "bsc")] + spec_to_generic!(NANO, assert_eq!(SPEC::SPEC_ID, NANO)); + #[cfg(feature = "bsc")] + spec_to_generic!(MORAN, assert_eq!(SPEC::SPEC_ID, MORAN)); + #[cfg(feature = "bsc")] + spec_to_generic!(GIBBS, assert_eq!(SPEC::SPEC_ID, MORAN)); + #[cfg(feature = "bsc")] + spec_to_generic!(PLANCK, assert_eq!(SPEC::SPEC_ID, PLANCK)); + #[cfg(feature = "bsc")] + spec_to_generic!(LUBAN, assert_eq!(SPEC::SPEC_ID, LUBAN)); + #[cfg(feature = "bsc")] + spec_to_generic!(PLATO, assert_eq!(SPEC::SPEC_ID, PLATO)); + #[cfg(feature = "bsc")] + spec_to_generic!(HERTZ, assert_eq!(SPEC::SPEC_ID, HERTZ)); + #[cfg(feature = "bsc")] + spec_to_generic!(HERTZ_FIX, assert_eq!(SPEC::SPEC_ID, HERTZ)); + #[cfg(feature = "bsc")] + spec_to_generic!(KEPLER, assert_eq!(SPEC::SPEC_ID, KEPLER)); + #[cfg(feature = "bsc")] + spec_to_generic!(FEYNMAN, assert_eq!(SPEC::SPEC_ID, FEYNMAN)); + #[cfg(feature = "bsc")] + spec_to_generic!(FEYNMAN_FIX, assert_eq!(SPEC::SPEC_ID, FEYNMAN)); + #[cfg(feature = "bsc")] + spec_to_generic!(HABER, assert_eq!(SPEC::SPEC_ID, HABER)); } } diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index aaddcb58..55a048a3 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -88,6 +88,7 @@ portable = ["revm-precompile/portable", "revm-interpreter/portable"] test-utils = [] +bsc = ["revm-interpreter/bsc", "revm-precompile/bsc"] optimism = ["revm-interpreter/optimism", "revm-precompile/optimism"] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = [ diff --git a/crates/revm/src/bsc.rs b/crates/revm/src/bsc.rs new file mode 100644 index 00000000..980d2e85 --- /dev/null +++ b/crates/revm/src/bsc.rs @@ -0,0 +1,7 @@ +//! Optimism-specific constants, types, and helpers. + +mod handler_register; + +pub use handler_register::{ + bsc_handle_register, collect_system_reward, output, validate_initial_tx_gas, SYSTEM_ADDRESS, +}; diff --git a/crates/revm/src/bsc/handler_register.rs b/crates/revm/src/bsc/handler_register.rs new file mode 100644 index 00000000..3100f9ba --- /dev/null +++ b/crates/revm/src/bsc/handler_register.rs @@ -0,0 +1,136 @@ +//! Handler related to BNB-Smart-chain + +use crate::{ + handler::register::EvmHandler, + interpreter::Gas, + primitives::{ + address, db::Database, spec_to_generic, Address, EVMError, Env, ExecutionResult, + InvalidTransaction, ResultAndState, Spec, SpecId, CANCUN, U256, + }, + Context, FrameResult, +}; +use revm_interpreter::{gas, SuccessOrHalt}; +use std::sync::Arc; + +pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe"); + +pub fn bsc_handle_register(handler: &mut EvmHandler<'_, EXT, DB>) { + spec_to_generic!(handler.cfg.spec_id, { + handler.validation.initial_tx_gas = Arc::new(validate_initial_tx_gas::); + handler.post_execution.reward_beneficiary = + Arc::new(collect_system_reward::); + handler.post_execution.output = Arc::new(output::); + }); +} + +/// Validate initial transaction gas. +pub fn validate_initial_tx_gas( + env: &Env, +) -> Result> { + // no initial gas for system transactions + if env.tx.bsc.is_system_transaction.unwrap_or(false) { + return Ok(0); + } + + let input = &env.tx.data; + let is_create = env.tx.transact_to.is_create(); + let access_list = &env.tx.access_list; + + let initial_gas_spend = + gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list); + + // Additional check to see if limit is big enough to cover initial gas. + if initial_gas_spend > env.tx.gas_limit { + return Err(InvalidTransaction::CallGasCostMoreThanGasLimit.into()); + } + Ok(initial_gas_spend) +} + +/// Collect gas fee to system account. +#[inline] +pub fn collect_system_reward( + context: &mut Context, + gas: &Gas, +) -> Result<(), EVMError> { + let effective_gas_price = context.evm.env.effective_gas_price(); + let mut tx_fee = U256::from(gas.spent() - gas.refunded() as u64) * effective_gas_price; + + // EIP-4844 + if SPEC::enabled(CANCUN) { + let data_fee = &context + .evm + .inner + .env + .calc_data_fee() + .expect("already checked"); + tx_fee = tx_fee.saturating_add(*data_fee); + } + + let (system_account, _) = context + .evm + .inner + .journaled_state + .load_account(SYSTEM_ADDRESS, &mut context.evm.inner.db)?; + + system_account.mark_touch(); + system_account.info.balance = system_account.info.balance.saturating_add(tx_fee); + + Ok(()) +} + +/// Main return handle, returns the output of the transaction. +#[inline] +pub fn output( + context: &mut Context, + result: FrameResult, +) -> Result> { + core::mem::replace(&mut context.evm.error, Ok(()))?; + // used gas with refund calculated. + let gas_refunded = if context + .evm + .env + .tx + .bsc + .is_system_transaction + .unwrap_or(false) + { + 0 + } else { + result.gas().refunded() as u64 + }; + let final_gas_used = result.gas().spent() - gas_refunded; + let output = result.output(); + let instruction_result = result.into_interpreter_result(); + + // reset journal and return present state. + let (state, logs) = context.evm.journaled_state.finalize(); + + let result = match instruction_result.result.into() { + SuccessOrHalt::Success(reason) => ExecutionResult::Success { + reason, + gas_used: final_gas_used, + gas_refunded, + logs, + output, + }, + SuccessOrHalt::Revert => ExecutionResult::Revert { + gas_used: final_gas_used, + output: output.into_data(), + }, + SuccessOrHalt::Halt(reason) => ExecutionResult::Halt { + reason, + gas_used: final_gas_used, + }, + // Only two internal return flags. + flag @ (SuccessOrHalt::FatalExternalError + | SuccessOrHalt::InternalContinue + | SuccessOrHalt::InternalCallOrCreate) => { + panic!( + "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", + flag, instruction_result + ) + } + }; + + Ok(ResultAndState { result, state }) +} diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 4b2a81ec..d15ed12c 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -168,6 +168,17 @@ impl<'a, EXT, DB: Database> EvmBuilder<'a, SetGenericStage, EXT, DB> { } } + /// Sets the Bsc handler with latest spec. + #[cfg(feature = "bsc")] + pub fn bsc(mut self) -> EvmBuilder<'a, HandlerStage, EXT, DB> { + self.handler = Handler::bsc_with_spec(self.handler.cfg.spec_id); + EvmBuilder { + context: self.context, + handler: self.handler, + phantom: PhantomData, + } + } + /// Sets the mainnet handler with latest spec. /// /// Enabled only with `optimism-default-handler` feature. diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index b92d711d..85a3d7e9 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -128,10 +128,17 @@ impl EvmContext { } } Err(e) => { - result.result = if e == crate::precompile::Error::OutOfGas { - InstructionResult::PrecompileOOG - } else { - InstructionResult::PrecompileError + result.result = match e { + crate::precompile::Error::OutOfGas => InstructionResult::PrecompileOOG, + // for BSC compatibility + crate::precompile::Error::Reverted(gas_used) => { + if result.gas.record_cost(gas_used) { + InstructionResult::Revert + } else { + InstructionResult::PrecompileOOG + } + } + _ => InstructionResult::PrecompileError, }; } } diff --git a/crates/revm/src/handler.rs b/crates/revm/src/handler.rs index fab20b12..66f2561b 100644 --- a/crates/revm/src/handler.rs +++ b/crates/revm/src/handler.rs @@ -43,6 +43,7 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { /// /// Internally it calls `mainnet_with_spec` with the given spec id. /// Or `optimism_with_spec` if the optimism feature is enabled and `cfg.is_optimism` is set. + /// Or `bsc_with_spec` if the bsc feature is enabled and `cfg.is_bsc` is set. pub fn new(cfg: HandlerCfg) -> Self { cfg_if::cfg_if! { if #[cfg(feature = "optimism")] { @@ -51,6 +52,8 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { } else { Handler::mainnet_with_spec(cfg.spec_id) } + } else if #[cfg(feature = "bsc")] { + Handler::bsc_with_spec(cfg.spec_id) } else { Handler::mainnet_with_spec(cfg.spec_id) } @@ -70,6 +73,12 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { } } + /// Creates handler with variable spec id, inside it will call `mainnet::` for + /// appropriate spec. + pub fn mainnet_with_spec(spec_id: SpecId) -> Self { + spec_to_generic!(spec_id, Self::mainnet::()) + } + /// Returns `true` if the optimism feature is enabled and flag is set to `true`. pub fn is_optimism(&self) -> bool { self.cfg.is_optimism() @@ -92,10 +101,26 @@ impl<'a, EXT, DB: Database> EvmHandler<'a, EXT, DB> { spec_to_generic!(spec_id, Self::optimism::()) } - /// Creates handler with variable spec id, inside it will call `mainnet::` for - /// appropriate spec. - pub fn mainnet_with_spec(spec_id: SpecId) -> Self { - spec_to_generic!(spec_id, Self::mainnet::()) + /// Returns `true` if the bsc feature is enabled and flag is set to `true`. + pub fn is_bsc(&self) -> bool { + self.cfg.is_bsc() + } + + /// Handler for bsc + #[cfg(feature = "bsc")] + pub fn bsc() -> Self { + let mut handler = Self::mainnet::(); + handler.cfg.is_bsc = true; + handler.append_handler_register(HandleRegisters::Plain( + crate::bsc::bsc_handle_register::, + )); + handler + } + + /// Bsc with spec. Similar to [`Self::mainnet_with_spec`]. + #[cfg(feature = "bsc")] + pub fn bsc_with_spec(spec_id: SpecId) -> Self { + spec_to_generic!(spec_id, Self::bsc::()) } /// Specification ID. diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 6b69b5bd..b63c311f 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -14,6 +14,8 @@ mod context; #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; +#[cfg(feature = "bsc")] +pub mod bsc; pub mod db; mod evm; mod frame; diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 6ce298b5..d4996cca 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -145,7 +145,7 @@ pub fn last_frame_return( pub fn load_precompiles() -> ContextPrecompiles { let mut precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)).clone(); - if SPEC::enabled(SpecId::FJORD) || SPEC::enabled(SpecId::HABER) { + if SPEC::enabled(SpecId::FJORD) { precompiles.extend([ // EIP-7212: secp256r1 P256verify secp256r1::P256VERIFY,