From 13f2034529aa2be5e6bc59d11c1586b0ce3d2fe1 Mon Sep 17 00:00:00 2001 From: David Salami <31099392+Wizdave97@users.noreply.github.com> Date: Thu, 7 Sep 2023 17:18:13 +0100 Subject: [PATCH] Arkworks for signature verification (#28) * signature verification * nit * chore * fix no-std * rebase (#29) Co-authored-by: David Salami * fix verifier * remove cloning of beacon state * cleanup verifier * provide function for generating light client updates * wait for block production on el * run docker in background * fix test failures * change port in ci --------- Co-authored-by: dharjeezy --- .github/workflows/test.yml | 115 +- Cargo.lock | 2649 ++++++++++++++--- primitives/Cargo.toml | 22 +- primitives/src/consensus_types.rs | 406 +++ primitives/src/constants.rs | 138 + primitives/src/derived_types.rs | 488 --- primitives/src/domains.rs | 29 + primitives/src/helpers.rs | 162 - primitives/src/lib.rs | 10 +- primitives/src/serde.rs | 142 + primitives/src/ssz/byte_list.rs | 88 + primitives/src/ssz/byte_vector.rs | 81 + primitives/src/ssz/mod.rs | 16 + primitives/src/types.rs | 82 +- primitives/src/util.rs | 61 +- prover/Cargo.toml | 35 +- prover/src/lib.rs | 295 +- .../responses/beacon_block_header_response.rs | 2 +- prover/src/responses/beacon_block_response.rs | 16 +- prover/src/responses/beacon_state_response.rs | 16 +- .../responses/finality_checkpoint_response.rs | 2 +- prover/src/responses/validator_response.rs | 2 +- prover/src/test.rs | 401 +-- verifier/Cargo.toml | 19 +- verifier/src/error.rs | 10 +- verifier/src/lib.rs | 266 +- verifier/src/signature_verification.rs | 108 + 27 files changed, 3856 insertions(+), 1805 deletions(-) create mode 100644 primitives/src/consensus_types.rs create mode 100644 primitives/src/constants.rs delete mode 100644 primitives/src/derived_types.rs create mode 100644 primitives/src/domains.rs delete mode 100644 primitives/src/helpers.rs create mode 100644 primitives/src/serde.rs create mode 100644 primitives/src/ssz/byte_list.rs create mode 100644 primitives/src/ssz/byte_vector.rs create mode 100644 primitives/src/ssz/mod.rs create mode 100644 verifier/src/signature_verification.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c1e9acc..7d506ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: test: name: Test Suite runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' +# if: github.ref == 'refs/heads/main' env: TUID: 123 steps: @@ -41,12 +41,6 @@ jobs: - name: Checkout sources uses: actions/checkout@master - - name: Clone eth-testnet-runner repository - run: | - git clone https://github.com/ralexstokes/eth-testnet-runner.git - cd eth-testnet-runner - git checkout 5f43097a03f8ff37217c843407bf7729617f2dff - - name: Install rust stable toolchain uses: actions-rs/toolchain@v1 with: @@ -57,108 +51,13 @@ jobs: sudo apt update sudo apt install protobuf-compiler - - name: Fetch geth binary - run: | - cd eth-testnet-runner - mkdir bin - wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.11.3-5ed08c47.tar.gz -O ./geth-linux-amd64-1.11.3-5ed08c47.tar.gz - tar -xvf geth-linux-amd64-1.11.3-5ed08c47.tar.gz - cd geth-linux-amd64-1.11.3-5ed08c47 - cp geth ../bin - - - name: Build lighthouse from source - run: | - cd eth-testnet-runner - git clone https://github.com/sigp/lighthouse.git - cd lighthouse - git checkout 38514c07f222ff7783834c48cf5c0a6ee7f346d0 - cargo +nightly build -p lighthouse --release - mv target/release/lighthouse ../bin - - - name: Install go - uses: actions/setup-go@v3 - with: - go-version: "stable" - - - name: check go version - run: go version - - - name: Clone eth2-val-tools repository - run: | - git clone https://github.com/protolambda/eth2-val-tools.git - cd eth2-val-tools - git checkout 4bf01453537ad1a9323c7cd99afc4f8ba2a420b1 - - - name: build eth2-val-tools and move binary to eth-testnet-runner bin folder - run: | - cd eth2-val-tools - go build - cp eth2-val-tools ../eth-testnet-runner/bin - - # Make $UID available to the justfile - - name: set UID env variable as a local justfile variable - run: | - cd eth-testnet-runner - sed -i 's/$UID/{{UID}}/' justfile - sed -i 's/^NOW := `date +%s`/NOW := `date +%s`\nUID := "${{ env.TUID }}"/' justfile - - - name: install just - run: | - cargo install just - - - name: modify testnet config values - run: | - cd eth-testnet-runner/testnet-config - sed -i 's/GENESIS_FORK_VERSION=.*/GENESIS_FORK_VERSION="0x00000000"/' values.env - sed -i 's/ALTAIR_FORK_VERSION=.*/ALTAIR_FORK_VERSION="0x01000000"/' values.env - sed -i 's/BELLATRIX_FORK_VERSION=.*/BELLATRIX_FORK_VERSION="0x02000000"/' values.env - sed -i 's/CAPELLA_FORK_VERSION=.*/CAPELLA_FORK_VERSION="0x03000000"/' values.env - sed -i 's/EIP4844_FORK_VERSION=.*/EIP4844_FORK_VERSION="0x04000000"/' values.env - - - name: remove tty flag from docker command in create-config recipe - run: | - cd eth-testnet-runner - sed -i 's/-it/-i/' justfile - - - name: run create-config - run: | - cd eth-testnet-runner - just create-config & ../scripts/wait_for_tcp_port_opening.sh localhost 8000 - - - name: set shanghaiTime - run: | - cd eth-testnet-runner/config-data/custom_config_data - sed -i 's/"shanghaiTime":.*/"shanghaiTime": 167119236847838392/' genesis.json - - - name: Set MIN_GENESIS_TIME - run: | - cd eth-testnet-runner/config-data/custom_config_data/ - sed -i 's/^MIN_GENESIS_TIME:.*/MIN_GENESIS_TIME: 1678876062/' config.yaml - - - name: run generate-keys - run: | - cd eth-testnet-runner - just generate-keys - - - name: run init-geth - run: | - cd eth-testnet-runner - just init-geth - - - name: run run-el - run: | - cd eth-testnet-runner - just run-el & ../scripts/wait_for_tcp_port_opening.sh localhost 8545 - - - name: run run-cl - run: | - cd eth-testnet-runner - just run-cl & ../scripts/wait_for_tcp_port_opening.sh localhost 5052 - - - name: run run-validator + - name: Clone eth-pos-devnet repository run: | - cd eth-testnet-runner - just run-validator & ../scripts/wait_for_tcp_port_opening.sh localhost 5062 + git clone https://github.com/polytope-labs/eth-pos-devnet.git + cd eth-pos-devnet + docker compose up & + ../scripts/wait_for_tcp_port_opening.sh localhost 3500 + ../scripts/wait_for_tcp_port_opening.sh localhost 8545 - name: Run all tests run: | diff --git a/Cargo.lock b/Cargo.lock index c7cd1af..00e3289 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,24 +3,13 @@ version = 3 [[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn 2.0.28", -] - -[[package]] -name = "actix-rt" -version = "2.8.0" +name = "Inflector" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" dependencies = [ - "actix-macros", - "futures-core", - "tokio", + "lazy_static", + "regex", ] [[package]] @@ -38,6 +27,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.8.3" @@ -59,21 +59,137 @@ dependencies = [ ] [[package]] -name = "amcl" -version = "0.3.0" -source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] -name = "anyhow" -version = "1.0.72" +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] [[package]] -name = "arrayref" -version = "0.3.7" +name = "array-init" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" +dependencies = [ + "nodrop", +] [[package]] name = "arrayvec" @@ -87,6 +203,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3419eecc9f5967e6f0f29a0c3fefe22bda6ea34b15798f3c452cb81f2c3fa7" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -109,6 +234,40 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -132,9 +291,9 @@ dependencies = [ [[package]] name = "base16ct" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base2" @@ -163,6 +322,27 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -205,11 +385,32 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bls_on_arkworks" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc35f5286b3fa350a0a77df5166c034c5a12dc4a3ee13bf2126ac9e9109ef8e" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", + "hkdf", + "hmac", + "libm", + "sha2 0.10.7", +] + [[package]] name = "bs58" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +dependencies = [ + "sha2 0.10.7", + "tinyvec", +] [[package]] name = "bumpalo" @@ -234,147 +435,435 @@ name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] [[package]] -name = "cc" -version = "1.0.82" +name = "bzip2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ + "bzip2-sys", "libc", ] [[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" - -[[package]] -name = "core-foundation" -version = "0.9.3" +name = "bzip2-sys" +version = "0.1.11+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" dependencies = [ - "core-foundation-sys", + "cc", "libc", + "pkg-config", ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "core2" -version = "0.4.0" +name = "camino" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ - "memchr", + "serde", ] [[package]] -name = "cpufeatures" -version = "0.2.9" +name = "cargo-platform" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ - "libc", + "serde", ] [[package]] -name = "crypto-bigint" -version = "0.4.9" +name = "cargo_metadata" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "cc" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" dependencies = [ - "generic-array", - "typenum", + "jobserver", + "libc", ] [[package]] -name = "data-encoding" -version = "2.4.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "der" -version = "0.6.1" +name = "chrono" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +checksum = "d87d9d13be47a5b7c3907137f1290b0459a7f80efb26be8c52afb11963bccb02" dependencies = [ - "const-oid", - "zeroize", + "num-traits", ] [[package]] -name = "digest" -version = "0.9.0" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] -name = "digest" -version = "0.10.7" +name = "coins-bip32" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", + "bs58", + "coins-core", + "digest 0.10.7", + "hmac", + "k256", + "serde", + "sha2 0.10.7", + "thiserror", ] [[package]] -name = "ecdsa" -version = "0.14.8" +name = "coins-bip39" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", + "bitvec", + "coins-bip32", + "hmac", + "once_cell", + "pbkdf2 0.12.2", + "rand", + "sha2 0.10.7", + "thiserror", ] [[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" +name = "coins-core" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" dependencies = [ - "base16ct", - "crypto-bigint", - "der", + "base64 0.21.2", + "bech32", + "bs58", + "digest 0.10.7", + "generic-array", + "hex", + "ripemd", + "serde", + "serde_derive", + "sha2 0.10.7", + "sha3", + "thiserror", +] + +[[package]] +name = "const-hex" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08849ed393c907c90016652a01465a12d86361cd38ad2a7de026c56a520cc259" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", "digest 0.10.7", "ff", "generic-array", @@ -386,6 +875,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + [[package]] name = "encoding_rs" version = "0.8.32" @@ -396,107 +894,434 @@ dependencies = [ ] [[package]] -name = "enr" -version = "0.6.2" +name = "enr" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be7b2ac146c1f99fe245c02d16af0696450d8e06c135db75e10eeb9e642c20d" +dependencies = [ + "base64 0.21.2", + "bytes", + "hex", + "k256", + "log", + "rand", + "rlp", + "serde", + "serde-hex", + "sha3", + "zeroize", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "eth-keystore" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +dependencies = [ + "aes", + "ctr", + "digest 0.10.7", + "hex", + "hmac", + "pbkdf2 0.11.0", + "rand", + "scrypt", + "serde", + "serde_json", + "sha2 0.10.7", + "sha3", + "thiserror", + "uuid", +] + +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "ethers" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba3fd516c15a9a587135229466dbbfc85796de55c5660afbbb1b1c78517d85c" +dependencies = [ + "ethers-addressbook", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-middleware", + "ethers-providers", + "ethers-signers", + "ethers-solc", +] + +[[package]] +name = "ethers-addressbook" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0245617f11b8178fa50b52e433e2c34ac69f39116b62c8be2437decf2edf1986" +dependencies = [ + "ethers-core", + "once_cell", + "serde", + "serde_json", +] + +[[package]] +name = "ethers-contract" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02bb80fd2c22631a5eb8a02cbf373cc5fd86937fc966bb670b9a884580c8e71c" +dependencies = [ + "const-hex", + "ethers-contract-abigen", + "ethers-contract-derive", + "ethers-core", + "ethers-providers", + "futures-util", + "once_cell", + "pin-project", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "ethers-contract-abigen" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22c54db0d393393e732a5b20273e4f8ab89f0cce501c84e75fab9c126799a6e6" +dependencies = [ + "Inflector", + "const-hex", + "dunce", + "ethers-core", + "ethers-etherscan", + "eyre", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "reqwest", + "serde", + "serde_json", + "syn 2.0.28", + "toml 0.7.6", + "walkdir", +] + +[[package]] +name = "ethers-contract-derive" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ee4f216184a1304b707ed258f4f70aa40bf7e1522ab8963d127a8d516eaa1a" +dependencies = [ + "Inflector", + "const-hex", + "ethers-contract-abigen", + "ethers-core", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.28", +] + +[[package]] +name = "ethers-core" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c29523f73c12753165781c6e5dc11c84d3e44c080a15f7c6cfbd70b514cb6f1" +dependencies = [ + "arrayvec", + "bytes", + "cargo_metadata", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "once_cell", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "syn 2.0.28", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-etherscan" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aab5af432b3fe5b7756b60df5c9ddeb85a13414575ad8a9acd707c24f0a77a5" +dependencies = [ + "ethers-core", + "reqwest", + "semver", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "ethers-middleware" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356151d5ded56d4918146366abc9dfc9df367cf0096492a7a5477b21b7693615" +dependencies = [ + "async-trait", + "auto_impl", + "ethers-contract", + "ethers-core", + "ethers-etherscan", + "ethers-providers", + "ethers-signers", + "futures-channel", + "futures-locks", + "futures-util", + "instant", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "tracing-futures", + "url", +] + +[[package]] +name = "ethers-providers" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c84664b294e47fc2860d6db0db0246f79c4c724e552549631bb9505b834bee" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.2", + "bytes", + "const-hex", + "enr", + "ethers-core", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "http", + "instant", + "jsonwebtoken", + "once_cell", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + +[[package]] +name = "ethers-signers" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fa0a0be8915790626d5759eb51fe47435a8eac92c2f212bd2da9aa7f30ea56" +checksum = "170b299698702ef1f53d2275af7d6d97409cfa4f9398ee9ff518f6bc9102d0ad" dependencies = [ - "base64 0.13.1", - "bs58", - "bytes", - "hex", - "k256", - "log", + "async-trait", + "coins-bip32", + "coins-bip39", + "const-hex", + "elliptic-curve", + "eth-keystore", + "ethers-core", "rand", - "rlp", - "serde", - "sha3", - "zeroize", + "sha2 0.10.7", + "thiserror", + "tracing", ] [[package]] -name = "env_logger" -version = "0.10.0" +name = "ethers-solc" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "66559c8f774712df303c907d087275a52a2046b256791aaa566d5abc8ea66731" dependencies = [ - "humantime", - "is-terminal", - "log", + "cfg-if", + "const-hex", + "dirs", + "dunce", + "ethers-core", + "glob", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", "regex", - "termcolor", + "semver", + "serde", + "serde_json", + "solang-parser", + "svm-rs", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi", ] [[package]] -name = "errno" -version = "0.3.2" +name = "eyre" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", + "indenter", + "once_cell", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "fastrand" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] -name = "error-chain" -version = "0.12.4" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "backtrace", - "version_check", + "rand_core", + "subtle", ] [[package]] -name = "ethereum-consensus" -version = "0.1.1" -source = "git+https://github.com/polytope-labs/ethereum-consensus?branch=main#48335b5c8074d63553ee4681993e294eba947f88" +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "async-stream", - "bs58", - "enr", - "error-chain", - "hashbrown 0.13.2", - "hex", - "integer-sqrt", - "milagro_bls", - "multiaddr", - "multihash", + "byteorder", "rand", - "serde", - "serde_json", - "serde_yaml", - "sha2 0.9.9", - "ssz-rs", - "tokio", - "tokio-stream", + "rustc-hex", + "static_assertions", ] [[package]] -name = "fastrand" -version = "2.0.0" +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] -name = "ff" -version = "0.12.1" +name = "flate2" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ - "rand_core", - "subtle", + "crc32fast", + "miniz_oxide", ] [[package]] @@ -529,12 +1354,37 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "funty" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -542,6 +1392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -550,6 +1401,44 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-locks" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" +dependencies = [ + "futures-channel", + "futures-task", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "futures-sink" version = "0.3.28" @@ -562,16 +1451,41 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] + [[package]] name = "futures-util" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", ] [[package]] @@ -582,6 +1496,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -601,11 +1516,29 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core", @@ -624,7 +1557,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -646,6 +1579,27 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.3.2" @@ -664,6 +1618,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -673,6 +1636,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "http" version = "0.2.9" @@ -737,6 +1709,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -760,41 +1746,93 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "equivalent", + "hashbrown 0.14.0", ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "generic-array", ] [[package]] -name = "int" -version = "0.3.0" +name = "instant" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d64bb35c7fc709fa8934dd85f3d0c0e418a3b067e62e6c6041dd19519c0899b" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "num-traits", + "cfg-if", ] [[package]] -name = "integer-sqrt" -version = "0.1.5" +name = "int" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +checksum = "9d64bb35c7fc709fa8934dd85f3d0c0e418a3b067e62e6c6041dd19519c0899b" dependencies = [ "num-traits", ] @@ -831,6 +1869,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.64" @@ -840,16 +1887,32 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.2", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "k256" -version = "0.11.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", + "once_cell", "sha2 0.10.7", + "signature", ] [[package]] @@ -861,6 +1924,34 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lalrpop" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" + [[package]] name = "lazy_static" version = "1.4.0" @@ -874,10 +1965,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] -name = "linked-hash-map" -version = "0.5.6" +name = "libm" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "linux-raw-sys" @@ -901,6 +1992,21 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.5.0" @@ -908,15 +2014,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "milagro_bls" -version = "1.5.1" -source = "git+https://github.com/sigp/milagro_bls#d3fc0a40cfe8b72ccda46ba050ee6786a59ce753" +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ - "amcl", - "hex", - "lazy_static", - "rand", - "zeroize", + "autocfg", ] [[package]] @@ -945,51 +2048,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "multiaddr" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c580bfdd8803cce319b047d239559a22f809094aaea4ac13902a1fdcfcd4261" -dependencies = [ - "arrayref", - "bs58", - "byteorder", - "data-encoding", - "multihash", - "percent-encoding", - "serde", - "static_assertions", - "unsigned-varint", - "url", -] - -[[package]] -name = "multihash" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" -dependencies = [ - "core2", - "digest 0.10.7", - "multihash-derive", - "sha2 0.10.7", - "unsigned-varint", -] - -[[package]] -name = "multihash-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" -dependencies = [ - "proc-macro-crate", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -1008,6 +2066,18 @@ dependencies = [ "tempfile", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "num-bigint" version = "0.4.3" @@ -1048,6 +2118,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "object" version = "0.31.1" @@ -1069,6 +2160,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "openssl" version = "0.10.56" @@ -1102,71 +2218,222 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] -name = "openssl-sys" -version = "0.9.91" +name = "openssl-sys" +version = "0.9.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "parity-scale-codec" +version = "3.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec 1.11.0", + "windows-targets", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", + "hmac", + "password-hash", + "sha2 0.10.7", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.0.0", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version", +] + +[[package]] +name = "phf" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", + "phf_macros", + "phf_shared 0.11.2", ] [[package]] -name = "parity-scale-codec" -version = "3.6.4" +name = "phf_generator" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", + "phf_shared 0.11.2", + "rand", ] [[package]] -name = "parity-scale-codec-derive" -version = "3.6.4" +name = "phf_macros" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "proc-macro-crate", + "phf_generator", + "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] -name = "parking_lot" -version = "0.12.1" +name = "phf_shared" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "lock_api", - "parking_lot_core", + "siphasher", ] [[package]] -name = "parking_lot_core" -version = "0.9.8" +name = "phf_shared" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", + "siphasher", ] [[package]] -name = "percent-encoding" -version = "2.3.0" +name = "pin-project" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] [[package]] name = "pin-project-lite" @@ -1182,9 +2449,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs8" -version = "0.9.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", @@ -1202,6 +2469,36 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" +dependencies = [ + "proc-macro2", + "syn 2.0.28", +] + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + [[package]] name = "proc-macro-crate" version = "1.1.3" @@ -1209,7 +2506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" dependencies = [ "thiserror", - "toml", + "toml 0.5.11", ] [[package]] @@ -1290,6 +2587,37 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1299,6 +2627,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "regex" version = "1.9.3" @@ -1330,9 +2669,9 @@ checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ "base64 0.21.2", "bytes", @@ -1343,6 +2682,7 @@ dependencies = [ "http", "http-body", "hyper", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -1352,28 +2692,55 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots 0.25.2", "winreg", ] [[package]] name = "rfc6979" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "crypto-bigint", "hmac", - "zeroize", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", ] [[package]] @@ -1383,9 +2750,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1398,6 +2777,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.8" @@ -1411,12 +2799,101 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.4", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-info" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "schannel" version = "0.1.22" @@ -1432,11 +2909,33 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +dependencies = [ + "hmac", + "pbkdf2 0.11.0", + "salsa20", + "sha2 0.10.7", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sec1" -version = "0.3.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", @@ -1469,20 +2968,52 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +dependencies = [ + "serde", +] + +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" -version = "1.0.183" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-hex" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca37e3e4d1b39afd7ff11ee4e947efae85adfddf4841787bfa47c470e96dc26d" +dependencies = [ + "array-init", + "serde", + "smallvec 0.6.14", +] + [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -1500,6 +3031,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1513,15 +3053,14 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.8.26" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "indexmap", - "ryu", - "serde", - "yaml-rust", + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] @@ -1559,31 +3098,49 @@ dependencies = [ ] [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "signature" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "libc", + "digest 0.10.7", + "rand_core", ] [[package]] -name = "signature" -version = "1.6.4" +name = "simple_asn1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ - "digest 0.10.7", - "rand_core", + "num-bigint", + "num-traits", + "thiserror", + "time", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ - "autocfg", + "maybe-uninit", ] [[package]] @@ -1612,11 +3169,31 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "solang-parser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c792fe9fae2a2f716846f214ca10d5a1e21133e0bf36cef34bcc4a852467b21" +dependencies = [ + "itertools", + "lalrpop", + "lalrpop-util", + "phf", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spki" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", "der", @@ -1625,13 +3202,14 @@ dependencies = [ [[package]] name = "ssz-rs" version = "0.8.0" -source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#96f9a89ccc56ab2abb4c3a83eaedb415034ada49" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#81e9f63c93ca33f5f484ac301553f04912f2de23" dependencies = [ "as-any", "bitvec", "hex", "itertools", "num-bigint", + "parity-scale-codec", "serde", "sha2 0.9.9", "ssz-rs-derive", @@ -1640,7 +3218,7 @@ dependencies = [ [[package]] name = "ssz-rs-derive" version = "0.8.0" -source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#96f9a89ccc56ab2abb4c3a83eaedb415034ada49" +source = "git+https://github.com/polytope-labs/ssz-rs?branch=main#81e9f63c93ca33f5f484ac301553f04912f2de23" dependencies = [ "proc-macro2", "quote", @@ -1653,12 +3231,67 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.28", +] + [[package]] name = "subtle" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "svm-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597e3a746727984cb7ea2487b6a40726cad0dbe86628e7d429aa6b8c4c153db4" +dependencies = [ + "dirs", + "fs2", + "hex", + "once_cell", + "reqwest", + "semver", + "serde", + "serde_json", + "sha2 0.10.7", + "thiserror", + "url", + "zip", +] + [[package]] name = "syn" version = "1.0.109" @@ -1685,9 +3318,15 @@ dependencies = [ name = "sync-committee-primitives" version = "0.1.0" dependencies = [ - "ethereum-consensus", + "anyhow", + "ark-bls12-381", + "ark-ec", + "bls_on_arkworks", + "hex", "hex-literal", "parity-scale-codec", + "primitive-types", + "serde", "ssz-rs", ] @@ -1695,13 +3334,17 @@ dependencies = [ name = "sync-committee-prover" version = "0.1.0" dependencies = [ - "actix-rt", "anyhow", + "ark-bls12-381", + "ark-ec", "async-stream", "base2", + "bls_on_arkworks", "env_logger", - "ethereum-consensus", + "ethers", "hex", + "log", + "primitive-types", "reqwest", "serde", "serde_json", @@ -1716,24 +3359,16 @@ dependencies = [ name = "sync-committee-verifier" version = "0.1.0" dependencies = [ - "ethereum-consensus", + "anyhow", + "ark-bls12-381", + "ark-ec", + "bls_on_arkworks", + "hex", "log", "ssz-rs", "sync-committee-primitives", ] -[[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 = "tap" version = "1.0.1" @@ -1742,17 +3377,28 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", "windows-sys", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -1782,6 +3428,43 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "time" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +dependencies = [ + "deranged", + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1799,18 +3482,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.31.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2 0.5.3", "tokio-macros", "windows-sys", @@ -1837,6 +3518,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -1848,6 +3539,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2" +dependencies = [ + "futures-util", + "log", + "rustls", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.23.1", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -1871,6 +3577,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -1885,9 +3625,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "tracing-core" version = "0.1.31" @@ -1897,18 +3649,60 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "try-lock" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "tungstenite" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e862a1c4128df0112ab625f55cd5c934bcb4312ba80b39ae4b4835a3fd58e649" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "typenum" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -1937,10 +3731,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] -name = "unsigned-varint" +name = "untrusted" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" @@ -1953,6 +3747,22 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", + "serde", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -1965,6 +3775,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2056,6 +3876,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.2", +] + +[[package]] +name = "webpki-roots" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" + [[package]] name = "winapi" version = "0.3.9" @@ -2153,13 +3988,42 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys", +] + +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -2172,16 +4036,77 @@ dependencies = [ ] [[package]] -name = "yaml-rust" -version = "0.4.5" +name = "yansi" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2 0.11.0", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index b5af461..f80ade7 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -6,17 +6,31 @@ authors = ["Polytope Labs"] [dependencies] -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main", default-features = false } hex-literal = { package = "hex-literal", version = "0.4.1", default-features = false } codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = [ "derive" ] } +primitive-types = { version = "0.12.1", default-features = false, features = ["serde_no_std", "impl-codec"] } +serde = { version = "1.0.185", optional = true, features = ["derive"] } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +anyhow = {version = "1.0.75", default-features = false} +ark-ec = { version = "0.4.2", default-features = false } +ark-bls12-381 = { version = "0.4.0", default-features = false } +bls_on_arkworks = { version = "0.2.2", default-features = false } [features] default = ["std"] std = [ - "ssz-rs/std", - 'codec/std' + "ssz-rs/default", + 'codec/std', + "primitive-types/std", + "anyhow/std", + "ark-ec/std", + "bls_on_arkworks/std", + "ark-bls12-381/std", + "primitive-types/std", + "serde" ] -testing = [] +mainnet = [] +testnet = [] diff --git a/primitives/src/consensus_types.rs b/primitives/src/consensus_types.rs new file mode 100644 index 0000000..52d4af5 --- /dev/null +++ b/primitives/src/consensus_types.rs @@ -0,0 +1,406 @@ +use crate::{ + constants::{ + BlsPublicKey, BlsSignature, Bytes32, Epoch, ExecutionAddress, Gwei, Hash32, + ParticipationFlags, Root, Slot, ValidatorIndex, Version, WithdrawalIndex, + DEPOSIT_PROOF_LENGTH, JUSTIFICATION_BITS_LENGTH, + }, + ssz::{ByteList, ByteVector}, +}; +use alloc::{vec, vec::Vec}; +use ssz_rs::{prelude::*, Deserialize, List, Vector}; + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconBlockHeader { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub slot: u64, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub proposer_index: u64, + pub parent_root: Root, + pub state_root: Root, + pub body_root: Root, +} + +#[derive(Default, Clone, Debug, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Checkpoint { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub epoch: u64, + pub root: Root, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Eth1Data { + pub deposit_root: Root, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub deposit_count: u64, + pub block_hash: Hash32, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Validator { + #[cfg_attr(feature = "std", serde(rename = "pubkey"))] + pub public_key: BlsPublicKey, + pub withdrawal_credentials: Bytes32, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub effective_balance: Gwei, + pub slashed: bool, + // Status epochs + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub activation_eligibility_epoch: Epoch, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub activation_epoch: Epoch, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub exit_epoch: Epoch, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub withdrawable_epoch: Epoch, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ProposerSlashing { + pub signed_header_1: SignedBeaconBlockHeader, + pub signed_header_2: SignedBeaconBlockHeader, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SignedBeaconBlockHeader { + pub message: BeaconBlockHeader, + pub signature: BlsSignature, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct IndexedAttestation { + #[cfg_attr(feature = "std", serde(with = "crate::serde::collection_over_string"))] + pub attesting_indices: List, + pub data: AttestationData, + pub signature: BlsSignature, +} + +#[derive(Default, Clone, Debug, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct AttestationData { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub slot: u64, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub index: u64, + pub beacon_block_root: Root, + pub source: Checkpoint, + pub target: Checkpoint, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct AttesterSlashing { + pub attestation_1: IndexedAttestation, + pub attestation_2: IndexedAttestation, +} + +#[derive(Default, Debug, SimpleSerialize, codec::Encode, codec::Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Attestation { + pub aggregation_bits: Bitlist, + pub data: AttestationData, + pub signature: BlsSignature, +} + +#[derive(Default, Debug, SimpleSerialize, codec::Encode, codec::Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Deposit { + pub proof: Vector, + pub data: DepositData, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, codec::Encode, codec::Decode, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct DepositData { + #[cfg_attr(feature = "std", serde(rename = "pubkey"))] + pub public_key: BlsPublicKey, + pub withdrawal_credentials: Hash32, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub amount: u64, + pub signature: BlsSignature, +} + +#[derive(Default, Debug, SimpleSerialize, codec::Encode, codec::Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct VoluntaryExit { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub epoch: u64, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub validator_index: u64, +} + +#[derive(Default, Debug, SimpleSerialize, codec::Encode, codec::Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SignedVoluntaryExit { + pub message: VoluntaryExit, + pub signature: BlsSignature, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, codec::Encode, codec::Decode, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SyncAggregate { + pub sync_committee_bits: Bitvector, + pub sync_committee_signature: BlsSignature, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SyncCommittee { + #[cfg_attr(feature = "std", serde(rename = "pubkeys"))] + pub public_keys: Vector, + #[cfg_attr(feature = "std", serde(rename = "aggregate_pubkey"))] + pub aggregate_public_key: BlsPublicKey, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Withdrawal { + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub index: WithdrawalIndex, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub validator_index: ValidatorIndex, + pub address: ExecutionAddress, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub amount: Gwei, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BlsToExecutionChange { + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub validator_index: ValidatorIndex, + #[cfg_attr(feature = "serde", serde(rename = "from_bls_pubkey"))] + pub from_bls_public_key: BlsPublicKey, + pub to_execution_address: ExecutionAddress, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct SignedBlsToExecutionChange { + message: BlsToExecutionChange, + signature: BlsSignature, +} + +pub type Transaction = ByteList; + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ExecutionPayload< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, +> { + pub parent_hash: Hash32, + pub fee_recipient: ExecutionAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: ByteVector, + pub prev_randao: Bytes32, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub block_number: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub gas_used: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub timestamp: u64, + pub extra_data: ByteList, + pub base_fee_per_gas: U256, + pub block_hash: Hash32, + pub transactions: List, MAX_TRANSACTIONS_PER_PAYLOAD>, + pub withdrawals: List, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ExecutionPayloadHeader< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, +> { + pub parent_hash: Hash32, + pub fee_recipient: ExecutionAddress, + pub state_root: Bytes32, + pub receipts_root: Bytes32, + pub logs_bloom: ByteVector, + pub prev_randao: Bytes32, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub block_number: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub gas_limit: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub gas_used: u64, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub timestamp: u64, + pub extra_data: ByteList, + pub base_fee_per_gas: U256, + pub block_hash: Hash32, + pub transactions_root: Root, + pub withdrawals_root: Root, +} + +#[derive(Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconBlockBody< + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, +> { + pub randao_reveal: BlsSignature, + pub eth1_data: Eth1Data, + pub graffiti: Bytes32, + pub proposer_slashings: List, + pub attester_slashings: + List, MAX_ATTESTER_SLASHINGS>, + pub attestations: List, MAX_ATTESTATIONS>, + pub deposits: List, + pub voluntary_exits: List, + pub sync_aggregate: SyncAggregate, + pub execution_payload: ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + >, + pub bls_to_execution_changes: List, +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, SimpleSerialize, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconBlock< + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, +> { + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub slot: Slot, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub proposer_index: ValidatorIndex, + pub parent_root: Root, + pub state_root: Root, + pub body: BeaconBlockBody< + MAX_PROPOSER_SLASHINGS, + MAX_VALIDATORS_PER_COMMITTEE, + MAX_ATTESTER_SLASHINGS, + MAX_ATTESTATIONS, + MAX_DEPOSITS, + MAX_VOLUNTARY_EXITS, + SYNC_COMMITTEE_SIZE, + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, + >, +} +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct Fork { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_hex"))] + pub previous_version: Version, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_hex"))] + pub current_version: Version, + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_string"))] + pub epoch: Epoch, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ForkData { + #[cfg_attr(feature = "std", serde(with = "crate::serde::as_hex"))] + pub current_version: Version, + pub genesis_validators_root: Root, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct HistoricalSummary { + pub block_summary_root: Root, + pub state_summary_root: Root, +} + +#[derive(Default, Debug, SimpleSerialize, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct BeaconState< + const SLOTS_PER_HISTORICAL_ROOT: usize, + const HISTORICAL_ROOTS_LIMIT: usize, + const ETH1_DATA_VOTES_BOUND: usize, + const VALIDATOR_REGISTRY_LIMIT: usize, + const EPOCHS_PER_HISTORICAL_VECTOR: usize, + const EPOCHS_PER_SLASHINGS_VECTOR: usize, + const MAX_VALIDATORS_PER_COMMITTEE: usize, + const SYNC_COMMITTEE_SIZE: usize, + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, +> { + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub genesis_time: u64, + pub genesis_validators_root: Root, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub slot: Slot, + pub fork: Fork, + pub latest_block_header: BeaconBlockHeader, + pub block_roots: Vector, + pub state_roots: Vector, + pub historical_roots: List, + pub eth1_data: Eth1Data, + pub eth1_data_votes: List, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub eth1_deposit_index: u64, + pub validators: List, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::collection_over_string"))] + pub balances: List, + pub randao_mixes: Vector, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::collection_over_string"))] + pub slashings: Vector, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::collection_over_string"))] + pub previous_epoch_participation: List, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::collection_over_string"))] + pub current_epoch_participation: List, + pub justification_bits: Bitvector, + pub previous_justified_checkpoint: Checkpoint, + pub current_justified_checkpoint: Checkpoint, + pub finalized_checkpoint: Checkpoint, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::collection_over_string"))] + pub inactivity_scores: List, + pub current_sync_committee: SyncCommittee, + pub next_sync_committee: SyncCommittee, + pub latest_execution_payload_header: + ExecutionPayloadHeader, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub next_withdrawal_index: WithdrawalIndex, + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_string"))] + pub next_withdrawal_validator_index: ValidatorIndex, + pub historical_summaries: List, +} diff --git a/primitives/src/constants.rs b/primitives/src/constants.rs new file mode 100644 index 0000000..df7a024 --- /dev/null +++ b/primitives/src/constants.rs @@ -0,0 +1,138 @@ +use crate::domains::DomainType; +use ssz_rs::Node; + +pub type BlsPublicKey = ByteVector; +pub type BlsSignature = ByteVector; + +pub type Epoch = u64; +pub type Slot = u64; +pub type Root = Node; +pub type ParticipationFlags = u8; + +pub type CommitteeIndex = u64; +pub type ValidatorIndex = u64; +pub type WithdrawalIndex = u64; +pub type Gwei = u64; +pub type Hash32 = Bytes32; + +pub type Version = [u8; 4]; +pub type ForkDigest = [u8; 4]; +pub type Domain = [u8; 32]; + +pub type ExecutionAddress = ByteVector<20>; + +pub type ChainId = usize; +pub type NetworkId = usize; + +pub type RandaoReveal = BlsSignature; +pub type Bytes32 = ByteVector<32>; + +pub const BLS_PUBLIC_KEY_BYTES_LEN: usize = 48; +pub const BLS_SECRET_KEY_BYTES_LEN: usize = 32; +pub const BLS_SIGNATURE_BYTES_LEN: usize = 96; + +pub const SYNC_COMMITTEE_SIZE: usize = 512; +pub const EPOCHS_PER_SYNC_COMMITTEE_PERIOD: Epoch = 256; + +pub const MAX_VALIDATORS_PER_COMMITTEE: usize = 2048; +pub const EPOCHS_PER_ETH1_VOTING_PERIOD: Epoch = 64; +pub const SLOTS_PER_HISTORICAL_ROOT: usize = 8192; +pub const EPOCHS_PER_HISTORICAL_VECTOR: usize = 65536; +pub const EPOCHS_PER_SLASHINGS_VECTOR: usize = 8192; +pub const HISTORICAL_ROOTS_LIMIT: usize = 16_777_216; +pub const VALIDATOR_REGISTRY_LIMIT: usize = 2usize.saturating_pow(40); +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 JUSTIFICATION_BITS_LENGTH: usize = 4; + +pub const MAX_BYTES_PER_TRANSACTION: usize = 1_073_741_824; +pub const MAX_TRANSACTIONS_PER_PAYLOAD: usize = 1_048_576; +pub const BYTES_PER_LOGS_BLOOM: usize = 256; +pub const MAX_EXTRA_DATA_BYTES: usize = 32; + +pub const DEPOSIT_PROOF_LENGTH: usize = 33; + +pub const ETH1_DATA_VOTES_BOUND: usize = (EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH) as usize; +pub const DOMAIN_SYNC_COMMITTEE: DomainType = DomainType::SyncCommittee; +pub const FINALIZED_ROOT_INDEX: u64 = 52; +pub const EXECUTION_PAYLOAD_STATE_ROOT_INDEX: u64 = 18; +pub const EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX: u64 = 22; +pub const EXECUTION_PAYLOAD_INDEX: u64 = 56; +pub const NEXT_SYNC_COMMITTEE_INDEX: u64 = 55; +pub const BLOCK_ROOTS_INDEX: u64 = 37; +pub const HISTORICAL_ROOTS_INDEX: u64 = 39; +pub const HISTORICAL_BATCH_BLOCK_ROOTS_INDEX: u64 = 2; +pub const EXECUTION_PAYLOAD_TIMESTAMP_INDEX: u64 = 25; +pub const FINALIZED_ROOT_INDEX_LOG2: u64 = 5; +pub const EXECUTION_PAYLOAD_INDEX_LOG2: u64 = 5; +pub const NEXT_SYNC_COMMITTEE_INDEX_LOG2: u64 = 5; +pub const BLOCK_ROOTS_INDEX_LOG2: u64 = 5; +pub const HISTORICAL_ROOTS_INDEX_LOG2: u64 = 5; + +#[cfg(feature = "testnet")] +pub use testnet::*; + +#[cfg(feature = "mainnet")] +pub use mainnet::*; + +use crate::ssz::ByteVector; +#[cfg(all(not(feature = "mainnet"), not(feature = "testnet")))] +pub use devnet::*; + +#[cfg(feature = "testnet")] +pub mod testnet { + use super::*; + pub const SLOTS_PER_EPOCH: Slot = 32; + pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = + hex_literal::hex!("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"); + pub const BELLATRIX_FORK_VERSION: Version = [3, 0, 16, 32]; + pub const ALTAIR_FORK_VERSION: Version = [1, 0, 16, 32]; + pub const GENESIS_FORK_VERSION: Version = [0; 4]; + pub const ALTAIR_FORK_EPOCH: Epoch = 36660; + pub const BELLATRIX_FORK_EPOCH: Epoch = 112260; + pub const CAPELLA_FORK_EPOCH: Epoch = u64::MAX; + pub const CAPELLA_FORK_VERSION: Version = [3, 0, 16, 32]; + pub const MAX_WITHDRAWALS_PER_PAYLOAD: usize = 16; + pub const MAX_BLS_TO_EXECUTION_CHANGES: usize = 16; + pub const MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: usize = 16384; +} + +#[cfg(feature = "mainnet")] +pub mod mainnet { + use super::*; + pub const SLOTS_PER_EPOCH: Slot = 32; + pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = + hex_literal::hex!("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"); + pub const BELLATRIX_FORK_VERSION: Version = [2, 0, 0, 0]; + pub const ALTAIR_FORK_VERSION: Version = [1, 0, 0, 0]; + pub const GENESIS_FORK_VERSION: Version = [0, 0, 0, 0]; + pub const ALTAIR_FORK_EPOCH: Epoch = 74240; + pub const BELLATRIX_FORK_EPOCH: Epoch = 144896; + pub const CAPELLA_FORK_EPOCH: Epoch = u64::MAX; + pub const CAPELLA_FORK_VERSION: Version = [3, 0, 0, 0]; + pub const MAX_WITHDRAWALS_PER_PAYLOAD: usize = 16; + pub const MAX_BLS_TO_EXECUTION_CHANGES: usize = 16; + pub const MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: usize = 16384; +} + +#[cfg(all(not(feature = "mainnet"), not(feature = "testnet")))] +pub mod devnet { + use super::*; + use hex_literal::hex; + pub const SLOTS_PER_EPOCH: Slot = 6; + pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = + hex_literal::hex!("83431ec7fcf92cfc44947fc0418e831c25e1d0806590231c439830db7ad54fda"); + pub const BELLATRIX_FORK_VERSION: Version = hex!("52525502"); + pub const ALTAIR_FORK_VERSION: Version = hex!("52525501"); + pub const GENESIS_FORK_VERSION: Version = hex!("52525500"); + pub const ALTAIR_FORK_EPOCH: Epoch = 0; + pub const BELLATRIX_FORK_EPOCH: Epoch = 0; + pub const CAPELLA_FORK_EPOCH: Epoch = 2; + pub const CAPELLA_FORK_VERSION: Version = hex!("52525503"); + pub const MAX_WITHDRAWALS_PER_PAYLOAD: usize = 16; + pub const MAX_BLS_TO_EXECUTION_CHANGES: usize = 16; + pub const MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: usize = 16384; +} diff --git a/primitives/src/derived_types.rs b/primitives/src/derived_types.rs deleted file mode 100644 index 3610e22..0000000 --- a/primitives/src/derived_types.rs +++ /dev/null @@ -1,488 +0,0 @@ -use crate::{ - error::Error, - helpers::{ - to_codec_light_client_state, to_codec_light_client_update, to_no_codec_beacon_header, - to_no_codec_light_client_state, to_no_codec_light_client_update, - to_no_codec_sync_committee, - }, - types, -}; -use alloc::vec::Vec; -use codec::{Decode, Encode}; -use ethereum_consensus::{bellatrix, primitives::Hash32}; - -/// Minimum state required by the light client to validate new sync committee attestations -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, Default)] -pub struct LightClientState { - /// The latest recorded finalized header - pub finalized_header: BeaconBlockHeader, - /// Latest finalized epoch - pub latest_finalized_epoch: u64, - // Sync committees corresponding to the finalized header - pub current_sync_committee: SyncCommittee, - pub next_sync_committee: SyncCommittee, -} - -impl TryFrom> - for LightClientState -{ - type Error = Error; - fn try_from(state: types::LightClientState) -> Result { - to_codec_light_client_state(state) - } -} - -impl TryFrom - for types::LightClientState -{ - type Error = Error; - fn try_from(state: LightClientState) -> Result { - to_no_codec_light_client_state(state) - } -} - -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, Default)] -pub struct BeaconBlockHeader { - pub slot: u64, - pub proposer_index: u64, - pub parent_root: [u8; 32], - pub state_root: [u8; 32], - pub body_root: [u8; 32], -} - -impl TryFrom for BeaconBlockHeader { - type Error = Error; - - fn try_from(beacon_block_header: bellatrix::BeaconBlockHeader) -> Result { - Ok(BeaconBlockHeader { - slot: beacon_block_header.slot, - proposer_index: beacon_block_header.proposer_index as u64, - parent_root: beacon_block_header - .parent_root - .as_bytes() - .try_into() - .map_err(|_| Error::InvalidNodeBytes)?, - state_root: beacon_block_header - .state_root - .as_bytes() - .try_into() - .map_err(|_| Error::InvalidNodeBytes)?, - body_root: beacon_block_header - .body_root - .as_bytes() - .try_into() - .map_err(|_| Error::InvalidNodeBytes)?, - }) - } -} - -#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, Default)] -pub struct SyncCommittee { - pub public_keys: Vec>, - pub aggregate_public_key: Vec, -} - -impl TryFrom> - for SyncCommittee -{ - type Error = Error; - - fn try_from( - sync_committee: bellatrix::SyncCommittee, - ) -> Result { - Ok(SyncCommittee { - public_keys: sync_committee - .public_keys - .iter() - .map(|public_key| public_key.to_vec()) - .collect(), - aggregate_public_key: sync_committee.aggregate_public_key.to_vec(), - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] -pub struct LightClientUpdate { - /// the header that the sync committee signed - pub attested_header: BeaconBlockHeader, - /// the sync committee has potentially changed, here's an ssz proof for that. - pub sync_committee_update: Option, - /// the actual header which was finalized by the ethereum attestation protocol. - pub finalized_header: BeaconBlockHeader, - /// execution payload of the finalized header - pub execution_payload: ExecutionPayloadProof, - /// Finalized header proof - pub finality_proof: FinalityProof, - /// signature & participation bits - pub sync_aggregate: SyncAggregate, - /// slot at which signature was produced - pub signature_slot: u64, - /// ancestors of the finalized block to be verified, may be empty. - pub ancestor_blocks: Vec, -} - -impl TryFrom> - for LightClientUpdate -{ - type Error = Error; - fn try_from( - update: types::LightClientUpdate, - ) -> Result { - to_codec_light_client_update(update) - } -} - -impl TryFrom - for types::LightClientUpdate -{ - type Error = Error; - fn try_from(derived_update: LightClientUpdate) -> Result { - to_no_codec_light_client_update(derived_update) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] -pub struct SyncCommitteeUpdate { - // actual sync committee - pub next_sync_committee: SyncCommittee, - // sync committee, ssz merkle proof. - pub next_sync_committee_branch: Vec>, -} - -impl TryFrom> - for SyncCommitteeUpdate -{ - type Error = Error; - - fn try_from( - sync_committee_update: types::SyncCommitteeUpdate, - ) -> Result { - Ok(SyncCommitteeUpdate { - next_sync_committee: sync_committee_update.next_sync_committee.try_into()?, - next_sync_committee_branch: sync_committee_update - .next_sync_committee_branch - .iter() - .map(|hash| hash.to_vec()) - .collect(), - }) - } -} - -impl TryFrom - for types::SyncCommitteeUpdate -{ - type Error = Error; - - fn try_from(sync_committee_update: SyncCommitteeUpdate) -> Result { - let next_sync_committee = - to_no_codec_sync_committee(sync_committee_update.next_sync_committee)?; - Ok(types::SyncCommitteeUpdate { - next_sync_committee, - next_sync_committee_branch: sync_committee_update - .next_sync_committee_branch - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, Error>>()?, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] -pub struct ExecutionPayloadProof { - /// The state root in the `ExecutionPayload` which represents the commitment to - /// the ethereum world state in the yellow paper. - pub state_root: Vec, - /// the block number of the execution header. - pub block_number: u64, - /// merkle mutli proof for the state_root & block_number in the [`ExecutionPayload`]. - pub multi_proof: Vec>, - /// merkle proof for the `ExecutionPayload` in the [`BeaconBlockBody`]. - pub execution_payload_branch: Vec>, - /// timestamp - pub timestamp: u64, -} - -impl TryFrom for ExecutionPayloadProof { - type Error = Error; - fn try_from( - execution_payload_proof: types::ExecutionPayloadProof, - ) -> Result { - Ok(ExecutionPayloadProof { - state_root: execution_payload_proof.state_root.to_vec(), - block_number: execution_payload_proof.block_number, - multi_proof: execution_payload_proof - .multi_proof - .iter() - .map(|proof| proof.to_vec()) - .collect(), - execution_payload_branch: execution_payload_proof - .execution_payload_branch - .iter() - .map(|branch| branch.to_vec()) - .collect(), - timestamp: execution_payload_proof.timestamp, - }) - } -} - -impl TryFrom for types::ExecutionPayloadProof { - type Error = Error; - fn try_from( - derived_execution_payload_proof: ExecutionPayloadProof, - ) -> Result { - let multi_proof = derived_execution_payload_proof - .multi_proof - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?; - - let execution_payload_branch = derived_execution_payload_proof - .execution_payload_branch - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?; - - Ok(types::ExecutionPayloadProof { - state_root: Hash32::try_from(derived_execution_payload_proof.state_root.as_slice()) - .map_err(|_| Error::InvalidRoot)?, - block_number: derived_execution_payload_proof.block_number, - multi_proof, - execution_payload_branch, - timestamp: derived_execution_payload_proof.timestamp, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] -pub struct FinalityProof { - /// The latest finalized epoch - pub epoch: u64, - /// Finalized header proof - pub finality_branch: Vec>, -} - -impl TryFrom for FinalityProof { - type Error = Error; - fn try_from(finality_proof: types::FinalityProof) -> Result { - Ok(FinalityProof { - epoch: finality_proof.epoch, - finality_branch: finality_proof - .finality_branch - .iter() - .map(|branch| branch.to_vec()) - .collect(), - }) - } -} - -impl TryFrom for types::FinalityProof { - type Error = Error; - fn try_from(derived_finality_proof: FinalityProof) -> Result { - Ok(types::FinalityProof { - epoch: derived_finality_proof.epoch, - finality_branch: derived_finality_proof - .finality_branch - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default, Encode, Decode)] -pub struct SyncAggregate { - pub sync_committee_bits: Vec, - pub sync_committee_signature: Vec, -} - -impl TryFrom> - for SyncAggregate -{ - type Error = Error; - fn try_from( - sync_aggregate: bellatrix::SyncAggregate, - ) -> Result { - Ok(SyncAggregate { - sync_committee_bits: sync_aggregate.sync_committee_bits.clone().to_bitvec().into_vec(), - sync_committee_signature: sync_aggregate.sync_committee_signature.clone().to_vec(), - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] -pub struct AncestorBlock { - /// The actual beacon chain header - pub header: BeaconBlockHeader, - /// Associated execution header proofs - pub execution_payload: ExecutionPayloadProof, - /// Ancestry proofs of the beacon chain header. - pub ancestry_proof: AncestryProof, -} - -impl TryFrom for AncestorBlock { - type Error = Error; - fn try_from(ancestor_block: types::AncestorBlock) -> Result { - Ok(AncestorBlock { - header: ancestor_block.header.try_into()?, - execution_payload: ancestor_block.execution_payload.try_into()?, - ancestry_proof: ancestor_block.ancestry_proof.try_into()?, - }) - } -} - -impl TryFrom for types::AncestorBlock { - type Error = Error; - fn try_from(derived_ancestor_block: AncestorBlock) -> Result { - let beacon_block_header = to_no_codec_beacon_header(derived_ancestor_block.header)?; - Ok(types::AncestorBlock { - header: beacon_block_header, - execution_payload: derived_ancestor_block.execution_payload.try_into()?, - ancestry_proof: derived_ancestor_block.ancestry_proof.try_into()?, - }) - } -} - -/// Holds the neccessary proofs required to verify a header in the `block_roots` field -/// either in [`BeaconState`] or [`HistoricalBatch`]. -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] -pub struct BlockRootsProof { - /// Generalized index of the header in the `block_roots` list. - pub block_header_index: u64, - /// The proof for the header, needed to reconstruct `hash_tree_root(state.block_roots)` - pub block_header_branch: Vec>, -} - -impl TryFrom for BlockRootsProof { - type Error = Error; - fn try_from(beacon_block_header: types::BlockRootsProof) -> Result { - Ok(BlockRootsProof { - block_header_index: beacon_block_header.block_header_index, - block_header_branch: beacon_block_header - .block_header_branch - .iter() - .map(|hash| hash.to_vec()) - .collect(), - }) - } -} - -impl TryFrom for types::BlockRootsProof { - type Error = Error; - fn try_from(derived_beacon_block_header: BlockRootsProof) -> Result { - let branch = derived_beacon_block_header - .block_header_branch - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?; - - Ok(types::BlockRootsProof { - block_header_index: derived_beacon_block_header.block_header_index, - block_header_branch: branch, - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] -pub enum AncestryProof { - /// This variant defines the proof data for a beacon chain header in the `state.block_roots` - BlockRoots { - /// Proof for the header in `state.block_roots` - block_roots_proof: BlockRootsProof, - /// The proof for the reconstructed `hash_tree_root(state.block_roots)` in [`BeaconState`] - block_roots_branch: Vec>, - }, - /// This variant defines the neccessary proofs for a beacon chain header in the - /// `state.historical_roots`. - HistoricalRoots { - /// Proof for the header in `historical_batch.block_roots` - block_roots_proof: BlockRootsProof, - /// The proof for the `historical_batch.block_roots`, needed to reconstruct - /// `hash_tree_root(historical_batch)` - historical_batch_proof: Vec>, - /// The proof for the `hash_tree_root(historical_batch)` in `state.historical_roots` - historical_roots_proof: Vec>, - /// The generalized index for the historical_batch in `state.historical_roots`. - historical_roots_index: u64, - /// The proof for the reconstructed `hash_tree_root(state.historical_roots)` in - /// [`BeaconState`] - historical_roots_branch: Vec>, - }, -} - -impl TryFrom for AncestryProof { - type Error = Error; - fn try_from(ancestry_proof: types::AncestryProof) -> Result { - Ok(match ancestry_proof { - types::AncestryProof::BlockRoots { block_roots_proof, block_roots_branch } => - AncestryProof::BlockRoots { - block_roots_proof: block_roots_proof.try_into()?, - block_roots_branch: block_roots_branch - .iter() - .map(|hash| hash.to_vec()) - .collect(), - }, - types::AncestryProof::HistoricalRoots { - block_roots_proof, - historical_batch_proof, - historical_roots_proof, - historical_roots_index, - historical_roots_branch, - } => AncestryProof::HistoricalRoots { - block_roots_proof: block_roots_proof.try_into()?, - historical_batch_proof: historical_batch_proof - .iter() - .map(|hash| hash.to_vec()) - .collect(), - historical_roots_proof: historical_roots_proof - .iter() - .map(|hash| hash.to_vec()) - .collect(), - historical_roots_index, - historical_roots_branch: historical_roots_branch - .iter() - .map(|hash| hash.to_vec()) - .collect(), - }, - }) - } -} - -impl TryFrom for types::AncestryProof { - type Error = Error; - fn try_from(ancestry_proof: AncestryProof) -> Result { - Ok(match ancestry_proof { - AncestryProof::BlockRoots { block_roots_proof, block_roots_branch } => - types::AncestryProof::BlockRoots { - block_roots_proof: block_roots_proof.try_into()?, - block_roots_branch: block_roots_branch - .iter() - .map(|proof| { - Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof) - }) - .collect::, _>>()?, - }, - AncestryProof::HistoricalRoots { - block_roots_proof, - historical_batch_proof, - historical_roots_proof, - historical_roots_index, - historical_roots_branch, - } => types::AncestryProof::HistoricalRoots { - block_roots_proof: block_roots_proof.try_into()?, - historical_batch_proof: historical_batch_proof - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?, - historical_roots_proof: historical_roots_proof - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?, - historical_roots_index, - historical_roots_branch: historical_roots_branch - .iter() - .map(|proof| Hash32::try_from(proof.as_ref()).map_err(|_| Error::InvalidProof)) - .collect::, _>>()?, - }, - }) - } -} diff --git a/primitives/src/domains.rs b/primitives/src/domains.rs new file mode 100644 index 0000000..fd8bd65 --- /dev/null +++ b/primitives/src/domains.rs @@ -0,0 +1,29 @@ +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum DomainType { + BeaconProposer, + BeaconAttester, + Randao, + Deposit, + VoluntaryExit, + SelectionProof, + AggregateAndProof, + SyncCommittee, + SyncCommitteeSelectionProof, + ContributionAndProof, + BlsToExecutionChange, + ApplicationMask, + ApplicationBuilder, +} + +impl DomainType { + pub fn as_bytes(&self) -> [u8; 4] { + match self { + Self::ApplicationMask => [0, 0, 0, 1], + Self::ApplicationBuilder => [0, 0, 0, 1], + _ => { + let data = *self as u32; + data.to_le_bytes() + }, + } + } +} diff --git a/primitives/src/helpers.rs b/primitives/src/helpers.rs deleted file mode 100644 index b16e8b9..0000000 --- a/primitives/src/helpers.rs +++ /dev/null @@ -1,162 +0,0 @@ -use crate::{ - derived_types, - error::Error, - types, - types::{LightClientState, LightClientUpdate, SyncCommitteeUpdate}, -}; -use alloc::vec::Vec; -use ethereum_consensus::{ - bellatrix::{BeaconBlockHeader, SyncAggregate, SyncCommittee}, - crypto::PublicKey, - primitives::BlsSignature, -}; -use ssz_rs::{Bitvector, Deserialize, Node, Vector}; - -pub fn to_no_codec_beacon_header( - derived_header: derived_types::BeaconBlockHeader, -) -> Result { - let finalized_header = BeaconBlockHeader { - slot: derived_header.slot, - proposer_index: derived_header.proposer_index as usize, - parent_root: Node::from_bytes( - derived_header.parent_root.as_ref().try_into().map_err(|_| Error::InvalidRoot)?, - ), - state_root: Node::from_bytes( - derived_header.state_root.as_ref().try_into().map_err(|_| Error::InvalidRoot)?, - ), - body_root: Node::from_bytes( - derived_header.body_root.as_ref().try_into().map_err(|_| Error::InvalidRoot)?, - ), - }; - - Ok(finalized_header) -} - -pub fn to_no_codec_sync_committee( - derived_sync_committee: derived_types::SyncCommittee, -) -> Result, Error> { - let public_keys_vector: Vec = derived_sync_committee - .public_keys - .iter() - .map(|public_key| { - PublicKey::try_from(public_key.as_slice()).map_err(|_| Error::InvalidPublicKey) - }) - .collect::, Error>>()?; - let sync_committee = SyncCommittee { - public_keys: Vector::try_from(public_keys_vector).unwrap(), - aggregate_public_key: PublicKey::try_from( - derived_sync_committee.aggregate_public_key.as_slice(), - ) - .map_err(|_| Error::InvalidPublicKey)?, - }; - - Ok(sync_committee) -} - -pub fn to_no_codec_sync_aggregate( - derived_sync_aggregate: derived_types::SyncAggregate, -) -> Result, Error> { - let derived_sync_committee_bits = derived_sync_aggregate.sync_committee_bits; - let bit_vector = Bitvector::::deserialize(&derived_sync_committee_bits) - .map_err(|_| Error::InvalidBitVec)?; - - let sync_aggregate = SyncAggregate { - sync_committee_bits: bit_vector, - sync_committee_signature: BlsSignature::try_from( - derived_sync_aggregate.sync_committee_signature.as_ref(), - ) - .map_err(|_| Error::InvalidPublicKey)?, - }; - - Ok(sync_aggregate) -} - -pub fn to_no_codec_light_client_state( - state: derived_types::LightClientState, -) -> Result, Error> { - let finalized_header = to_no_codec_beacon_header(state.finalized_header)?; - - let current_sync_committee = to_no_codec_sync_committee(state.current_sync_committee.clone())?; - let next_sync_committee = to_no_codec_sync_committee(state.next_sync_committee)?; - - Ok(LightClientState { - finalized_header, - latest_finalized_epoch: state.latest_finalized_epoch, - current_sync_committee, - next_sync_committee, - }) -} - -pub fn to_no_codec_light_client_update( - derived_update: derived_types::LightClientUpdate, -) -> Result, Error> { - let sync_committee_update_option: Option>; - - match derived_update.sync_committee_update { - Some(sync_committee_update) => - sync_committee_update_option = Some(sync_committee_update.try_into()?), - None => sync_committee_update_option = None, - } - Ok(LightClientUpdate { - attested_header: to_no_codec_beacon_header(derived_update.attested_header)?, - sync_committee_update: sync_committee_update_option, - finalized_header: to_no_codec_beacon_header(derived_update.finalized_header)?, - execution_payload: derived_update.execution_payload.try_into()?, - finality_proof: derived_update.finality_proof.try_into()?, - sync_aggregate: to_no_codec_sync_aggregate(derived_update.sync_aggregate)?, - signature_slot: derived_update.signature_slot, - ancestor_blocks: derived_update - .ancestor_blocks - .iter() - .map(|ancestor_block| { - ancestor_block - .clone() - .try_into() - .map_err(|_| Error::ErrorConvertingAncestorBlock) - }) - .collect::, Error>>()?, - }) -} - -pub fn to_codec_light_client_state( - state: types::LightClientState, -) -> Result { - Ok(derived_types::LightClientState { - finalized_header: state.finalized_header.try_into()?, - latest_finalized_epoch: state.latest_finalized_epoch, - current_sync_committee: state.current_sync_committee.try_into()?, - next_sync_committee: state.next_sync_committee.try_into()?, - }) -} - -pub fn to_codec_light_client_update( - update: types::LightClientUpdate, -) -> Result { - let sync_committee_update_option: Option; - - match update.sync_committee_update { - Some(sync_committee_update) => - sync_committee_update_option = Some(sync_committee_update.try_into()?), - - None => sync_committee_update_option = None, - } - Ok(derived_types::LightClientUpdate { - attested_header: update.attested_header.try_into()?, - sync_committee_update: sync_committee_update_option, - finalized_header: update.finalized_header.try_into()?, - execution_payload: update.execution_payload.try_into()?, - finality_proof: update.finality_proof.try_into()?, - sync_aggregate: update.sync_aggregate.try_into()?, - signature_slot: update.signature_slot, - ancestor_blocks: update - .ancestor_blocks - .iter() - .map(|ancestor_block| { - ancestor_block - .clone() - .try_into() - .map_err(|_| Error::ErrorConvertingAncestorBlock) - }) - .collect::, Error>>()?, - }) -} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index b53869e..afce5f5 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -1,10 +1,16 @@ +//! Primitive types for sync committee verifier +//! This crate contains code adapted from https://github.com/ralexstokes/ethereum-consensus #![cfg_attr(not(feature = "std"), no_std)] #[warn(unused_imports)] #[warn(unused_variables)] extern crate alloc; -pub mod derived_types; +pub mod consensus_types; +pub mod constants; +pub mod domains; pub mod error; -pub mod helpers; +#[cfg(feature = "std")] +pub mod serde; +mod ssz; pub mod types; pub mod util; diff --git a/primitives/src/serde.rs b/primitives/src/serde.rs new file mode 100644 index 0000000..e1c59c7 --- /dev/null +++ b/primitives/src/serde.rs @@ -0,0 +1,142 @@ +use core::fmt::{Display, Formatter}; +use hex::FromHexError; + +const HEX_ENCODING_PREFIX: &str = "0x"; + +#[cfg_attr(feature = "serde", derive(Debug))] +pub enum HexError { + Hex, + MissingPrefix, +} + +impl From for HexError { + fn from(_: FromHexError) -> Self { + HexError::Hex + } +} + +impl Display for HexError { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + HexError::Hex => write!(f, ""), + HexError::MissingPrefix => write!(f, "missing prefix when deserializing hex data"), + } + } +} + +pub fn try_bytes_from_hex_str(s: &str) -> Result, HexError> { + let target = s.strip_prefix(HEX_ENCODING_PREFIX).ok_or(HexError::MissingPrefix)?; + let data = hex::decode(target)?; + Ok(data) +} + +pub mod as_hex { + use super::*; + use alloc::format; + use serde::de::Deserialize; + + pub fn serialize>(data: T, serializer: S) -> Result + where + S: serde::Serializer, + { + let encoding = hex::encode(data.as_ref()); + let output = format!("{HEX_ENCODING_PREFIX}{encoding}"); + serializer.collect_str(&output) + } + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + T: TryFrom>, + { + let s = ::deserialize(deserializer)?; + + let data = try_bytes_from_hex_str(&s).map_err(serde::de::Error::custom)?; + + let inner = T::try_from(data) + .map_err(|_| serde::de::Error::custom("type failed to parse bytes from hex data"))?; + Ok(inner) + } +} + +pub mod as_string { + use alloc::format; + use core::{fmt, str::FromStr}; + use serde::de::Deserialize; + + pub fn serialize(data: T, serializer: S) -> Result + where + S: serde::Serializer, + { + let output = format!("{data}"); + serializer.collect_str(&output) + } + + pub fn deserialize<'de, D, T: FromStr>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s: String = ::deserialize(deserializer)?; + let inner: T = s + .parse() + .map_err(|_| serde::de::Error::custom("failure to parse string data"))?; + Ok(inner) + } +} + +pub mod collection_over_string { + use core::{fmt, marker::PhantomData, str::FromStr}; + use serde::{ + de::{Deserializer, Error}, + ser::SerializeSeq, + }; + + pub fn serialize(data: T, serializer: S) -> Result + where + S: serde::Serializer, + T: AsRef<[U]>, + U: fmt::Display, + { + let mut seq = serializer.serialize_seq(None)?; + for elem in data.as_ref().iter() { + let rendered_elem = format!("{elem}"); + seq.serialize_element(&rendered_elem)?; + } + seq.end() + } + + struct Visitor(PhantomData>); + + impl<'de, T: FromStr> serde::de::Visitor<'de> for Visitor { + type Value = Vec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("array of string") + } + + fn visit_seq(self, mut access: S) -> Result + where + S: serde::de::SeqAccess<'de>, + { + let mut coll = Vec::with_capacity(access.size_hint().unwrap_or(0)); + + while let Some(elem) = access.next_element()? { + let recovered_elem = T::from_str(elem).map_err(|_| { + Error::custom("failure to parse element of sequence from string") + })?; + coll.push(recovered_elem); + } + Ok(coll) + } + } + + pub fn deserialize<'de, D, T, U>(deserializer: D) -> Result + where + D: Deserializer<'de>, + T: TryFrom>, + U: FromStr, + { + let data = deserializer.deserialize_seq(Visitor(PhantomData))?; + T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse collection")) + } +} diff --git a/primitives/src/ssz/byte_list.rs b/primitives/src/ssz/byte_list.rs new file mode 100644 index 0000000..a22b2c1 --- /dev/null +++ b/primitives/src/ssz/byte_list.rs @@ -0,0 +1,88 @@ +use super::write_bytes_to_lower_hex; +use alloc::{vec, vec::Vec}; +use core::{ + fmt, + hash::{Hash, Hasher}, + ops::{Deref, DerefMut}, +}; +use ssz_rs::prelude::*; + +#[derive(Default, Clone, Eq, SimpleSerialize, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ByteList( + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_hex"))] List, +); + +impl TryFrom<&[u8]> for ByteList { + type Error = ssz_rs::DeserializeError; + + fn try_from(bytes: &[u8]) -> Result { + ByteList::::deserialize(bytes) + } +} + +// impl here to satisfy clippy +impl PartialEq for ByteList { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Hash for ByteList { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +impl fmt::LowerHex for ByteList { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_bytes_to_lower_hex(f, self) + } +} + +impl fmt::Debug for ByteList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ByteList<{N}>(len={})({:#x})", self.len(), self) + } +} + +impl fmt::Display for ByteList { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self:#x}") + } +} + +impl AsRef<[u8]> for ByteList { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl Deref for ByteList { + type Target = List; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ByteList { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_byte_list_serde() { + let list = ByteList::<32>::try_from([255u8, 255u8].as_ref()).unwrap(); + let encoding = ssz_rs::serialize(&list).unwrap(); + assert_eq!(encoding, [255, 255]); + + let recovered_list = ByteList::<32>::deserialize(&encoding).unwrap(); + assert_eq!(list, recovered_list); + } +} diff --git a/primitives/src/ssz/byte_vector.rs b/primitives/src/ssz/byte_vector.rs new file mode 100644 index 0000000..1b1b5ba --- /dev/null +++ b/primitives/src/ssz/byte_vector.rs @@ -0,0 +1,81 @@ +use super::write_bytes_to_lower_hex; +use alloc::{vec, vec::Vec}; +use core::{ + fmt, + hash::{Hash, Hasher}, + ops::{Deref, DerefMut}, +}; +use ssz_rs::prelude::*; + +#[derive(Default, Clone, Eq, SimpleSerialize, codec::Encode, codec::Decode)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] +pub struct ByteVector( + #[cfg_attr(feature = "serde", serde(with = "crate::serde::as_hex"))] Vector, +); + +impl TryFrom<&[u8]> for ByteVector { + type Error = ssz_rs::DeserializeError; + + fn try_from(bytes: &[u8]) -> Result { + ByteVector::::deserialize(bytes) + } +} + +impl TryFrom> for ByteVector { + type Error = ssz_rs::DeserializeError; + + fn try_from(bytes: Vec) -> Result { + ByteVector::::deserialize(&bytes) + } +} + +// impl here to satisfy clippy +impl PartialEq for ByteVector { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl Hash for ByteVector { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + } +} + +impl fmt::LowerHex for ByteVector { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write_bytes_to_lower_hex(f, self) + } +} + +impl fmt::Debug for ByteVector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ByteVector<{N}>({self:#x})") + } +} + +impl fmt::Display for ByteVector { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self:#x}") + } +} + +impl AsRef<[u8]> for ByteVector { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl Deref for ByteVector { + type Target = Vector; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for ByteVector { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/primitives/src/ssz/mod.rs b/primitives/src/ssz/mod.rs new file mode 100644 index 0000000..ebeaa9b --- /dev/null +++ b/primitives/src/ssz/mod.rs @@ -0,0 +1,16 @@ +mod byte_list; +mod byte_vector; +use core::fmt; + +fn write_bytes_to_lower_hex>(f: &mut fmt::Formatter<'_>, data: T) -> fmt::Result { + if f.alternate() { + write!(f, "0x")?; + } + for i in data.as_ref() { + write!(f, "{i:02x}")?; + } + Ok(()) +} + +pub use byte_list::ByteList; +pub use byte_vector::ByteVector; diff --git a/primitives/src/types.rs b/primitives/src/types.rs index d5fc44b..c0ca114 100644 --- a/primitives/src/types.rs +++ b/primitives/src/types.rs @@ -1,69 +1,47 @@ -use alloc::vec::Vec; -use ethereum_consensus::{ - bellatrix::{BeaconBlockHeader, SyncAggregate, SyncCommittee}, - domains::DomainType, - primitives::{Hash32, Slot}, +use crate::{ + consensus_types::{BeaconBlockHeader, SyncAggregate, SyncCommittee}, + constants::{Slot, SYNC_COMMITTEE_SIZE}, }; - -pub const DOMAIN_SYNC_COMMITTEE: DomainType = DomainType::SyncCommittee; -pub const FINALIZED_ROOT_INDEX: u64 = 52; -pub const EXECUTION_PAYLOAD_STATE_ROOT_INDEX: u64 = 18; -pub const EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX: u64 = 22; -pub const EXECUTION_PAYLOAD_INDEX: u64 = 56; -pub const NEXT_SYNC_COMMITTEE_INDEX: u64 = 55; -pub const BLOCK_ROOTS_INDEX: u64 = 37; -pub const HISTORICAL_ROOTS_INDEX: u64 = 39; -pub const HISTORICAL_BATCH_BLOCK_ROOTS_INDEX: u64 = 2; -pub const EXECUTION_PAYLOAD_TIMESTAMP_INDEX: u64 = 25; -pub const FINALIZED_ROOT_INDEX_LOG2: u64 = 5; -pub const EXECUTION_PAYLOAD_INDEX_LOG2: u64 = 5; -pub const NEXT_SYNC_COMMITTEE_INDEX_LOG2: u64 = 5; -pub const BLOCK_ROOTS_INDEX_LOG2: u64 = 5; -pub const HISTORICAL_ROOTS_INDEX_LOG2: u64 = 5; - -#[cfg(not(feature = "testing"))] -pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = - hex_literal::hex!("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95"); -#[cfg(feature = "testing")] -pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = - hex_literal::hex!("6034f557b4560fc549ac0e2c63269deb07bfac7bf2bbd0b8b7d4d321240bffd9"); +use alloc::vec::Vec; +use primitive_types::H256; +use ssz_rs::Node; /// This holds the relevant data required to prove the state root in the execution payload. -#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default, codec::Encode, codec::Decode)] pub struct ExecutionPayloadProof { /// The state root in the `ExecutionPayload` which represents the commitment to /// the ethereum world state in the yellow paper. - pub state_root: Hash32, + pub state_root: H256, /// the block number of the execution header. pub block_number: u64, /// merkle mutli proof for the state_root & block_number in the [`ExecutionPayload`]. - pub multi_proof: Vec, + pub multi_proof: Vec, /// merkle proof for the `ExecutionPayload` in the [`BeaconBlockBody`]. - pub execution_payload_branch: Vec, + pub execution_payload_branch: Vec, /// timestamp pub timestamp: u64, } /// Holds the neccessary proofs required to verify a header in the `block_roots` field /// either in [`BeaconState`] or [`HistoricalBatch`]. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] pub struct BlockRootsProof { /// Generalized index of the header in the `block_roots` list. pub block_header_index: u64, /// The proof for the header, needed to reconstruct `hash_tree_root(state.block_roots)` - pub block_header_branch: Vec, + pub block_header_branch: Vec, } /// The block header ancestry proof, this is an enum because the header may either exist in /// `state.block_roots` or `state.historical_roots`. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] pub enum AncestryProof { /// This variant defines the proof data for a beacon chain header in the `state.block_roots` BlockRoots { /// Proof for the header in `state.block_roots` block_roots_proof: BlockRootsProof, /// The proof for the reconstructed `hash_tree_root(state.block_roots)` in [`BeaconState`] - block_roots_branch: Vec, + block_roots_branch: Vec, }, /// This variant defines the neccessary proofs for a beacon chain header in the /// `state.historical_roots`. @@ -72,20 +50,20 @@ pub enum AncestryProof { block_roots_proof: BlockRootsProof, /// The proof for the `historical_batch.block_roots`, needed to reconstruct /// `hash_tree_root(historical_batch)` - historical_batch_proof: Vec, + historical_batch_proof: Vec, /// The proof for the `hash_tree_root(historical_batch)` in `state.historical_roots` - historical_roots_proof: Vec, + historical_roots_proof: Vec, /// The generalized index for the historical_batch in `state.historical_roots`. historical_roots_index: u64, /// The proof for the reconstructed `hash_tree_root(state.historical_roots)` in /// [`BeaconState`] - historical_roots_branch: Vec, + historical_roots_branch: Vec, }, } /// This defines the neccesary data needed to prove ancestor blocks, relative to the finalized /// header. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, codec::Encode, codec::Decode)] pub struct AncestorBlock { /// The actual beacon chain header pub header: BeaconBlockHeader, @@ -97,17 +75,17 @@ pub struct AncestorBlock { /// Holds the latest sync committee as well as an ssz proof for it's existence /// in a finalized header. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct SyncCommitteeUpdate { +#[derive(Debug, Clone, PartialEq, Eq, Default, codec::Encode, codec::Decode)] +pub struct SyncCommitteeUpdate { // actual sync committee pub next_sync_committee: SyncCommittee, // sync committee, ssz merkle proof. - pub next_sync_committee_branch: Vec, + pub next_sync_committee_branch: Vec, } /// Minimum state required by the light client to validate new sync committee attestations -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct LightClientState { +#[derive(Debug, Clone, PartialEq, Eq, Default, codec::Encode, codec::Decode)] +pub struct LightClientState { /// The latest recorded finalized header pub finalized_header: BeaconBlockHeader, /// Latest finalized epoch @@ -118,21 +96,21 @@ pub struct LightClientState { } /// Finalized header proof -#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default, codec::Encode, codec::Decode)] pub struct FinalityProof { /// The latest finalized epoch pub epoch: u64, /// Finalized header proof - pub finality_branch: Vec, + pub finality_branch: Vec, } /// Data required to advance the state of the light client. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct LightClientUpdate { +#[derive(Debug, Clone, PartialEq, Eq, Default, codec::Encode, codec::Decode)] +pub struct LightClientUpdate { /// the header that the sync committee signed pub attested_header: BeaconBlockHeader, /// the sync committee has potentially changed, here's an ssz proof for that. - pub sync_committee_update: Option>, + pub sync_committee_update: Option, /// the actual header which was finalized by the ethereum attestation protocol. pub finalized_header: BeaconBlockHeader, /// execution payload of the finalized header @@ -143,6 +121,6 @@ pub struct LightClientUpdate { pub sync_aggregate: SyncAggregate, /// slot at which signature was produced pub signature_slot: Slot, - /// ancestors of the finalized block to be verified, may be empty. - pub ancestor_blocks: Vec, + // ancestors of the finalized block to be verified, may be empty. + // pub ancestor_blocks: Vec, } diff --git a/primitives/src/util.rs b/primitives/src/util.rs index 20701c9..4c1abaa 100644 --- a/primitives/src/util.rs +++ b/primitives/src/util.rs @@ -1,11 +1,15 @@ -use ethereum_consensus::{ - altair::mainnet::EPOCHS_PER_SYNC_COMMITTEE_PERIOD, - configs::mainnet::{ - ALTAIR_FORK_EPOCH, ALTAIR_FORK_VERSION, BELLATRIX_FORK_EPOCH, BELLATRIX_FORK_VERSION, - GENESIS_FORK_VERSION, +use crate::{ + consensus_types::ForkData, + constants::{ + Domain, Root, Version, ALTAIR_FORK_EPOCH, ALTAIR_FORK_VERSION, BELLATRIX_FORK_EPOCH, + BELLATRIX_FORK_VERSION, CAPELLA_FORK_EPOCH, CAPELLA_FORK_VERSION, + EPOCHS_PER_SYNC_COMMITTEE_PERIOD, GENESIS_FORK_VERSION, SLOTS_PER_EPOCH, }, - phase0::mainnet::SLOTS_PER_EPOCH, + domains::DomainType, }; +use alloc::{vec, vec::Vec}; +use anyhow::anyhow; +use ssz_rs::prelude::*; /// Return the sync committe period at the given ``epoch`` pub fn compute_sync_committee_period(epoch: u64) -> u64 { @@ -20,7 +24,9 @@ pub fn compute_epoch_at_slot(slot: u64) -> u64 { #[cfg(not(feature = "testing"))] /// Return the fork version at the given ``epoch``. pub fn compute_fork_version(epoch: u64) -> [u8; 4] { - if epoch >= BELLATRIX_FORK_EPOCH { + if epoch >= CAPELLA_FORK_EPOCH { + CAPELLA_FORK_VERSION + } else if epoch >= BELLATRIX_FORK_EPOCH { BELLATRIX_FORK_VERSION } else if epoch >= ALTAIR_FORK_EPOCH { ALTAIR_FORK_VERSION @@ -29,9 +35,44 @@ pub fn compute_fork_version(epoch: u64) -> [u8; 4] { } } -#[cfg(feature = "testing")] -pub fn compute_fork_version(_epoch: u64) -> [u8; 4] { - BELLATRIX_FORK_VERSION +pub fn compute_domain( + domain_type: DomainType, + fork_version: Option, + genesis_validators_root: Option, + genesis_fork_version: Version, +) -> Result { + let fork_version = fork_version.unwrap_or(genesis_fork_version); + let genesis_validators_root = genesis_validators_root.unwrap_or_default(); + let fork_data_root = compute_fork_data_root(fork_version, genesis_validators_root)?; + let mut domain = Domain::default(); + domain[..4].copy_from_slice(&domain_type.as_bytes()); + domain[4..].copy_from_slice(&fork_data_root.as_ref()[..28]); + Ok(domain) +} + +#[derive(Default, Debug, SimpleSerialize)] +pub struct SigningData { + pub object_root: Root, + pub domain: Domain, +} + +pub fn compute_signing_root( + ssz_object: &mut T, + domain: Domain, +) -> Result { + let object_root = ssz_object.hash_tree_root().map_err(|e| anyhow!("{:?}", e))?; + + let mut s = SigningData { object_root, domain }; + s.hash_tree_root().map_err(|e| anyhow!("{:?}", e)) +} + +pub fn compute_fork_data_root( + current_version: Version, + genesis_validators_root: Root, +) -> Result { + ForkData { current_version, genesis_validators_root } + .hash_tree_root() + .map_err(|e| anyhow!("{:?}", e)) } /// Return the sync committee period at ``slot`` diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 5ec1cae..1abc687 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -8,22 +8,41 @@ edition = "2021" [dependencies] sync-committee-primitives = { path= "../primitives" } sync-committee-verifier = { path= "../verifier" } -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main" } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" } reqwest = {version="0.11.14", features=["json"]} -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0.185", features = ["derive"] } serde_json = { version = "1.0.81"} anyhow = "1.0.68" -actix-rt = "*" -tokio = { version = "1.18.2", features = ["full"]} +tokio = { version = "1.32.0", features = ["sync"]} tokio-stream = { version = "0.1.8" } async-stream = { version = "0.3.3"} -base2 = {version= "0.3.1", default-features=false} +base2 = {version= "0.3.1" } env_logger = "0.10.0" +ark-ec = { version = "0.4.2" } +ark-bls12-381 = { version = "0.4.0" } +bls_on_arkworks = { version = "0.2.2" } +primitive-types = { version = "0.12.1", features = ["serde_no_std", "impl-codec"] } +log = "0.4.20" +hex = "0.4.3" [dev-dependencies] -hex = "0.4.3" -sync-committee-primitives = { path= "../primitives", features = ["testing"] } -sync-committee-verifier = { path= "../verifier", features = ["testing"] } +env_logger = "0.10.0" +sync-committee-primitives = { path= "../primitives" } +sync-committee-verifier = { path= "../verifier" } +ethers = { version = "2.0.8", features = ["ws"] } +tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"]} + +[features] +default = ["std"] +std = [ + "ssz-rs/default", + "sync-committee-primitives/std", + "anyhow/std", + "ark-ec/std", + "bls_on_arkworks/std", + "ark-bls12-381/std" +] +testnet = ["sync-committee-primitives/testnet", "sync-committee-verifier/testnet"] +mainnet = ["sync-committee-primitives/mainnet", "sync-committee-verifier/mainnet"] diff --git a/prover/src/lib.rs b/prover/src/lib.rs index a519aca..5fe4bfe 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -5,11 +5,14 @@ mod routes; #[cfg(test)] mod test; -use ethereum_consensus::{ - altair::Validator, - bellatrix::{BeaconBlock, BeaconBlockHeader, BeaconState, SyncCommittee}, -}; +use anyhow::anyhow; +use bls_on_arkworks::{point_to_pubkey, types::G1ProjectivePoint}; +use log::debug; use reqwest::Client; +use std::time::Duration; +use sync_committee_primitives::consensus_types::{ + BeaconBlock, BeaconBlockHeader, BeaconState, SyncCommittee, Validator, +}; use crate::{ responses::{ @@ -18,30 +21,28 @@ use crate::{ }, routes::*, }; -use ethereum_consensus::{ - bellatrix::mainnet::{ - BYTES_PER_LOGS_BLOOM, MAX_BYTES_PER_TRANSACTION, MAX_EXTRA_DATA_BYTES, - MAX_TRANSACTIONS_PER_PAYLOAD, SYNC_COMMITTEE_SIZE, - }, - crypto::eth_aggregate_public_keys, - phase0::mainnet::{ - EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR, ETH1_DATA_VOTES_BOUND, - HISTORICAL_ROOTS_LIMIT, MAX_ATTESTATIONS, MAX_ATTESTER_SLASHINGS, MAX_DEPOSITS, - MAX_PROPOSER_SLASHINGS, MAX_VALIDATORS_PER_COMMITTEE, MAX_VOLUNTARY_EXITS, SLOTS_PER_EPOCH, - SLOTS_PER_HISTORICAL_ROOT, VALIDATOR_REGISTRY_LIMIT, - }, - primitives::{BlsPublicKey, Bytes32, Hash32, ValidatorIndex}, -}; +use primitive_types::H256; use ssz_rs::{List, Merkleized, Node, Vector}; use sync_committee_primitives::{ - types::{ - AncestryProof, BlockRootsProof, ExecutionPayloadProof, BLOCK_ROOTS_INDEX, + constants::{ + BlsPublicKey, ValidatorIndex, BLOCK_ROOTS_INDEX, BYTES_PER_LOGS_BLOOM, + EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR, ETH1_DATA_VOTES_BOUND, EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX, EXECUTION_PAYLOAD_INDEX, EXECUTION_PAYLOAD_STATE_ROOT_INDEX, EXECUTION_PAYLOAD_TIMESTAMP_INDEX, - FINALIZED_ROOT_INDEX, NEXT_SYNC_COMMITTEE_INDEX, + FINALIZED_ROOT_INDEX, HISTORICAL_ROOTS_LIMIT, MAX_ATTESTATIONS, MAX_ATTESTER_SLASHINGS, + MAX_BLS_TO_EXECUTION_CHANGES, MAX_BYTES_PER_TRANSACTION, MAX_DEPOSITS, + MAX_EXTRA_DATA_BYTES, MAX_PROPOSER_SLASHINGS, MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_VALIDATORS_PER_COMMITTEE, MAX_VOLUNTARY_EXITS, MAX_WITHDRAWALS_PER_PAYLOAD, + NEXT_SYNC_COMMITTEE_INDEX, SLOTS_PER_EPOCH, SLOTS_PER_HISTORICAL_ROOT, SYNC_COMMITTEE_SIZE, + VALIDATOR_REGISTRY_LIMIT, }, - util::compute_epoch_at_slot, + types::{ + AncestryProof, BlockRootsProof, ExecutionPayloadProof, FinalityProof, LightClientUpdate, + SyncCommitteeUpdate, + }, + util::{compute_epoch_at_slot, compute_sync_committee_period_at_slot}, }; +use sync_committee_verifier::{signature_verification::pubkey_to_projective, LightClientState}; pub type BeaconStateType = BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -71,7 +72,7 @@ impl SyncCommitteeProver { SyncCommitteeProver { node_url, client } } - pub async fn fetch_finalized_checkpoint(&self) -> Result { + pub async fn fetch_finalized_checkpoint(&self) -> Result { let full_url = self.generate_route(&finality_checkpoints("head")); let response = self.client.get(full_url).send().await?; @@ -80,7 +81,7 @@ impl SyncCommitteeProver { Ok(response_data.data) } - pub async fn fetch_header(&self, block_id: &str) -> Result { + pub async fn fetch_header(&self, block_id: &str) -> Result { let path = header_route(block_id); let full_url = self.generate_route(&path); let response = self.client.get(full_url).send().await?; @@ -109,8 +110,10 @@ impl SyncCommitteeProver { MAX_EXTRA_DATA_BYTES, MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, >, - reqwest::Error, + anyhow::Error, > { let path = block_route(block_id); let full_url = self.generate_route(&path); @@ -127,7 +130,7 @@ impl SyncCommitteeProver { pub async fn fetch_sync_committee( &self, state_id: &str, - ) -> Result { + ) -> Result { let path = sync_committee_route(state_id); let full_url = self.generate_route(&path); @@ -144,7 +147,7 @@ impl SyncCommitteeProver { &self, state_id: &str, validator_index: &str, - ) -> Result { + ) -> Result { let path = validator_route(state_id, validator_index); let full_url = self.generate_route(&path); @@ -160,7 +163,7 @@ impl SyncCommitteeProver { pub async fn fetch_beacon_state( &self, state_id: &str, - ) -> Result { + ) -> Result { let path = beacon_state_route(state_id); let full_url = self.generate_route(&path); @@ -176,14 +179,14 @@ impl SyncCommitteeProver { pub async fn fetch_processed_sync_committee( &self, state_id: &str, - ) -> Result, reqwest::Error> { + ) -> Result, anyhow::Error> { // fetches sync committee from Node - let node_sync_committee = self.fetch_sync_committee(state_id.clone()).await?; + let node_sync_committee = self.fetch_sync_committee(state_id).await?; let mut validators: List = Default::default(); - for validator_index in node_sync_committee.validators.clone() { + for validator_index in node_sync_committee.validators.iter() { // fetches validator based on validator index - let validator = self.fetch_validator(state_id.clone(), &validator_index).await?; + let validator = self.fetch_validator(state_id, validator_index).await?; validators.push(validator); } @@ -191,16 +194,16 @@ impl SyncCommitteeProver { .validators .into_iter() .map(|i| { - let validator_index: ValidatorIndex = i.parse().unwrap(); - validators[validator_index].public_key.clone() + let validator_index: ValidatorIndex = i.parse()?; + Ok(validators[validator_index as usize].public_key.clone()) }) - .collect::>(); + .collect::, anyhow::Error>>()?; - let aggregate_public_key = eth_aggregate_public_keys(&public_keys_vector).unwrap(); + let aggregate_public_key = eth_aggregate_public_keys(&public_keys_vector)?; let sync_committee = SyncCommittee:: { public_keys: Vector::::try_from(public_keys_vector) - .unwrap(), + .map_err(|e| anyhow!("{:?}", e))?, aggregate_public_key, }; @@ -210,6 +213,152 @@ impl SyncCommitteeProver { fn generate_route(&self, path: &str) -> String { format!("{}{}", self.node_url.clone(), path) } + + pub async fn fetch_light_client_update( + &self, + client_state: LightClientState, + debug_target: &str, + ) -> Result, anyhow::Error> { + let finality_checkpoint = self.fetch_finalized_checkpoint().await?; + if finality_checkpoint.finalized.root == Node::default() || + finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch || + finality_checkpoint.finalized.root == + client_state.finalized_header.clone().hash_tree_root()? + { + return Ok(None) + } + + debug!(target: debug_target, "A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); + + let block_id = { + let mut block_id = hex::encode(finality_checkpoint.finalized.root.as_bytes()); + block_id.insert_str(0, "0x"); + block_id + }; + + let finalized_header = self.fetch_header(&block_id).await?; + let mut finalized_state = + self.fetch_beacon_state(finalized_header.slot.to_string().as_str()).await?; + let execution_payload_proof = prove_execution_payload(&mut finalized_state)?; + + let mut attested_epoch = finality_checkpoint.finalized.epoch + 2; + // Get attested header and the signature slot + + let mut attested_slot = attested_epoch * SLOTS_PER_EPOCH; + // Due to the fact that all slots in an epoch can be missed we are going to try and fetch + // the attested block from four possible epochs. + let mut attested_epoch_loop_count = 0; + let (attested_block_header, signature_block) = loop { + if attested_epoch_loop_count == 4 { + Err(anyhow!("Could not fetch any block from the attested epoch after going through four epochs"))? + } + // If we have maxed out the slots in the current epoch and still didn't find any block, + // we move to the next epoch + if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == + attested_slot + { + // No block was found in attested epoch we move to the next possible attested epoch + debug!(target: debug_target, + "No slots found in epoch {attested_epoch} Moving to the next possible epoch {}", + attested_epoch + 1 + ); + tokio::time::sleep(Duration::from_secs(24)).await; + attested_epoch += 1; + attested_slot = attested_epoch * SLOTS_PER_EPOCH; + attested_epoch_loop_count += 1; + } + + if let Ok(header) = self.fetch_header(attested_slot.to_string().as_str()).await { + let mut signature_slot = header.slot + 1; + let mut loop_count = 0; + let signature_block = loop { + if loop_count == 2 { + break None + } + if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == + signature_slot + { + debug!(target: debug_target, "Waiting for signature block for attested header"); + tokio::time::sleep(Duration::from_secs(24)).await; + signature_slot = header.slot + 1; + loop_count += 1; + } + if let Ok(signature_block) = + self.fetch_block(signature_slot.to_string().as_str()).await + { + break Some(signature_block) + } + signature_slot += 1; + }; + // If the next block does not have sufficient sync committee participants + if let Some(signature_block) = signature_block { + if signature_block + .body + .sync_aggregate + .sync_committee_bits + .as_bitslice() + .count_ones() < (2 * (SYNC_COMMITTEE_SIZE)) / 3 + { + attested_slot += 1; + debug!(target:debug_target, "Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); + continue + } + break (header, signature_block) + } else { + debug!(target: debug_target,"No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); + tokio::time::sleep(Duration::from_secs(24)).await; + attested_epoch += 1; + attested_slot = attested_epoch * SLOTS_PER_EPOCH; + attested_epoch_loop_count += 1; + continue + } + } + attested_slot += 1 + }; + + let mut attested_state = + self.fetch_beacon_state(attested_block_header.slot.to_string().as_str()).await?; + + let finalized_hash_tree_root = finalized_header.clone().hash_tree_root()?; + + if cfg!(test) { + assert_eq!(finalized_hash_tree_root, attested_state.finalized_checkpoint.root); + } + + let finality_proof = FinalityProof { + epoch: finality_checkpoint.finalized.epoch, + finality_branch: prove_finalized_header(&mut attested_state)?, + }; + + let state_period = compute_sync_committee_period_at_slot(finalized_header.slot); + + let update_attested_period = + compute_sync_committee_period_at_slot(attested_block_header.slot); + + let sync_committee_update = if state_period == update_attested_period { + let sync_committee_proof = prove_sync_committee_update(&mut attested_state)?; + + Some(SyncCommitteeUpdate { + next_sync_committee: attested_state.next_sync_committee, + next_sync_committee_branch: sync_committee_proof, + }) + } else { + None + }; + + // construct light client + let light_client_update = LightClientUpdate { + attested_header: attested_block_header, + sync_committee_update, + finalized_header, + execution_payload: execution_payload_proof, + finality_proof, + sync_aggregate: signature_block.body.sync_aggregate, + signature_slot: signature_block.slot, + }; + + Ok(Some(light_client_update)) + } } pub fn get_attested_epoch(finalized_epoch: u64) -> u64 { @@ -217,7 +366,7 @@ pub fn get_attested_epoch(finalized_epoch: u64) -> u64 { } pub fn prove_execution_payload( - mut beacon_state: BeaconStateType, + beacon_state: &mut BeaconStateType, ) -> anyhow::Result { let indices = [ EXECUTION_PAYLOAD_STATE_ROOT_INDEX as usize, @@ -231,40 +380,33 @@ pub fn prove_execution_payload( )?; Ok(ExecutionPayloadProof { - state_root: beacon_state.latest_execution_payload_header.state_root.clone(), + state_root: H256::from_slice( + beacon_state.latest_execution_payload_header.state_root.as_slice(), + ), block_number: beacon_state.latest_execution_payload_header.block_number, timestamp: beacon_state.latest_execution_payload_header.timestamp, - multi_proof: multi_proof - .into_iter() - .map(|node| Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice")) - .collect(), + multi_proof, execution_payload_branch: ssz_rs::generate_proof( - &mut beacon_state, + beacon_state, &[EXECUTION_PAYLOAD_INDEX as usize], - )? - .into_iter() - .map(|node| Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice")) - .collect(), + )?, }) } -pub fn prove_sync_committee_update(mut state: BeaconStateType) -> anyhow::Result> { - let proof = ssz_rs::generate_proof(&mut state, &[NEXT_SYNC_COMMITTEE_INDEX as usize])?; +pub fn prove_sync_committee_update(state: &mut BeaconStateType) -> anyhow::Result> { + let proof = ssz_rs::generate_proof(state, &[NEXT_SYNC_COMMITTEE_INDEX as usize])?; Ok(proof) } -pub fn prove_finalized_header(mut state: BeaconStateType) -> anyhow::Result> { +pub fn prove_finalized_header(state: &mut BeaconStateType) -> anyhow::Result> { let indices = [FINALIZED_ROOT_INDEX as usize]; - let proof = ssz_rs::generate_proof(&mut state, indices.as_slice())?; + let proof = ssz_rs::generate_proof(state, indices.as_slice())?; - Ok(proof - .into_iter() - .map(|node| Hash32::try_from(node.as_ref()).expect("Node is always a 32 byte slice")) - .collect()) + Ok(proof) } pub fn prove_block_roots_proof( - mut state: BeaconStateType, + state: &mut BeaconStateType, mut header: BeaconBlockHeader, ) -> anyhow::Result { // Check if block root should still be part of the block roots vector on the beacon state @@ -288,25 +430,26 @@ pub fn prove_block_roots_proof( let proof = ssz_rs::generate_proof(&mut state.block_roots, &[block_index])?; - let block_roots_proof = BlockRootsProof { - block_header_index: block_index as u64, - block_header_branch: proof - .into_iter() - .map(|node| { - Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice") - }) - .collect(), - }; + let block_roots_proof = + BlockRootsProof { block_header_index: block_index as u64, block_header_branch: proof }; - let block_roots_branch = ssz_rs::generate_proof(&mut state, &[BLOCK_ROOTS_INDEX as usize])?; - Ok(AncestryProof::BlockRoots { - block_roots_proof, - block_roots_branch: block_roots_branch - .into_iter() - .map(|node| { - Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice") - }) - .collect(), - }) + let block_roots_branch = ssz_rs::generate_proof(state, &[BLOCK_ROOTS_INDEX as usize])?; + Ok(AncestryProof::BlockRoots { block_roots_proof, block_roots_branch }) } } + +pub fn eth_aggregate_public_keys(points: &[BlsPublicKey]) -> anyhow::Result { + let points = points + .iter() + .map(|point| pubkey_to_projective(point)) + .collect::, _>>()?; + let aggregate = points + .into_iter() + .fold(G1ProjectivePoint::default(), |acc, g1_point| acc + g1_point); + let public_key = point_to_pubkey(aggregate.into()); + + let bls_public_key = + BlsPublicKey::try_from(public_key.as_slice()).map_err(|e| anyhow!("{:?}", e))?; + + Ok(bls_public_key) +} diff --git a/prover/src/responses/beacon_block_header_response.rs b/prover/src/responses/beacon_block_header_response.rs index 3d6d3a5..9a3e6b1 100644 --- a/prover/src/responses/beacon_block_header_response.rs +++ b/prover/src/responses/beacon_block_header_response.rs @@ -1,4 +1,4 @@ -use ethereum_consensus::bellatrix::BeaconBlockHeader; +use sync_committee_primitives::consensus_types::BeaconBlockHeader; #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Response { diff --git a/prover/src/responses/beacon_block_response.rs b/prover/src/responses/beacon_block_response.rs index 62839e3..ac3c2b2 100644 --- a/prover/src/responses/beacon_block_response.rs +++ b/prover/src/responses/beacon_block_response.rs @@ -1,10 +1,12 @@ -use ethereum_consensus::bellatrix::{ - mainnet::{ - BYTES_PER_LOGS_BLOOM, MAX_ATTESTATIONS, MAX_ATTESTER_SLASHINGS, MAX_BYTES_PER_TRANSACTION, - MAX_DEPOSITS, MAX_EXTRA_DATA_BYTES, MAX_PROPOSER_SLASHINGS, MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_VALIDATORS_PER_COMMITTEE, MAX_VOLUNTARY_EXITS, SYNC_COMMITTEE_SIZE, +use sync_committee_primitives::{ + consensus_types::BeaconBlock, + constants::{ + BYTES_PER_LOGS_BLOOM, MAX_ATTESTATIONS, MAX_ATTESTER_SLASHINGS, + MAX_BLS_TO_EXECUTION_CHANGES, MAX_BYTES_PER_TRANSACTION, MAX_DEPOSITS, + MAX_EXTRA_DATA_BYTES, MAX_PROPOSER_SLASHINGS, MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_VALIDATORS_PER_COMMITTEE, MAX_VOLUNTARY_EXITS, MAX_WITHDRAWALS_PER_PAYLOAD, + SYNC_COMMITTEE_SIZE, }, - BeaconBlock, }; #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -28,6 +30,8 @@ pub struct ResponseData { MAX_EXTRA_DATA_BYTES, MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, >, pub signature: String, } diff --git a/prover/src/responses/beacon_state_response.rs b/prover/src/responses/beacon_state_response.rs index 14b0b91..56c5059 100644 --- a/prover/src/responses/beacon_state_response.rs +++ b/prover/src/responses/beacon_state_response.rs @@ -1,11 +1,13 @@ -use ethereum_consensus::bellatrix::BeaconState; - -use ethereum_consensus::bellatrix::mainnet::{ - BYTES_PER_LOGS_BLOOM, EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR, - ETH1_DATA_VOTES_BOUND, HISTORICAL_ROOTS_LIMIT, MAX_BYTES_PER_TRANSACTION, MAX_EXTRA_DATA_BYTES, - MAX_TRANSACTIONS_PER_PAYLOAD, MAX_VALIDATORS_PER_COMMITTEE, SLOTS_PER_HISTORICAL_ROOT, - SYNC_COMMITTEE_SIZE, VALIDATOR_REGISTRY_LIMIT, +use sync_committee_primitives::{ + consensus_types::BeaconState, + constants::{ + BYTES_PER_LOGS_BLOOM, EPOCHS_PER_HISTORICAL_VECTOR, EPOCHS_PER_SLASHINGS_VECTOR, + ETH1_DATA_VOTES_BOUND, HISTORICAL_ROOTS_LIMIT, MAX_BYTES_PER_TRANSACTION, + MAX_EXTRA_DATA_BYTES, MAX_TRANSACTIONS_PER_PAYLOAD, MAX_VALIDATORS_PER_COMMITTEE, + SLOTS_PER_HISTORICAL_ROOT, SYNC_COMMITTEE_SIZE, VALIDATOR_REGISTRY_LIMIT, + }, }; + #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Response { version: String, diff --git a/prover/src/responses/finality_checkpoint_response.rs b/prover/src/responses/finality_checkpoint_response.rs index db251de..c0e439e 100644 --- a/prover/src/responses/finality_checkpoint_response.rs +++ b/prover/src/responses/finality_checkpoint_response.rs @@ -1,4 +1,4 @@ -use ethereum_consensus::bellatrix::Checkpoint; +use sync_committee_primitives::consensus_types::Checkpoint; #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub(crate) struct Response { diff --git a/prover/src/responses/validator_response.rs b/prover/src/responses/validator_response.rs index 6a37e0a..d4969cc 100644 --- a/prover/src/responses/validator_response.rs +++ b/prover/src/responses/validator_response.rs @@ -1,4 +1,4 @@ -use ethereum_consensus::bellatrix::Validator; +use sync_committee_primitives::consensus_types::Validator; #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Response { diff --git a/prover/src/test.rs b/prover/src/test.rs index 9acc97f..a509501 100644 --- a/prover/src/test.rs +++ b/prover/src/test.rs @@ -1,86 +1,126 @@ use super::*; use base2::Base2; -use sync_committee_primitives::{ - types::{LightClientState, LightClientUpdate, SyncCommitteeUpdate}, - util::compute_sync_committee_period_at_slot, +use ethers::{ + prelude::{Http, Middleware, ProviderExt}, + providers::Provider, }; - -use ethereum_consensus::{ - bellatrix::compute_domain, primitives::Root, signing::compute_signing_root, - state_transition::Context, +use ssz_rs::{ + calculate_multi_merkle_root, get_generalized_index, is_valid_merkle_branch, GeneralizedIndex, + Merkleized, SszVariableOrIndex, }; -use ssz_rs::{calculate_multi_merkle_root, is_valid_merkle_branch, GeneralizedIndex, Merkleized}; use std::time::Duration; use sync_committee_primitives::{ - types::{AncestorBlock, FinalityProof, DOMAIN_SYNC_COMMITTEE, GENESIS_VALIDATORS_ROOT}, - util::compute_fork_version, + constants::{Root, DOMAIN_SYNC_COMMITTEE, GENESIS_FORK_VERSION, GENESIS_VALIDATORS_ROOT}, + types::LightClientState, + util::{compute_domain, compute_fork_version, compute_signing_root}, +}; +use sync_committee_verifier::{ + signature_verification::verify_aggregate_signature, verify_sync_committee_attestation, }; -use sync_committee_verifier::{verify_sync_committee_attestation, SignatureVerifier}; use tokio::time; use tokio_stream::{wrappers::IntervalStream, StreamExt}; -const NODE_URL: &'static str = "http://localhost:5052"; +const CONSENSUS_NODE_URL: &'static str = "http://localhost:3500"; +const EL_NODE_URL: &'static str = "http://localhost:8545"; + +async fn wait_for_el() { + let provider = Provider::::connect(EL_NODE_URL).await; + let sub = provider.watch_blocks().await.unwrap(); + let _ = sub.take(10).collect::>(); +} #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn fetch_block_header_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let block_header = sync_committee_prover.fetch_header("head").await; assert!(block_header.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn fetch_block_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let block = sync_committee_prover.fetch_block("head").await; assert!(block.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] -async fn fetch_sync_committee_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); - let block = sync_committee_prover.fetch_sync_committee("head").await; - assert!(block.is_ok()); +#[tokio::test] +async fn fetch_validator_works() { + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); + let validator = sync_committee_prover.fetch_validator("head", "0").await; + assert!(validator.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] -async fn fetch_validator_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); - let validator = sync_committee_prover.fetch_validator("head", "48").await; +#[tokio::test] +async fn fetch_processed_sync_committee_works() { + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); + let validator = sync_committee_prover.fetch_processed_sync_committee("head").await; assert!(validator.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] #[ignore] -async fn fetch_processed_sync_committee_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); - let validator = sync_committee_prover.fetch_processed_sync_committee("head").await; - assert!(validator.is_ok()); +async fn generate_indexes() { + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); + let beacon_state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); + let execution_payload_index = get_generalized_index( + &beacon_state, + &[SszVariableOrIndex::Name("latest_execution_payload_header")], + ); + let next_sync = + get_generalized_index(&beacon_state, &[SszVariableOrIndex::Name("next_sync_committee")]); + let finalized = + get_generalized_index(&beacon_state, &[SszVariableOrIndex::Name("finalized_checkpoint")]); + let execution_payload_root = get_generalized_index( + &beacon_state.latest_execution_payload_header, + &[SszVariableOrIndex::Name("state_root")], + ); + let block_number = get_generalized_index( + &beacon_state.latest_execution_payload_header, + &[SszVariableOrIndex::Name("block_number")], + ); + let timestamp = get_generalized_index( + &beacon_state.latest_execution_payload_header, + &[SszVariableOrIndex::Name("timestamp")], + ); + + dbg!(execution_payload_index); + dbg!(next_sync); + dbg!(finalized); + dbg!(execution_payload_root); + dbg!(block_number); + dbg!(timestamp); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn fetch_beacon_state_works() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let beacon_state = sync_committee_prover.fetch_beacon_state("head").await; assert!(beacon_state.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn state_root_and_block_header_root_matches() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let mut beacon_state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); let block_header = sync_committee_prover.fetch_header(&beacon_state.slot.to_string()).await; @@ -89,23 +129,25 @@ async fn state_root_and_block_header_root_matches() { let block_header = block_header.unwrap(); let hash_tree_root = beacon_state.hash_tree_root(); - assert!(block_header.state_root == hash_tree_root.unwrap()); + assert_eq!(block_header.state_root, hash_tree_root.unwrap()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn fetch_finality_checkpoints_work() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await; assert!(finality_checkpoint.is_ok()); } #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn test_finalized_header() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let mut state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); let proof = ssz_rs::generate_proof(&mut state, &vec![FINALIZED_ROOT_INDEX as usize]); @@ -129,30 +171,27 @@ async fn test_finalized_header() { #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn test_execution_payload_proof() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); - let finalized_state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); + let mut finalized_state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); let block_id = finalized_state.slot.to_string(); - let execution_payload_proof = prove_execution_payload(finalized_state.clone()).unwrap(); + let execution_payload_proof = prove_execution_payload(&mut finalized_state).unwrap(); let finalized_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); // verify the associated execution header of the finalized beacon header. let mut execution_payload = execution_payload_proof.clone(); let multi_proof_vec = execution_payload.multi_proof; - let multi_proof_nodes = multi_proof_vec - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); let execution_payload_root = calculate_multi_merkle_root( &[ Node::from_bytes(execution_payload.state_root.as_ref().try_into().unwrap()), execution_payload.block_number.hash_tree_root().unwrap(), execution_payload.timestamp.hash_tree_root().unwrap(), ], - &multi_proof_nodes, + &multi_proof_vec, &[ GeneralizedIndex(EXECUTION_PAYLOAD_STATE_ROOT_INDEX as usize), GeneralizedIndex(EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX as usize), @@ -168,18 +207,14 @@ async fn test_execution_payload_proof() { assert_eq!(execution_payload_root, execution_payload_hash_tree_root); - let execution_payload_branch = execution_payload - .execution_payload_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); + let execution_payload_branch = execution_payload.execution_payload_branch.iter(); let is_merkle_branch_valid = is_valid_merkle_branch( &execution_payload_root, - execution_payload_branch.iter(), + execution_payload_branch, EXECUTION_PAYLOAD_INDEX.floor_log2() as usize, GeneralizedIndex(EXECUTION_PAYLOAD_INDEX as usize).0, - &Node::from_bytes(finalized_header.clone().state_root.as_ref().try_into().unwrap()), + &finalized_header.state_root, ); assert!(is_merkle_branch_valid); @@ -187,43 +222,30 @@ async fn test_execution_payload_proof() { #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn test_sync_committee_update_proof() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); - let finalized_header = sync_committee_prover.fetch_header("head").await.unwrap(); - - let finalized_state = sync_committee_prover - .fetch_beacon_state(&finalized_header.slot.to_string()) - .await - .unwrap(); + let mut finalized_state = sync_committee_prover.fetch_beacon_state("head").await.unwrap(); + let block_id = finalized_state.slot.to_string(); + let finalized_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); - let sync_committee_proof = prove_sync_committee_update(finalized_state.clone()).unwrap(); + let sync_committee_proof = prove_sync_committee_update(&mut finalized_state).unwrap(); - let sync_committee_proof = sync_committee_proof - .into_iter() - .map(|node| Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice")) - .collect::>(); let mut sync_committee = finalized_state.next_sync_committee; let calculated_finalized_root = calculate_multi_merkle_root( - &[Node::from_bytes(sync_committee.hash_tree_root().unwrap().as_ref().try_into().unwrap())], - &sync_committee_proof - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(), + &[sync_committee.hash_tree_root().unwrap()], + &sync_committee_proof, &[GeneralizedIndex(NEXT_SYNC_COMMITTEE_INDEX as usize)], ); assert_eq!(calculated_finalized_root.as_bytes(), finalized_header.state_root.as_bytes()); - let next_sync_committee_branch = sync_committee_proof - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); let is_merkle_branch_valid = is_valid_merkle_branch( &Node::from_bytes(sync_committee.hash_tree_root().unwrap().as_ref().try_into().unwrap()), - next_sync_committee_branch.iter(), + sync_committee_proof.iter(), NEXT_SYNC_COMMITTEE_INDEX.floor_log2() as usize, NEXT_SYNC_COMMITTEE_INDEX as usize, &Node::from_bytes(finalized_header.state_root.as_ref().try_into().unwrap()), @@ -234,12 +256,17 @@ async fn test_sync_committee_update_proof() { #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn test_prover() { - env_logger::init(); + use log::LevelFilter; + env_logger::builder() + .filter_module("prover", LevelFilter::Debug) + .format_module_path(false) + .init(); + wait_for_el().await; let mut stream = IntervalStream::new(time::interval(Duration::from_secs(12 * 12))); - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let block_id = "head"; @@ -259,190 +286,20 @@ async fn test_prover() { let mut count = 0; while let Some(_ts) = stream.next().await { - let finality_checkpoint = sync_committee_prover.fetch_finalized_checkpoint().await.unwrap(); - if finality_checkpoint.finalized.root == Node::default() || - finality_checkpoint.finalized.epoch <= client_state.latest_finalized_epoch || - finality_checkpoint.finalized.root == - client_state.finalized_header.clone().hash_tree_root().unwrap() - { - continue - } - - println!("A new epoch has been finalized {}", finality_checkpoint.finalized.epoch); - - let block_id = { - let mut block_id = hex::encode(finality_checkpoint.finalized.root.as_bytes()); - block_id.insert_str(0, "0x"); - block_id - }; - - let finalized_header = sync_committee_prover.fetch_header(&block_id).await.unwrap(); - let finalized_state = sync_committee_prover - .fetch_beacon_state(finalized_header.slot.to_string().as_str()) + let light_client_update = if let Some(update) = sync_committee_prover + .fetch_light_client_update(client_state.clone(), "prover") .await - .unwrap(); - let execution_payload_proof = prove_execution_payload(finalized_state.clone()).unwrap(); - - let mut attested_epoch = finality_checkpoint.finalized.epoch + 2; - // Get attested header and the signature slot - - let mut attested_slot = attested_epoch * SLOTS_PER_EPOCH; - // Due to the fact that all slots in an epoch can be missed we are going to try and fetch - // the attested block from four possible epochs. - let mut attested_epoch_loop_count = 0; - let (attested_block_header, signature_block) = loop { - if attested_epoch_loop_count == 4 { - panic!("Could not fetch any block from the attested epoch after going through four epochs, your Eth devnet is fucked") - } - // If we have maxed out the slots in the current epoch and still didn't find any block, - // we move to the next epoch - if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == - attested_slot - { - // No block was found in attested epoch we move to the next possible attested epoch - println!( - "No slots found in epoch {attested_epoch} Moving to the next possible epoch {}", - attested_epoch + 1 - ); - std::thread::sleep(Duration::from_secs(24)); - attested_epoch += 1; - attested_slot = attested_epoch * SLOTS_PER_EPOCH; - attested_epoch_loop_count += 1; - } - - if let Ok(header) = - sync_committee_prover.fetch_header(attested_slot.to_string().as_str()).await - { - let mut signature_slot = header.slot + 1; - let mut loop_count = 0; - let signature_block = loop { - if loop_count == 2 { - break None - } - if (attested_epoch * SLOTS_PER_EPOCH).saturating_add(SLOTS_PER_EPOCH - 1) == - signature_slot - { - println!("Waiting for signature block for attested header"); - std::thread::sleep(Duration::from_secs(24)); - signature_slot = header.slot + 1; - loop_count += 1; - } - if let Ok(signature_block) = - sync_committee_prover.fetch_block(signature_slot.to_string().as_str()).await - { - break Some(signature_block) - } - signature_slot += 1; - }; - // If the next block does not have sufficient sync committee participants - if let Some(signature_block) = signature_block { - if signature_block - .body - .sync_aggregate - .sync_committee_bits - .as_bitslice() - .count_ones() < (2 * (SYNC_COMMITTEE_SIZE)) / 3 - { - attested_slot += 1; - println!("Signature block does not have sufficient sync committee participants -> participants {}", signature_block.body.sync_aggregate.sync_committee_bits.as_bitslice().count_ones()); - continue - } - break (header, signature_block) - } else { - println!("No signature block found in {attested_epoch} Moving to the next possible epoch {}", attested_epoch + 1); - std::thread::sleep(Duration::from_secs(24)); - attested_epoch += 1; - attested_slot = attested_epoch * SLOTS_PER_EPOCH; - attested_epoch_loop_count += 1; - continue - } - } - attested_slot += 1 - }; - - let attested_state = sync_committee_prover - .fetch_beacon_state(attested_block_header.slot.to_string().as_str()) - .await - .unwrap(); - - let finalized_hash_tree_root = finalized_header.clone().hash_tree_root().unwrap(); - println!("{:?}, {}", attested_state.finalized_checkpoint, attested_state.slot); - println!("{:?}, {}", finalized_hash_tree_root, finalized_header.slot); - - assert_eq!(finalized_hash_tree_root, attested_state.finalized_checkpoint.root); - - let finality_proof = FinalityProof { - epoch: finality_checkpoint.finalized.epoch, - finality_branch: prove_finalized_header(attested_state.clone()).unwrap(), - }; - - let state_period = compute_sync_committee_period_at_slot(finalized_header.slot); - - let update_attested_period = - compute_sync_committee_period_at_slot(attested_block_header.slot); - - let sync_committee_update = if state_period == update_attested_period { - let sync_committee_proof = prove_sync_committee_update(attested_state.clone()).unwrap(); - - let sync_committee_proof = sync_committee_proof - .into_iter() - .map(|node| { - Bytes32::try_from(node.as_bytes()).expect("Node is always 32 byte slice") - }) - .collect::>(); - - Some(SyncCommitteeUpdate { - next_sync_committee: attested_state.next_sync_committee, - next_sync_committee_branch: sync_committee_proof, - }) + .unwrap() + { + update } else { - None - }; - - let mut i = finalized_header.slot - 1; - let mut ancestor_blocks = vec![]; - while ancestor_blocks.len() < 5 { - if (finalized_header.slot - i) > 100 { - break - } - if let Ok(ancestor_header) = - sync_committee_prover.fetch_header(i.to_string().as_str()).await - { - let ancestry_proof = - prove_block_roots_proof(finalized_state.clone(), ancestor_header.clone()) - .unwrap(); - let header_state = - sync_committee_prover.fetch_beacon_state(i.to_string().as_str()).await.unwrap(); - let execution_payload_proof = prove_execution_payload(header_state).unwrap(); - ancestor_blocks.push(AncestorBlock { - header: ancestor_header, - execution_payload: execution_payload_proof, - ancestry_proof, - }) - } - i -= 1; - } - - println!("\nAncestor blocks count: \n {:?} \n", ancestor_blocks.len()); - - // construct light client - let light_client_update = LightClientUpdate { - attested_header: attested_block_header, - sync_committee_update, - finalized_header, - execution_payload: execution_payload_proof, - finality_proof, - sync_aggregate: signature_block.body.sync_aggregate, - signature_slot: signature_block.slot, - ancestor_blocks: vec![], + continue }; - client_state = verify_sync_committee_attestation::( - client_state.clone(), - light_client_update, - ) - .unwrap(); - println!( + client_state = + verify_sync_committee_attestation(client_state.clone(), light_client_update).unwrap(); + debug!( + target: "prover", "Sucessfully verified Ethereum block at slot {:?}", client_state.finalized_header.slot ); @@ -455,11 +312,13 @@ async fn test_prover() { } } +#[ignore] #[cfg(test)] #[allow(non_snake_case)] -#[actix_rt::test] +#[tokio::test] async fn test_sync_committee_signature_verification() { - let sync_committee_prover = SyncCommitteeProver::new(NODE_URL.to_string()); + wait_for_el().await; + let sync_committee_prover = SyncCommitteeProver::new(CONSENSUS_NODE_URL.to_string()); let block = loop { let block = sync_committee_prover.fetch_block("head").await.unwrap(); if block.slot < 16 { @@ -480,31 +339,31 @@ async fn test_sync_committee_signature_verification() { let sync_committee_pubkeys = sync_committee.public_keys; - let participant_pubkeys = block + let non_participant_pubkeys = block .body .sync_aggregate .sync_committee_bits .iter() .zip(sync_committee_pubkeys.iter()) - .filter_map(|(bit, key)| if *bit { Some(key) } else { None }) + .filter_map(|(bit, key)| if !(*bit) { Some(key.clone()) } else { None }) .collect::>(); let fork_version = compute_fork_version(compute_epoch_at_slot(block.slot)); - let context = Context::for_mainnet(); let domain = compute_domain( DOMAIN_SYNC_COMMITTEE, Some(fork_version), Some(Root::from_bytes(GENESIS_VALIDATORS_ROOT.try_into().unwrap())), - &context, + GENESIS_FORK_VERSION, ) .unwrap(); - let signing_root = compute_signing_root(&mut attested_header, domain); + let signing_root = compute_signing_root(&mut attested_header, domain).unwrap(); - ethereum_consensus::crypto::fast_aggregate_verify( - &*participant_pubkeys, - signing_root.unwrap().as_bytes(), + verify_aggregate_signature( + &sync_committee.aggregate_public_key, + &non_participant_pubkeys, + signing_root.as_bytes().to_vec(), &block.body.sync_aggregate.sync_committee_signature, ) .unwrap(); diff --git a/verifier/Cargo.toml b/verifier/Cargo.toml index e381b04..2bfc475 100644 --- a/verifier/Cargo.toml +++ b/verifier/Cargo.toml @@ -6,14 +6,27 @@ authors = ["Polytope Labs"] [dependencies] sync-committee-primitives = { path= "../primitives", default-features = false } -ethereum-consensus = { git = "https://github.com/polytope-labs/ethereum-consensus", branch = "main", default-features = false } ssz-rs = { git = "https://github.com/polytope-labs/ssz-rs", branch = "main" , default-features = false } log = { version = "0.4.17", default-features = false } +anyhow = { version = "1.0.75", default-features = false } +ark-ec = { version = "0.4.2", default-features = false } +ark-bls12-381 = { version = "0.4.0", default-features = false } +bls_on_arkworks = { version = "0.2.2", default-features = false } [features] default = ["std"] std = [ "ssz-rs/std", - "log/std" + "log/std", + "sync-committee-primitives/std", + "log/std", + "anyhow/std", + "ark-ec/std", + "ark-bls12-381/std", + "bls_on_arkworks/std" ] -testing = ["sync-committee-primitives/testing"] +testnet = ["sync-committee-primitives/testnet"] +mainnet = ["sync-committee-primitives/mainnet"] + +[dev-dependencies] +hex = "0.4.3" \ No newline at end of file diff --git a/verifier/src/error.rs b/verifier/src/error.rs index 4fd88fa..567e74c 100644 --- a/verifier/src/error.rs +++ b/verifier/src/error.rs @@ -5,16 +5,10 @@ pub enum Error { SyncCommitteeParticipantsTooLow, InvalidUpdate, DomainError, - FastAggregateError(ethereum_consensus::crypto::Error), InvalidMerkleBranch, InvalidRoot, MerkleizationError, -} - -impl From for Error { - fn from(error: ethereum_consensus::crypto::Error) -> Self { - Error::FastAggregateError(error) - } + SignatureVerification, } impl Display for Error { @@ -25,10 +19,10 @@ impl Display for Error { }, Error::InvalidUpdate => write!(f, "Invalid update"), Error::DomainError => write!(f, "Couldn't get domain"), - Error::FastAggregateError(err) => write!(f, "Fast aggregate error {:?}", err), Error::InvalidMerkleBranch => write!(f, "Invalid merkle branch"), Error::InvalidRoot => write!(f, "Invalid root"), Error::MerkleizationError => write!(f, "Merkleization error"), + Error::SignatureVerification => write!(f, "Signature verification failed"), } } } diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index 56958c0..157da6a 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -4,43 +4,34 @@ extern crate alloc; pub mod error; +pub mod signature_verification; -use crate::error::Error; +use crate::{error::Error, signature_verification::verify_aggregate_signature}; use alloc::vec::Vec; -use ethereum_consensus::{ - bellatrix::{compute_domain, mainnet::SYNC_COMMITTEE_SIZE, Checkpoint}, - crypto::{PublicKey, Signature}, - primitives::Root, - signing::compute_signing_root, - state_transition::Context, -}; use ssz_rs::{ - calculate_merkle_root, calculate_multi_merkle_root, prelude::is_valid_merkle_branch, - GeneralizedIndex, Merkleized, Node, + calculate_multi_merkle_root, prelude::is_valid_merkle_branch, GeneralizedIndex, Merkleized, + Node, }; use sync_committee_primitives::{ - types::{ - AncestryProof, BLOCK_ROOTS_INDEX, BLOCK_ROOTS_INDEX_LOG2, DOMAIN_SYNC_COMMITTEE, - EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX, EXECUTION_PAYLOAD_INDEX, + consensus_types::Checkpoint, + constants::{ + Root, DOMAIN_SYNC_COMMITTEE, EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX, EXECUTION_PAYLOAD_INDEX, EXECUTION_PAYLOAD_INDEX_LOG2, EXECUTION_PAYLOAD_STATE_ROOT_INDEX, EXECUTION_PAYLOAD_TIMESTAMP_INDEX, FINALIZED_ROOT_INDEX, FINALIZED_ROOT_INDEX_LOG2, - GENESIS_VALIDATORS_ROOT, HISTORICAL_BATCH_BLOCK_ROOTS_INDEX, HISTORICAL_ROOTS_INDEX, - HISTORICAL_ROOTS_INDEX_LOG2, NEXT_SYNC_COMMITTEE_INDEX, NEXT_SYNC_COMMITTEE_INDEX_LOG2, + GENESIS_FORK_VERSION, GENESIS_VALIDATORS_ROOT, NEXT_SYNC_COMMITTEE_INDEX, + NEXT_SYNC_COMMITTEE_INDEX_LOG2, + }, + util::{ + compute_domain, compute_epoch_at_slot, compute_fork_version, compute_signing_root, + compute_sync_committee_period_at_slot, }, - util::{compute_epoch_at_slot, compute_fork_version, compute_sync_committee_period_at_slot}, }; -pub type LightClientState = sync_committee_primitives::types::LightClientState; -pub type LightClientUpdate = - sync_committee_primitives::types::LightClientUpdate; - -/// Verify sync committee signatures -pub trait BlsVerify { - fn verify(public_keys: &[&PublicKey], msg: &[u8], signature: &Signature) -> Result<(), Error>; -} +pub type LightClientState = sync_committee_primitives::types::LightClientState; +pub type LightClientUpdate = sync_committee_primitives::types::LightClientUpdate; /// This function simply verifies a sync committee's attestation & it's finalized counterpart. -pub fn verify_sync_committee_attestation( +pub fn verify_sync_committee_attestation( trusted_state: LightClientState, update: LightClientUpdate, ) -> Result { @@ -94,30 +85,32 @@ pub fn verify_sync_committee_attestation( let sync_committee_pubkeys = sync_committee.public_keys; - let participant_pubkeys = sync_committee_bits + let non_participant_pubkeys = sync_committee_bits .iter() .zip(sync_committee_pubkeys.iter()) - .filter_map(|(bit, key)| if *bit { Some(key) } else { None }) + .filter_map(|(bit, key)| if !(*bit) { Some(key.clone()) } else { None }) .collect::>(); let fork_version = compute_fork_version(compute_epoch_at_slot(update.signature_slot)); - let context = Context::for_mainnet(); let domain = compute_domain( DOMAIN_SYNC_COMMITTEE, Some(fork_version), Some(Root::from_bytes(GENESIS_VALIDATORS_ROOT.try_into().map_err(|_| Error::InvalidRoot)?)), - &context, + GENESIS_FORK_VERSION, ) .map_err(|_| Error::InvalidUpdate)?; - let signing_root = compute_signing_root(&mut update.attested_header.clone(), domain); + let signing_root = compute_signing_root(&mut update.attested_header.clone(), domain) + .map_err(|_| Error::InvalidRoot)?; - V::verify( - &*participant_pubkeys, - signing_root.map_err(|_| Error::InvalidRoot)?.as_bytes(), + verify_aggregate_signature( + &trusted_state.current_sync_committee.aggregate_public_key, + &non_participant_pubkeys, + signing_root.as_bytes().to_vec(), &update.sync_aggregate.sync_committee_signature, - )?; + ) + .map_err(|_| Error::SignatureVerification)?; // Verify that the `finality_branch` confirms `finalized_header` // to match the finalized checkpoint root saved in the state of `attested_header`. @@ -131,16 +124,9 @@ pub fn verify_sync_committee_attestation( .map_err(|_| Error::InvalidRoot)?, }; - let branch = update - .finality_proof - .finality_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let is_merkle_branch_valid = is_valid_merkle_branch( &finalized_checkpoint.hash_tree_root().map_err(|_| Error::InvalidRoot)?, - branch.iter(), + update.finality_proof.finality_branch.iter(), FINALIZED_ROOT_INDEX_LOG2 as usize, FINALIZED_ROOT_INDEX as usize, &update.attested_header.state_root, @@ -152,11 +138,6 @@ pub fn verify_sync_committee_attestation( // verify the associated execution header of the finalized beacon header. let mut execution_payload = update.execution_payload; - let multi_proof_vec = execution_payload.multi_proof; - let multi_proof_nodes = multi_proof_vec - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); let execution_payload_root = calculate_multi_merkle_root( &[ Node::from_bytes( @@ -172,7 +153,7 @@ pub fn verify_sync_committee_attestation( .map_err(|_| Error::InvalidRoot)?, execution_payload.timestamp.hash_tree_root().map_err(|_| Error::InvalidRoot)?, ], - &multi_proof_nodes, + &execution_payload.multi_proof, &[ GeneralizedIndex(EXECUTION_PAYLOAD_STATE_ROOT_INDEX as usize), GeneralizedIndex(EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX as usize), @@ -180,15 +161,9 @@ pub fn verify_sync_committee_attestation( ], ); - let execution_payload_branch = execution_payload - .execution_payload_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let is_merkle_branch_valid = is_valid_merkle_branch( &execution_payload_root, - execution_payload_branch.iter(), + execution_payload.execution_payload_branch.iter(), EXECUTION_PAYLOAD_INDEX_LOG2 as usize, EXECUTION_PAYLOAD_INDEX as usize, &update.finalized_header.state_root, @@ -206,17 +181,12 @@ pub fn verify_sync_committee_attestation( Err(Error::InvalidUpdate)? } - let next_sync_committee_branch = sync_committee_update - .next_sync_committee_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); let is_merkle_branch_valid = is_valid_merkle_branch( &sync_committee_update .next_sync_committee .hash_tree_root() .map_err(|_| Error::MerkleizationError)?, - next_sync_committee_branch.iter(), + sync_committee_update.next_sync_committee_branch.iter(), NEXT_SYNC_COMMITTEE_INDEX_LOG2 as usize, NEXT_SYNC_COMMITTEE_INDEX as usize, &update.attested_header.state_root, @@ -227,170 +197,6 @@ pub fn verify_sync_committee_attestation( } } - // verify the ancestry proofs - for mut ancestor in update.ancestor_blocks { - match ancestor.ancestry_proof { - AncestryProof::BlockRoots { block_roots_proof, block_roots_branch } => { - let block_header_branch = block_roots_proof - .block_header_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - - let block_roots_root = calculate_merkle_root( - &ancestor.header.hash_tree_root().map_err(|_| Error::MerkleizationError)?, - &*block_header_branch, - &GeneralizedIndex(block_roots_proof.block_header_index as usize), - ); - - let block_roots_branch_node = block_roots_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - - let is_merkle_branch_valid = is_valid_merkle_branch( - &block_roots_root, - block_roots_branch_node.iter(), - BLOCK_ROOTS_INDEX_LOG2 as usize, - BLOCK_ROOTS_INDEX as usize, - &update.finalized_header.state_root, - ); - if !is_merkle_branch_valid { - Err(Error::InvalidMerkleBranch)?; - } - }, - AncestryProof::HistoricalRoots { - block_roots_proof, - historical_batch_proof, - historical_roots_proof, - historical_roots_index, - historical_roots_branch, - } => { - let block_header_branch = block_roots_proof - .block_header_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let block_roots_root = calculate_merkle_root( - &ancestor - .header - .clone() - .hash_tree_root() - .map_err(|_| Error::MerkleizationError)?, - &block_header_branch, - &GeneralizedIndex(block_roots_proof.block_header_index as usize), - ); - - let historical_batch_proof_nodes = historical_batch_proof - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let historical_batch_root = calculate_merkle_root( - &block_roots_root, - &historical_batch_proof_nodes, - &GeneralizedIndex(HISTORICAL_BATCH_BLOCK_ROOTS_INDEX as usize), - ); - - let historical_roots_proof_nodes = historical_roots_proof - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let historical_roots_root = calculate_merkle_root( - &historical_batch_root, - &historical_roots_proof_nodes, - &GeneralizedIndex(historical_roots_index as usize), - ); - - let historical_roots_branch_nodes = historical_roots_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let is_merkle_branch_valid = is_valid_merkle_branch( - &historical_roots_root, - historical_roots_branch_nodes.iter(), - HISTORICAL_ROOTS_INDEX_LOG2 as usize, - HISTORICAL_ROOTS_INDEX as usize, - &Node::from_bytes( - update - .finalized_header - .state_root - .as_ref() - .try_into() - .map_err(|_| Error::InvalidRoot)?, - ), - ); - - if !is_merkle_branch_valid { - Err(Error::InvalidMerkleBranch)?; - } - }, - }; - - // verify the associated execution paylaod header. - let execution_payload = ancestor.execution_payload; - let multi_proof = execution_payload - .multi_proof - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let execution_payload_root = calculate_multi_merkle_root( - &[ - Node::from_bytes( - execution_payload - .state_root - .as_ref() - .try_into() - .map_err(|_| Error::InvalidRoot)?, - ), - Node::from_bytes( - execution_payload - .block_number - .clone() - .hash_tree_root() - .map_err(|_| Error::MerkleizationError)? - .as_ref() - .try_into() - .map_err(|_| Error::InvalidRoot)?, - ), - Node::from_bytes( - execution_payload - .timestamp - .clone() - .hash_tree_root() - .map_err(|_| Error::MerkleizationError)? - .as_ref() - .try_into() - .map_err(|_| Error::InvalidRoot)?, - ), - ], - &multi_proof, - &[ - GeneralizedIndex(EXECUTION_PAYLOAD_STATE_ROOT_INDEX as usize), - GeneralizedIndex(EXECUTION_PAYLOAD_BLOCK_NUMBER_INDEX as usize), - GeneralizedIndex(EXECUTION_PAYLOAD_TIMESTAMP_INDEX as usize), - ], - ); - - let execution_payload_branch = execution_payload - .execution_payload_branch - .iter() - .map(|node| Node::from_bytes(node.as_ref().try_into().unwrap())) - .collect::>(); - let is_merkle_branch_valid = is_valid_merkle_branch( - &execution_payload_root, - execution_payload_branch.iter(), - EXECUTION_PAYLOAD_INDEX_LOG2 as usize, - EXECUTION_PAYLOAD_INDEX as usize, - &Node::from_bytes( - ancestor.header.state_root.as_ref().try_into().map_err(|_| Error::InvalidRoot)?, - ), - ); - - if !is_merkle_branch_valid { - Err(Error::InvalidMerkleBranch)?; - } - } - let new_light_client_state = if let Some(sync_committee_update) = update.sync_committee_update { LightClientState { finalized_header: update.finalized_header, @@ -404,13 +210,3 @@ pub fn verify_sync_committee_attestation( Ok(new_light_client_state) } - -pub struct SignatureVerifier; - -impl BlsVerify for SignatureVerifier { - fn verify(public_keys: &[&PublicKey], msg: &[u8], signature: &Signature) -> Result<(), Error> { - ethereum_consensus::crypto::fast_aggregate_verify(public_keys, msg, signature)?; - - Ok(()) - } -} diff --git a/verifier/src/signature_verification.rs b/verifier/src/signature_verification.rs new file mode 100644 index 0000000..06aa4f2 --- /dev/null +++ b/verifier/src/signature_verification.rs @@ -0,0 +1,108 @@ +use alloc::vec::Vec; +use anyhow::anyhow; +use ark_bls12_381::Bls12_381; +use ark_ec::{pairing::Pairing, AffineRepr}; +use bls_on_arkworks::{ + hash_to_point, pubkey_to_point, signature_to_point, + types::{BLS12381Pairing, G1AffinePoint, G1ProjectivePoint, G2AffinePoint, Signature}, + DST_ETHEREUM, +}; +use sync_committee_primitives::constants::BlsPublicKey; + +pub fn pubkey_to_projective(compressed_key: &BlsPublicKey) -> anyhow::Result { + let affine_point = pubkey_to_point(&compressed_key.to_vec()).map_err(|e| anyhow!("{:?}", e))?; + Ok(affine_point.into()) +} + +fn subtract_points_from_aggregate( + aggregate: &BlsPublicKey, + points: &[BlsPublicKey], +) -> anyhow::Result { + let aggregate = pubkey_to_projective(aggregate)?; + let points = points + .iter() + .map(|point| pubkey_to_projective(point)) + .collect::, _>>()?; + let subset_aggregate = points.into_iter().fold(aggregate, |acc, point| acc - point); + Ok(subset_aggregate) +} + +fn pairing(u: G2AffinePoint, v: G1AffinePoint) -> BLS12381Pairing { + Bls12_381::pairing(v, u) +} + +/// Adapted from https://github.com/ArnaudBrousseau/bls_on_arkworks/blob/main/src/lib.rs#L335 +/// Verifies an aggregate bls12-381 signature from ethereum sync-committee +/// Expects signature subgroup to be valid +pub fn verify_aggregate_signature( + aggregate: &BlsPublicKey, + non_participants: &[BlsPublicKey], + msg: Vec, + signature: &Signature, +) -> anyhow::Result<()> { + let subset_aggregate = subtract_points_from_aggregate(aggregate, non_participants)?; + let aggregate_key_point: G1AffinePoint = subset_aggregate.into(); + let signature = signature_to_point(signature).map_err(|e| anyhow!("{:?}", e))?; + let dst = DST_ETHEREUM.as_bytes().to_vec(); + + let q = hash_to_point(&msg, &dst); + + let c1 = pairing(q, aggregate_key_point); + + // From the spec: + // > When the signature variant is minimal-pubkey-size, P is the distinguished point P1 that + // > generates the group G1. + // + let p = G1AffinePoint::generator(); + + let c2 = pairing(signature, p); + + if c1 == c2 { + Ok(()) + } else { + Err(anyhow!("Aggregate signature verification failed")) + } +} + +#[cfg(test)] +mod tests { + use crate::signature_verification::verify_aggregate_signature; + + #[test] + fn test_signature_verification() { + let pks = vec![ + hex::decode("882417eb57b98c7dd8e4adb5d4c7b59cb46ad093072f10db99e02597e3432fe094e2698df4c3bf65ff757ac602182f87").unwrap(), + hex::decode("8ef016d09c49af41d028fdf6ef04972d11f6931bf57f0922df4e77a52847227c880581eebb6b485af1d68bb4895cc35c").unwrap(), + hex::decode("88b92def24f441be1eba41ff76182e0eb224cf06e751df45635db1530bf37765861c82a8f381f81f6ac6a2b3d3d9875b").unwrap(), + hex::decode("afc92546e835a4dbe31e2b3a4e6f44a94466a6f9b5752113b9b828349254582eb7b5b596a32b79fc936a82db8802af0c").unwrap(), + hex::decode("8391e3a00add4bcbe4c339fa7c35238855861cbbc89ceefa6832de6b28bc378a0d038a329636d53404e0deaa444bdfd0").unwrap(), + hex::decode("9102e77817e572a16fab849f7681d130d10876880d7fe05d40091af93592150ad4829145a7327d125e71a8847a368121").unwrap(), + hex::decode("8d966a5cfd601661bfb6e15b8c849d3bd85006aec628b44e88022b01054be5159de73f16504a969d6009a59d9214b043").unwrap(), + hex::decode("b6778f88f9df6d5d09baf9bccd2ea1e4cb88469239a0a14ffcca37fc1c29bad69711dc64fc4e1bb1be0792b005a1729a").unwrap(), + hex::decode("afc664d1160d2a55fab55fe9d94551b18aa2543f218b9fbdd733509463416c96ee13da6cf75f97165922ca61372c6fb7").unwrap(), + hex::decode("ad413282bc501315d2cccf8e2a5dd54a5baca851515a04e5f252c98cfeeb670604fa48c707127017e0b8cda218d98207").unwrap() + ]; + + let message = + hex::decode("813a89a296973e35545cfa74fe3efd172a7d19443c97c625d699e9737229b0a2") + .unwrap(); + let aggregate_signature = hex::decode("a1abfcf9bd54b7a003e1f45f7543b194d8d25b816577b02ee4f1c99aa9821c620be6ecedbc8c5fab64d343a6cc832040029040e591fa24db54f5441f28d73918775e8feeac6177c9e016d2576b982d1cce453896a8aace2bda7374e5a76ce213").unwrap(); + let aggregate_pub_key = hex::decode("a3f2da752bd1dfc7288b46cc061668856e0cefa93ba6e8ff4699f355138f63a541fdb3444ddebcdce695d6313fa4b244").unwrap().try_into().unwrap(); + + let bit_vector = hex::decode("01000100010001000100").unwrap(); + + let non_participants = pks + .into_iter() + .zip(bit_vector) + .filter_map(|(pk, bit)| if bit == 0 { Some(pk.try_into().unwrap()) } else { None }) + .collect::>(); + + verify_aggregate_signature( + &aggregate_pub_key, + &non_participants, + message, + &aggregate_signature, + ) + .unwrap() + } +}