From 29043d9f3ab3582da5f544f3390ee49b8cf83485 Mon Sep 17 00:00:00 2001 From: Vladimir Stepanenko Date: Fri, 30 Dec 2022 10:55:48 +0300 Subject: [PATCH] Add beacon primitives --- Cargo.lock | 201 ++------- Cargo.toml | 3 + pallets/leaf-provider/Cargo.toml | 5 - pallets/types/Cargo.toml | 18 +- pallets/types/src/lib.rs | 35 +- pallets/types/src/types.rs | 4 +- primitives/ethereum/Cargo.toml | 67 +++ primitives/ethereum/src/beacon/config.rs | 229 ++++++++++ primitives/ethereum/src/beacon/mod.rs | 401 ++++++++++++++++++ .../ethereum}/src/difficulty.rs | 0 .../ethereum}/src/ethashdata.rs | 0 .../ethereum}/src/ethashproof.rs | 0 .../ethereum}/src/header.rs | 0 primitives/ethereum/src/lib.rs | 36 ++ .../types => primitives/ethereum}/src/log.rs | 0 .../types => primitives/ethereum}/src/mpt.rs | 0 .../ethereum}/src/network_config.rs | 55 ++- .../ethereum}/src/receipt.rs | 0 primitives/ethereum/src/serde_utils.rs | 80 ++++ .../ethereum}/src/test_utils.rs | 5 +- .../ethereum}/tests/fixtures/11090290.json | 0 .../ethereum}/tests/fixtures/11550000.json | 0 .../ethereum}/tests/fixtures/3.json | 0 .../tests/difficultyArrowGlacier.json | 0 .../difficultyArrowGlacierForkBlock.json | 0 .../tests/difficultyArrowGlacierMinus1.json | 0 .../difficultyArrowGlacierTimeDiff1.json | 0 .../difficultyArrowGlacierTimeDiff2.json | 0 .../fixtures/tests/difficultyByzantium.json | 0 .../tests/difficultyConstantinople.json | 0 .../fixtures/tests/difficultyEIP2384.json | 0 .../tests/difficultyEIP2384_random.json | 0 .../tests/difficultyEIP2384_random_to20M.json | 0 .../fixtures/tests/difficultyFrontier.json | 0 .../fixtures/tests/difficultyGrayGlacier.json | 0 .../tests/difficultyGrayGlacierForkBlock.json | 0 .../tests/difficultyGrayGlacierMinus1.json | 0 .../tests/difficultyGrayGlacierTimeDiff1.json | 0 .../tests/difficultyGrayGlacierTimeDiff2.json | 0 .../fixtures/tests/difficultyHomestead.json | 0 .../fixtures/tests/difficultyMainNetwork.json | 0 .../fixtures/tests/difficultyRopsten.json | 0 42 files changed, 915 insertions(+), 224 deletions(-) create mode 100644 primitives/ethereum/Cargo.toml create mode 100644 primitives/ethereum/src/beacon/config.rs create mode 100644 primitives/ethereum/src/beacon/mod.rs rename {pallets/types => primitives/ethereum}/src/difficulty.rs (100%) rename {pallets/types => primitives/ethereum}/src/ethashdata.rs (100%) rename {pallets/types => primitives/ethereum}/src/ethashproof.rs (100%) rename {pallets/types => primitives/ethereum}/src/header.rs (100%) create mode 100644 primitives/ethereum/src/lib.rs rename {pallets/types => primitives/ethereum}/src/log.rs (100%) rename {pallets/types => primitives/ethereum}/src/mpt.rs (100%) rename {pallets/types => primitives/ethereum}/src/network_config.rs (70%) rename {pallets/types => primitives/ethereum}/src/receipt.rs (100%) create mode 100644 primitives/ethereum/src/serde_utils.rs rename {pallets/types => primitives/ethereum}/src/test_utils.rs (97%) rename {pallets/types => primitives/ethereum}/tests/fixtures/11090290.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/11550000.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/3.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyArrowGlacier.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyArrowGlacierForkBlock.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyArrowGlacierMinus1.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyArrowGlacierTimeDiff1.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyArrowGlacierTimeDiff2.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyByzantium.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyConstantinople.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyEIP2384.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyEIP2384_random.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyEIP2384_random_to20M.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyFrontier.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyGrayGlacier.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyGrayGlacierForkBlock.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyGrayGlacierMinus1.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyGrayGlacierTimeDiff1.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyGrayGlacierTimeDiff2.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyHomestead.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyMainNetwork.json (100%) rename {pallets/types => primitives/ethereum}/tests/fixtures/tests/difficultyRopsten.json (100%) diff --git a/Cargo.lock b/Cargo.lock index 9397492c..b7bb60e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -129,7 +129,7 @@ checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -339,21 +339,18 @@ name = "bridge-types" version = "0.1.0" dependencies = [ "beefy-primitives", - "enum-iterator", "ethabi", - "ethash", "ethbloom", + "ethereum-primitives", "ethereum-types", "frame-support", "frame-system", "getrandom 0.2.8", - "hex-literal", + "hex", "libsecp256k1", - "parity-bytes", "parity-scale-codec", "rand 0.7.3", "rlp", - "rustc-hex", "scale-info", "serde", "serde_json", @@ -361,7 +358,6 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", - "wasm-bindgen-test", "xcm", ] @@ -419,12 +415,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -443,15 +433,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ckb-merkle-mountain-range" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f061f97d64fd1822664bdfb722f7ae5469a97b77567390f7442be5b5dc82a5b" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -468,7 +449,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen", ] @@ -773,26 +754,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "enum-iterator" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "environmental" version = "1.1.4" @@ -837,6 +798,33 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "ethereum-primitives" +version = "0.1.0" +dependencies = [ + "ethabi", + "ethash", + "ethbloom", + "ethereum-types", + "frame-support", + "getrandom 0.2.8", + "hex", + "hex-literal", + "libsecp256k1", + "parity-bytes", + "parity-scale-codec", + "rand 0.7.3", + "rlp", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "wasm-bindgen-test", +] + [[package]] name = "ethereum-types" version = "0.14.1" @@ -916,7 +904,7 @@ version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "parity-scale-codec", "scale-info", "serde", @@ -1135,7 +1123,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", @@ -1148,7 +1136,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -1562,7 +1550,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19c3a5e0a0b8450278feda242592512e09f61c72e018b8cd5c859482802daf2d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "sec1", @@ -1597,7 +1585,6 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" name = "leaf-provider" version = "0.1.1" dependencies = [ - "beefy-merkle-tree", "beefy-primitives", "bridge-types", "ethabi", @@ -1605,8 +1592,6 @@ dependencies = [ "frame-support", "frame-system", "hex-literal", - "pallet-beefy-mmr", - "pallet-mmr", "parity-scale-codec", "scale-info", "serde", @@ -1743,7 +1728,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -2042,84 +2027,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-beefy" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "beefy-primitives", - "frame-support", - "frame-system", - "pallet-session", - "parity-scale-codec", - "scale-info", - "serde", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-beefy-mmr" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "array-bytes", - "beefy-merkle-tree", - "beefy-primitives", - "frame-support", - "frame-system", - "log", - "pallet-beefy", - "pallet-mmr", - "pallet-session", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-mmr" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "ckb-merkle-mountain-range", - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-mmr-primitives", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-session" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "frame-support", - "frame-system", - "impl-trait-for-tuples", - "log", - "pallet-timestamp", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-session", - "sp-staking", - "sp-std", - "sp-trie", -] - [[package]] name = "pallet-timestamp" version = "4.0.0-dev" @@ -2177,7 +2084,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown", "impl-trait-for-tuples", "parity-util-mem-derive", @@ -2219,7 +2126,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -2582,7 +2489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d8a765117b237ef233705cc2cc4c6a27fccd46eea6ef0c8c6dae5f3ef407f8" dependencies = [ "bitvec", - "cfg-if 1.0.0", + "cfg-if", "derive_more", "parity-scale-codec", "scale-info-derive", @@ -2715,7 +2622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2740,7 +2647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2752,7 +2659,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.6", ] @@ -3200,20 +3107,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sp-session" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.31#7a4e5163091384c4c10b6d76f5cb80dac0834f38" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-api", - "sp-core", - "sp-runtime", - "sp-staking", - "sp-std", -] - [[package]] name = "sp-staking" version = "4.0.0-dev" @@ -3586,7 +3479,7 @@ version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e45b7bf6e19353ddd832745c8fcf77a17a93171df7151187f26623f2b75b5b26" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "proc-macro-error", "proc-macro2", "quote", @@ -3741,7 +3634,7 @@ version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3861,7 +3754,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "digest 0.10.6", "rand 0.8.5", "static_assertions", @@ -3961,7 +3854,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -3986,7 +3879,7 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", diff --git a/Cargo.toml b/Cargo.toml index 872ae1d3..5cb54b67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,7 @@ members = [ "pallets/substrate-channel/rpc", "pallets/beefy-light-client/runtime-api", "pallets/beefy-light-client/rpc", + "primitives/*", ] + +resolver = "2" diff --git a/pallets/leaf-provider/Cargo.toml b/pallets/leaf-provider/Cargo.toml index b3ef5219..dd2fd98a 100644 --- a/pallets/leaf-provider/Cargo.toml +++ b/pallets/leaf-provider/Cargo.toml @@ -25,9 +25,6 @@ sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkado sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } sp-mmr-primitives = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } -pallet-mmr = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } -pallet-beefy-mmr = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } -beefy-merkle-tree = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } beefy-primitives = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } bridge-types = { path = "../types", default-features = false } @@ -51,8 +48,6 @@ std = [ "sp-std/std", "bridge-types/std", "sp-mmr-primitives/std", - "pallet-mmr/std", - "pallet-beefy-mmr/std", ] runtime-benchmarks = [ "bridge-types/runtime-benchmarks", diff --git a/pallets/types/Cargo.toml b/pallets/types/Cargo.toml index d6802ca8..51e30a2c 100644 --- a/pallets/types/Cargo.toml +++ b/pallets/types/Cargo.toml @@ -5,7 +5,6 @@ authors = ["Snowfork "] edition = "2021" [dependencies] -enum-iterator = "0.6.0" codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ "derive", ] } @@ -19,13 +18,11 @@ ethereum-types = { version = "0.14.1", default-features = false, features = [ "rlp", "serialize", ] } -hex = { package = "rustc-hex", version = "2.1.0", default-features = false } -hex-literal = { version = "0.3.1", default-features = false } +hex = { version = "0.4", default-features = false } libsecp256k1 = { version = "0.7", default-features = false } -parity-bytes = { version = "0.1.2", default-features = false } rlp = { version = "0.5", default-features = false } -serde = { version = "1.0.101", optional = true } -getrandom = { version = "0.2.1", features = ["js"] } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +getrandom = { version = "0.2.8", features = ["js"], default-features = false } frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } frame-system = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } @@ -36,12 +33,12 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "po beefy-primitives = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } ethabi = { git = "https://github.com/sora-xor/ethabi.git", branch = "sora-v1.6.0", default-features = false } -ethash = { git = "https://github.com/sora-xor/ethash.git", branch = "sora-v1.6.0", default-features = false } serde_json = { version = "1.0", optional = true } xcm = { git = "https://github.com/paritytech/polkadot.git", branch = "release-v0.9.31", default-features = false } +ethereum-primitives = { path = "../../primitives/ethereum", default-features = false } + [dev-dependencies] -wasm-bindgen-test = "0.3.19" rand = "0.7.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -59,14 +56,17 @@ std = [ "ethereum-types/std", "hex/std", "libsecp256k1/std", - "parity-bytes/std", "rlp/std", + "frame-support/std", + "frame-system/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", "beefy-primitives/std", + "ethereum-primitives/std", "xcm/std", + "getrandom/std", ] runtime-benchmarks = [ diff --git a/pallets/types/src/lib.rs b/pallets/types/src/lib.rs index 98499fe0..7c2c735d 100644 --- a/pallets/types/src/lib.rs +++ b/pallets/types/src/lib.rs @@ -31,30 +31,16 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod channel_abi; -pub mod difficulty; -pub mod ethashdata; -pub mod ethashproof; -pub mod header; -pub mod log; -mod mpt; -pub mod network_config; -pub mod receipt; pub mod substrate; pub mod traits; pub mod types; -#[cfg(any(feature = "test", test))] -pub mod test_utils; - +#[cfg(feature = "std")] +use ::serde::{Deserialize, Serialize}; use codec::{Decode, Encode}; -pub use ethereum_types::{Address, H128, H160, H256, H512, H64, U256}; use frame_support::RuntimeDebug; -use sp_std::vec; -use sp_std::vec::Vec; -pub use header::{Header, HeaderId}; -pub use log::Log; -pub use receipt::Receipt; +pub use ethereum_primitives::*; #[derive(Debug)] pub enum DecodeError { @@ -91,7 +77,7 @@ pub type EVMChainId = U256; scale_info::TypeInfo, codec::MaxEncodedLen, )] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum SubNetworkId { Mainnet, Kusama, @@ -111,7 +97,7 @@ pub enum SubNetworkId { scale_info::TypeInfo, codec::MaxEncodedLen, )] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum GenericNetworkId { EVM(EVMChainId), Sub(SubNetworkId), @@ -139,14 +125,3 @@ pub enum GenericAccount { } pub const CHANNEL_INDEXING_PREFIX: &[u8] = b"commitment"; - -pub fn import_digest(network_id: &EVMChainId, header: &Header) -> Vec -where - EVMChainId: Encode, - Header: Encode, -{ - let mut digest = vec![]; - network_id.encode_to(&mut digest); - header.encode_to(&mut digest); - digest -} diff --git a/pallets/types/src/types.rs b/pallets/types/src/types.rs index 98356372..87a3befe 100644 --- a/pallets/types/src/types.rs +++ b/pallets/types/src/types.rs @@ -89,7 +89,7 @@ pub struct Message { /// A message relayed from Parachain. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ParachainMessage { pub payload: Vec, pub nonce: MessageNonce, @@ -132,7 +132,7 @@ impl From for AuxiliaryDigest { /// Auxiliary [`DigestItem`] to include in header digest. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, scale_info::TypeInfo)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum AuxiliaryDigestItem { /// A batch of messages has been committed. Commitment(GenericNetworkId, H256), diff --git a/primitives/ethereum/Cargo.toml b/primitives/ethereum/Cargo.toml new file mode 100644 index 00000000..197c7b2a --- /dev/null +++ b/primitives/ethereum/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "ethereum-primitives" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "3", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2", default-features = false, features = ["derive"] } +ethbloom = { version = "0.13.0", default-features = false, features = [ + "rlp", + "codec", +] } +ethereum-types = { version = "0.14.1", default-features = false, features = [ + "codec", + "rlp", + "serialize", +] } +hex = { version = "0.4", default-features = false } +hex-literal = { version = "0.3.1", default-features = false } +libsecp256k1 = { version = "0.7", default-features = false } +parity-bytes = { version = "0.1.2", default-features = false } +rlp = { version = "0.5", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +getrandom = { version = "0.2.1", features = ["js"] } + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.31", default-features = false } + +ethabi = { git = "https://github.com/sora-xor/ethabi.git", branch = "sora-v1.6.0", default-features = false } +ethash = { git = "https://github.com/sora-xor/ethash.git", branch = "sora-v1.6.0", default-features = false } +serde_json = { version = "1.0", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.19" +rand = "0.7.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[features] +default = ["std"] +expensive_tests = [] +test = ["serde_json"] +std = [ + "serde", + "codec/std", + "scale-info/std", + "ethabi/std", + "ethbloom/std", + "ethereum-types/std", + "hex/std", + "libsecp256k1/std", + "parity-bytes/std", + "rlp/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] + +runtime-benchmarks = ["frame-support/runtime-benchmarks"] diff --git a/primitives/ethereum/src/beacon/config.rs b/primitives/ethereum/src/beacon/config.rs new file mode 100644 index 00000000..e257e1bd --- /dev/null +++ b/primitives/ethereum/src/beacon/config.rs @@ -0,0 +1,229 @@ +use codec::{Decode, Encode}; +use frame_support::RuntimeDebug; +use hex_literal::hex; +use scale_info::TypeInfo; + +#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconFork { + #[cfg_attr( + feature = "std", + serde(with = "crate::serde_utils::serde_fork_version") + )] + fork_version: ForkVersion, + epoch: u64, +} + +#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconForkSchedule { + pub phase0: BeaconFork, + pub altair: BeaconFork, + pub bellatrix: BeaconFork, + // Disabled forks + // capella: BeaconFork, + // sharding: BeaconFork, +} + +impl BeaconForkSchedule { + pub fn fork_version(&self, epoch: u64) -> ForkVersion { + if epoch >= self.bellatrix.epoch { + self.bellatrix.fork_version + } else if epoch >= self.altair.epoch { + self.altair.fork_version + } else { + self.phase0.fork_version + } + } + + // https://github.com/ChainSafe/lodestar/blob/aa4349cee2b5bbefdf4e7c0bd58df36aaebff6de/packages/config/src/chainConfig/networks/sepolia.ts + pub fn sepolia() -> Self { + Self { + phase0: BeaconFork { + fork_version: hex!("90000069"), + epoch: 0, + }, + altair: BeaconFork { + fork_version: hex!("90000070"), + epoch: 50, + }, + bellatrix: BeaconFork { + fork_version: hex!("90000071"), + epoch: 100, + }, + } + } + + // https://github.com/ChainSafe/lodestar/blob/aa4349cee2b5bbefdf4e7c0bd58df36aaebff6de/packages/config/src/chainConfig/networks/goerli.ts + pub fn goerli() -> Self { + Self { + phase0: BeaconFork { + fork_version: hex!("00001020"), + epoch: 0, + }, + altair: BeaconFork { + fork_version: hex!("01001020"), + epoch: 36660, + }, + bellatrix: BeaconFork { + fork_version: hex!("02001020"), + epoch: 112260, + }, + } + } + + // https://github.com/eth-clients/merge-testnets/blob/302fe27afdc7a9d15b1766a0c0a9d64319140255/mainnet-shadow-fork-13/config.yaml + pub fn mainnet() -> Self { + Self { + phase0: BeaconFork { + fork_version: hex!("00000000"), + epoch: 0, + }, + altair: BeaconFork { + fork_version: hex!("01000000"), + epoch: 74240, + }, + bellatrix: BeaconFork { + fork_version: hex!("02000000"), + epoch: 144896, + }, + } + } + + pub fn local() -> Self { + Self { + phase0: BeaconFork { + fork_version: hex!("00000001"), + epoch: 0, + }, + altair: BeaconFork { + fork_version: hex!("01000001"), + epoch: 0, + }, + bellatrix: BeaconFork { + fork_version: hex!("02000001"), + epoch: 0, + }, + } + } +} + +#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub enum BeaconNetworkConfig { + Mainnet, + Minimal, +} + +#[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconConsensusConfig { + pub config: BeaconNetworkConfig, + pub fork_schedule: BeaconForkSchedule, +} + +impl BeaconConsensusConfig { + pub fn mainnet() -> Self { + Self { + config: BeaconNetworkConfig::Mainnet, + fork_schedule: BeaconForkSchedule::mainnet(), + } + } + + pub fn goerli() -> Self { + Self { + config: BeaconNetworkConfig::Mainnet, + fork_schedule: BeaconForkSchedule::goerli(), + } + } + + pub fn sepolia() -> Self { + Self { + config: BeaconNetworkConfig::Mainnet, + fork_schedule: BeaconForkSchedule::sepolia(), + } + } + + pub fn local() -> Self { + Self { + config: BeaconNetworkConfig::Minimal, + fork_schedule: BeaconForkSchedule::local(), + } + } + + pub fn fork_version_from_slot(&self, slot: u64) -> ForkVersion { + let epoch = self.config.compute_epoch(slot); + self.fork_schedule.fork_version(epoch) + } +} + +impl BeaconNetworkConfig { + pub fn compute_current_sync_period(&self, slot: u64) -> u64 { + match self { + Self::Minimal => { + slot / MINIMAL_SLOTS_PER_EPOCH / MINIMAL_EPOCHS_PER_SYNC_COMMITTEE_PERIOD + } + Self::Mainnet => { + slot / MAINNET_SLOTS_PER_EPOCH / MAINNET_EPOCHS_PER_SYNC_COMMITTEE_PERIOD + } + } + } + + pub fn compute_epoch(&self, slot: u64) -> u64 { + match self { + Self::Minimal => slot / MINIMAL_SLOTS_PER_EPOCH, + Self::Mainnet => slot / MAINNET_SLOTS_PER_EPOCH, + } + } + + pub fn epoch_length(&self) -> u64 { + match self { + Self::Minimal => MINIMAL_SLOTS_PER_EPOCH, + Self::Mainnet => MAINNET_SLOTS_PER_EPOCH, + } + } +} + +pub const MAINNET_SLOTS_PER_EPOCH: u64 = 32; +pub const MAINNET_EPOCHS_PER_SYNC_COMMITTEE_PERIOD: u64 = 256; +pub const MAINNET_SYNC_COMMITTEE_SIZE: usize = 512; + +pub const MINIMAL_SLOTS_PER_EPOCH: u64 = 8; +pub const MINIMAL_EPOCHS_PER_SYNC_COMMITTEE_PERIOD: u64 = 8; +pub const MINIMAL_SYNC_COMMITTEE_SIZE: usize = 32; + +use super::ForkVersion; + +pub const CURRENT_SYNC_COMMITTEE_INDEX: u64 = 22; +pub const CURRENT_SYNC_COMMITTEE_DEPTH: u64 = 5; + +pub const NEXT_SYNC_COMMITTEE_DEPTH: u64 = 5; +pub const NEXT_SYNC_COMMITTEE_INDEX: u64 = 23; + +pub const FINALIZED_ROOT_DEPTH: u64 = 6; +pub const FINALIZED_ROOT_INDEX: u64 = 41; + +pub const MAX_PROPOSER_SLASHINGS: usize = 16; +pub const MAX_ATTESTER_SLASHINGS: usize = 2; +pub const MAX_ATTESTATIONS: usize = 128; +pub const MAX_DEPOSITS: usize = 16; +pub const MAX_VOLUNTARY_EXITS: usize = 16; +pub const MAX_VALIDATORS_PER_COMMITTEE: usize = 2048; +pub const MAX_EXTRA_DATA_BYTES: usize = 32; +pub const MAX_LOGS_BLOOM_SIZE: usize = 256; +pub const MAX_FEE_RECIPIENT_SIZE: usize = 20; +pub const MAX_TRANSACTIONS: usize = 1048576; +pub const MAX_BYTES_PER_TRANSACTION: usize = 1073741824; +pub const MAX_H256_PER_TRANSACTION: usize = (MAX_BYTES_PER_TRANSACTION + 31) / 32; + +pub const DEPOSIT_CONTRACT_TREE_DEPTH: usize = 32; + +/// GENESIS_FORK_VERSION('0x00000000') +pub const GENESIS_FORK_VERSION: ForkVersion = [30, 30, 30, 30]; + +/// DomainType('0x07000000') +/// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#domain-types +pub const DOMAIN_SYNC_COMMITTEE: [u8; 4] = [7, 0, 0, 0]; + +pub const PUBKEY_SIZE: usize = 48; +pub const SIGNATURE_SIZE: usize = 96; diff --git a/primitives/ethereum/src/beacon/mod.rs b/primitives/ethereum/src/beacon/mod.rs new file mode 100644 index 00000000..e249478b --- /dev/null +++ b/primitives/ethereum/src/beacon/mod.rs @@ -0,0 +1,401 @@ +pub mod config; + +use crate::mpt; + +#[cfg(feature = "std")] +use crate::serde_utils::{serde_hex, serde_str}; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::{H160, H256, U256}; +use sp_runtime::{ + traits::{Hash, Keccak256}, + RuntimeDebug, +}; +use sp_std::prelude::*; + +#[cfg(feature = "std")] +use core::fmt::Formatter; +#[cfg(feature = "std")] +use serde::{de::Error, de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] +use sp_std::fmt::Result as StdResult; + +pub fn keccak_256(data: &[u8]) -> [u8; 32] { + Keccak256::hash(data).0 +} + +pub type Root = H256; +pub type Domain = H256; +pub type ValidatorIndex = u64; +pub type ProofBranch = Vec; +pub type ForkVersion = [u8; 4]; + +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct PublicKey(pub [u8; 48]); + +impl Default for PublicKey { + fn default() -> Self { + PublicKey([0u8; 48]) + } +} + +#[cfg(feature = "std")] +impl Serialize for PublicKey { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_bytes(&self.0) + } +} + +#[cfg(feature = "std")] +struct PublicKeyVisitor; + +#[cfg(feature = "std")] +impl<'de> Visitor<'de> for PublicKeyVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut Formatter) -> StdResult { + formatter.write_str("a hex string") + } + + fn visit_str(self, v: &str) -> Result + where + E: Error, + { + let str_without_0x = match v.strip_prefix("0x") { + Some(val) => val, + None => v, + }; + + let hex_bytes = match hex::decode(str_without_0x) { + Ok(bytes) => bytes, + Err(e) => return Err(Error::custom(e.to_string())), + }; + if hex_bytes.len() != 48 { + return Err(Error::custom("publickey expected to be 48 characters")); + } + + let mut data = [0u8; 48]; + data[0..48].copy_from_slice(&hex_bytes); + Ok(PublicKey(data)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for PublicKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(PublicKeyVisitor) + } +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct ForkData { + // 1 or 0 bit, indicates whether a sync committee participated in a vote + pub current_version: [u8; 4], + pub genesis_validators_root: [u8; 32], +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct SigningData { + pub object_root: Root, + pub domain: Domain, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ExecutionHeader { + pub parent_hash: H256, + pub fee_recipient: H160, + pub state_root: H256, + pub receipts_root: H256, + pub logs_bloom: Vec, + pub prev_randao: H256, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub block_number: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub gas_limit: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub gas_used: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub timestamp: u64, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub extra_data: Vec, + pub base_fee_per_gas: U256, + pub block_hash: H256, + pub transactions_root: H256, +} + +/// Sync committee as it is stored in the runtime storage. +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SyncCommittee { + pub pubkeys: Vec, + pub aggregate_pubkey: PublicKey, +} + +/// Beacon block header as it is stored in the runtime storage. The block root is the +/// Merklization of a BeaconHeader. +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BeaconHeader { + // The slot for which this block is created. Must be greater than the slot of the block defined by parentRoot. + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub slot: u64, + // The index of the validator that proposed the block. + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub proposer_index: ValidatorIndex, + // The block root of the parent block, forming a block chain. + pub parent_root: Root, + // The hash root of the post state of running the state transition through this block. + pub state_root: Root, + // The hash root of the beacon block body + pub body_root: Root, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct DepositData { + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub pubkey: Vec, + pub withdrawal_credentials: H256, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub amount: u64, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub signature: Vec, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Deposit { + pub proof: Vec, + pub data: DepositData, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Checkpoint { + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub epoch: u64, + pub root: H256, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct AttestationData { + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub slot: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub index: u64, + pub beacon_block_root: H256, + pub source: Checkpoint, + pub target: Checkpoint, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct IndexedAttestation { + pub attesting_indices: Vec, + pub data: AttestationData, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub signature: Vec, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SignedHeader { + pub message: BeaconHeader, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub signature: Vec, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ProposerSlashing { + pub signed_header_1: SignedHeader, + pub signed_header_2: SignedHeader, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct AttesterSlashing { + pub attestation_1: IndexedAttestation, + pub attestation_2: IndexedAttestation, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Attestation { + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub aggregation_bits: Vec, + pub data: AttestationData, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub signature: Vec, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct VoluntaryExit { + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub epoch: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub validator_index: u64, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Eth1Data { + pub deposit_root: H256, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub deposit_count: u64, + pub block_hash: H256, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SyncAggregate { + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub sync_committee_bits: Vec, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub sync_committee_signature: Vec, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ExecutionPayload { + pub parent_hash: H256, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub fee_recipient: Vec, + pub state_root: H256, + pub receipts_root: H256, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub logs_bloom: Vec, + pub prev_randao: H256, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub block_number: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub gas_limit: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub gas_used: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub timestamp: u64, + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub extra_data: Vec, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub base_fee_per_gas: U256, + pub block_hash: H256, + pub transactions_root: H256, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Body { + #[cfg_attr(feature = "std", serde(with = "serde_hex"))] + pub randao_reveal: Vec, + pub eth1_data: Eth1Data, + pub graffiti: H256, + pub proposer_slashings: Vec, + pub attester_slashings: Vec, + pub attestations: Vec, + pub deposits: Vec, + pub voluntary_exits: Vec, + pub sync_aggregate: SyncAggregate, + pub execution_payload: ExecutionPayload, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BeaconBlock { + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub slot: u64, + #[cfg_attr(feature = "std", serde(with = "serde_str"))] + pub proposer_index: u64, + pub parent_root: H256, + pub state_root: H256, + pub body: Body, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct InitialSync { + pub header: BeaconHeader, + pub current_sync_committee: SyncCommittee, + pub current_sync_committee_branch: ProofBranch, + pub validators_root: Root, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SyncCommitteePeriodUpdate { + pub attested_header: BeaconHeader, + pub next_sync_committee: SyncCommittee, + pub next_sync_committee_branch: ProofBranch, + pub finalized_header: BeaconHeader, + pub finality_branch: ProofBranch, + pub sync_aggregate: SyncAggregate, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct FinalizedHeaderUpdate { + pub attested_header: BeaconHeader, + pub finalized_header: BeaconHeader, + pub finality_branch: ProofBranch, + pub sync_aggregate: SyncAggregate, +} + +#[derive(Clone, Default, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BlockUpdate { + pub block: BeaconBlock, + pub sync_aggregate: SyncAggregate, +} + +#[derive(Default, Encode, Decode, TypeInfo)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ExecutionHeaderState { + pub beacon_block_root: H256, + pub beacon_slot: u64, + pub block_hash: H256, + pub block_number: u64, +} + +impl ExecutionHeader { + // Copied from ethereum_snowbridge::header + pub fn check_receipt_proof( + &self, + proof: &[Vec], + ) -> Option> { + match self.apply_merkle_proof(proof) { + Some((root, data)) if root == self.receipts_root => Some(rlp::decode(&data)), + Some((_, _)) => None, + None => None, + } + } + + // Copied from ethereum_snowbridge::header + pub fn apply_merkle_proof(&self, proof: &[Vec]) -> Option<(H256, Vec)> { + let mut iter = proof.iter().rev(); + let first_bytes = match iter.next() { + Some(b) => b, + None => return None, + }; + let item_to_prove: mpt::ShortNode = rlp::decode(first_bytes).ok()?; + + let final_hash: Option<[u8; 32]> = + iter.fold(Some(keccak_256(first_bytes)), |maybe_hash, bytes| { + let expected_hash = maybe_hash?; + let node: Box = bytes.as_slice().try_into().ok()?; + if (*node).contains_hash(expected_hash.into()) { + return Some(keccak_256(bytes)); + } + None + }); + + final_hash.map(|hash| (hash.into(), item_to_prove.value)) + } +} diff --git a/pallets/types/src/difficulty.rs b/primitives/ethereum/src/difficulty.rs similarity index 100% rename from pallets/types/src/difficulty.rs rename to primitives/ethereum/src/difficulty.rs diff --git a/pallets/types/src/ethashdata.rs b/primitives/ethereum/src/ethashdata.rs similarity index 100% rename from pallets/types/src/ethashdata.rs rename to primitives/ethereum/src/ethashdata.rs diff --git a/pallets/types/src/ethashproof.rs b/primitives/ethereum/src/ethashproof.rs similarity index 100% rename from pallets/types/src/ethashproof.rs rename to primitives/ethereum/src/ethashproof.rs diff --git a/pallets/types/src/header.rs b/primitives/ethereum/src/header.rs similarity index 100% rename from pallets/types/src/header.rs rename to primitives/ethereum/src/header.rs diff --git a/primitives/ethereum/src/lib.rs b/primitives/ethereum/src/lib.rs new file mode 100644 index 00000000..de6b15e5 --- /dev/null +++ b/primitives/ethereum/src/lib.rs @@ -0,0 +1,36 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod beacon; +pub mod difficulty; +pub mod ethashdata; +pub mod ethashproof; +pub mod header; +pub mod log; +pub mod mpt; +pub mod network_config; +pub mod receipt; +#[cfg(feature = "std")] +pub mod serde_utils; +#[cfg(any(feature = "test", test))] +pub mod test_utils; + +use codec::Encode; +pub use ethereum_types::{Address as EthAddress, H128, H160, H256, H512, H64, U256}; +pub use header::Header; +pub use header::HeaderId; +pub use log::Log; +pub use receipt::Receipt; +use sp_std::prelude::*; + +pub type EVMChainId = U256; + +pub fn import_digest(network_id: &EVMChainId, header: &Header) -> Vec +where + EVMChainId: Encode, + Header: Encode, +{ + let mut digest = vec![]; + network_id.encode_to(&mut digest); + header.encode_to(&mut digest); + digest +} diff --git a/pallets/types/src/log.rs b/primitives/ethereum/src/log.rs similarity index 100% rename from pallets/types/src/log.rs rename to primitives/ethereum/src/log.rs diff --git a/pallets/types/src/mpt.rs b/primitives/ethereum/src/mpt.rs similarity index 100% rename from pallets/types/src/mpt.rs rename to primitives/ethereum/src/mpt.rs diff --git a/pallets/types/src/network_config.rs b/primitives/ethereum/src/network_config.rs similarity index 70% rename from pallets/types/src/network_config.rs rename to primitives/ethereum/src/network_config.rs index b7185007..216e4468 100644 --- a/pallets/types/src/network_config.rs +++ b/primitives/ethereum/src/network_config.rs @@ -29,6 +29,7 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use crate::{ + beacon::config::BeaconConsensusConfig, difficulty::{ClassicForkConfig, ForkConfig}, EVMChainId, }; @@ -44,6 +45,7 @@ pub enum Consensus { Ethash { fork_config: ForkConfig }, Etchash { fork_config: ClassicForkConfig }, Clique { period: u64, epoch: u64 }, + Beacon(BeaconConsensusConfig), } impl Consensus { @@ -52,6 +54,7 @@ impl Consensus { Consensus::Clique { epoch, .. } => *epoch, Consensus::Ethash { fork_config } => fork_config.epoch_length(), Consensus::Etchash { fork_config } => fork_config.calc_epoch_length(block_number), + Consensus::Beacon(consensus) => consensus.config.epoch_length(), } } } @@ -60,61 +63,71 @@ impl Consensus { #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum NetworkConfig { Mainnet, - Ropsten, Sepolia, - Rinkeby, Goerli, Classic, Mordor, + Local, Custom { chain_id: EVMChainId, consensus: Consensus, }, + // Keep it for tests + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + RopstenEthash, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + SepoliaEthash, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + MainnetEthash, } impl NetworkConfig { pub fn chain_id(&self) -> EVMChainId { match self { NetworkConfig::Mainnet => 1u32.into(), - NetworkConfig::Ropsten => 3u32.into(), NetworkConfig::Sepolia => 11155111u32.into(), - NetworkConfig::Rinkeby => 4u32.into(), NetworkConfig::Goerli => 5u32.into(), NetworkConfig::Classic => 61u32.into(), NetworkConfig::Mordor => 63u32.into(), + NetworkConfig::Local => 4224u32.into(), NetworkConfig::Custom { chain_id, .. } => *chain_id, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::RopstenEthash => 3u32.into(), + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::MainnetEthash => 1u32.into(), + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::SepoliaEthash => 11155111u32.into(), } } pub fn consensus(&self) -> Consensus { match self { - NetworkConfig::Mainnet => Consensus::Ethash { - fork_config: ForkConfig::mainnet(), - }, - NetworkConfig::Ropsten => Consensus::Ethash { - fork_config: ForkConfig::ropsten(), - }, - NetworkConfig::Sepolia => Consensus::Ethash { - fork_config: ForkConfig::sepolia(), - }, + NetworkConfig::Mainnet => Consensus::Beacon(BeaconConsensusConfig::mainnet()), + NetworkConfig::Goerli => Consensus::Beacon(BeaconConsensusConfig::goerli()), + NetworkConfig::Sepolia => Consensus::Beacon(BeaconConsensusConfig::sepolia()), + NetworkConfig::Local => Consensus::Beacon(BeaconConsensusConfig::local()), NetworkConfig::Classic => Consensus::Etchash { fork_config: ClassicForkConfig::classic(), }, NetworkConfig::Mordor => Consensus::Etchash { fork_config: ClassicForkConfig::mordor(), }, - NetworkConfig::Rinkeby => Consensus::Clique { - period: 15, - epoch: 30000, - }, - NetworkConfig::Goerli => Consensus::Clique { - period: 15, - epoch: 30000, - }, NetworkConfig::Custom { consensus: protocol, .. } => *protocol, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::RopstenEthash => Consensus::Ethash { + fork_config: ForkConfig::ropsten(), + }, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::MainnetEthash => Consensus::Ethash { + fork_config: ForkConfig::mainnet(), + }, + #[cfg(any(test, feature = "test", feature = "runtime-benchmarks"))] + NetworkConfig::SepoliaEthash => Consensus::Ethash { + fork_config: ForkConfig::sepolia(), + }, } } } diff --git a/pallets/types/src/receipt.rs b/primitives/ethereum/src/receipt.rs similarity index 100% rename from pallets/types/src/receipt.rs rename to primitives/ethereum/src/receipt.rs diff --git a/primitives/ethereum/src/serde_utils.rs b/primitives/ethereum/src/serde_utils.rs new file mode 100644 index 00000000..d54cc30e --- /dev/null +++ b/primitives/ethereum/src/serde_utils.rs @@ -0,0 +1,80 @@ +pub mod serde_fork_version { + use serde::Deserialize; + + use crate::beacon::ForkVersion; + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + let value = if value.len() > 1 && value[0..2] == *"0x" { + &value[2..] + } else { + &value + }; + let res = hex::decode(value).map_err(|err| { + serde::de::Error::custom(format!("Failed to deserialize from hex: {:?}", err)) + })?; + let res = res.try_into().map_err(|err| { + serde::de::Error::custom(format!("Failed to deserialize from hex: {:?}", err)) + })?; + Ok(res) + } + + pub fn serialize(value: &[u8], serializer: S) -> Result { + serializer.serialize_str(&format!("0x{}", hex::encode(value))) + } +} + +pub mod serde_str { + use core::str::FromStr; + use serde::Deserialize; + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + T: TryFrom, + >::Error: std::fmt::Debug, + { + let value = String::deserialize(deserializer)?; + let res = u128::from_str(&value).map_err(|err| { + serde::de::Error::custom(format!("Failed to deserialize from string: {:?}", err)) + })?; + let res = T::try_from(res).map_err(|err| { + serde::de::Error::custom(format!("Failed to deserialize from string: {:?}", err)) + })?; + Ok(res) + } + + pub fn serialize( + value: &T, + serializer: S, + ) -> Result { + serializer.serialize_str(&value.to_string()) + } +} + +pub mod serde_hex { + use serde::Deserialize; + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: serde::Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + let value = if value.len() > 1 && value[0..2] == *"0x" { + &value[2..] + } else { + &value + }; + let res = hex::decode(value).map_err(|err| { + serde::de::Error::custom(format!("Failed to deserialize from hex: {:?}", err)) + })?; + Ok(res) + } + + pub fn serialize(value: &[u8], serializer: S) -> Result { + serializer.serialize_str(&format!("0x{}", hex::encode(value))) + } +} diff --git a/pallets/types/src/test_utils.rs b/primitives/ethereum/src/test_utils.rs similarity index 97% rename from pallets/types/src/test_utils.rs rename to primitives/ethereum/src/test_utils.rs index ea232127..efd06184 100644 --- a/pallets/types/src/test_utils.rs +++ b/primitives/ethereum/src/test_utils.rs @@ -47,10 +47,9 @@ impl<'de> Deserialize<'de> for Hex { s = s[2..].to_string(); } if s.len() % 2 == 1 { - s.insert(0, '0'); + s.insert_str(0, "0"); } - let v: Vec = hex::FromHexIter::new(&s).map(|x| x.unwrap()).collect(); - Ok(Hex(v)) + Ok(Hex(hex::decode(&s).unwrap())) } } diff --git a/pallets/types/tests/fixtures/11090290.json b/primitives/ethereum/tests/fixtures/11090290.json similarity index 100% rename from pallets/types/tests/fixtures/11090290.json rename to primitives/ethereum/tests/fixtures/11090290.json diff --git a/pallets/types/tests/fixtures/11550000.json b/primitives/ethereum/tests/fixtures/11550000.json similarity index 100% rename from pallets/types/tests/fixtures/11550000.json rename to primitives/ethereum/tests/fixtures/11550000.json diff --git a/pallets/types/tests/fixtures/3.json b/primitives/ethereum/tests/fixtures/3.json similarity index 100% rename from pallets/types/tests/fixtures/3.json rename to primitives/ethereum/tests/fixtures/3.json diff --git a/pallets/types/tests/fixtures/tests/difficultyArrowGlacier.json b/primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacier.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyArrowGlacier.json rename to primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacier.json diff --git a/pallets/types/tests/fixtures/tests/difficultyArrowGlacierForkBlock.json b/primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierForkBlock.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyArrowGlacierForkBlock.json rename to primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierForkBlock.json diff --git a/pallets/types/tests/fixtures/tests/difficultyArrowGlacierMinus1.json b/primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierMinus1.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyArrowGlacierMinus1.json rename to primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierMinus1.json diff --git a/pallets/types/tests/fixtures/tests/difficultyArrowGlacierTimeDiff1.json b/primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierTimeDiff1.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyArrowGlacierTimeDiff1.json rename to primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierTimeDiff1.json diff --git a/pallets/types/tests/fixtures/tests/difficultyArrowGlacierTimeDiff2.json b/primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierTimeDiff2.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyArrowGlacierTimeDiff2.json rename to primitives/ethereum/tests/fixtures/tests/difficultyArrowGlacierTimeDiff2.json diff --git a/pallets/types/tests/fixtures/tests/difficultyByzantium.json b/primitives/ethereum/tests/fixtures/tests/difficultyByzantium.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyByzantium.json rename to primitives/ethereum/tests/fixtures/tests/difficultyByzantium.json diff --git a/pallets/types/tests/fixtures/tests/difficultyConstantinople.json b/primitives/ethereum/tests/fixtures/tests/difficultyConstantinople.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyConstantinople.json rename to primitives/ethereum/tests/fixtures/tests/difficultyConstantinople.json diff --git a/pallets/types/tests/fixtures/tests/difficultyEIP2384.json b/primitives/ethereum/tests/fixtures/tests/difficultyEIP2384.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyEIP2384.json rename to primitives/ethereum/tests/fixtures/tests/difficultyEIP2384.json diff --git a/pallets/types/tests/fixtures/tests/difficultyEIP2384_random.json b/primitives/ethereum/tests/fixtures/tests/difficultyEIP2384_random.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyEIP2384_random.json rename to primitives/ethereum/tests/fixtures/tests/difficultyEIP2384_random.json diff --git a/pallets/types/tests/fixtures/tests/difficultyEIP2384_random_to20M.json b/primitives/ethereum/tests/fixtures/tests/difficultyEIP2384_random_to20M.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyEIP2384_random_to20M.json rename to primitives/ethereum/tests/fixtures/tests/difficultyEIP2384_random_to20M.json diff --git a/pallets/types/tests/fixtures/tests/difficultyFrontier.json b/primitives/ethereum/tests/fixtures/tests/difficultyFrontier.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyFrontier.json rename to primitives/ethereum/tests/fixtures/tests/difficultyFrontier.json diff --git a/pallets/types/tests/fixtures/tests/difficultyGrayGlacier.json b/primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacier.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyGrayGlacier.json rename to primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacier.json diff --git a/pallets/types/tests/fixtures/tests/difficultyGrayGlacierForkBlock.json b/primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierForkBlock.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyGrayGlacierForkBlock.json rename to primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierForkBlock.json diff --git a/pallets/types/tests/fixtures/tests/difficultyGrayGlacierMinus1.json b/primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierMinus1.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyGrayGlacierMinus1.json rename to primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierMinus1.json diff --git a/pallets/types/tests/fixtures/tests/difficultyGrayGlacierTimeDiff1.json b/primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierTimeDiff1.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyGrayGlacierTimeDiff1.json rename to primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierTimeDiff1.json diff --git a/pallets/types/tests/fixtures/tests/difficultyGrayGlacierTimeDiff2.json b/primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierTimeDiff2.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyGrayGlacierTimeDiff2.json rename to primitives/ethereum/tests/fixtures/tests/difficultyGrayGlacierTimeDiff2.json diff --git a/pallets/types/tests/fixtures/tests/difficultyHomestead.json b/primitives/ethereum/tests/fixtures/tests/difficultyHomestead.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyHomestead.json rename to primitives/ethereum/tests/fixtures/tests/difficultyHomestead.json diff --git a/pallets/types/tests/fixtures/tests/difficultyMainNetwork.json b/primitives/ethereum/tests/fixtures/tests/difficultyMainNetwork.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyMainNetwork.json rename to primitives/ethereum/tests/fixtures/tests/difficultyMainNetwork.json diff --git a/pallets/types/tests/fixtures/tests/difficultyRopsten.json b/primitives/ethereum/tests/fixtures/tests/difficultyRopsten.json similarity index 100% rename from pallets/types/tests/fixtures/tests/difficultyRopsten.json rename to primitives/ethereum/tests/fixtures/tests/difficultyRopsten.json