diff --git a/bridges/snowbridge/LICENSE b/bridges/snowbridge/LICENSE deleted file mode 100644 index 261eeb9e9f8b..000000000000 --- a/bridges/snowbridge/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/bridges/snowbridge/README.md b/bridges/snowbridge/README.md deleted file mode 100644 index a38910da3164..000000000000 --- a/bridges/snowbridge/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# Snowbridge · -[![codecov](https://codecov.io/gh/Snowfork/snowbridge/branch/main/graph/badge.svg?token=9hvgSws4rN)] -(https://codecov.io/gh/Snowfork/snowbridge) -![GitHub](https://img.shields.io/github/license/Snowfork/snowbridge) - -Snowbridge is a trustless bridge between Polkadot and Ethereum. For documentation, visit https://docs.snowbridge.network. - -## Components - -### Parachain - -Polkadot parachain and our pallets. See [parachain/README.md](https://github.com/Snowfork/snowbridge/blob/main/parachain/README.md). - -### Contracts - -Ethereum contracts and unit tests. See [contracts/README.md](https://github.com/Snowfork/snowbridge/blob/main/contracts/README.md) - -### Relayer - -Off-chain relayer services for relaying messages between Polkadot and Ethereum. See -[relayer/README.md](https://github.com/Snowfork/snowbridge/blob/main/relayer/README.md) - -### Local Testnet - -Scripts to provision a local testnet, running the above services to bridge between local deployments of Polkadot and -Ethereum. See [web/packages/test/README.md](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/README.md). - -### Smoke Tests - -Integration tests for our local testnet. See [smoketest/README.md](https://github.com/Snowfork/snowbridge/blob/main/smoketest/README.md). - -## Development - -We use the Nix package manager to provide a reproducible and maintainable developer environment. - -After [installing nix](https://nixos.org/download.html) Nix, enable [flakes](https://nixos.wiki/wiki/Flakes): - -```sh -mkdir -p ~/.config/nix -echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf -``` - -Then activate a developer shell in the root of our repo, where -[`flake.nix`](https://github.com/Snowfork/snowbridge/blob/main/flake.nix) is located: - -```sh -nix develop -``` - -Also make sure to run this initialization script once: -```sh -scripts/init.sh -``` - -### Support for code editors - -To ensure your code editor (such as VS Code) can execute tools in the nix shell, startup your editor within the -interactive shell. - -Example for VS Code: - -```sh -nix develop -code . -``` - -### Custom shells - -The developer shell is bash by default. To preserve your existing shell: - -```sh -nix develop --command $SHELL -``` - -### Automatic developer shells - -To automatically enter the developer shell whenever you open the project, install -[`direnv`](https://direnv.net/docs/installation.html) and use the template `.envrc`: - -```sh -cp .envrc.example .envrc -direnv allow -``` - -### Upgrading the Rust toolchain - -Sometimes we would like to upgrade rust toolchain. First update `parachain/rust-toolchain.toml` as required and then -update `flake.lock` running -```sh -nix flake lock --update-input rust-overlay -``` - -## Troubleshooting - -Check the contents of all `.envrc` files. - -Remove untracked files: -```sh -git clean -idx -``` - -Ensure that the current Rust toolchain is the one selected in `scripts/init.sh`. - -Ensure submodules are up-to-date: -```sh -git submodule update -``` - -Check untracked files & directories: -```sh -git clean -ndx | awk '{print $3}' -``` -After removing `node_modules` directories (eg. with `git clean above`), clear the pnpm cache: -```sh -pnpm store prune -``` - -Check Nix config in `~/.config/nix/nix.conf`. - -Run a pure developer shell (note that this removes access to your local tools): -```sh -nix develop -i --pure-eval -``` - -## Security - -The security policy and procedures can be found in SECURITY.md. diff --git a/bridges/snowbridge/parachain/LICENSE b/bridges/snowbridge/parachain/LICENSE deleted file mode 100644 index 261eeb9e9f8b..000000000000 --- a/bridges/snowbridge/parachain/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/bridges/snowbridge/parachain/README.md b/bridges/snowbridge/parachain/README.md deleted file mode 100644 index a38910da3164..000000000000 --- a/bridges/snowbridge/parachain/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# Snowbridge · -[![codecov](https://codecov.io/gh/Snowfork/snowbridge/branch/main/graph/badge.svg?token=9hvgSws4rN)] -(https://codecov.io/gh/Snowfork/snowbridge) -![GitHub](https://img.shields.io/github/license/Snowfork/snowbridge) - -Snowbridge is a trustless bridge between Polkadot and Ethereum. For documentation, visit https://docs.snowbridge.network. - -## Components - -### Parachain - -Polkadot parachain and our pallets. See [parachain/README.md](https://github.com/Snowfork/snowbridge/blob/main/parachain/README.md). - -### Contracts - -Ethereum contracts and unit tests. See [contracts/README.md](https://github.com/Snowfork/snowbridge/blob/main/contracts/README.md) - -### Relayer - -Off-chain relayer services for relaying messages between Polkadot and Ethereum. See -[relayer/README.md](https://github.com/Snowfork/snowbridge/blob/main/relayer/README.md) - -### Local Testnet - -Scripts to provision a local testnet, running the above services to bridge between local deployments of Polkadot and -Ethereum. See [web/packages/test/README.md](https://github.com/Snowfork/snowbridge/blob/main/web/packages/test/README.md). - -### Smoke Tests - -Integration tests for our local testnet. See [smoketest/README.md](https://github.com/Snowfork/snowbridge/blob/main/smoketest/README.md). - -## Development - -We use the Nix package manager to provide a reproducible and maintainable developer environment. - -After [installing nix](https://nixos.org/download.html) Nix, enable [flakes](https://nixos.wiki/wiki/Flakes): - -```sh -mkdir -p ~/.config/nix -echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf -``` - -Then activate a developer shell in the root of our repo, where -[`flake.nix`](https://github.com/Snowfork/snowbridge/blob/main/flake.nix) is located: - -```sh -nix develop -``` - -Also make sure to run this initialization script once: -```sh -scripts/init.sh -``` - -### Support for code editors - -To ensure your code editor (such as VS Code) can execute tools in the nix shell, startup your editor within the -interactive shell. - -Example for VS Code: - -```sh -nix develop -code . -``` - -### Custom shells - -The developer shell is bash by default. To preserve your existing shell: - -```sh -nix develop --command $SHELL -``` - -### Automatic developer shells - -To automatically enter the developer shell whenever you open the project, install -[`direnv`](https://direnv.net/docs/installation.html) and use the template `.envrc`: - -```sh -cp .envrc.example .envrc -direnv allow -``` - -### Upgrading the Rust toolchain - -Sometimes we would like to upgrade rust toolchain. First update `parachain/rust-toolchain.toml` as required and then -update `flake.lock` running -```sh -nix flake lock --update-input rust-overlay -``` - -## Troubleshooting - -Check the contents of all `.envrc` files. - -Remove untracked files: -```sh -git clean -idx -``` - -Ensure that the current Rust toolchain is the one selected in `scripts/init.sh`. - -Ensure submodules are up-to-date: -```sh -git submodule update -``` - -Check untracked files & directories: -```sh -git clean -ndx | awk '{print $3}' -``` -After removing `node_modules` directories (eg. with `git clean above`), clear the pnpm cache: -```sh -pnpm store prune -``` - -Check Nix config in `~/.config/nix/nix.conf`. - -Run a pure developer shell (note that this removes access to your local tools): -```sh -nix develop -i --pure-eval -``` - -## Security - -The security policy and procedures can be found in SECURITY.md. diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/parachain/pallets/ethereum-client/Cargo.toml deleted file mode 100644 index 2bf5bfcd12f8..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/Cargo.toml +++ /dev/null @@ -1,99 +0,0 @@ -[package] -name = "snowbridge-pallet-ethereum-client" -description = "Snowbridge Ethereum Client Pallet" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -serde = { version = "1.0.195", optional = true } -serde_json = { version = "1.0.111", optional = true } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -ssz_rs = { version = "0.9.0", default-features = false } -ssz_rs_derive = { version = "0.9.0", default-features = false } -byte-slice-cast = { version = "1.2.1", default-features = false } -rlp = { version = "0.5.2", default-features = false } -hex-literal = { version = "0.4.1", optional = true } -log = { version = "0.4.20", default-features = false } - -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false, optional = true } - -snowbridge-core = { path = "../../primitives/core", default-features = false } -snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } -primitives = { package = "snowbridge-beacon-primitives", path = "../../primitives/beacon", default-features = false } -static_assertions = { version = "1.1.0", default-features = false } -bp-runtime = { path = "../../../../primitives/runtime", default-features = false } -pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false, optional = true } - -[dev-dependencies] -rand = "0.8.5" -sp-keyring = { path = "../../../../../substrate/primitives/keyring" } -serde_json = "1.0.111" -hex-literal = "0.4.1" -pallet-timestamp = { path = "../../../../../substrate/frame/timestamp" } -sp-io = { path = "../../../../../substrate/primitives/io" } -serde = "1.0.195" - -[features] -default = ["std"] -fuzzing = [ - "hex-literal", - "pallet-timestamp", - "serde", - "serde_json", - "sp-io", -] -std = [ - "bp-runtime/std", - "byte-slice-cast/std", - "codec/std", - "frame-support/std", - "frame-system/std", - "log/std", - "pallet-timestamp/std", - "primitives/std", - "rlp/std", - "scale-info/std", - "serde", - "snowbridge-core/std", - "snowbridge-ethereum/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "ssz_rs/std", - 'frame-benchmarking/std', -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "hex-literal", - "pallet-timestamp?/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-timestamp?/try-runtime", - "sp-runtime/try-runtime", -] -beacon-spec-minimal = [] -fast-runtime = ["beacon-spec-minimal"] diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/README.md b/bridges/snowbridge/parachain/pallets/ethereum-client/README.md deleted file mode 100644 index 0cd3b9f85587..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ethereum Beacon Client - -The Ethereum Beacon Client is an on-chain light client that tracks Ethereum consensus using the beacon chain. diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/benchmark.md b/bridges/snowbridge/parachain/pallets/ethereum-client/benchmark.md deleted file mode 100644 index 2e19fece7cbd..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/benchmark.md +++ /dev/null @@ -1,88 +0,0 @@ -# Motivation -Demonstrate that -[FastAggregateVerify](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-04#section-3.3.4) is the most -expensive call in ethereum beacon light client, though in [#13031](https://github.com/paritytech/substrate/pull/13031) -Parity team has wrapped some low level host functions for `bls-12381` but adding a high level host function specific -for it is super helpful. - -# Benchmark -We add several benchmarks -[here](https://github.com/Snowfork/snowbridge/blob/8891ca3cdcf2e04d8118c206588c956541ae4710/parachain/pallets/ethereum-client/src/benchmarking/mod.rs#L98-L124) -as following to demonstrate -[bls_fast_aggregate_verify](https://github.com/Snowfork/snowbridge/blob/8891ca3cdcf2e04d8118c206588c956541ae4710/parachain/pallets/ethereum-client/src/lib.rs#L764) -is the main bottleneck. Test data -[here](https://github.com/Snowfork/snowbridge/blob/8891ca3cdcf2e04d8118c206588c956541ae4710/parachain/pallets/ethereum-client/src/benchmarking/data_mainnet.rs#L553-L1120) -is real from goerli network which contains 512 public keys from sync committee. - -## sync_committee_period_update -Base line benchmark for extrinsic [sync_committee_period_update](https://github.com/Snowfork/snowbridge/blob/8891ca3cdcf2e04d8118c206588c956541ae4710/parachain/pallets/ethereum-client/src/lib.rs#L233) - -## bls_fast_aggregate_verify -Subfunction of extrinsic `sync_committee_period_update` which does what -[FastAggregateVerify](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-04#section-3.3.4) requires. - -## bls_aggregate_pubkey -Subfunction of `bls_fast_aggregate_verify` which decompress and instantiate G1 pubkeys only. - -## bls_verify_message -Subfunction of `bls_fast_aggregate_verify` which verify the prepared signature only. - - -# Result - -## hardware spec -Run benchmark in a EC2 instance -``` -cargo run --release --bin polkadot-parachain --features runtime-benchmarks -- benchmark machine --base-path /mnt/scratch/benchmark - -+----------+----------------+-------------+-------------+-------------------+ -| Category | Function | Score | Minimum | Result | -+===========================================================================+ -| CPU | BLAKE2-256 | 1.08 GiBs | 1.00 GiBs | ✅ Pass (107.5 %) | -|----------+----------------+-------------+-------------+-------------------| -| CPU | SR25519-Verify | 568.87 KiBs | 666.00 KiBs | ❌ Fail ( 85.4 %) | -|----------+----------------+-------------+-------------+-------------------| -| Memory | Copy | 13.67 GiBs | 14.32 GiBs | ✅ Pass ( 95.4 %) | -|----------+----------------+-------------+-------------+-------------------| -| Disk | Seq Write | 334.35 MiBs | 450.00 MiBs | ❌ Fail ( 74.3 %) | -|----------+----------------+-------------+-------------+-------------------| -| Disk | Rnd Write | 143.59 MiBs | 200.00 MiBs | ❌ Fail ( 71.8 %) | -+----------+----------------+-------------+-------------+-------------------+ -``` - -## benchmark - -``` -cargo run --release --bin polkadot-parachain \ ---features runtime-benchmarks \ --- \ -benchmark pallet \ ---base-path /mnt/scratch/benchmark \ ---chain=bridge-hub-rococo-dev \ ---pallet=snowbridge_pallet_ethereum_client \ ---extrinsic="*" \ ---execution=wasm --wasm-execution=compiled \ ---steps 50 --repeat 20 \ ---output ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_pallet_ethereum_client.rs -``` - -### [Weights](https://github.com/Snowfork/cumulus/blob/ron/benchmark-beacon-bridge/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_pallet_ethereum_client.rs) - -|extrinsic | minimum execution time benchmarked(us) | -| --------------------------------------- |----------------------------------------| -|sync_committee_period_update | 123_126 | -|bls_fast_aggregate_verify| 121_083 | -|bls_aggregate_pubkey | 90_306 | -|bls_verify_message | 28_000 | - -- [bls_fast_aggregate_verify](#bls_fast_aggregate_verify) consumes 98% execution time of [sync_committee_period_update](#sync_committee_period_update) - -- [bls_aggregate_pubkey](#bls_aggregate_pubkey) consumes 75% execution time of [bls_fast_aggregate_verify](#bls_fast_aggregate_verify) - -- [bls_verify_message](#bls_verify_message) consumes 23% execution time of [bls_fast_aggregate_verify](#bls_fast_aggregate_verify) - -# Conclusion - -A high level host function specific for -[bls_fast_aggregate_verify](https://github.com/Snowfork/snowbridge/blob/8891ca3cdcf2e04d8118c206588c956541ae4710/parachain/pallets/ethereum-client/src/lib.rs#L764) -is super helpful. diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_mainnet.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_mainnet.rs deleted file mode 100644 index 4b88d887091d..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_mainnet.rs +++ /dev/null @@ -1,1215 +0,0 @@ -// Generated, do not edit! -// See README.md for instructions to generate -use crate::{CheckpointUpdate, ExecutionHeaderUpdate, Update}; -use hex_literal::hex; -use primitives::{ - updates::AncestryProof, BeaconHeader, ExecutionPayloadHeader, NextSyncCommitteeUpdate, - SyncAggregate, SyncCommittee, -}; -use sp_core::U256; -use sp_std::{boxed::Box, vec}; - -pub fn make_checkpoint() -> Box { - Box::new(CheckpointUpdate { - header: BeaconHeader { - slot: 4058624, - proposer_index: 631, - parent_root: hex!("4abadda13b61df8d40fcb061d1ec15d0fb7bc5144252bb54c57b41893b642bf3").into(), - state_root: hex!("6fe9fa01a04dcdeaa64eba04a72fa6dbadc8596dc5ec1fff2ef343520fe722e1").into(), - body_root: hex!("6cd83df0ee7669e06e64496a1d2be083bc3bb9f2da17e9b1e62979d200328106").into(), - }, - current_sync_committee: SyncCommittee { - pubkeys: [ - hex!("a13bf1fc1826b61cceefcc941c5a4865cefdfa6c91e5223308fa6a0aa6e7b13a0499a63edf5d9fff48fdeae83e38dcbf").into(), - hex!("b3285148b91dab139b053442bdd14d627ba1e1250fe469f0f2df854b6e6ff4a18671ae3879ec9f7d8091f99f092162e9").into(), - hex!("b00d95908e72c6051478a422eb2231b5f797c2fa5c696ed1e6b9c9996ba1d8236f512443f18c01ce63312c38fa383fd4").into(), - hex!("a866633b4293e726accf6e97ac90c1898cac83e8531a25b50ae99f0ecb477a692e6a5f2488447ccd83ed869ab5abc406").into(), - hex!("a308ed8737b3a9346ff20dc9f112efccc193472e6fde6aa218ceae11e288bbd2c35fa45c1d8bb238696a96767cd68b46").into(), - hex!("81534e2a182da0c6831479c7e722953d267ba9c63a204ac96a178b1dc90d0a6ba8737002688ba5f102eda5669249f114").into(), - hex!("87c5670e16a84e27529677881dbedc5c1d6ebb4e4ff58c13ece43d21d5b42dc89470f41059bfa6ebcf18167f97ddacaa").into(), - hex!("b37334c41a3456b73b61d0eb0777260af9c2e400bbec0e0c0fdb45c39ce0dd19f021d9760f35da801f20486c6be30e9e").into(), - hex!("ab73a043ccdfe63437a339e6ee96ef1241264e04dd4d917f6d6bc99396006de54e1e156d38596ba3d15cb1aaa329f8f5").into(), - hex!("8983fdebbeba6e3cc3ee1c9feb24faaeee712356975e359b0ddca3f7c9c7448132d665f54a4629002252d3fcf375f7b0").into(), - hex!("a03c1e287ccc4d457f5e71e9dc769294835945561e6f236ac7de210d2e614eee8a85e21dfb46e2143c68de22ccee8660").into(), - hex!("8e6b888197010ebadd216da35b9716daa8675d93b3c33a96a19fd9ca42624f6b430b2ff115cd0f5b717341605dda24bf").into(), - hex!("8fb51e3ef3c1047ae7c527dc24dc8824b2655faff2c4c78da1fcedde48b531d19abaf517363bf30605a87336b8642073").into(), - hex!("893272a63650b08e5b8f9b3f17f8547b456192ad649c168bafd7166b4c08c5adf795c508b88fd2425f7be8334592afb2").into(), - hex!("a90c42266ca0a65976fb4dc18465b0a44a63ed3b2747cae74e46e3ccf158f98384e2e86c852e7c5556b083b3ded9d243").into(), - hex!("b67c621d9b6313a9f6744dfcdd77d4e9cb4bd413fb5e3199cdcd7f675fc39f1ba492860749bfddf98f4088756e844a98").into(), - hex!("a9760afaa51002be0948acf7aebd90ec4e60e0dba8456e445aea93408a0468b62bb6da4984b92f8f6061561c9d56f4c4").into(), - hex!("981b2d7c56ff38f1d02c5d7a7f8bfe71daaf94d48c3bc93e8083a0a23c1ae1ff05f90312deb09b35d4513c1ffa573d86").into(), - hex!("9515dedf061e654d58a43e4e525a63ad2a6274ea6f20b1d624a6ba7d3062ed68a0226eee6951ab8464906c52ba5556b0").into(), - hex!("901f724ee1891ca876e5551bd8f4ad4da422576c618465f63d65700c2dd7953496d83abe148c6a4875a46a5a36c218cf").into(), - hex!("a8d152e5d94b75cb9e249230db21af31de4d4f3d4ef60ccbf2212babf69aed2a38435a993ee2f13cca410ad55a4875ab").into(), - hex!("875ebfe737cea438e967d70ceaffb4360cce28ecc76c8c4ee612c47fb6b3e89af03c66981571066107323f49a6242772").into(), - hex!("a798a0371e8cc4dc42ccd79934b0db5a3a59f18a0ae09f2eb172596428fcb3f00312e783d6fd21cbc1610317f44e08cb").into(), - hex!("99c629c9cd603a9344b04d22d2bcc06cf45ebf62d97f968df19c73c7a50f4f6a2a2cc7fb633f509f961edfb94fbab94e").into(), - hex!("854410e6fb856da8b997ebf28ae2415ce6e1f9f6a4579fad15b5df61709c924a925397b33fe67c89ffad6143a39d756a").into(), - hex!("a3969926aa2e52f1a48ac53074b764648b4c71bd43430944679628463cd68398f700d874c14503b53756be451c8ba284").into(), - hex!("8ee8873de7cd28a54ba2c63a80b63399effed76b154e96ed26e7c0668b9f2476e298688b6a00c4b2ab9d020a897695d7").into(), - hex!("ad54241ba3de6a4426c788690d3f78d2eb678814edc49d3fb988d7fc752e43512972567bb384bcc1b18d083d15e376da").into(), - hex!("942bee9ee880ac5e2f8ba35518b60890a211974d273b2ae415d34ce842803de7d29a4d26f6ee79c09e910559bdcac6d3").into(), - hex!("96b478b1e5e49d4ea3fd97c4846ae0f781dcc9f9ff61ee022ca92c3d8dfba89c513c46e8bb38b73e6b678a79b9b12177").into(), - hex!("aad9577501d7f3a5dbac329f2c1fe711710869cc825740f365488fc55a278d687bb72423560f7cb2cbd60546a82ea1e6").into(), - hex!("8aa3d9dad1c122b9aed75e3cc94b3a9dab160fa4cad92ebab68a58c0151a5d93f0f6b40b86fba00e63d45bd29a93b982").into(), - hex!("a12fc78b8d3334a3eb7b535cd5e648bb030df645cda4e90272a1fc3b368ee43975051bbecc3275d6b1e4600cc07239b0").into(), - hex!("ab01a7b13c967620d98de736b8ff23d856daa26d5cd8576993ee02a5d694332c0464ed018ebffcd5c71bab5cada850ce").into(), - hex!("96cf5760c79cfc830d1d5bd6df6cfd67596bef24e22eed52cee04c290ad418add74e77965ea5748b7f0fb34ee4f43232").into(), - hex!("9443e6ba4400fb3370c573cd7e33f05e1475f9cf1d6adb905bee3aff8f1452d8d384c8a72c9110070f35c6aad940bba6").into(), - hex!("95c60b5561e53cfc26d620be90f84199ffd6dd9687c1be3a547048e7cba10a0be9bb6da000e7521cbd488d0901d48ee9").into(), - hex!("ab69cf79750436d310dc3c5e96c2b97003f4394f31dfa8a9ac420595dc7b4d96dad5787d93347ba2bc6f196c241a3dbf").into(), - hex!("9145ee1fb6e84114c903819db94fa5a72bcbc15fcb8a7fd8eefba23b156cc46309281dcf78b48a2847b3754f7d7d7a79").into(), - hex!("b118f77f99ac947df97e7682f0fb446175185b842380af4ee7394531e4f93002c72b41a57a7c1b923a4f24b10924c84f").into(), - hex!("a4aabd1890ebf35423565dbff3477a09eea4e35f5a26ed449eab38e0a21fb89e9ddfe3a2003cddc457db648a1b5891a3").into(), - hex!("8ff5d2e6c98b1fea70cb36ea8ed497fd1233b9418948ac58c6c379ed35fb10f8253ef188c909d5e77e81b5b8e2a4ad17").into(), - hex!("a23f076306c120dccf69d7d2ac7f83a377a72d35bf448f88feff8b6dba9307fdabf34452e30b87407b2258b9edfd1174").into(), - hex!("87d2217eb05d657aba7b048cf3c661b463e78e51135a5b937e71975ff5102e596434720f02349c73415decb88418cb0d").into(), - hex!("8bb51b380a8a52d61a94e7b382ff6ce601260fa9b8c5d616764a3df719b382ec43aec9266444a16951e102d8b1fb2f38").into(), - hex!("b0053550040ab3a3996cba5caf9ad5718867b5f5df273ed8c6520761571f03a94e50b5f8a6a8c42d725383cce97d3cae").into(), - hex!("ae50f93230983a82e732903d6ed50a506d678f35b6b4a4b3686a92b12aeb9d34cb095e8562b0900125bbced0359b37de").into(), - hex!("8bfa106ada4914419bf1d8900c5981dd5b90c3023196d7e918d62879fc3a575bd0a25f939366f7fd2240df6108b069ec").into(), - hex!("b3a5497365bd40a81202b8a94a5e28a8a039cc2e639d73de289294cbda2c0e987c1f9468daba09ea4390f8e4e806f3c8").into(), - hex!("b4f583e10aa9af79b4ebd647e0fffe1c720112727e5ffac4313f236737491fceeee194537786c561cd5777b453e5b03c").into(), - hex!("826be957cf66db958028fa95655b54b2337f78fb6ef26bd29e2e3a64b130b90521333f31d132c04779e4b23a6b6cd951").into(), - hex!("aace45334070c51cc8b3579598d4cd8cda2153bba51f56e3b1fe5e135c83ef70503c322756b9cad9d3cd28f1ecfc8227").into(), - hex!("94bb68c8180496472262455fd6ab338697810825fa4e82fc673f3ac2dacfd29ee539ac0bfe97eb39d4ef118db875bab6").into(), - hex!("b560c33950a355119845f63defb355807e56773f636fb836f7746155fad070e384fc1091b8e5c057e4cbc7da9275ecf7").into(), - hex!("820cc2ac3eed5bce7dc72df2aa3214e71690b91445d8bb1634c0488a671e3669028efbe1eae52f7132bde29b16a020b7").into(), - hex!("9244703338879e3ea00663dcde8f11095de3e38df9277d8c2acc26e72021c222ae40bcc91228789fdf0b69acc3144783").into(), - hex!("8d474636a638e7b398566a39b3f939a314f1cf88e64d81db0f556ca60951ec1dca1b93e3906a6654ed9ba06f2c31d4ea").into(), - hex!("889a5cf9315383bf64dfe88e562d772213c256b0eed15ce27c41c3767c048afe06410d7675e5d59a2302993e7dc45d83").into(), - hex!("b544c692b046aad8b6f5c2e3493bc8f638659795f06327fff1e9f4ffc8e9f7abdbf4b7f6fcdfb8fe19654d8fa7d68170").into(), - hex!("aefc682f8784b18d36202a069269be7dba8ab67ae3543838e6d473fbc5713d103abcc8da1729a288503b786baac182d3").into(), - hex!("a0f2092ac34d2363614fb2f57fc7b72db247eb1fa53f395881ce6b4aacd6fb920d6dc59507701d487288102e4c4fa389").into(), - hex!("b33de3de106be61481ccb7f07a7a63cf4d1674010e462388fb8ab5ea08f444ed7a277905207e0b3aa2f00bb9efca984f").into(), - hex!("84173aeaf3d96368dc7ca1ad5e5575da279113567e5815a364a0356a720c5e08cb58ca1fdd891924f4871d3eaae5de40").into(), - hex!("b6d6482ad7b9b412ffbefbbdcc28eb3d091b1291f54f77bdd53c4ac85f705c454940f466dc272dde7b03c26f0cd6ecb3").into(), - hex!("a2053719da2b7501dab42011ae144b3c8d72bd17493181bf3ae79a678068dc3ee2f19d29a60b5a323692c3f684f96392").into(), - hex!("8296f8caf58316af535def398a43357e48cb3b1e674b857eba1bd1b970da3dd045e22fe6d17dee4e9117f62ece3ec31c").into(), - hex!("84faf4d90edaa6cc837e5e04dc67761084ae24e410345f21923327c9cb5494ffa51b504c89bee168c11250edbdcbe194").into(), - hex!("879aea8f09dec92f354e31aa479d00cb77457d363de2d9a51ddf7d734061b6f83d6345cf33dbef22004cd23dd6c4b760").into(), - hex!("b8fca0f7bc276f03c526d42df9f88c19b8dc630ad1299689e2d52cd4717bbe5425479b13bdf6e6337c48832e4cd34bb5").into(), - hex!("b2a01dc47dd98f089f28eee67ba2f789153516b7d3b47127f430f542869ec42dd8fd4dc83cfbe625c5c40a2d2d0633ea").into(), - hex!("a19f2ce14e09ece5972fe5af1c1778b86d2ab6e825eccdb0ac368bb246cfe53433327abfe0c6fa00e0553863d0a8128e").into(), - hex!("95d1f944b0c53eb3e9fcd5632713602bbb9195b87a172a370ae2df98504612a55f3968615a39b569ce6a0fe9fb559be7").into(), - hex!("ae36ab11be96f8c8fcfd75382bb7f4727511596bc08c25814d22f2b894952489d08396b458f7884d6b3c0adb69856a6d").into(), - hex!("824d0dc002e158adef06fc38d79b01553be5a3903566029cf0beddb2248b11da40e66feb168e8e3e2a63ea033a75f382").into(), - hex!("8f9f85ae6377414fcf8297ed45a736210cd3803f54f33116b0f290b853dc61e99ea08f3c422ed9bc6bdc2f42ab4f56ba").into(), - hex!("86c53fc078846c3d9bc47682506f8285ba4551475921fd388b96291741970c34b8de4210202e40d2de4acb6e2892072b").into(), - hex!("853184f246d098139230962e511585368b44d46a115c5f06ccaeef746773951bead595fb6246c69975496bac61b42a4f").into(), - hex!("b91b4260e2884bae9778fe29a2c1e4525e4663ec004159def5d47320de304c96d2a33ad7a670e05acf90cbba3efdd4d9").into(), - hex!("83492e27e07e35c0836aee6bee95d040b8d3e82db6f94a3917d07797800f7200f5dbc6c9596c6c3c70f8f470b65a9b6e").into(), - hex!("b1bb33607d10ea8c954064ecb00c1f02b446355ef73763a122f43b9ea42cd5650b54c5c9d1cfa81d4a421d17a0a451aa").into(), - hex!("99cb1728157a1b7cdd9607cf15911bbcb56b64d52fb0d0117b457853a81ec55913f977850f26e188fa2652579efe9ddf").into(), - hex!("8b7cb5b8de09a6dfceddcbaa498bc65f86297bcf95d107880c08854ed2289441a67721340285cfe1749c62e8ef0f3c58").into(), - hex!("b97447233c8b97a8654749a840f12dab6764209c3a033154e045c76e0c8ed93b89788aac5cd1e24ed4a18c36de3fbf60").into(), - hex!("b4790910e2cbef848448f24f63e9dd4a1b122cf65feecf152d5fde282ad6fcc6ea3f9cc23178baf85612020795e4b13a").into(), - hex!("81fc724846b5781f3736795c32b217458bb29972af36cc4483dd98ab91680d3d9bc18842db2661487d3a85430dc9e326").into(), - hex!("a154892ff23b284040e623bba940a6a1ef1207b8b089fc699cb152b00bcce220464502cfa1dfb5a2f62e6f3960cdf349").into(), - hex!("af3f765fd293c253072b33a780ed68933f78d7e079d9a2079b6232755bedf6ebcbce9ba65c01f695602fa8ee17899867").into(), - hex!("97578474be98726192cb0eac3cb9195a54c7315e9c619d5c44c56b3f98671636c383416f73605d4ea7ca9fbeff8dd699").into(), - hex!("917c4fd52538d34c26ccdd816e54ebea09517712aa74cec68a2e3d759c6a69b5ccb4089ad1e0b988e916b2ce9f5c8918").into(), - hex!("8cf3c29531a17489a5f8232d56c5251ffddc95be3ff7ff61472e19fb38c5eaec841ef3b1ee36756b3dd8ff71ae199982").into(), - hex!("96d4b9b411319e531bab6af55c13f0adb1dd6b4286784ff807f283e7990dc368c16d536fc5db3d992deb4b0278914e6f").into(), - hex!("8903f7e0c9764ce844b15d84feea04406dc66b195a5f82ff4027f27361e11cf368538137d139368f5a6f42876b04f056").into(), - hex!("a4047173b5906c9b4292aaee1e91d9080ae74b1d3eb990449ed1f96bf22c3ee80f4915361e5bf7dccce24ae1618dae77").into(), - hex!("a4c4b96071e7bc92e41defba3507ddf423d93f3a94271b1f9812dfc4660e4c9fd24e0dd7aef324c46deb8d7a7c97eaa4").into(), - hex!("8289b65d6245fde8a768ce48d7c4cc7d861880ff5ff1b110db6b7e1ffbfdc5eadff0b172ba79fd426458811f2b7095eb").into(), - hex!("ab4119eef94133198adb684b81f5e90070d3ca8f578c4c6c3d07de592a9af4e9fa18314db825f4c31cea1e2c7c62ed87").into(), - hex!("a3ffc3dad920d41ec3f4c39743ef571bcabb4430465d9aa811d0f0a7daa12bee4ed256527d16a6e937bf709ebb560ebd").into(), - hex!("8553748da4e0b695967e843277d0f6efeb8ba24b44aa9fa3230f4b731caec6ed5e87d3a2fcd31d8ee206e2e4414d6cf4").into(), - hex!("b15e1b4ac64bafbc4fdfead9aeff126bf102fdd125c1c914f7979680ec1715fbeccf3dc35c77d284421ec1371ed8bc32").into(), - hex!("9377aab082c8ae33b26519d6a8c3f586c7c7fccc96ec29a6f698b67d72d9266ad07378ba90d18e8c86a2ec77ecc7f137").into(), - hex!("b71c11828ecad7731136cb1f5b80392a4add8d62f8866a781fdde797a201ebf6d483b2348aacbea2061a5108933b757d").into(), - hex!("86793899ef71740ab2ec221d0085701f7909251b1cf59a276c8d629492f9ef15fc0b471beedc446a25b777391ab00718").into(), - hex!("8100b48ac2785477a123a7967bfcea8bacef59391680a411692880098a08771ff9786bd3b8dfb034cae00d5a7665621c").into(), - hex!("8b027c14affe47f83ee59b504d83b2fd2d9303de2c03ee59d169bb199d9f4bd6533d7f8c812dd7a6f1e8155e3e185689").into(), - hex!("9615800f8c95f95bf25055ae079b964e0a64fa0176cc98da272662014f57e7cd2745929daf838df0094b9f54be18b415").into(), - hex!("951aa38464912a29df2101c60771d6de7fadb63f2db3f13527f8bdacb66e9e8a97aaac7b81b19e3d1025b54e2c8facff").into(), - hex!("a0e68d24f784fcb2b71acc2d5871285623c829d0e939146b145e04908b904468a67c07a2f156e6b17bf531adc5777c4b").into(), - hex!("86a533b02ae929f67c301649a2d58651b98cdffe731b63fa32aa1013c271634bbb088c0d02865913c11bbb1bf57c0e12").into(), - hex!("81f145ebb9a5674a5b052d0e9059acc8f8ab612dd9f54d43ff620202606e19a86a9b284dc6480d555a030e5fefee8c50").into(), - hex!("a698b04227e8593a6fed6a1f6f6d1eafe186b9e73f87e42e7997f264d97225165c3f76e929a3c562ec93ee2babe953ed").into(), - hex!("b3180ded54610b1b3a2db7db539197ced6a75e9bb381d1f4b802ca7cd450f5418522ad2bee3df1956ed63ff1ffe95dc1").into(), - hex!("86fa3d4b60e8282827115c50b1b49b29a371b52aa9c9b8f83cd5268b535859f86e1a60aade6bf4f52e234777bea30bda").into(), - hex!("97d076617cf0a64ab3d1f030cfd72a303b6b252c0a7b96157ff7fc8af5970f00d14492c46e8f6f37caafe837d0dc95c7").into(), - hex!("ac2c98a0ab3f9d041fc115d9be4a6c77bd2219bb4b851cbee0d9257a4de5791251735b5b8fad09c55d16eb0d97080eff").into(), - hex!("ace7fda25c2fb7c18710603c16a0ff0f963352d1582a42a20c9f5603c66f485df8383465c35c31e8379b4cb2ec15b4c4").into(), - hex!("a07b35ec8d6849e95cbd89645283050882209617a3bb53eae0149d78a60dbf8c1626d7af498e363025896febdba86ee7").into(), - hex!("b2fc4478830f2ae4234569346d80b59899247c609b75bd2190a896498539e1f30dca5edbad69f0224918d09f0d7eb332").into(), - hex!("84926cf2265981e5531d90d8f2da1041cb73bdb1a7e11eb8ab21dbe94fefad5bbd674f6cafbcaa597480567edf0b2029").into(), - hex!("b5f32034d0f66bcbccefe2a177a60f31132d98c0899aa1ffff5ebf807546ff3104103077b1435fa6587bfe3e67ac0266").into(), - hex!("938206740a33d82ffda3e01598216324731335d367965aa0b740486d60ba2e86a4ecd546851046a61a4b0fc88295b5cb").into(), - hex!("ad2b1ab32161e37ee553e3787f05f9281073d7ef7d0ae035daa353bc83da8ef8c76c99ad2928463c7c708f7404020476").into(), - hex!("94f4720c194e7ea4232048b0af18b8a920fde7b82869e2abcc7e14a9906530be1ef61132884bb159df019e66d83a0315").into(), - hex!("a26dd9b28564c3d95679aca03e3432ac26e287f80e870714c5946b05538b3cb43bba7b85c16bceb5430e81b7a04c1b1d").into(), - hex!("8ef0930db046c45ca5c69d565d54681d2b6d249e27092736aee582b29de3aac3fd96e1066a57cadd851b4e5334261594").into(), - hex!("92096ebf98ebac5c82345d3ef0db0f5a14af23ceea73279087426b281d6701997fe131fe65a7df7d624b4ff91d997ae8").into(), - hex!("81c850f419cf426223fc976032883d87daed6d8a505f652e363a10c7387c8946abee55cf9f71a9181b066f1cde353993").into(), - hex!("97070a33393a7c9ce99c51a7811b41d477d57086e7255f7647fd369de9d40baed63ce1ea23ad82b6412e79f364c2d9a3").into(), - hex!("a99cde5c7c85ae291c74c893e598cc0e6eb2dda2a81dbb504a638eb21dd2c41d6e5caf7baa29e3c1c32e94dca0d791f1").into(), - hex!("937ccbf8cd19b82af2755b4856cfcca3d791e33ae37e4881982ea89d3b21d205a9402d754fac63037243e699484d21f6").into(), - hex!("ad7dca7640444f1268f03b67544815d4366c6a4a2f0d25ee78f3361c63095416216fd31aa0bcce7448cdd7ba73a6344e").into(), - hex!("84991ca8ef255610ebc6aff6d66ea413a768e4d3a7764750fd02b5cd4735d41df399b36e87647fc83cf73421a39d09e9").into(), - hex!("91215fc3f7243638733fe293dab7029e0c4275550102acf5f1638773cf8f8ef2c53ffa5bdfc1b602c269a2b5ab164b7a").into(), - hex!("aa6cfb3a25f4d06c3ce1e8fd87496a74a5b951ab72557472a181a2e278c5e982d290dd4facf40bd2f4f8be62263dadb0").into(), - hex!("ac9f29ad08aaf27581fe1f12e210ad4ac6011507fe3100763a4120f9e439f3c6d191f3fb55aadf58bd865cfd4406c68e").into(), - hex!("87c6cb9ca628d4081000bc6c71425b95570291eb32ef2cf62416bd1ce3666eb2ce54accd69f79d506cefbfe6feb5a1da").into(), - hex!("93042dd42e56671155bb40d85d9d56f42caf27bd965c6a7a7948b39089dba8487d4d5fd30522dba6ba392964e3ffd590").into(), - hex!("a76adeddf2454d131c91d5e2e3a464ef5d3c40ee6a2ab95e70ef2e49e0920d24f9b09276250ed7b29851affbdbc7885a").into(), - hex!("92a488068e1b70bf01e6e417f81e1dc3bcec71d51e7eabbc53b6736e8afdb8b67d191940fe09c55783be9210e1cbd73c").into(), - hex!("8180ffffb5abe78c38f2a42a3b7f1a408a6d70d3f698d047d5f1eef3018068256110fcb9fb028c8bdccbc22c0a4c3a20").into(), - hex!("a50ab79cf3f6777a45f28d1b5cdad2c7ea718c60efeeb4c828d6307b29ef319445e6a9f98aa90f351c78b496575150c1").into(), - hex!("a4632399c1a813e41fb2055ef293466098ea7752a9d3722d019aa01620f8c5ecdc5954f176c6c0901a770cbe6990eb11").into(), - hex!("83bf5055d6332009c060fd50b8dc698d42b764b079c90a1fad8a83101f8dd1cc27acb27dc9d1c25ac8d3db4107471b4a").into(), - hex!("8c432e044af778fb5e5e5677dbd29cd52d6574a66b09b0cd6e2a5812e71c91559c3f257587bfc557b4b072a822973a60").into(), - hex!("8368a0f17c8427beb71dbf11a09a2fe8495a33f08c29c74a9a996a88aa01c0a09f9555abeb1ef1592cab99a9e05875cf").into(), - hex!("a8795e7f4c4c5d025ead0077c3aa374daaf9858f1025c0d3024d72f5d6c03355ae6ac7418bf0757fe49c220acff89f7f").into(), - hex!("a6d9f67ca319ea9de50c3fed513269b83fa067977adfd1e9d9ee07ad61b2ac1de64a39d7b6897ab55870cf982fe481dd").into(), - hex!("86b3a4ea9b1fde00cce79d5ae480353d60cb6ddce363c535bbbc3e41a4b8e39fcf2978eb430091ae1b10420d43193971").into(), - hex!("90fb5cac22a22fb8a6b619f1eacd95873be974d4d5d1f7080e523bb9b4b2644eda7340d780bd1ea8ce36407ca0410fea").into(), - hex!("b5036d4c241685bcd67156e4ab0eba42b97f639947d54b17af2c88fbcc5fc57359c7df4bc7f8df955a524fb1501a6fda").into(), - hex!("b1c56f028f31f0ff86bdf55788703b4d809becaf3e4d9d349f1b660a07d2f15e127eb72a0e2a5a2742313785a3de43a5").into(), - hex!("a3e909196f447e492200cc67000c5d7f0f585fb98e966cf9bf08257597fea8d92a90ceb054d4b5553d561330b5d0c89a").into(), - hex!("87cac423d0847ee3547f45ac5babf53bddb154814e291f368cbb62ddd4f2c6f18d77a1c39fddb482befe1a0e77d5b7fd").into(), - hex!("8605b88ce23190b1fa9d389b15e6907417239a72b97673d1479c4ccb8f4515c7921d14537775c74e738a9c3f122b1443").into(), - hex!("87587504e819bc7f0349705a05c15e8504fd6b2c25c3fd264096cdb7aaa22d8078da776215925d9d775a7f9355b6f0c0").into(), - hex!("afba279768f0f928b864645aa4e491e9c949bf3dab57efa24eeaa1a9a7d4d5a53c840019354068e64c65a2f5889b8f3c").into(), - hex!("86b1cdd26ea9a3ae04d31a0b34aa3edc9e8d038437152214d195381173e79e4ccf7f8f0ce9801086724a1c927c20e4c8").into(), - hex!("812d3ded3a3c9e58eecf13a29bb4cc13b01b2a0af322423a29bb0e4f6d9021d1d87ac4af7a2a6b88d34f44a8bc1b3c55").into(), - hex!("a988cfed9f481bc98beb5fc188ed3f6893a3ebba27c3ebace669792f6abf0997727023c3b6930a6421224f5b257b8b49").into(), - hex!("a38c974b57da968f0c4611f5d85d8014fd48594c8cd763ef2f721cfd2c738e828d41ff029e3591d7447e3125641db8ef").into(), - hex!("880b4ef2b278e1b2cccf36a3b5b7fbce94f106ed9fa2820cb9099a7a540a57e9fdeef5c0fb0a743049828fc2b8c46163").into(), - hex!("96e7d1bbd42195360267c2a324b4d9bccad3231ed8a7f070278472a90371867e2ef2c29c9979a1ec6e194893afd992df").into(), - hex!("a92beb343caf6a945990adcf84302c55d1fccdef96c34a21f2c00d3e206a9b2c6c6b412f66e5d4fafe26ef6446cde705").into(), - hex!("aa48afa77d5a81cd967b285c0035e941ca6d783493e1840d7cbc0f2829a114ace9146a8fbe31ecbd8e63e9b3c216a8c5").into(), - hex!("893a2d97ae067202c8401f626ab3938b135110105b719b94b8d54b56e9158665e96d8096effe9b15c5a40c6701b83c41").into(), - hex!("b614910b247c6ade31001b0435686c3026b425b9bff80b6c23df81c55968633349e1408a9a5a9398a7d5d6ed5d9d3835").into(), - hex!("991c660e4d476ad92aa32ef2c5b27669ab84026eeb5ca70af69bbbcd8ebc0a8fec17843423306edc78b4436629d55c25").into(), - hex!("b926a21f555c296603dc9e24e176243199a533914f48994b20abca16f19c30cfd0baf319268139fe3f83ce69afdc324d").into(), - hex!("8e70e4867d2731901d603928d72bbeb34b2e0339a4f5cf06e7a771640717421b4ea039c61dde951582a28c2ff152ff70").into(), - hex!("95aafa379cc6a2b4bdd0cad30b7f0a47839952af41f584219ec201c6c4d54610eb2c04b67b29080acb8cecc5e7543fbc").into(), - hex!("8465bd8be9bd9c2c6116d4ae44ec6618c109cb9aaee2d241e7a6ed906d398ef15a6fc18bc8b1d3398184241405954bba").into(), - hex!("b455f751232de0a48440d09983f4f4718b6169907979c9f282acf7177ab5b1f338fe1f2acd8d0bee4b4aad61d0340839").into(), - hex!("970df2314849c27daa16c6845f95b7be178c034d795b00a5b6757cc2f43c4c8d8c2e4d082bec28d58dd4de0cb5718d61").into(), - hex!("8d52413f981bc611427ad0534d25e914113d0ebcd6960aab6421608bec6648b89ae4b2ca2153c57d3cf4f1f37212aa5c").into(), - hex!("b7ac87da14b783914ab2e914fb7b536893b7a650cdc5baa1f3b4aca9da77b93a3336671335250e6467a8cd4aa8dc61e9").into(), - hex!("b37a2ec9dec3d7d9cbc911fa1e5310a47d23a841d02c8b99a923991c73fc0185d130a494748c64f2b5a4c07bcd06920e").into(), - hex!("86108b661fb2c363adcca84c114c83346413df748b959015c018452cfac14890bf585dc0a646d68727cc3cdfd2b61897").into(), - hex!("8421044f794a1bcb497de6d8705f57faaba7f70632f99982e1c66b7e7403a4fb10d9ef5fb2877b66da72fd556fd6ffb0").into(), - hex!("84d2eb008578aebd6f01254b7e46584c1524e6fd7a5a2ae5fa0ea560865ca50d52290cf2d12dd20b042f402e62181b4d").into(), - hex!("8d6bed5f6b3f47b1428f00c306df550784cd24212ebac7e6384a0b1226ab50129c0341d0a10d990bd59b229869e7665a").into(), - hex!("80e30cabe1b6b4c3454bc8632b9ba068a0bcfd20ce5b6d44c8b1e2e39cbe84792fd96c51cf45cf9855c847dc92ce9437").into(), - hex!("b7e74ab2b379ceb9e660087ee2160dafe1e36926dfab1d321a001a9c5adde6c60cd48c6da146d8adfa2bd33162eeaf1a").into(), - hex!("a2b1ea43f51460b3cb83657b4e296944658945d3ad6ae7b392e60f40829ba1da6a812d89f0380474578cbd0ab09801ac").into(), - hex!("91ead7dacf43905eb5d4b179af29f945479ed074126bad3b5a2bbc1663af5f664fe53a36684e9389ab5819e53f1344fc").into(), - hex!("927c030d5a69f0908c08f95715f7a8d1e33bed5e95fc4cfb17f7743cb0262755b1e6b56d409adcfb7351b2706c964d3b").into(), - hex!("883f38af3b2c1d50f6e7c515a5e02468d76890f6e669f7acd2df89365862fa65877095deb001b4e2868bc5b59439dbb1").into(), - hex!("a0ebae60a998907a19baa396ae5a82bfe6aa22cf71bfca4e1b4df7d297bd9367bbeb2463bda37aa852ad8fd51803e482").into(), - hex!("8ae80eeaed3fc456f8a25c2176bd09f52a2546d45d77a70f48a9e30aa29e35ff561c510ae1f64e476e4a0f330b9fdbdd").into(), - hex!("a7be457b8bc1bfde4865a35b7b1826118edba213b0f0d3cf5d877267cc1559cabe61cefb1e300142a978c29676036179").into(), - hex!("af51da717d2a45ab96fad5d9317ea867ec4c6a411af6fabd72e568230099a04c036a0f114158815b1a75da6474dc892a").into(), - hex!("b549cef11bf7c8bcf4bb11e5cdf5a289fc4bf145826e96a446fb4c729a2c839a4d8d38629cc599eda7efa05f3cf3425b").into(), - hex!("8d264fbfeeebb6c4df37ff02224e75e245e508f53fb3446192cd786ecf10d0f704c4fc2e53e7f7318ae1407e46fc0fb8").into(), - hex!("ac3195143035cdb4ddcd5f93c150035d327addee5503ea2087b1a10b2f73b02453ddd1a94d8e7d883e365f9f0e3c38c9").into(), - hex!("acbb398ea9d782388c834cf7b3d95b9ff80ee2a8d072acae8f9979595910849e657889b994531c949d2601b3ce7b235d").into(), - hex!("811e6a5478f708495addbb1445a2ef23e39ee90287f3a23ecd3d57d4b844e4f85b828bae8fa0f1893dfcc456f86f7889").into(), - hex!("8cde690247d4831dfe312145ae879f4e53cb26641b3a3bb9eb4d590c56c11ece3cfe77180bd809468df5cddaea4f5ab1").into(), - hex!("b42578df29a9eb23bed91db6a1698df49654d2bc1b0d7973b2a7e300e9cf32e0e6ac464d463d4d26e394e7598239c4bf").into(), - hex!("97ffcbf88b668cde86b2839c7f14d19cb7f634a4cf05d977e65f3cd0e8051b2670e521ae74edc572d88201cff225e38a").into(), - hex!("a322b5d2a6e3cb98b8aaa4c068e097188affef5dec2f08c3e9ce29e73687340d4e5a743a8be5f10e138f9cabbe0c7211").into(), - hex!("a076ea1084b7a1a33115ef62d6524f36e7820579868763a6ed1f8bce468f150cbfbf0ed04be2487aaa34100d828b0db6").into(), - hex!("944259a56e3b4f745996289912740281bde47e22705f142c2a483ffd701e780f51a01b177d2494dc8db9e69157f45d44").into(), - hex!("91cb79d52951d1b901e4a686bf4ad587e31db57ea5af6ffeb93eeafae3929879c386ddec860f803c2dc61055437e6bee").into(), - hex!("91efdbcaad9931312d7c41d24de977f94d7f3f7b88090a1f72d9a097a1e30cc805c5ea16180f463022d9b26b8863f958").into(), - hex!("b26f5ed09f7d5bb640ec94ddd1df0b76466f69a943b4699f53d45296d5d6b8010bb61477539bc377d1a673d89074d22f").into(), - hex!("80822499f96a1a8c0048f01f389dfcaaa5d8269c332dbb507fe46f270bcfd5f67c53f827fd867221592dbde77b6b37ab").into(), - hex!("8860ba25d5530cb8585975d8013a1c2d5b0f0f96066044fdc43ed13488ae44e379c624ff6993a18cb6e037809d7985e7").into(), - hex!("999d1c44e14184349064415ae28a149b3b11aba5baab6792744378d14df554a3625fac82038eaca920064822294dd513").into(), - hex!("a62c2e7c692403e874a16e08e46a067e19dd561993ca07ff79cecb53c753763b3e49d372638c96c0a8c921bfa0798a0c").into(), - hex!("a1c84730a5c41dcab9a5ef9e1508a48213dbc69b00c8f814baf3f5e676355fc0b432d58a23ad542b55b527a3909b3af6").into(), - hex!("a1c0c317e6e352e16e25c140820b927161ce5d2c4c2e10bca3057ba4d46b4f42ad7aba20de86dad9fc6368ea92695268").into(), - hex!("85c216e314eb7bd8ba02e092c90e132bc4bafb21c6a0fbe058b0dd4272cb76f183b83c6783fc321786065ff78c95f952").into(), - hex!("8e8f63ec8f4f1f7fcc61f893b671710c3c17f9d2d26c5c6ca40e671bd4b252bc0cc1655e6780d2ddcf2915d8f623b9a4").into(), - hex!("aaeb0005d77e120ef764f1764967833cba61f2b30b0e9fed1d3f0c90b5ad6588646b8153bdf1d66707ac2e59fd4a2671").into(), - hex!("92ff79402d5005d463006e0a6991eaacc3136c4823487d912cc7eec1fe9f61caf24cd10022afdab5f6b4f85bfb3eee4f").into(), - hex!("a32a5bd9b7bec31dd138c44d8365186b9323afbba359550414a01e1cdb529426bfa0b6f7daaf3536e9402821faa80003").into(), - hex!("845982c2672fdd44b33d2e56ad676e704c02f756b09e8765bea42b924c14724484567b55f0db42ac20cb70a7f5201c14").into(), - hex!("89cd9f6ae7d9a9ff2b4db916ba3af9fe700fcfbd16577bf73a965af938e8cf633020466b0298d3c31300360aa6851af2").into(), - hex!("8fa2d7b22af8e6b82679ebdfa13efdcb34289a554653ea6c1b16efb9f957f7fe64df787e7b03d8cdc8a732b91c916bd1").into(), - hex!("94f327bc57ed1ce88ce4504b4810cc8af5bd21a7e07b280a7866ce08e39b6cf7a6560bf73a5f10671271624cd7893970").into(), - hex!("90f4476224b64c2a5333198a4300ece8b3a59ae315469b23fd98dadcdceaaf38642d2076e9cd0bfacc515306f807819f").into(), - hex!("ae0db78548261216ad7d6a7ed4e6089ee17b3fa311494b2f2c559e215cd3de7e5f3a781a49dcff428a8a61c2a4f49a19").into(), - hex!("a83371f44e007c708dc4bcafa7bd3581f9080a4583c9be88624265014fd92f060127e628de5af3c442a25f049c7e7766").into(), - hex!("b471c72bd2971353f4b44248b8e6cf5316812861a88ccfc20fd0d89a5e010428c387228b2f6f14c12f79e31afc9d0753").into(), - hex!("8962afddcb1a26cc8ccd3c993109e79a4dd747ca473b8b5ef93d9c2e71d29623b834ac945074acf118248e3ae7878a6c").into(), - hex!("aa0940e4e5586e79a3d97397c8aff3d112c6f759d2efac29366acc5b5c6a7cfef8d50516bf309da8b787de265dc8deda").into(), - hex!("a211120e1bb3b10138df1fa58efb009a298b8771f884b82bb3de15822b1252124a68f3980f96122a775fb96f05ddc3d5").into(), - hex!("a1047401598b1e6e2613d746bb4689e0406eccdbadf319a6609a3261cd09deec215d90eba6d0ddc50dd3787d60104e7f").into(), - hex!("96791b2b8066b155de0b57a2e4b814bc9b6b7c5a1db3d2475a2183b09f9dcd9c6f273e2b0c922a23d1cf049a6ce602a3").into(), - hex!("91013e0d537fb085a49bf1aa3b727239b3e2c1d74c0f52050ff066982d23d5ee6104e70b533047b685e8b1529a0f14dc").into(), - hex!("aa65c11071be23c9bddaa5203f3166e5cf043efe5fb8f4b26f8a9cabe71db701a450e79eb001c401da5752755d9cf1af").into(), - hex!("8645cc44d180c18a6d8f57ba57bae05879451997533cfe558cad4d3d586caec877e348915e32a09ee73483283c4df744").into(), - hex!("8eafbb7002f5bc4cea23e7b1ba1ec10558de447c7b3e209b77f4df7b042804a07bb27c85d76aea591fa5693542c070de").into(), - hex!("919c81bd1f3d9918e121e4793690f9ddd96c925ae928536322d4b98132f21979c1f34731d393f0ae6e0871af4355a8ad").into(), - hex!("98181e9291622f3f3f72937c3828cee9a1661ca522250dfbbe1c39cda23b23be5b6e970faf400c6c7f15c9ca1d563868").into(), - hex!("8f44c43b80a3c5f488118859fab054745cfe5b0824821944b82fcf870fda6d93489ea9ca4220c24db2f4ad09c6080cb7").into(), - hex!("a683d4865ddcc099f7b698153007b92f853b80f49b3be75163ea8cd1f8ff584b43a68e68de3ae61cda8ad4b41f355c87").into(), - hex!("942772b7c7c47d4e5957ccf1d6f1450070930af3e2b7eaab0dd7699372445df0cc910e6c0efcf501887dd1adabdaee23").into(), - hex!("805c06e565ee67cab0cbccb92b6656fdb240b430766eade3c6b0a0b1b93c840e2b4f028601451dca135c783239463880").into(), - hex!("84d3e2a06e16ced26094b356a16a4fb6aad50ad9ab23ef804a5852a33ef0bff76f3c5fbf7beb062376c2e669cb598679").into(), - hex!("803df08aa745cc3c0a799f3a91bb6ed423cd520c9d255d36c21bed1a0c3b12e8cad32f54da09dadca97683e9548fba91").into(), - hex!("aa2c3ef95b8d4265f01666129646004b6950d3e8ce74b4ca12aa3b90fbb445079a569178df772c272463a44d48922b8f").into(), - hex!("b0a4c136fb93594913ffcebba98ee1cdf7bc60ad175af0bc2fb1afe7314524bbb85f620dd101e9af765588b7b4bf51d0").into(), - hex!("93e4c18896f3ebbbf3cdb5ca6b346e1a76bee6897f927f081d477993eefbc54bbdfaddc871a90d5e96bc445e1cfce24e").into(), - hex!("89019e9550648962420984e9fd03597a854ae824567d9aa6cd5db01a4616b4e1477230f2d1362a2d307e2425a3eeb898").into(), - hex!("861b710d5ec8ce873e921655a2ca877429e34d432643f65d50e8b2669929be40a9ce11c6353b0ada1fe115e45396b2b7").into(), - hex!("88554c83648ea97dac83d806cd81d92531980346b208d281fba489da15a0084fd4d9a00591d1ca67aad3c5793685d55f").into(), - hex!("851fcadebee06930186f35293feefd40d7daedec9b94e6fe5967536c2c0e4cc68f58d3f5fbc76f1e77b90c9580074f98").into(), - hex!("b96a11048c7c327709d52e72e6f6ed0b7653329a374ea341ad909311b5b303e5629d6dcf11dcdb195e8c7592ceefac21").into(), - hex!("836075979eaf386ff6cb459cfd48fed171ae812b0ac3b38dc24dd8ca905cac1c600be717d4a0defa0a854f40cfaf8c33").into(), - hex!("90fc170529bcc0b80c46a53fffd8323fd2cc5cfa9b75ea4d36db21bd1f198335ad2bfa87f8990cf9cd9fd7989ecca718").into(), - hex!("b7eb6a49bf8f942dd8c37c41c1b35df43e4536e07ca9f4c1cfbbf8a8c03f84c54c1a0d8e901c49de526900aeac0f922f").into(), - hex!("af6911edd6c7ad30f905a0a3f78634808832fdeb4206b006934822d673bcced8e378779261b3c4b772b34b8871987f57").into(), - hex!("a74d240d0d7ea0afe68813fab55388d77e75eca0519d21771dcb7170cedb11dc14b237b26c5ae1f7f728b52e5ec0f02d").into(), - hex!("a7b86e4f1366da44fd59a3ee68018a99c23ba3588789463bd88b0177a9b94030b58cb879a506e64421af966f261eaa86").into(), - hex!("ad8d94e46cc02a1c0ad27105e8f672ec15b8296051801f1918d0bd470625686e8e8a0abde8f6852b846ee8d9132b26bc").into(), - hex!("980508c4d1e655cc6200f89a884b3a25c0c05708a3e4a101205c4fd901c3e20a943071a6300bb2614be41a139d4ef1df").into(), - hex!("b0173651b4ba0590b1d2f0265183f3729b5bb09893523ca12c4936120cbe5ef0d9b98733734407d99fdc766792ff10ac").into(), - hex!("abf72ec0280d56971e599b3be7915f5f224c0ccde2c440237e67b95489f0c9154ace04b7763db228473715f68053f071").into(), - hex!("b404beebf60026ca6843f2953cfcdee494d495c8e2d18865147102ef29a8f0ee470961d2246fe5a450c622d20ca51d53").into(), - hex!("89461cb2dadf51d6f1208b0965c8eabec895d7b19b7d90d3c6e49dbe75a75c30fd26db3dfb169dd46a4342280225032a").into(), - hex!("a61cb5b148cb7ff34775dead8efa7d54d7141182356bf614070dfaa710ebf07a4dfb684dad151db60c0f8261c30a4f40").into(), - hex!("83a798f47a4f62dcb8b531d463b0fd4a876d47a8ca990710290549255033c909de709471b4e823a60bf94d8baf8b5acf").into(), - hex!("a23431589f3a25070a188deead9adb0ed423d6b00af267f3f125cdd4391c1527909b5cfa88130dc4b67915f5002128fa").into(), - hex!("8d77e65ba6250fe18c54ce70d0ba4571a7d3e68a8b169055cd208e4434b35a4297e154775c73e7dfba511faadb2598c5").into(), - hex!("90e5db75f3787b819df471712f87b6f3281437090f5db7a2c21b07164446292a414c687e41de2d1ca00786b093239c64").into(), - hex!("b382fa28670a5e14dc954b2db8ace250c73df71ab095304bd8ee28f455ab26cc54f82775a831428e110d1a3a2af709bb").into(), - hex!("a58d2fb1c2612d28c54fafa7f2e1e6c336c24435abdb53e1be9dce9aebecbf7468a348b872549535ac18aa003f83ea87").into(), - hex!("9545f94c4e9056e360dd999985f8ad06210556fa6f07cff77136a2460605afb0ff1fb1d1a2abe4a4e319fd6c29fff80f").into(), - hex!("93121aa60f904a48e624e00f5410cf8c8925d2b0719f90c20e00cba584626f833de7c8a18dbfa6a07df24b916156bfc0").into(), - hex!("aa3446aac25f6c23ea16e8f7d19c58d187746ef3c2ac7d8fdf9bdc329409a07589ec8eebafbe2b156e7ba60addc15af8").into(), - hex!("b964f50011f03135e993739e2e63a71933ba4583040b3af96c7e2dce874226518f7b68f622c4a1d78b9c3ec671d33ad7").into(), - hex!("8cb5cb7cba886af58acadc5a4348524b1395a39dc51196316d759a9b72d9fc0fe45b706e264393a13ff911f0d15de45c").into(), - hex!("b50c306f78143b37986e68efa10dbe1fb047d58562e9b5c5439b341dd8f1896c7ae586afac0a3213759784a905c1caaa").into(), - hex!("97825edba8410e8bcb85c5943628c02ea95ee7595f559c030b94395c0d1d0d84c38eca199fce9c1992e572b5029b124c").into(), - hex!("b0922acd6da2a95b36de6d0755316594a7e2e32ea774792dc314e8c3cd76d9f1d69df38231e166e24bd42c664f4fbac7").into(), - hex!("ae5ea228c1b91ef23c245928186fbafa1275ff1817535018d7d2d913abff0fd76bf41fd04a96d816f2f1891bd16e9264").into(), - hex!("b106c6d13ca17a4c8ea599306e84918127cf2de21027ac3fe5a57d35cf6f3b1d7671c70b866f6e02168ae4e7adb56860").into(), - hex!("a044cd5a3b727dc1cb59875e4025718375d12e706fffcdb48874e51a675dc2cabb209670192e408cdced5aeac65192e4").into(), - hex!("ab1cc44983e46a6ea2430aa6616ab28614f43624665e3e6ae31a9357c0c5434f34e56c720906e184327693cc4ebe1fa2").into(), - hex!("890def696fc04bbb9e9ed87a2a4965b896a9ae127bc0e1cc515549b88ddbcbc02647e983561cab691f7d25cf7c7eb254").into(), - hex!("a86be58fef115445b909dffac6f51da3fe9214afd9c31fd564bb8f39b1dc3cb895b1222f2c63226b54b60b278ec45edb").into(), - hex!("8757e9a6a2dac742ab66011c53fa76edb5ebc3c2fbd9a7265529a3e5608b5c24b4482fed095725e9b8fed5a8319c17a4").into(), - hex!("a7e0ddbae16e4491822684c0da3affecbbd17ef96c5c491ac093c6eb4e162fc7854c367535e296fd3d6265c2ed1210bb").into(), - hex!("941fe0dabcdb3225a625af70a132bc1e24ccab1f8331dde87db3e26cbee710b12b85535e46b55de7f5d1c67a52ddd5c8").into(), - hex!("a24d05b51c7c128bb49979cbd9019e6618545d95275a44b5c3d1d03e71bf2ebffdf43fff50c30846ec27d279043cef4e").into(), - hex!("b526f40d519e7a8f2c81b69f71b3e2ef079028004c0448ba0608296c2787972491ec6d05ed6a8fbd5ef2da76325a93cb").into(), - hex!("87ca4fa85a257adf7e21af302437e0fa094e09efced2d7ebab6cf848e6a77ae7bfc7cf76079117f6ed6eded9d79ce9cb").into(), - hex!("9276e8051bed8f5dbfc6b35765aac577dd9351d9d6ac1bb14496bd98091005b9a4737b213e347336413743f681f5043b").into(), - hex!("a7741c52498e0a24db3ce7699882de8f462a2b3ed5e9f77dc7200cbdf46b6cdd923b1128759909d6dddd64700c4c20c5").into(), - hex!("ab5b363ed9551e32042e43495a456e394cbc6d53b15d37a8859850162608bdf36d3d4564b88fdbaf36ff391bb4090b8c").into(), - hex!("838ff6630dc3908a04c51fb44a29eca5a0d88330f48c1d0dd68b8890411a394fd728f14215482b03477d33f39645dceb").into(), - hex!("997d3b82e4753f1fc3fc2595cfe25b22ac1956d89c0950767c6b9de20623d310b1d84aaa72ab967ef1ea6d397e13524b").into(), - hex!("85416cf3eef63d5530062d6f031aeddad101c7f1aea3bccb826c73f8a25d5d963caefd789a6b9832bd4ed459f268ae64").into(), - hex!("9194bc45e11d7276ed1c9ef3ad5a33d6a27372f5568563ca8ee213e2e7029dee404ab5acbaecaef698129798d35fd895").into(), - hex!("a4828a003513ab887082390262a932a7e8c5e25431824b7b4cc10fccba73265c0e5ee5b315ccef13906d971644913806").into(), - hex!("b907ec84b6ae5729d36e2acd585a350acacdeef148bcc5dc4a91edb57505526462bd4371574865541d8bb0d786a29b2f").into(), - hex!("aa5d1c1f0a7f6b9b3c3734f85864aa60bddad5121450218d76d82edefd2602685a820965c56d7eefe789d5115cb41e01").into(), - hex!("ad28fe70a8606f87bcb5d6f44e1fca499c24bcee791971f599ffef1f403dc7aec2ab6ebed73c1f8750a9b0ff8f69a1e6").into(), - hex!("a641eaa149c366de228a2833907ad60eea423dd3edf47e76042fdf6f5dc47a5b5fc1f1b92c8b96c70e6d8a68d3b8896c").into(), - hex!("abac08f4df786b2d524f758bca43b403b724d12601dc0a8362b7a2779d55b060c6682a5618fffea2e4def169fcbd2bfb").into(), - hex!("8658a15df961c25648fd444bdf48a8f7bb382d9212c0c65d56bf9cdb61aab3bd86604c687fb682260dbc0ad2dc84bf01").into(), - hex!("ac7983d50ec447b65e62ed38054d8e8242c31b40030f630098ce0a4e93536da9179c3f3ae0b34a0b02aad427a97ee60d").into(), - hex!("b8877a00a24b0ffcb2bd3fce8a8ba327d8ee2e98d85531cb61fec21fd49cd1696491cd51024a9c3820cf06a77cacf04b").into(), - hex!("ae075b66e5f211c2149c45b211d1297bbc1d9e6497cb3315363c492a9a51ae5b9d0a28bfecd755d68553736901ac6606").into(), - hex!("afdc091a224486e7bfac169e6a7b4e008d2d04144508a337fd93b6f4d385ee3f0d927b1f5c1cd79a15e0fd6078e45dd4").into(), - hex!("b75c28941ee3f91b3535b4eaa0fb17b59ca65b5256601a1f6d0cf2bb4d66837fd16e51d6942856679012a5730a66e519").into(), - hex!("84a6edac5ac68a7ca837c46d5ada8fab136748b6c3a3b9165dbbc231ec386b15328e4ef7d69a15d4cf354135348a4ee4").into(), - hex!("b01ee30d120b97e7b60ea89b9b6c537cdf20b6e36337e70d289ed5949355dd32679dc0a747525d6f2076f5be051d3a89").into(), - hex!("a80deb10bba4bc7e729145e4caf009a39f5c69388a2a86eaba3de275b441d5217d615554a610466a33cfe0bbe09ef355").into(), - hex!("8d6e3df29419bd0da1deba52c1feebe37744108685b49ca703e1b76fb4d612e3959d3b60b822506e5c0aac50b2f5eee2").into(), - hex!("a373408beb5e4e0d3ebd5ca3843fe39bb56b77a5d3d2121d4a7a87f9add3ec7376388e9d4b8da0ba69164850cb4b077d").into(), - hex!("ae0beb452af7479134a7fbc31a5f59d248e8a67d4c7f73a0e30a51db9cd33a1da3f0ae947fa7e5983aea1343e7daf06a").into(), - hex!("aa103a329b699d4102f948101ce5fae27226419f75d866d235da8956f11367e71db5c0a179dd63007ed53f7eec333aaa").into(), - hex!("a094cca9d120d92c0e92ce740bc774a89667c6f796b438b0d98df0b7aef0935d8c915d5b0dad4b53e383dc9f095c29fa").into(), - hex!("a4d88467136b99d6e55603b3665b6da0f7fb27c7759687f7e6977b6230272773d7b95049d999538c008f310c05ed948a").into(), - hex!("a23710308d8e25a0bb1db53c8598e526235c5e91e4605e402f6a25c126687d9de146b75c39a31c69ab76bab514320e05").into(), - hex!("a36d6952c2d7f88bf28032a76ed46c4dabbf1901a46efc50deb798d1b44adf7e0210fbdf2473a1ba408b5c98d76943e5").into(), - hex!("ab45f5b756ec6e0b98d0d4301c87675a0a1f0b1178b8a9780c1ab23e482cd821834835afa1de890962212159e464b10a").into(), - hex!("b800be1788175a01a9228b0d3e7eb4302484a2654eb2a86c0f0900b593da0a436ef031ac230e2b05e968b33e90a342ce").into(), - hex!("8cc8d279ec08d0a5a2a09ad07fabb0122eb65f48da2571d83f86efa2c1c5bc51b04ae94b145f0a8ef19a3988638b9380").into(), - hex!("b4cd409256819e8e4627edbba90ec40b7da17a57f95749104d90db0364f5007b1accc816f4d51a0dbe5ffbcb737cb37e").into(), - hex!("99365fe5ab8ea8bd768ae7181a6ba49b79d240f512ce309b02f09d465fea276298ff55b5b9cb5b4162a901b390606024").into(), - hex!("ad77fcac9753efba7a9d9ef8ff4ec9889aa4b9e43ba185e5df6bf6574a5cf9b9ad3f0f3ef2bcbea660c7eef869ce76c8").into(), - hex!("ad2456725ac3aeb0e4ca5c0502a8abb4dbd8a8897d9d91e673fea6a0cffd64d907b714b662d73c0877b98d4ab3ce6a89").into(), - hex!("ac8436e33619e2907659741d66082acbda32612d245fcc8ae31e55f99703fac1a15657342fa66751d3be44fc35d71c36").into(), - hex!("b0eecd04c8d09fd364f9ca724036995c16ba6830d6c13a480b30eb2118c66c019cfdc9dacce6bfd8215abe025733e43d").into(), - hex!("9439b663e4104d64433be7d49d0beaae263f20cfac0b5af402a59412056094bd71f0450bc52a294fc759ca8a3fddfee9").into(), - hex!("b72de0187809aaea904652d81dcabd38295e7988e3b98d5279c1b6d097b05e35ca381d4e32083d2cf24ca73cc8289d2b").into(), - hex!("93706f8d7daca7c3b339538fb7087ddbf09c733662b55c35f2a71073f4a17c91741955d4d549c2ee6c22eaa84193c1ad").into(), - hex!("926dc729e135f1f0bff4662ee3d6823a64597fe189b763ada34f246e77705fd4e062d85506a338e9fa98c4d225a3b27a").into(), - hex!("93f03495d53c781be8b76e37e68b64aa260523004eff6455ddc8a8552af39854e5181f8c5365812b1f65926534fba5dd").into(), - hex!("9834f66e5c946c3a8241ca2bbde046a7e88072124911d5d15c037a95b61e82b88b5c2058fa4a3721537dee39dee5da18").into(), - hex!("92ec1aeb2aa24c51cd5f724972c8b6095e77b237d83f93ed34ca0bc91a1dbf1ad95adccc59e0f0abbfef33f331f3298c").into(), - hex!("94402d05dbe02a7505da715c5b26438880d086e3130dce7d6c59a9cca1943fe88c44771619303ec71736774b3cc5b1f6").into(), - hex!("8368bb9b9bb2e17730c42ed1100eb870c88a8431601312aa8cb1e738cdb9ca2704dfd432cf1703c0db043259819631dc").into(), - hex!("a35189a105401f0cfba4b43be21723486c04659e5a01e67c43e8f9911030810b878beee696f04f63d314ccfe97ebb790").into(), - hex!("93ccd8c5f82374e0bef6562e16576f742d79b6f400e3485ef36e148088b61fbd882c3d2bb38ab0b43fa1dac77f31d543").into(), - hex!("b85d9a426a23ca9ee582bc16c203a9352dcc5f85440e46979de80eb572384479b697dc964cafd9457d9f34eeb77bb72a").into(), - hex!("aefb70e89dbf4456e077690509afcdcabf975416ff2fa16777fdf90b3abd3f5dcd865c43f1ebe6f8a669edc7f3bd6ad8").into(), - hex!("8eb03001ac9e22c6956a682ed458e650785c36d23ddbcd51ac4d9cc991325c02519ff1958987a08eb29ff56ff6e2c293").into(), - hex!("ab4a1ffef7e001723c71f5d28f3dd030a06c42d91773733d117247bbf9c01cd66fca2cff8c6ce04c4bfb68dfcdd851f2").into(), - hex!("a9ef845ab489f61dbfdcd71abcc29fc38f3494a00243b9c20b9cd0dd9e8a0f23304df84939b9652cdf5542d9b3ee085e").into(), - hex!("b5726aee939d8aee0d50bf15565f99e6d0c4df7388073b4534f581f572ad55893c5566eab1a7e22db8feeb8a90175b7d").into(), - hex!("9953a7cbc152f101a60e3e381f2af17ebe7401e16ef6462d132b8f0f6c6a18837914a1299d1605f9f289b9561112f4bb").into(), - hex!("a0c9b944a338325f5efb675c9c12619fb43c8e25e80d38d6140e31d5070573b1a0ed9bb52576e4f22f37d0292d36a648").into(), - hex!("8bfd6a173a56b73480cc950ef266a18933ecafc86915a7453ded09efd8a0cf4466101f1373f05d48eae3e7fc5c0f7f54").into(), - hex!("983fc1ddf17f9756c9cecc00b39bb2ad432587a5c6d1c3296a383b9f539c9afe84c6c818447a709c0b686ba26ce5ea3e").into(), - hex!("94bbc6b2742d21eff4fae77c720313015dd4bbcc5add8146bf1c4b89e32f6f5df46ca770e1f385fdd29dc5c7b9653361").into(), - hex!("b26b4d483bca73d3f3a976bb595a0e40f9a42094e0febbad3a1874934be1939a1b362ee4ea14a4f5cbfa9b1392796a12").into(), - hex!("8dbe8fcbcc414eb352245c52549973f73d987012de9d5f2b2f55dfdc43cf8cc9ea6b147abf149817f80f9e15aea566c6").into(), - hex!("9604da21e23c994a0a875ad5e0d279c79210f7a7de5c9699fac4aebbd76d39b703eeec5dd5efc9ad6b9dc58936089ddc").into(), - hex!("8934e9a3feababa12ed142daa30e91bd6d28b432d182ac625501fe1dc82f973c67f0fe82d39c9b1da3613bb8bfe2f77b").into(), - hex!("85f2ed3ffb03e50c8f22553b8e6349be6244d893aa37a7c6dbd221e9e121579e5a04466e60d6b4d3567bc747b1fc1e9f").into(), - hex!("ab0ad421f6fd056687b4fa5e99dff97bd08840b7c4e00435eb9da80e0d7d071a447a22f8e5c1c5e93a9c729e5b875a1e").into(), - hex!("841d77b358c4567396925040dffe17b3b82c6f199285ac621b2a95aa401ddb2bc6f07ebd5fa500af01f64d3bb44de2df").into(), - hex!("83f21dfe0272a5a8682c3c7814c5e0e4db6a9098f1fa80fda725f77ea81fdfd2fa36b0c8db013503a89bd035f86306fa").into(), - hex!("95c98e3b6b62f84edf7f297cae93ee5f82593478877f92fb5bf43fd4422c3c78e37d48c1ee7ca474f807ab3e848d4496").into(), - hex!("81c3a8c00cfe4e82f3d8cb48de7d4926d5ec2f7689f9cb85c1886a23758bc107a4bc6e978601c3519156a169d0bf6779").into(), - hex!("8e956ca6050684b113a6c09d575996a9c99cc0bf61c6fb5c9eaae57b453838821cc604cf8adb70111de2c5076ae9d456").into(), - hex!("83474776ef2341051b781a8feaf971915b4a1034fa30a9232c4bf4b1bd0b57bc069c72c79510acef92e75da6f6b8843d").into(), - hex!("b41780d9d67e9e8b81b1f62d25c0c72ecfda659d2bfe6825edb70ecd0e0724250ac364e7be521cdc112ba638f16360d4").into(), - hex!("842ba3c847c99532bf3a9339380e84839326d39d404f9c2994821eaf265185c1ac87d3dc04a7f851df4961e540330323").into(), - hex!("af17532b35bcb373ce1deebce1c84abe34f88a412082b97795b0c73570cb6b88ea4ba52e7f5eb5ca181277cdba7a2d6d").into(), - hex!("b9574edb9567f07f85c7c2e6ca6c02d90ad7c7b87d49796f1e2fb7240ad071fb755cf13ca8678668a56217c62df168eb").into(), - hex!("82212706111fb1cf5def02b5b0eb7ae9e6ea42b4c7a2b9fcacb7aec928326edb9ac940850dd933f2822f6cf519de0d50").into(), - hex!("9579973ee2559da09b327c62b1cc0177f2859872885dca709e24dcfbb9bdf9224a6d26869aafce498f44c0e6bd8a996c").into(), - hex!("a102c2ade15ea2f2b0cbc7dbd8c1171de0c8092fc4ecef84b5fd2bae7424aea8be1629f851c75e4d1d0e96104e54bfbc").into(), - hex!("a5d7e847ce7793386e17fe525f82aabb790d5417c3c6e3f6312f8e5ff52efa8b345c1ff60c4c9bf7636f5ff17b7a0061").into(), - hex!("b4b80d7fbdb1dbf1567dfb30d8e814e63de670839a8f6ff434fe171416599fef831b8e978d6498851b8a81e0bc8dfb85").into(), - hex!("b6e6277b86cd5284299ced867d37ab98090ac44a94deef6898aeadd177e64605440c15b9609c07e71fe54c95b61873b0").into(), - hex!("8135a0633082e4465090d6930b770340e82366bc5c37be6ef6dd105f85acf63361e17de8b5fcab4c82e9f9b4029954b7").into(), - hex!("864d5d9858cd881eecb0dde5e3e0c6c5de623cd9ef619e87b82fd25c5edf45a1a025b1dc763c27c5f4d520fd564b464a").into(), - hex!("8784a8fa62e0ce23283386175007bb781a8ec91b06fd94f22a20cd869929de37259847a94a0f22078ab14bb74709fac6").into(), - hex!("8adb748d5fa5c22ce4c76a1debf394b00d58add9f4e08524cf9c503f95981b36b8d0cb2dfaef0d59d07768e555733ecc").into(), - hex!("b76cb8cb446eb3cb4f682a5cd884f6c93086a8bf626c5b5c557a06499de9c13315618d48a0c5693512a3dc143a799c07").into(), - hex!("b2af1f7ece1fd640c205a09614122d69d5d2e81a7618bedefd6dbb91c7f432679be4ced1e6dddd3de323bd44991931c5").into(), - hex!("b950b457c34bfdfdd9d6da9628d41749ccae03659518a04b56487bf1b4c0681b719ec5230c0b0fd5dd710894df6aa2f8").into(), - hex!("b21785008910a949804d1291e7533752641d31beae3cb518806488f81d58c38a5efe5ed9534ac692e68c3121e2f9d97d").into(), - hex!("a9b120a77d70c1cbc0178a12d97a78b2dd0b98d0584e8e780b937800ceb18c90eaa1f0a83c5b50e34cae1c20468f004f").into(), - hex!("998c9ee20d33f96a2388b1df642aa602bc8900ba335e8810baab17060c1eace4bc5203672c257b9ae750008b707b0aa1").into(), - hex!("a7d1676816e81a752267d309014de1772b571b109c2901dc7c9810f45417faa18c81965c114be489ed178e54ac3687a1").into(), - hex!("b409f87f0632aae9bc081345b17a50a767ba4198f9ac9d352246fb3bebd29ed53c9d6f148c2f318c2eb12846b0aac4cb").into(), - hex!("b40a3bae2b08c13db00f993db49e2042be99cde3d6f4f03d9991e42297933d6049394c659e31f316fcb081b60461dabf").into(), - hex!("8c1de4264e04ff7e8282faf81c0bfb5943656451be52170211cb7adf4ff21bccbb789400735579c622f69982fcb8e9c6").into(), - hex!("8085c60b6b12ac8a5be8a7e24977663125c34827842aa3b2730854ab199dd0d2eaa93084c9599f0939be8db6758b198b").into(), - hex!("972cfaefda96f5edfe0614c01533b76153118712c1c02c505008204a5be2aa438675d97f43384199517b1c08c7c9fdb2").into(), - hex!("a1e47798a782a024da340d6d6a1b1e5e15a0f2d8668adf349ca375086964414a563cc1eea3226ae637f87e78c0a630b3").into(), - hex!("8171f20c020faae112bb92ca213c1df5b1050151496c70db5c5319212bada83b120d515bd7d8b24736090c574e1b7203").into(), - hex!("afe779a9ca4edc032fed08ee0dd069be277d7663e898dceaba6001399b0b77bbce653c9dc90f27137b4278d754c1551a").into(), - hex!("a5a07bf219432e9c80c38596c93560b49c7de287f31e30b7a06fcb4d15982add4a24085adbc5b753c462be989c64c96d").into(), - hex!("9210be290176d7e8a5005d27e7ed825067b1c678b174bc8180f92b5c03b6c3d1822356edba84f460caf6bf5275cd7efb").into(), - hex!("a95bec86a7c8417a8df3a0158199327ba0924d3b7dd94cd7c1ef8489b10270ae64b8537ed39cd3699a48942bfc80c35d").into(), - hex!("ad9725114b01152fff134c1a8ccb8d171b8cd11685ef6815b76f442d757d130bab9ef4c9845e66f4aa0237ee2b525c20").into(), - hex!("8018499ef720e28759133033833edfe17ed23e42f99058bb79fe844ddee823cfdc43916be2dc9724d18f9726e6f1b409").into(), - hex!("809c7a08fbef7caf4c137cd639f2e47a8ca60d13bca3990eac51ac2a9e4442cd1a1473bebb63c61d595b586525d7b027").into(), - hex!("9793a74fa578ace75b083578277a1ae8766d41a5c508b0f1135fb97dff1d0826002393a7276b18cbc4b3c5671360ce0b").into(), - hex!("a6d7e65bf9f889532090ae4f9067bb63f15b21f05f22c2540ff1bb5b0b5d98f205e150b1b1690e9aa13d0dee37222143").into(), - hex!("99c935fe18699bca9852200c292690a2b834bac508890c4ee9af1aa6999a8d590bf6a3a274bb55d5a73f1b7095d10f37").into(), - hex!("860f5649c5299211728a36722a142bf1aa7cbbfbd225b671d427c67546375de96832c06709c73b7a51439b091249d34f").into(), - hex!("9104ac7ad13b441c6b2234a319e1c54e7f172c9a3efcb8c5fab0ac1d388b01895a9a208f59910bc00fb998b0adab1bc3").into(), - hex!("a3b109249ac2900806f0f39338da72d4f2cc6d1ac403b59834b46da5705cf436af8499fa83717f954edb32312397c8d9").into(), - hex!("b9893f7a47af457a9efd90ddc0c0ef383ab34e9c1284e617c126965cd9f0de5c54ee8b7b5208ff190366fe445e9c1325").into(), - hex!("b77416ea9a6b819e63ae427057d5741788bd6301b02d180083c7aa662200f5ebed14a486efae63c3de81572fe0d92a9c").into(), - hex!("8b20a852fc8f0b7cdbbd808c04a0cfd2fbccbdc0cb2361434f0d96341c8bde6155695977768d563b95746dcb4339fe2c").into(), - hex!("96b15806d9009962fa07f8c32e92e3bc30be4ded0645ab9f486962a1b317e313830992179826d746ea26d4d906bdb7b6").into(), - hex!("b0d69b3861ca6791632ec8a87114b463e0da571bc076c22a8f0d9e88a1a5eaef24683f3efa8f34900d0112412e3dc4fa").into(), - hex!("b01a30d439def99e676c097e5f4b2aa249aa4d184eaace81819a698cb37d33f5a24089339916ee0acb539f0e62936d83").into(), - hex!("b19ca6e55f349bbb2dc3e429520ff5b2e817972470794f35c1aac8c118b37a694cfcc875b6d72225343799825d2f5c39").into(), - hex!("b7ea5e0d3cfcf0570204b0371d69df1ab8f1fdc4e58688ecd2b884399644f7d318d660c23bd4d6d60d44a43aa9cf656d").into(), - hex!("a778da56ddfe4a383816b43b027464d7a28689fc4a6b35b36883d3f36d9c41f0177bdbfc8f258afe8da90f02d3b64fea").into(), - hex!("910fd030feb5538f538e5ba74b9bd017d889ed6d2a797be9c26d2be8caeba7a473006102de27e87755742ba34e445bca").into(), - hex!("b49593ea6040ce82cfb5aa2881a4b0c42b78aa9fc8467d79c8e4a8ae4ee7355842841c8e1cc0558362047ed80de44fd3").into(), - hex!("b07447c7e87459315fcbda3fb86fef27f98373b1246e2ce367e26afd87f6d698a438501fdc13cc5de9eef8d545aab768").into(), - hex!("8a9f7e8d45f11c4bfb0921c6008f3c79ff923452bcfa7769beb3222f1f37dcb861be979e6eae187f06cf26af05e8ee5b").into(), - hex!("8ebfbcaccddd2489c4a29a374a2babc26987c3312607eadb2c4b0a53a17de97107c54eab34def09144b3098c082c286b").into(), - hex!("93be3d4363659fb6fbf3e4c91ac25524f486450a3937bc210c2043773131f81018dbc042f40be623192fbdd174369be2").into(), - hex!("8cf8412bd48b21b008f0207b1f430ed96bc6512c3712dffbbecb66e493e33698c051b27a2998c5bddd89d6c373d02d06").into(), - hex!("a5562fbaa952d4dcfe234023f969fa691307a8dfa46de1b2dcff73d3791d56b1c52d3b949365911fdff6dde44c08e855").into(), - hex!("a8c167b93023b60e2050e704fcaca8951df180b2ae17bfb6af464533395ece7ed9d9ec200fd08b27b6f04dafa3a7a0bd").into(), - hex!("93e4d7740847caeeaca68e0b8f9a81b9475435108861506e3d3ccd3d716e05ced294ac30743eb9f45496acd6438b255d").into(), - hex!("8016d3229030424cfeff6c5b813970ea193f8d012cfa767270ca9057d58eddc556e96c14544bf4c038dbed5f24aa8da0").into(), - hex!("ab7eff4ef8696db334bce564bc273af0412bb4de547056326dff2037e1eca7abde039a51953948dd61d3d15925cd92f6").into(), - hex!("a3f9dcc48290883d233100b69404b0b05cf34df5f6e6f6833a17cc7b23a2612b85c39df03c1e6e3cd380f259402c6120").into(), - hex!("8b476b3b065a3b95a3d11ec60a749c2258ddcc5885bfb50b8a086d3fd1e49ff73e1dde733b8981c3d2d206aa0c87b09b").into(), - hex!("af3e694ad71684f7214f86bed85149db039971e1c362119b979a135255aa226128802e58e2caaeaf8d89304371dd0440").into(), - hex!("aa19a75f21a14ad5f170e336a0bd07e0c98b9f5d71f91e784d1dc28a5f5eb6870a4eb35bb41edcf9e6efe982ae5c2c5b").into(), - hex!("b9528983419ab5766596683faebb3592982a76b68593f810186b4e5f94f6de60830739ad8dcc164c601d575b84bd2700").into(), - hex!("88e7a12a90428bb45bcf4b01442c11607433211fc2f9bee9545304eb66e0b4b5339360160bc782e185391385da7c5ad7").into(), - hex!("a4c4df0e29db19ab4c82dd6ca8570b337d15b59c7d84577a7a444a8f762ff16ff5ab3e4203a1d6b60a23ff949a93ea81").into(), - hex!("8f11ee58ef82b1bbd2240d3f548d8681e22bed5ce118d605bed4523b4bb39899ac78e15337daab92666750dfcaf32aff").into(), - hex!("8d3cba4d10f94bd3406a341c903ad144cfcfe6b61678d5c03084a56b4413bc30bd20d7a9fd5d839dbb565cc9b2aa99fe").into(), - hex!("ab8a8769c754008a7976b6799e81d7bfe97413d0a79b90715703c1f8f567675463ec93aabee59277121fc4df88b5c7a9").into(), - hex!("b201b0546f19c5db88df9c684cf55ed623bdb43927d06051bd595497df741feb1485961f64e8d3d1811d9e2e9e1e54ad").into(), - hex!("a04016e9e13ad845763cfe44af4e29fecf920b4aa42f581715fc34fb9ca27776feee45c82093c7274839eef1838b10c4").into(), - hex!("8f84cba7ceb7652023fc8ebde4b00ecde1f550935bab12feb630d6f49517b4148f3cde184bf55d4f6ec99a849fc6f862").into(), - hex!("a2248409026f35c3da8bc4d5c02315066df8fca44ff5a358cc42b5c88bdf6866dc133617c697bff004b1ef20ec4b5748").into(), - hex!("a52c5a63b55a8001b6b67c5db4fd5e95923052f03618369312896ed9892d99354aebc0dee8c3b365bafa29e211a5c3f9").into(), - hex!("8c9fefe233d0d657349b7efcdc368f5aaead27071d224af780874751e7d241f6b88f7650fbb4133043b24bbebc12aa48").into(), - hex!("86ceb649a337a5a79c17b496993ca07fa93b38a582367ca04f3dfec5cef8f268d4e8080e5a76b150f5be1b177ef6984e").into(), - hex!("87dcb537e38cefa32e629ae669da42e809b5afcabdeeef244b72ce057fc18584a1e8c3f073d5d33775232707f0cc59ca").into(), - hex!("a020404547407be6d42856780a1b9cf46b5bc48122902880909bdcf45b204c083f3b03447c6e90d97fd241975566e9bf").into(), - hex!("a1beb9f673409ec678020ea4dcbe65177aa18e2932ceb9cfb33fccb94b9a8ccb664f71647d58b3c8b2bdbbffbc02d5f7").into(), - hex!("ae47b31c5b62b38ee886ee04945649054369018dd6543c91f0138464af489a32c1fea339e0e0cbe82e3e8b9f2ef3918c").into(), - hex!("b18c41c0f827f6d8656d3fb93c90b663eb2eac034923972f8842cb30e96c32842b3fbc1127930e1ba4322d5b6641f04d").into(), - hex!("a6d6ef51a361df2e8f1d993980e4df93dbbb32248a8608e3e2b724093936f013edabb2e3374842b7cce9630e57c7e4dd").into(), - hex!("a49da42c27d019a21cc6489ada7b712b98c4ede28ba25dbcfa916acef48446a2baf73e03a48be763378a09774d4a03fc").into(), - hex!("8b62902fb2855300580e94830a4bc825d997ede33bf356fe3b7c08d6a8bd85a37879433fc6bee58f9b44ca280f4e8dfd").into(), - hex!("af9d13103868c854821ba518907b067cfba025d739125f1e9cce0a04fffc3a2a1f25506c1209a0cfe1d6c1572c229ff0").into(), - hex!("8910f41db6952c25dfbf6b6b5ba252a2d999c51537d35a0d86b7688bb54dcb6f11eb755a5dce366113dfb2f6b56802b7").into(), - hex!("b551d1ce88cbf4ffbdcb0113a6e319513bd676d0078dd4e6a6f23ad336c1d0fb47a4e427bdedbe0fc8f152353971f81d").into(), - hex!("b8876bda1e709ab16e1347a1107852a7898a334a84af978de39920790b4d82eb0739cbfc34da1c7154dd6e9f7674759c").into(), - hex!("a7d9ae9621dd1f3da3cd2d435e891cc3579c4c0d60d6a4565cac86c315cea21a9ad883559fe7b897ae6e05f1aa989ad9").into(), - hex!("aac995a41c14d379853ef18ffc854ad62ad77061ca9bdf5029cab3d6c2630de114e777a7fc3322455939d5205ed59c55").into(), - hex!("999cec6a31d9b2f280017ddd59138014829fa34cab58e6c35a5014ec364b84712441e7a2f717cf2f0de8d5451e250924").into(), - hex!("b1f43b498cba1797f9793dc794a437500c3c44a8a4b59f9125a4d358afa304fc05b88ac31ed40b6eb68f0396b60cb7cd").into(), - hex!("93ba2e000bdb7269818d390bc4232992d280e69abebe2db2ecb6fcb1390d323238c9793574509bc1fa34051ac1928f07").into(), - hex!("a64808a2d15c30460651c200a09b50fc83e9d84d87abc156d06cee73b76fbd74e6d64424cb5bb83d3f16b21bdb7ae9d2").into(), - hex!("a75bcd04fcb44ce5cbab7eef6649155ec0bef46202e4eb86c88b4ced65e111f764ee7fb37e9f68e38067040fedf715ee").into(), - hex!("b95fc0ec39596deee2c4363f57bb4786f5bb8dfb345c1e5b14e2927be482615971d0d81f9a88b3389fac7079b3cb2f46").into(), - hex!("aef456af90354ff88039d2dde02b0f5a6790aa762b23e0a9da8c6ec92c3b8b3320687bb21666608b4a22615843afd1ef").into(), - hex!("b38be9ada17ced704a34a7498c4fd6ba2503f6bd886b693d4712267847efa887a26e7da5d60f8bc5014b92bca8b3a12d").into(), - hex!("991a7c93f06d50ec6a4340c6751b73eb5825bad02a954e44e1e2d424af928819ebbb590c6129ce35b3f1e908e2152f33").into(), - hex!("84888f2efd897a2aca04e34505774f6f4d62a02a5ae93f71405f2d3b326366b4038854458fd6553d12da6d4891788e59").into(), - hex!("941e2e3ba414a371a11c3fe92cabf688ff363da6230ec7c83ac7303f652a19ebc89cc494427c456d0c2ae84c72053f73").into(), - hex!("925f3bb79c89a759cbf1fabdaa4d332dfe1b2d146c9b782fe4a9f85fee522834e05c4c0df8915f8f7b5389604ba66c19").into(), - hex!("941c8962debd2756f92a6a0451a2bf7fbc01f32ed03d0823dffd4a61186628a4c3c7c482b18589ff65e4c449fa35c2a4").into(), - hex!("88ce41025aa153a94f91f22e7b96f9342b5e0e1d76274fc70c4df7d08f66d9f7ac86e55a1c6e77693b8b01b2b38bf900").into(), - hex!("8f142bde50abe4dac8e059003db41610436d5ca60d2dfe2660ecaa5f9628aeb8b5d443e1b57662076f77363c89a1479d").into(), - hex!("b2affe048c187d311a185503d8958cacbe03796edf79bc32e8533941004d9178bd2e376e627e1ba61ed43850c0c455cf").into(), - hex!("8f7bbaaac458bada6d852fe665c87c646133bab16c0d5136c3dc922095b9d647d93a9de7671cb7bfd4cbd138ae0709d1").into(), - hex!("b76f598fd5c28d742bc1a81af84f35f1284d62239989f1025e9eba9bece2d746a52f246f9bb6bcfde888b9f7b67fc4f6").into(), - hex!("a4c665a3e4e25a7af51e433c978573841bfa2c75c075e17dd1f43b2f0369249f3d3a46ff51051e8ce7da528b0fa98d16").into(), - hex!("81e0992e7c1c54c21cac32e36b90b25e1e5b72aac99c953c3c4d019eced64d7e316cbc0840204a4a51a4ad17d8b1d508").into(), - hex!("96d7a69eaf2761bf0e5ebcd607b134d5dedba8e262ca1d6d3e8fbf23e6419a8ce1bbe4cd23b9e4b5f80db54a802a9795").into(), - hex!("b2235bdf60dde5d0d78c72cb69e6e09153b0154efdbab97e1bc91f18d3cec4f660a80311fe6a1acd419a448ab65b18f1").into(), - hex!("838d5eee51f5d65c9ed1632d042bb7f88161f3789e6bb461318c5400eaf6728e7ba0f92c18e1a994aa4743145c96164b").into(), - hex!("acfbac397ae2ff23b31bb27b90788fd0fd51a50f8e8c9f4b31be8499194252014f0b1972b204aeb9c2836a20beb3c868").into(), - hex!("ad85789bb62b60e9768bd330a31a16f711b6018445af6a47646f318f12df8d4d256ad00d1ed7c3afa4e98fef73c6c610").into(), - hex!("b2349265be33d90aaf51362d015ce47c5ffe33e9e6e018c8c6e39336d9327ccdd13d25e792eb33b43ed89a162f6ac2fd").into(), - hex!("aa458aaca6ecb43b6e45ea72d02682e5a7dc8dc22782669a0628e1638e73999319f011803f4ec8cf072467bf2c49c629").into(), - hex!("b9e6c9f2562e90bd3008669a42151538b70faf028cc5bbc09fd6ab3febc626df911fcc65744a2ad793ecaf3f91a1f701").into(), - hex!("a37185bd96faa526dfd3ddaff89b1eb29ceb4597bfc7e346bff9d6b3225b9ca87cbce0db94f05243c7232ead5f6607e8").into(), - hex!("824fde65f1ff4f1f83207d0045137070e0facc8e70070422369a3b72bbf486a9387375c5ef33f4cb6c658a04c3f2bd7e").into(), - hex!("b0ed68167a67490bd7d7d49e83341606d6e6fdd99b82e46747c2190d270719f81c5f5f8733646c246260f438a695aa3a").into(), - hex!("a87c2f13f2a824b7e2c39cfb63ca7b94ae6a11ade0c6b8e83f5092b933fa8b6157a5d2f09c23081f49d35cc85f5db36c").into(), - hex!("88f5e795cb36ab22bdcff01caca0e9d04db463c3d88cf656c3a0e0f5ac864b7092c738758b4c8f3b65e31995c6aaf267").into(), - hex!("ac66f3a7041586ac1576e33598f01921e16d99afbf4249c3350f0ee1654de98bd37a61c243eb6a18a942db529e36af0d").into(), - hex!("aca69a4095567331a665e2841210655636a3273d7b7590e021925fe50757617898e1883532f9cfd46428c2e3d854f9f7").into(), - hex!("946d585d7aa452d37a8c89d404757c3cce2adf2410e18613483c19199abd88f7a12e206f87a43f6009e42f4e31ed20c0").into(), - hex!("9722c1079db7e2e1c49756288a02302b43b8fd92d5671585ac1ea7491123742a2744a526c12c9a0b4c4a80f26342a3a6").into(), - hex!("b80e8516598c59dddcf13fdb7a42d8f5a52c84e01bd6a39880f4acaefe8e4b8f09cc1b1a2423cd5121f4952201f20078").into(), - hex!("85bca2f86423a09014b562f7dc613246bedffdcb3aa41fee02270c13e6b00c8d6704dcbfbafc5997df6a90c7fc08c29f").into(), - hex!("a36dad4f7cba9f4cc843fe40f6240e1973a4c412cae29b4a68712598523cfaecb05272fc47d30772bf06906b5a26e282").into(), - hex!("a3d8610c2522d330df02511710e52b1d9bdc9f2b156deca12b1bf754266caeac4f449ed965d9863558df43ce9ae65a44").into(), - hex!("b3e313e79d905a3cc9cc8a86bd4dba7286fb641c2f93706adb3b932443e32eff2cbed695beeb26d93101c53d5f49d7db").into(), - hex!("88d8a32231ff2bfc39f1f9d39ccf638727b4ead866660b1b8bfbdf59c5ab4d76efddd76930eff49ea0af048b2e396b6c").into(), - hex!("a90d9502a9785e55c199630456fcb1e794bbeb0f5f8c022e66f238a0789998b126cf9911fd0b7d463b7706dc6f9ec128").into(), - hex!("8c627caf25eae6764501b9eff35aa90bd4f24952cad712aae20344579e83ecd104ad1f7915edc4f9023b17fddbdb4cd7").into(), - hex!("87d4b20bbe2dcd4f65f4e1087f58532d5140b39a5288e1a63fc0b7e97a6a56946eafdd90ba09300c3d1fef6356ac6b7c").into(), - hex!("a18f4464cf5cebade8ee280fa00e0917cbf1743aeb0dacc748ab68773b909e30dc60f40fdef3041b5f082e650985f7a6").into(), - hex!("a6ae4fd03fbb4e2150795f75a241ab3a95c622b4615f553bab342a1803b86b1c1a2fc93bd92ee12786bf2de22d455786").into(), - hex!("a89bc7548ea245ce9556eeee3fba98a3256f87499f54a7c5eec0c43b9fb4ef2fe8f6810867ed0df814a88ee100c245af").into(), - hex!("97f1a7370b4f5acf83b466f519da361c366915f560385dd7eff9d53700ad81b25c9862bc71d35428e82372a5ae555ea0").into(), - hex!("825359cfe68ad6a75578a94be6419179e0aa088170b6c20fc5c249dc3be7a260d687c93d8d8a343c7c72c2ed6a716de3").into(), - hex!("aa9b9cc039d147677aedd1e47ad9013fcc0da0164070ff7305b18e5786c7fac0471368637a3adbb78f3af174a5c1592a").into(), - hex!("a61687511b627bde7b3977e9a34cb7fddc2aaa509a7b99b6b6c7b97133845c721e1e69f99758698d82cca265d8703610").into(), - hex!("8853c582e86cf916750d670a621246a63c7fd78f68c556642053bcdfa7937de58885d728209736b7d5521b591387e9a7").into(), - hex!("82b8c013f24fe64b8e0337ae8b6a682cae336b8404eafc1404744f80f765efdb8b2873d1d3f31141e8dfe4d93346ac56").into(), - hex!("866ec39b9eda580d96bc2bff76af5cd4887b6788675149ab33bfefe38db82ad01b8d64c6b60704210918f3564cde1110").into(), - hex!("81337ebe90d6942d8b61922ea880c4d28ebc745ddc10a1acc85b745a15c6c8754af1a73b1b3483b6a5024b783510b35c").into(), - hex!("807c510df25c0ba10d4aa06a462e02f050c69a977c64c071401ab74f9ac1e60788aa504743b4cc1982da835ff9ac2541").into(), - hex!("96b1c82b85cdb8a7026fd3431bea9cd008f0261ee7f4179f4e69a399872837ab836a14e2dd45f5448d54800a4ae7c7f2").into(), - hex!("a48b1031ca2f5a5acb4dbdd0e9a2b4e9add5ccfc0b17d94818273c8df11e825193fade364e0aec10f1ff91d57d03a52f").into(), - ], - aggregate_pubkey: hex!("a825959280c88c6716f6df807204feb84d745dfbee3cb3474ce81a1ef0c4cd142e5ca962a0335e68b7b4266769d631b8").into(), - }, - current_sync_committee_branch: vec![ - hex!("bcfe80e1d24fbdad7bc058b011403a4c26cb56967654494cde51517f888023f4").into(), - hex!("4710ae46156553fee6231622052f7fb2f6945cdb59a5501cef824b1925c87445").into(), - hex!("6df62e05ef3e1ac92c659c3a519b8fa651d1b649c2b46fda58c48cdeffe8337c").into(), - hex!("d26ff22ef5958a707a8d98eb1ffaaf1f9f412e816c04b79f5434cb1792ccf608").into(), - hex!("90d5e61f0af673ab4d8b3ab0b978d05142a8295a163b198e6dea9d8c8f1c6d89").into(), - ], - validators_root: hex!("d8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078").into(), - block_roots_root: hex!("5078f286fa90b88a09dcccd4ac72f6c3615b77c0ab3132508cb8c0c07b20282d").into(), - block_roots_branch: vec![ - hex!("558b658b1230e225ac3adce3daf0b066ed0484b4a768d55b74ba81579ca0e5d0").into(), - hex!("2cbb27d38065ff3f230247af918e67d1998b67bc7e2ce6c244bab7146e16b8ad").into(), - hex!("c63bfc96585f424385e3b4b39ce46e957017b716c54d105eb7e07c841d1d4309").into(), - hex!("e662b38f57427b58c46b09980db3856f17e56b60b36bd5471823b0f2cc1b6467").into(), - hex!("8b3bd99618b1e50cf284b4c3b03d0cc272312bce377d585eded77154aa5580a5").into(), - ], - }) -} - -pub fn make_sync_committee_update() -> Box { - Box::new(Update { - attested_header: BeaconHeader { - slot: 4055104, - proposer_index: 1862, - parent_root: hex!("5f44df1f70338aca4b3046f9e5b144bda8b27276320ca000077389d0aba35317").into(), - state_root: hex!("9daecfedc819b45231bf93819a73efd4304ca79528032fae2e852ebbe514cfdf").into(), - body_root: hex!("a33f5cdc6732684e6f248e5a7636c7e7bf705f0bf709098a46ba15c660b4fc65").into(), - }, - sync_aggregate: SyncAggregate{ - sync_committee_bits: hex!("ffffffffff7bfdfffff7fffff1effffef7f9ffbdfdffffffdffbfffbbf7ffffffffffefdf7ffbeffdffef7bfffffffffffbffffffffffbffffffffffffffdfda"), - sync_committee_signature: hex!("880f147850ac0a94130b81f94203e2f69d512c929df8b954b6adc20cb1e8598aafadf366c074b590c0905d584dd980af18e0c8a837bbcadf6b4438507aa46ef95879c0acd9c2d273ccb13d93e4938e9c601f0dd466f53369ae94e1287955cae6").into(), - }, - signature_slot: 4055105, - next_sync_committee_update: Some(NextSyncCommitteeUpdate { - next_sync_committee: SyncCommittee { - pubkeys: [ - hex!("aedc2d47fa2662be6ab58ddd3682bd5e53f508162968fce8326c75f92fb3c1a25c4d4d0e6904f9b6cb1ccbaaa9dc28d8").into(), - hex!("8097b13908662d245820f3b045d8c2c665fe9a054e9c661323924ec86dfa713b36b0c787ad4dfdeb979318810e687a48").into(), - hex!("98aebd4bf15916512508a5fe89d814d5d76423c562cd3f0a0af504c8cde53be30f4df00e3ba0229cbf8528e198a0df11").into(), - hex!("86bba46d0031989d0f1baccea4174fc3fa0d595e60d35a464e86c33c233e2d6def84fced7a00f59afe397cf4fb5b67c5").into(), - hex!("845982c2672fdd44b33d2e56ad676e704c02f756b09e8765bea42b924c14724484567b55f0db42ac20cb70a7f5201c14").into(), - hex!("926dc729e135f1f0bff4662ee3d6823a64597fe189b763ada34f246e77705fd4e062d85506a338e9fa98c4d225a3b27a").into(), - hex!("b930ecc2a26183240f8da107e80979b59da4e05f090316d982815ed6151d7750490b85273187ec4e07eb221813a4f279").into(), - hex!("81564bee5a3bd09476f658cf7719326c353485e2f4fea58d110071c5dddd3cabc349a8d1ecea45d589ed4479952a2ba2").into(), - hex!("a66d5b1cf24a38a598a45d16818d04e1c1331f8535591e7b9d3d13e390bfb466a0180098b4656131e087b72bf10be172").into(), - hex!("b9b9b6113301bd2b409b71afa1ab9e31d22f84f8cb03badaa408e1d37032350094124e533de766622d7975a047fade6c").into(), - hex!("8eb3b3e3135720036c1120c4e8b8d405b00d002f2bdbe601a06f2c2fffb940a9966d18636ee34fc003dfef547d8f3b76").into(), - hex!("898deb30ede570d391266c81132a78239083aa9e27a9068e26a3bc14ff6468c3f2423484efb2f808b4996c16bfee0932").into(), - hex!("a90d9502a9785e55c199630456fcb1e794bbeb0f5f8c022e66f238a0789998b126cf9911fd0b7d463b7706dc6f9ec128").into(), - hex!("ae8af784224b434b4dfa9ae94481da4c425602097936623e8abb875f25deb907aa7530bce357786a26ed64ef53d5e6b3").into(), - hex!("b544c692b046aad8b6f5c2e3493bc8f638659795f06327fff1e9f4ffc8e9f7abdbf4b7f6fcdfb8fe19654d8fa7d68170").into(), - hex!("ac5c01c51dac6ee1cb365c9b03f09906d9b7b9b4d1b73c44d9e8e06823025d7070f242898a975420bc87d6372382cab8").into(), - hex!("a4632399c1a813e41fb2055ef293466098ea7752a9d3722d019aa01620f8c5ecdc5954f176c6c0901a770cbe6990eb11").into(), - hex!("85f7ae1a7a7c793c408750ddec2d7f58b985fc3cdf9fcf6b2192bc57092b8a271b2fb6ced0639baaffe0bec3203e568b").into(), - hex!("aaeb466f4316874c2107a0de38dafafa65ce50039c20723e8797815238011426f4e77e29fc573e7c6d2df85c1bbfefdd").into(), - hex!("a8fd63da16dd6a4aa1532568058d7f12831698134049c156a2d20264df6539318f65ec1e1a733e0f03a9845076bb8df8").into(), - hex!("93600f65c090814cee5cbd5f22f98e79c69e63510501a0be6a74b111e4c52441133fc1c198c7bf235f9005aeacf1d441").into(), - hex!("a69f0a66173645ebda4f0be19235c620c1a1024c66f90e76715068804b0d86a23dc68b60bca5a3e685cce2501d76de97").into(), - hex!("ac6e7e9960207138d5b4b6a7f061756c01cc4a830e5988423d344f23544ed0eaa790aed63a22df375768f670cc9b9bd4").into(), - hex!("93042dd42e56671155bb40d85d9d56f42caf27bd965c6a7a7948b39089dba8487d4d5fd30522dba6ba392964e3ffd590").into(), - hex!("85bca2f86423a09014b562f7dc613246bedffdcb3aa41fee02270c13e6b00c8d6704dcbfbafc5997df6a90c7fc08c29f").into(), - hex!("9550072f64a48cb86bfa224d492be9a91e5a6c9def04b6a290b7a19d96981937d5a2c35de6515d1881bcb167f6e3d661").into(), - hex!("8d797819318cdf7b26405d1a327d80d4c289e56f830b28d4e303bcb019aeb0b3d69bfed58adcde8a2445dd5281b86af1").into(), - hex!("90c04eb3f3679cd630434418cb3a225a73254887692429960bd45b1613f85b2c14723cd8c7f1e875588ed82b7f5576b7").into(), - hex!("9953a7cbc152f101a60e3e381f2af17ebe7401e16ef6462d132b8f0f6c6a18837914a1299d1605f9f289b9561112f4bb").into(), - hex!("a9300a33927335f482dd0e44d0d57704ebeb278f732ae8301073cb7d5e457f02a0cb03268de71d284b8c23fb96947469").into(), - hex!("88554c83648ea97dac83d806cd81d92531980346b208d281fba489da15a0084fd4d9a00591d1ca67aad3c5793685d55f").into(), - hex!("9131874b09aa95ba186bcaa9e040fabc811b9c7b905b7dc79e902cf2bb5816d7ee39b0b55be609f22bc8c538760b2037").into(), - hex!("8368bb9b9bb2e17730c42ed1100eb870c88a8431601312aa8cb1e738cdb9ca2704dfd432cf1703c0db043259819631dc").into(), - hex!("b49379bbb9f954d2ef5574199607bc6b3aa2cc3b48dcc3745cc77406bba2a394929844fec1b87c4ce65cd0ca0f83062d").into(), - hex!("876afcd045c8a18967923733a3a43757652289b0974cd348238a693f30bb57f38664ecb97877a5e5f7d0185039a2bf54").into(), - hex!("8db19f6dd3789df179ab606508ca7e3da7967ad4340f630bda83df54c197d6bd3a14980c87fe10cbced7678c0c300ef1").into(), - hex!("997a91da55801acb6134d067ad65a9a44ead0b53d3871bb97b46ec36149d25e712d7230d38605479796190abd3d134b7").into(), - hex!("ab1abf9cf630d6cbcac0c503df44603142ac81acd647784ae0e8fc97800ef04378bc9d7f2087f959ad4bbbeec65b8dfe").into(), - hex!("95718b06017ba9d45894867fd67148645d25d9db2229aa89971f444641ba9db4c5c6f0785f3b25cf2cd7fadaa6adc5eb").into(), - hex!("8ec38c68afdfb6ba019204039c2fb49a35467058f561f626fa87314d705fd615a7b9966576052be1b3690028d3c5c7bc").into(), - hex!("a5d72ac4cdcd847d67cb5a68c6141cde99a91303ca84165bbdc6fd7f643422faec783de60739e1b2753088280c90a68b").into(), - hex!("a778da56ddfe4a383816b43b027464d7a28689fc4a6b35b36883d3f36d9c41f0177bdbfc8f258afe8da90f02d3b64fea").into(), - hex!("a2ab566033062b6481eb7e4bbc64ed022407f56aa8dddc1aade76aa54a30ce3256052ce99218b66e6265f70837137a10").into(), - hex!("b9c347c1c350fb7ef6ee9ca6780cf0604f30e3a74e9d0234bca6b3e7faed26148f2b736d9fbff6b04f5b947fda458e8c").into(), - hex!("815f53751f6d3e7d76c489f3c98d2b49214938cac8c2b417e2d17bb13446c285fa76fd32a97e9c4564a68f4faa069ad2").into(), - hex!("b3f1319ae34ad1d59207288f01d3d7b7e1bad7733fb4a819a09b011d72a4d736bd3c7afeb74cf56da0e00cf712042ad2").into(), - hex!("abbfb501071148e98b6aa56308197356fd993c93e27fd58987eca82036c1ae0ea89f9fb1a06c82851234643904c58453").into(), - hex!("a0899189bba608887c6cb729580e570ecce9ca7107865ebd30def867afaaa250bac407c30dbee11b7ef6cd423269a8fd").into(), - hex!("88e7a12a90428bb45bcf4b01442c11607433211fc2f9bee9545304eb66e0b4b5339360160bc782e185391385da7c5ad7").into(), - hex!("82714b00a822c30b317ffc1d4ba163990cc1ffe5769f91906a7f71ad1f62b39865a5314433a4ab2ba762b1d62b01003e").into(), - hex!("a3a930dd70aeeaff0f2e3790927d5425db40467ee106261615de5fcb937bb1621be213ccd8b3a14d96c5908bedc2e421").into(), - hex!("b2902161b565dd5b8e8c54187b26f01741a39ea8bc1120598661bd367cf8fc73e21eda2f0f6f9ba2270c80a59ff5985e").into(), - hex!("b77cdf45f39bf85ab3e8c8afa602f159de8352188aba5378957d468315a2d2326daef83d8ac6b227f1e7a514488afbc6").into(), - hex!("a9e573274f5a131d6c7641bc0576a2621b6466a5bf2cecb21058160a854b1b9e0be176da2b6b9b3ed562fc36c5f09119").into(), - hex!("876561bba29e656b7122f1cb51a02dff1ac7d470217d8a4799c01e61816c4660eea91843a5a42502ddf842d2daeb0586").into(), - hex!("a0ebae60a998907a19baa396ae5a82bfe6aa22cf71bfca4e1b4df7d297bd9367bbeb2463bda37aa852ad8fd51803e482").into(), - hex!("84a6edac5ac68a7ca837c46d5ada8fab136748b6c3a3b9165dbbc231ec386b15328e4ef7d69a15d4cf354135348a4ee4").into(), - hex!("8b476b3b065a3b95a3d11ec60a749c2258ddcc5885bfb50b8a086d3fd1e49ff73e1dde733b8981c3d2d206aa0c87b09b").into(), - hex!("b48490c5a3bc9e66cdc78994f7c73e0f2724fec8a304b4147799e5142396df155ef7c42065ed6d2c0393d138fb4d2a0b").into(), - hex!("849ddbdc3ac55ff22a3b2f4bc51892fed694490ab4dd342165ac38c725c8b38921eaefe3c443962925fc3726aa41e236").into(), - hex!("b49c45d9da4aaa64967c28f1fd77b7f709f5a331b58823eb1613856fd8f92635135981830a287e8dbda3a0e0fc481c5b").into(), - hex!("93ccd8c5f82374e0bef6562e16576f742d79b6f400e3485ef36e148088b61fbd882c3d2bb38ab0b43fa1dac77f31d543").into(), - hex!("81522576ae4ec9358f1a16934cd1c1116de609634e68f552924a972101eb7215f037ab8e0582d7b13541537d55554d31").into(), - hex!("aad60e58a19598c5013b37e2e4adc6721eaa7e6e184960d1dc4e6f012246abbb58a047c0679064d5eaaaaff02de881e5").into(), - hex!("b4f034f2b53ff9989e8a0f12c1484c58ed7942432a429af58a6659feaf23f7d2bf20ff7b9a7e0a28a2e09c9a730681d8").into(), - hex!("88b2c68b425269850c1a4f4608aca194da5c641adeb99e2f7fb92e34b8245dff066e73bde072be60f7f2c3d3d13de3b6").into(), - hex!("a749ab53fc2662a0796489be84fcfa59bb723ff748bd8980df0cb4b3d1e2943845b0d7c67576fa0a33c8b0ff8a86932d").into(), - hex!("abd7248ae069d3a3a45b0ef4dd5d7d54b62994e578ea20bdd3b7876596673953b94c5b109a6e4b953b517544b915368f").into(), - hex!("a49da42c27d019a21cc6489ada7b712b98c4ede28ba25dbcfa916acef48446a2baf73e03a48be763378a09774d4a03fc").into(), - hex!("b3c36fa39f668bbc3fec028875a820057dbf96f727bb423280da96d5d50e885d23bc23fb73457bf79089691ce7663a7b").into(), - hex!("8dca376df4847cb8fc2e54a31894c820860c30b5e123b76670a37435e950f53312f089a8e9bd713f68f59fd1bf09202f").into(), - hex!("95d1f944b0c53eb3e9fcd5632713602bbb9195b87a172a370ae2df98504612a55f3968615a39b569ce6a0fe9fb559be7").into(), - hex!("8c9fefe233d0d657349b7efcdc368f5aaead27071d224af780874751e7d241f6b88f7650fbb4133043b24bbebc12aa48").into(), - hex!("a2ee6c29efa982e9b9abd3c5e4f14b99d5d0369d7bfc3c8edae1ab927398dc8a147a89e127b3324d7f4e3a7494c5d811").into(), - hex!("b7ea5e0d3cfcf0570204b0371d69df1ab8f1fdc4e58688ecd2b884399644f7d318d660c23bd4d6d60d44a43aa9cf656d").into(), - hex!("a07826925f401a7b4222d869bb8794b5714ef2fc66fba2b1170fcac98bed4ba85d976cf9ee268be8a349ae99e17ac075").into(), - hex!("b0a47515752c15e4dbeaf9ee27fab3b5c0db82f5c685e8f716fd7d8764164944340430fe3db1a5679e6ffea5a16dd919").into(), - hex!("b7de6d7a4afb05984dce153e5570b104338265e45c8f0156f4d45c458f47add234a479e01c02d3c1817c170b5b65b100").into(), - hex!("acd4d1e11f81f4833353b09d4473ec8b15b8ff31dbf39e97654f5338a26c4020306d51018f1f4b9c4efdb92992408a6e").into(), - hex!("80e09f3bf3ea87d48e04b53d8f3b43b7e53d61f445f8c8a5a35472b84f6bb4f58f17d9832f5881bb44fc06156151e5c5").into(), - hex!("98d6d46f603afebcbc561c130e416d5a588a7e6c1f17f89ed6e30538b7f8dbf4b3c75b8a3331425c4ca21e03fe8b57f3").into(), - hex!("ab671eb947490c43fd05e42a787344b21af89babb705393c82748eaa0cfcf80bee498d275a1eaf1d647ca3b2923d76ea").into(), - hex!("80e1dbf3296bdfa98aeec1a7560682165d13bc628061bd3257f345aa1ba13f8bd1bea14f117af562be22118f5a8265af").into(), - hex!("aef456af90354ff88039d2dde02b0f5a6790aa762b23e0a9da8c6ec92c3b8b3320687bb21666608b4a22615843afd1ef").into(), - hex!("a5a07bf219432e9c80c38596c93560b49c7de287f31e30b7a06fcb4d15982add4a24085adbc5b753c462be989c64c96d").into(), - hex!("84d2eb008578aebd6f01254b7e46584c1524e6fd7a5a2ae5fa0ea560865ca50d52290cf2d12dd20b042f402e62181b4d").into(), - hex!("b8e5226ad3515627ae6840235f5f7b7ecd54e8f01079c324d126ec852f6665ebb77168b3f2b3b51580e04a6ff602d5b3").into(), - hex!("8c1de4264e04ff7e8282faf81c0bfb5943656451be52170211cb7adf4ff21bccbb789400735579c622f69982fcb8e9c6").into(), - hex!("90bfbe37ac3992432e68c95c0d4342a9712126d1f50089239c9f4f6c0c202b54334e08604d245b97dc8e8f6706f6992c").into(), - hex!("b0a771b9a0dd7e352d46c8efcc1834e610dd097711bf7117678a99d386890c93b9b901872d4dcacb6dcbcf3aea0883ea").into(), - hex!("a4eb903990bee2374b14fa66fc262d6821669537e9ba241c87b4b5c9e2b89b32fff4bfc28ab8471ef52e8eebc3e743d1").into(), - hex!("a6b74c706b33d3cae9b7adc5c7502ac98f7bf94a14d579d2bf77b613ae555634ad6fe631ba36dc14bf44526436355e24").into(), - hex!("8296f8caf58316af535def398a43357e48cb3b1e674b857eba1bd1b970da3dd045e22fe6d17dee4e9117f62ece3ec31c").into(), - hex!("a129c9cf33df42b5a98ad98be9d940207ae154c715d3bde701b7160dfe45304679fb0481a4f9dde242c22a9849fc2d9c").into(), - hex!("858b6f1bd3e68fc536bdf1f4bd96db032994eb76e71571e2d85af73b898478b82f9ab432732b0beebc0864ad8025ae33").into(), - hex!("8658a15df961c25648fd444bdf48a8f7bb382d9212c0c65d56bf9cdb61aab3bd86604c687fb682260dbc0ad2dc84bf01").into(), - hex!("a8d152e5d94b75cb9e249230db21af31de4d4f3d4ef60ccbf2212babf69aed2a38435a993ee2f13cca410ad55a4875ab").into(), - hex!("95757096c132e7f6c096d7b93a5a0d2594d5e609b9f13c4a9f878e95a389fa1a111b185dc1fd8f7d98b737dcf8d2af60").into(), - hex!("a22542a4a2ebde18cc6aa29d5dace8b4f6720703f519610dcf01e671018392aff15728e3764730840272c9cfb074b612").into(), - hex!("8f90e72a54e6894d511061957162e753010812346afd4d90cfedb678b99ba1aacf2b6bd0e49b4b0e684da8082a048619").into(), - hex!("b2affe048c187d311a185503d8958cacbe03796edf79bc32e8533941004d9178bd2e376e627e1ba61ed43850c0c455cf").into(), - hex!("b549d272a7f3180826a978d747507e4dc80d82784abb655cfcd3a69cc72e7d58c70febea1ce002a89852a8f934ea70fb").into(), - hex!("a9ef845ab489f61dbfdcd71abcc29fc38f3494a00243b9c20b9cd0dd9e8a0f23304df84939b9652cdf5542d9b3ee085e").into(), - hex!("aa744c552b5fc41e1ac6ca53184df87a1b7e54d73500751a6903674041f5f36af25711e7bc8a6fbba975dc247ddad52d").into(), - hex!("a802b9ffbd4f01b877791aba27da972be4bacacc64a1f45687be4af01b84bd4b83fe2ba1ea78e29d7683f6c777ab2543").into(), - hex!("b44d2d9510516c0abb4fc101241cf0e0223b179fb70686519628c27f0ef56381232961bc79a30f592ef093ffecbc4486").into(), - hex!("a684a09add047c0fe648d9c5618500d1816047168e055e8ac8c952c3544a462cc095b32fab07d939947a58fcb4ec7ba7").into(), - hex!("b5eb31e5cba0193e74968099ace5808dfc457c6f404f270fdc4949b60daa7607ba1811abab1bb19fccdad61d489b6657").into(), - hex!("a10f19657a9bc5a5c16ebab9f9fddc3f1d812749cd5d80cb331f51de651873ff899e0670f1b079b29a194572de387a17").into(), - hex!("af61f03e3ceef5bef36afa29ba2edc7a3b01ca26cec2589edbc9d124dd46e41410e0e3afbae959c83a6f839bbcf8049a").into(), - hex!("8e6bbfe492ecbbb8dc8889d3dcd7037a58db605bc6bb79131a72a9b9c1bad630e75f5e5e0c1bc407e73f3d13b116739f").into(), - hex!("983fc1ddf17f9756c9cecc00b39bb2ad432587a5c6d1c3296a383b9f539c9afe84c6c818447a709c0b686ba26ce5ea3e").into(), - hex!("8d52413f981bc611427ad0534d25e914113d0ebcd6960aab6421608bec6648b89ae4b2ca2153c57d3cf4f1f37212aa5c").into(), - hex!("ae075b66e5f211c2149c45b211d1297bbc1d9e6497cb3315363c492a9a51ae5b9d0a28bfecd755d68553736901ac6606").into(), - hex!("a02f7fec0661394399a82b2e3151009160b3f5392017ba579b301ed42c85100c295acbfed46b6c58a9d71796ed0930e6").into(), - hex!("a3a7196fecd25e9cc7cac79c35365676e48c7be1493df255676adff2209c0719f2190ceff3ce008d08efa07c244c11a6").into(), - hex!("a5fe3dfb5031517bb8db0d5ade1e9f438e84bcf23221de003b03d2a2f4ea97629e81c79abc3769bdb8c69a512c189b91").into(), - hex!("8cd9d7e953c7ae07ee785d68a999e702565960d376692d9ea468556ad141229b1f3bc97926818c078901f73ecc578e93").into(), - hex!("81d6fc2f01633e8eab3ba4d72588e14f45b00e68ab887bdd4ec5e8558965db21189310df973837106216777b07fc0805").into(), - hex!("b75ac3d5b3dad1edf40a9f6b5d8923a81872832eb3a38e515539cec871a353b07cb477f6d55cf15ba2815a70458aac32").into(), - hex!("94d3c9406dc6dd7241a726355643d706e46b35f1ffe4509ac43e97c64c07592821156ba02ec9a78978e66709995a0ac8").into(), - hex!("a3b109249ac2900806f0f39338da72d4f2cc6d1ac403b59834b46da5705cf436af8499fa83717f954edb32312397c8d9").into(), - hex!("8336744d8ef3a3bb3e9ed3d6b83e08cafffc76b7438adedd3a7358b32acec0e73a4635aa3166362ab4e158e68576255d").into(), - hex!("99b74edbac662fff69ba412de466a427a928ce2363c9e59dddd664f6fa50f2e1dd3d464701b01784aa224b3d96dedea3").into(), - hex!("b397ed7134f447d9bf1c511bf92f2d27d7b6d425b8b411365fbef696cff95c2175461cf5dd83d93bb700e50ebb99b949").into(), - hex!("a3e1fe11f38d3954a7f48c8b68ff956ea0b6f8a3e603fd258c9406ec2b685ff48241db5257179ea020a83c31dc963854").into(), - hex!("949cf015ce50e27cf5c2ff1b8e2e066679905ac91164e3423d3fb7e05c64429e77e432db0f549acb99f91fb134b6edad").into(), - hex!("a1c0c317e6e352e16e25c140820b927161ce5d2c4c2e10bca3057ba4d46b4f42ad7aba20de86dad9fc6368ea92695268").into(), - hex!("8d6e3df29419bd0da1deba52c1feebe37744108685b49ca703e1b76fb4d612e3959d3b60b822506e5c0aac50b2f5eee2").into(), - hex!("a15e0cb96a463ab81e661ca44c619b71a159680bbc04707ea5a5867ff38b15416e3abe55d2fabdab9aede1f157dd37e1").into(), - hex!("b6d6482ad7b9b412ffbefbbdcc28eb3d091b1291f54f77bdd53c4ac85f705c454940f466dc272dde7b03c26f0cd6ecb3").into(), - hex!("8391e3ad6ec2686bdc686671d579edac2d5efa8cf0923577df28fe0735e4d5103173d44452816e3c2b2a7fcc1fcc20d9").into(), - hex!("818202d7cb60e4148c71633ccbe1ce311de7b7ff93a1988e86ba29cc58037189f0f275b3323a6719dc9bdcfbc49c35c3").into(), - hex!("a7c0fcc422c6da878926cc6763ae6ec685a5d8fd1afe61269957be6bfb3f1705a8e4c6e6d85bd15636521f5a2ceb3a00").into(), - hex!("8f7bbaaac458bada6d852fe665c87c646133bab16c0d5136c3dc922095b9d647d93a9de7671cb7bfd4cbd138ae0709d1").into(), - hex!("b6e9fe9fa3d4c833c3beae7f798f30f07e3cdf6f6c8eb8e2b70cad51b37af2549dc9f2e7f97f194e5897d4dedb904a45").into(), - hex!("b455f751232de0a48440d09983f4f4718b6169907979c9f282acf7177ab5b1f338fe1f2acd8d0bee4b4aad61d0340839").into(), - hex!("8aadfcf3562f1c357068323352cb1745349a27a7362358d869e617c2410db747149b993ee9e881e252ecdd42fd75f351").into(), - hex!("91bf4c32fa8888d3829d3c33e12550d2ecb70762d5eeecd044d4902e4a7f8b7a2592cf6cb7736eb6bd9d312f85c2777c").into(), - hex!("859426bf6211e68924eefdb26cdc168ac0deab291aaff7036163997bff34d45809932f91e12d113784c05553ca773b15").into(), - hex!("81730b4bc5f755e5b99c321a6996c65e57ea2ebe6c0e4e404ed30920194fd76db65304635ad054a8b25bfd982cead47a").into(), - hex!("b26f5ed09f7d5bb640ec94ddd1df0b76466f69a943b4699f53d45296d5d6b8010bb61477539bc377d1a673d89074d22f").into(), - hex!("aa65c11071be23c9bddaa5203f3166e5cf043efe5fb8f4b26f8a9cabe71db701a450e79eb001c401da5752755d9cf1af").into(), - hex!("a019370ca799c2c98a605850910cf43531bfb616393039fdfc370848feedd3339b2427b750ccc91952b03a09f690e9ed").into(), - hex!("8f84cba7ceb7652023fc8ebde4b00ecde1f550935bab12feb630d6f49517b4148f3cde184bf55d4f6ec99a849fc6f862").into(), - hex!("838733220d1559c800cf1714db8a43a67a0c0d1d3a9fc1e2cdcf615d20406501e5146fe8b59bf64f4c5daa1a6d74f15c").into(), - hex!("9708cfcc9ff95cf23f544119e17518a338575018f153b1ef50118da0681304919a226b2089a417c2ab7b4320dffafc2a").into(), - hex!("a988cfed9f481bc98beb5fc188ed3f6893a3ebba27c3ebace669792f6abf0997727023c3b6930a6421224f5b257b8b49").into(), - hex!("812d3ded3a3c9e58eecf13a29bb4cc13b01b2a0af322423a29bb0e4f6d9021d1d87ac4af7a2a6b88d34f44a8bc1b3c55").into(), - hex!("b2baa7eba496ac4ef60ad8ef27a9677f9507820d95a1c572d322621c4d0226b36146bfc3a9ca1645d123acbd945de3f4").into(), - hex!("89ab1e5c2565f154f92c9b3554160832d176613f1a2f872b6ed62ed925a33fb0b40b71b7443eaaa15099ab24693c8d13").into(), - hex!("8982534f2c343dda20cccf5a9c8bf98240bba5f4e8eb2206e63a1847097deadb6bf0d24b358014d564c5ef1d0448c43e").into(), - hex!("a1e47798a782a024da340d6d6a1b1e5e15a0f2d8668adf349ca375086964414a563cc1eea3226ae637f87e78c0a630b3").into(), - hex!("847b58626f306ef2d785e3fe1b6515f98d9f72037eea0604d92e891a0219142fec485323bec4e93a4ee132af61026b80").into(), - hex!("8368a0f17c8427beb71dbf11a09a2fe8495a33f08c29c74a9a996a88aa01c0a09f9555abeb1ef1592cab99a9e05875cf").into(), - hex!("b38e558a5e62ad196be361651264f5c28ced6ab7c2229d7e33fb04b7f4e441e9dcb82b463b118e73e05055dcc9ce64b6").into(), - hex!("8018499ef720e28759133033833edfe17ed23e42f99058bb79fe844ddee823cfdc43916be2dc9724d18f9726e6f1b409").into(), - hex!("aa9b9cc039d147677aedd1e47ad9013fcc0da0164070ff7305b18e5786c7fac0471368637a3adbb78f3af174a5c1592a").into(), - hex!("a5c0e42851b769d2d822e39222e708068455aae3bdf782975b59d3201e67a58fd66e16d380558bf2086bcab890a92dd5").into(), - hex!("af3f765fd293c253072b33a780ed68933f78d7e079d9a2079b6232755bedf6ebcbce9ba65c01f695602fa8ee17899867").into(), - hex!("8a0192ef0903d7a5ed2e5614a715901f2554b324ee72390974dc90727ff08dafa580041a21a8e6c48a3e08e1b042afab").into(), - hex!("907c827a4fb5f698bf0e6f10ca07741c5b8e3ecb26aa53f938ba34ceb50c01be80c4afc5ac4358a5fda88eadea0cbe73").into(), - hex!("a35ee5c2d7800489723c78008b495e1742f0542dbb487172ef438f60424c81aa41c2397095821248066140662133f6f4").into(), - hex!("b1925ee53c9228cf80e2f5ac0117008a91e98d878f69bf03d00d873ef45f4351cb6988772d89d4ccddb40778d11e0dd6").into(), - hex!("95aafa379cc6a2b4bdd0cad30b7f0a47839952af41f584219ec201c6c4d54610eb2c04b67b29080acb8cecc5e7543fbc").into(), - hex!("8f44c43b80a3c5f488118859fab054745cfe5b0824821944b82fcf870fda6d93489ea9ca4220c24db2f4ad09c6080cb7").into(), - hex!("af861bb21f84c3e7cab55370839d18ac24c475a9e833607fcd7e65c773ee9d64bea203ee9e8fd9d337f1cd28d5ca0d90").into(), - hex!("8f6fde2ebbd7682c69026069cfe93aa5410071f05de9ccd7070c8c3299a6539b39b3798f01a0b4e9b1330510bdb51de7").into(), - hex!("a35d9d6d5dd5428cce7616842203b5fa3721cb4b20f50c0113f138604954fe0cf214ca3d065b578f921054b9efe823df").into(), - hex!("8d562d6c0e0d8325032e1fbf836022c82a8f600a6fbb56c553ee5d1fac0f052c7ce2504c0fd48c9fa6494a6bff63c9fc").into(), - hex!("b02ce594310f1eb8acc92bb80de524a43e663e12fb64fc28291ff207f9d8ae761631416410c3c8f4d6890b8b7e6ed24d").into(), - hex!("a258f8c0eff666c2bb70e505544c3d10d6b258310e4fb2206fd0999f69bfb739a1e232d1e810e7206f490f6c44f6934a").into(), - hex!("a8a77936ca91df3b2ee7394ea821f2bfe91c6ad8193f44651466c170b6ecca97ab356fa7d947ebb4b767e8967092f143").into(), - hex!("88ad79a0320a896415e15b827a89969b4590d4dfa269b662bdc8f4633618f67b249f7e35a35884b131772d08025bfc32").into(), - hex!("a3c66439724d737d20a640bceed8671b20cf6795671b6d442ed1ea5eda6723ae559396c24f44e982ba7751dcc6adef5c").into(), - hex!("8d0e6475acfa2b904e7d53bc7acd070a2ee4894ff5720a20e560e9ecb7872ea442a51cf2f2eee4bef66604a5c08ad9eb").into(), - hex!("804c021152c3304853941847e80480fdaceba3b9676fbe018268cf77d1a1856966c2f9686bb4d4aa0c4118a7e85f83cc").into(), - hex!("a6565a060dc98e2bfab26b59aff2e494777654015c3292653ecdcefbeeebd2ce9091a4f3d1da10f0a4061f81d721f6ec").into(), - hex!("8d5de60e934ea0471d9e0a46489f21e03abb9722f5b3633631a9a099b9524beac5d67716969c83d824498796d9c106b7").into(), - hex!("8c5a9f6eb0a3ea95e75362b06e5cd23968447a212cf22e1419c984d74432c51d290b717f80e8ed3e76b1232216f99758").into(), - hex!("918ebb73eef984d0ce28083306626d04817038056aab4a82ff9ac8176ffdfbf3173c0b05e936daf553248b323fe54f56").into(), - hex!("8f9aededb605db4e499d3c383b0984b1322007c748dea18dc2f1c73da104a5c0bece6bb41d83abdfac594954801b6b62").into(), - hex!("adb198f70a7f1969ed0958be4a9a60dcc1806bced79c63692b9aad6c5648ffea1fed60b24bf4b1862e817cf229e93e83").into(), - hex!("b118f77f99ac947df97e7682f0fb446175185b842380af4ee7394531e4f93002c72b41a57a7c1b923a4f24b10924c84f").into(), - hex!("944f722d9a4879b5997dc3a3b06299182d8f68d767229220a2c9e369c00539a7a076c95f998bea86595e8ec9f1b957bb").into(), - hex!("b7270f33011db1bad18e076a162d6e53d9123808609773eb46e3a4ac69c84c257407907bd5d05b6eb5e926b8d8c6d884").into(), - hex!("b09c0a505457c6b473fc7b2d634222905b36a6ffcc015dbdffa3bd62218c94e891615e77f28e6e18dd8474be8c156695").into(), - hex!("97d076617cf0a64ab3d1f030cfd72a303b6b252c0a7b96157ff7fc8af5970f00d14492c46e8f6f37caafe837d0dc95c7").into(), - hex!("b405520ef829a2a3b8947f1687ab56a7af4026c1a6f99f59aa192bc4f3b12a2de407862ff74ba1b2c51889b8d6b090c7").into(), - hex!("8bb045e7482b7abe670d72eb2f7afe4207b5a3d488364ff7bb4266f8784ea41893553a4bf7d01e78c99ed9008e2c13bb").into(), - hex!("b2df29442b469c8e9e85a03cb8ea6544598efe3e35109b14c8101a0d2da5837a0427d5559f4e48ae302dec73464fec04").into(), - hex!("99daf03fa434a482d9aa4d090884c99b7208c1f5380b9acbf304e1bc33d3d6902afa5d248d20ccf03795e26901356ede").into(), - hex!("b60df25a7ac1ad14aef7e8809c4bfc190b715f94f14b0534cc2e4015ff6c322883cbdc5309e05d67dca4bc641c69725a").into(), - hex!("b46a818f3e492e231d8fa8de8848c16f0d648a2e0d1c816adf9306a8596fdf45922e59cbf745430570a19e54f45e28f7").into(), - hex!("b3ca2ab7d64b71e40693bd3e2288a1f78741a139403c783d259cb9dc9c29f16c00796b6302cdcea4a4314e132b4f9d1c").into(), - hex!("af3d3dffbe55842dfb4417295a6ed1a82d26a579199494b305445215045785759be4cb57dc870c7ddaffbc101a854a92").into(), - hex!("b21785008910a949804d1291e7533752641d31beae3cb518806488f81d58c38a5efe5ed9534ac692e68c3121e2f9d97d").into(), - hex!("ab7eff4ef8696db334bce564bc273af0412bb4de547056326dff2037e1eca7abde039a51953948dd61d3d15925cd92f6").into(), - hex!("8bb4d08318386c91a0136d980a42da18c05743a5c52a861ce52a436e66a8ebe472dac7f7461db32ea5da59a23e9bd6c9").into(), - hex!("a1c84730a5c41dcab9a5ef9e1508a48213dbc69b00c8f814baf3f5e676355fc0b432d58a23ad542b55b527a3909b3af6").into(), - hex!("948f808c6b8e3e109a999657ef966e1e02c96a7aae6eecaf912344e1c7bf7ea51c911cecd3cea2b41ff55acc31df9454").into(), - hex!("8d264fbfeeebb6c4df37ff02224e75e245e508f53fb3446192cd786ecf10d0f704c4fc2e53e7f7318ae1407e46fc0fb8").into(), - hex!("8d47a7c2c62b459b91e8f67e9841b34a282ceb11e2c4b0549883b627c8526d9e0ebd7333ba70630bc0ec2478114b6ae8").into(), - hex!("a4348ad30c12bb7dd03dd014cca599c3499ddf348e7795b0392a18f998289979478374e374a8297b5b6c427441e2b5af").into(), - hex!("92ec1aeb2aa24c51cd5f724972c8b6095e77b237d83f93ed34ca0bc91a1dbf1ad95adccc59e0f0abbfef33f331f3298c").into(), - hex!("941f73b2138b4347ecafcc7b8c3d03f2a54dc49f580394ed08f22b0878ee7cb63d42978f1d320c09e7dbc67648c06f8c").into(), - hex!("a308ed8737b3a9346ff20dc9f112efccc193472e6fde6aa218ceae11e288bbd2c35fa45c1d8bb238696a96767cd68b46").into(), - hex!("8eb03001ac9e22c6956a682ed458e650785c36d23ddbcd51ac4d9cc991325c02519ff1958987a08eb29ff56ff6e2c293").into(), - hex!("80637db55287f891baa0e865d2423191b9a575620bc4493ea76166d47b99fd89ad8625c21f446b01e3ae17292c78f7ef").into(), - hex!("a5b3da08aad945effdb645c797a0a8bfa828c9d658df2783a214597acebda3ffc07ee48d0ce1147d77540b557d9ada91").into(), - hex!("8d5e0b8cde1f62cc8f15d9f596e31de09c221da91b10335b92ef1155802e742442def161223333573158723f3408bbd3").into(), - hex!("931923f0c1f75a197e6244d67525b524ceb07510a6aae8cb3d56167cc1aacc76d26fadfa1bdfc55d8439c6ee4d4d8174").into(), - hex!("963a298fc8876b702424a697929c7a1938d298075e38b616c8711f1c7116f74868113a7617e0b4783fc00f88c614e72d").into(), - hex!("91ead7dacf43905eb5d4b179af29f945479ed074126bad3b5a2bbc1663af5f664fe53a36684e9389ab5819e53f1344fc").into(), - hex!("b8a6c999068c13fb71a99d75eabadf7edd2d32e28607baf001a0aeec412fdd3575602c68d3feb4d743b90396705e37f3").into(), - hex!("938bbaa0ba14597067ff4c0a7cfc1529c44160d6f61cfad12246526d84fb7a1ba964d3bbb065a348cf7a98356ee15234").into(), - hex!("80e44d3577f12cabaed7074feeb57162ff80b61f86cce8f41d1d1250bc455070b09f6ea9d0c263b7b4824701480f4c14").into(), - hex!("8d74f4c192561ce3acf87ffadc523294197831f2c9ff764734baa61cbad179f8c59ef81c437faaf0480f2b1f0ba1d4c8").into(), - hex!("a0133deca5ae8f1100df8db69920b2d0c31aa21bd3849dbaf4c264eaeaec8937ab8f982770ce1ea17e0e258910a56d02").into(), - hex!("b6a25d493d708b035b853f1f7a6628d8e0b205d2678293f763d7ea4da11d298539533b22b43ed2e5f708648556f3094e").into(), - hex!("a58c3a4ba86d0d6b81c8411bb73a528b4f3bc2debac0e0208f788c080a3a96541d57c927143c165f595070afe14b0517").into(), - hex!("a52c15840b89d92897d1e140b2b8468a88886c5e1092861e598b3a433b340ded5b35b3d632a9879820fd56f20ca3a68b").into(), - hex!("8c122bea78deee98f00a86184ded61c10c97335bd672dadddc8224a1da21a325e221f8a7cfd4e723608ebcd85a2f19fe").into(), - hex!("87a51e0011dd0488009baac9c611fbde01878f9cf1584ea407599742bb32ef10586d9040dae3e9800a125de54f80c047").into(), - hex!("98181e9291622f3f3f72937c3828cee9a1661ca522250dfbbe1c39cda23b23be5b6e970faf400c6c7f15c9ca1d563868").into(), - hex!("b01a30d439def99e676c097e5f4b2aa249aa4d184eaace81819a698cb37d33f5a24089339916ee0acb539f0e62936d83").into(), - hex!("830e70476c6093d8b9c621ddf0468a7890942589cae744300416639a8b3bc59a57a7e1150b8207b6ab83dafcc5b65d3c").into(), - hex!("83ca733849830cb8fc2ef469e7e464fd94def561ce49ff0aa352a6ecd0e52c7aefcd69ab59f3d1ed2d5b8536d0a7895d").into(), - hex!("b76cb8cb446eb3cb4f682a5cd884f6c93086a8bf626c5b5c557a06499de9c13315618d48a0c5693512a3dc143a799c07").into(), - hex!("8b027c14affe47f83ee59b504d83b2fd2d9303de2c03ee59d169bb199d9f4bd6533d7f8c812dd7a6f1e8155e3e185689").into(), - hex!("8e6b888197010ebadd216da35b9716daa8675d93b3c33a96a19fd9ca42624f6b430b2ff115cd0f5b717341605dda24bf").into(), - hex!("b6652440bd01316523feefceb460158cd9ba268dd8dbe860a0271f0176230f057767597e4197885ba907318ca202ba06").into(), - hex!("a0b3dff15982a38a2f56d8c6cfc5c5543c045bf2db24571d23387ccab42abe2756f34d5f0bf6a426bbad3c358b8bdb00").into(), - hex!("a8b593de2c6c90392325b2d7a6cb3f54ec441b33ed584076cc9da4ec6012e3aaf02cec64cc1fd222df32bf1c452cc024").into(), - hex!("96b478b1e5e49d4ea3fd97c4846ae0f781dcc9f9ff61ee022ca92c3d8dfba89c513c46e8bb38b73e6b678a79b9b12177").into(), - hex!("946d585d7aa452d37a8c89d404757c3cce2adf2410e18613483c19199abd88f7a12e206f87a43f6009e42f4e31ed20c0").into(), - hex!("8c432e044af778fb5e5e5677dbd29cd52d6574a66b09b0cd6e2a5812e71c91559c3f257587bfc557b4b072a822973a60").into(), - hex!("ad2cdae4ce412c92c6d0e6d7401639eecb9e31de949b5e6c09941aeafb89753a00ea1eb79fa70b54699acbfa31eda6b7").into(), - hex!("b504cb87a024fd71b7ee7bed2833115567461d1ae8902cccd26809005c4a56078617ec5d3fa5b29a1c5954adc3867a26").into(), - hex!("b8876bda1e709ab16e1347a1107852a7898a334a84af978de39920790b4d82eb0739cbfc34da1c7154dd6e9f7674759c").into(), - hex!("973dcf44ab60f55f5d10a8753ea16db9faedd839466a130729538f3a0724f00f74b3ca1de16987d7c6e24e9467f62bc7").into(), - hex!("94df5fe87661101a89b49091a3d4de89331cdbd88531ebb08a95f2629886ee53b3dcbcc26bb6bc68b443303d8d397141").into(), - hex!("a92beb343caf6a945990adcf84302c55d1fccdef96c34a21f2c00d3e206a9b2c6c6b412f66e5d4fafe26ef6446cde705").into(), - hex!("b298aa927713c86adfe0de1a8d6f4083b718c8be27156da9fd11abd8edb3a54a926ad487801eb39cfc9363a0a3be0d44").into(), - hex!("b34d4d2e15079e7e80fdba30cddf4fc0e6c9a61f7ab06a6ea0a4e55fd5bf632c6d72e021d6264d935439d321de883bb6").into(), - hex!("b4a86fb5b0049718caead1bc036833a2caeb88e1afadbbbcb0cd021d95e1f33fcc916f0b97fc1b9226c37050e3463796").into(), - hex!("b6cec65e5268818c82c0a4a029b02f8d23de98b68730a445119fee670118eb34027c23c987fac950f9b0151631328a4e").into(), - hex!("880b4ef2b278e1b2cccf36a3b5b7fbce94f106ed9fa2820cb9099a7a540a57e9fdeef5c0fb0a743049828fc2b8c46163").into(), - hex!("ab2053c376c6bd113b89fdb2ae3b8401aa891135345885730c61cac7813f69ea7d906c531be752e28657f73af92d1f4e").into(), - hex!("8fa2d7b22af8e6b82679ebdfa13efdcb34289a554653ea6c1b16efb9f957f7fe64df787e7b03d8cdc8a732b91c916bd1").into(), - hex!("8e825c03c8409a3302266dc5f47fbfc381dfbafbadc37bd8d40f079ca8963d4c5ae6ef0d0ba6aef2d4688736f5f6bb45").into(), - hex!("a40ef3d2291d8782540961ce285054678b3d322d3cf7fc154207228c290708b1abfc37a4d7762dab3dfea582a112444a").into(), - hex!("8dbe8fcbcc414eb352245c52549973f73d987012de9d5f2b2f55dfdc43cf8cc9ea6b147abf149817f80f9e15aea566c6").into(), - hex!("a7e8775e04214e3b9898ffb9625dc8bcd1b683e333acdceddb8ca6db241df08a7b80e9d476a711b8b7d66aefca81e9cd").into(), - hex!("8b6ed54668f78a4a7624683b9bf3abf2bb0b6dccffccd8c0967df6297dadaf51732800fb9832b069437a6bf82ed7e6ae").into(), - hex!("9437ce85146202d3815df7f341a182678665dfb74b96006dc9d6acc16110d00b4a02717b702a765566457710ff5a7280").into(), - hex!("86a790072efa2cafa97be4b6b31f8c533f3b20cf3922fc0285fd403da436e4c49c65c5f08d77bfe823526c67bb58fab6").into(), - hex!("8ee8873de7cd28a54ba2c63a80b63399effed76b154e96ed26e7c0668b9f2476e298688b6a00c4b2ab9d020a897695d7").into(), - hex!("975c3261f0f32d59473e588f89593be38f5694cfa09394a861e4330b7800fb2528ea832106a928c54c76a303d49140e2").into(), - hex!("b5222582ed6604b9856a48039bd643340f4bf1bf0fc805e8453a9eb7630d6cea1452d28536706d6fa3ec16617617991c").into(), - hex!("b75c28941ee3f91b3535b4eaa0fb17b59ca65b5256601a1f6d0cf2bb4d66837fd16e51d6942856679012a5730a66e519").into(), - hex!("97b510f9f46bdf77a002b2403d8e42b6d6ad5329ea080940844429763ad3efd592652789c8d3d4fac0903c705f533cf7").into(), - hex!("a3fd9d8bbdc98394883022299fd9793e0c4f374d8e40d6ce89b2869d3173cb6a5476371d6095dad068ff217729f60af4").into(), - hex!("a57d5de556853484b1d88808d2529450238bc467376ded84cfd7b4a1ba258f6d43b5958220f962c57b033abcef1d5158").into(), - hex!("8465bd8be9bd9c2c6116d4ae44ec6618c109cb9aaee2d241e7a6ed906d398ef15a6fc18bc8b1d3398184241405954bba").into(), - hex!("ab1cc44983e46a6ea2430aa6616ab28614f43624665e3e6ae31a9357c0c5434f34e56c720906e184327693cc4ebe1fa2").into(), - hex!("aafe14dd3b680f096010788226d8413ca628feedad79a2bc78cb04d47c6ad910f7f46ca87b8f8281744625d8f42d5eea").into(), - hex!("86a533b02ae929f67c301649a2d58651b98cdffe731b63fa32aa1013c271634bbb088c0d02865913c11bbb1bf57c0e12").into(), - hex!("b28df3e04bde4ec373171401dbd0546f4cb6fa8e9a4a8019aadc653d4e05e0b5b9a64417715dd87f6df9e7b3145f6659").into(), - hex!("ac63fc758c1a3bc5cbff0f5e0b5a07a5aa801363b129d4e0360165c7dc1057ec37b0d808e9fd6b179e2c1e66bbc6090e").into(), - hex!("93f941b4fe6c05621e7a651b87669eefd60b6e8a4a8e630a51fa3fee27417b9eebce39f80a5bade9ca779133ad8388f6").into(), - hex!("96d7a69eaf2761bf0e5ebcd607b134d5dedba8e262ca1d6d3e8fbf23e6419a8ce1bbe4cd23b9e4b5f80db54a802a9795").into(), - hex!("8b62902fb2855300580e94830a4bc825d997ede33bf356fe3b7c08d6a8bd85a37879433fc6bee58f9b44ca280f4e8dfd").into(), - hex!("b043156fcd02b75dbe940c763fa8e8a7c7f6d74c1d5395db5ce544af3b6097eab61686950535a810aa95889ced12f74d").into(), - hex!("8614a7599c8d97aa9ca63b876f677977cf0daa969ff2a9a153f297a4a46e08fa5d91492995de94dc32cf009ce6bb5b5f").into(), - hex!("81351fd284d6d07092875f366bc5e53bfd7944b81eece85eab71a00443d1d2a9fc0337aaf34c980f6778dd211caa9f64").into(), - hex!("8c722aaf5d5dad1845056bf5e56dbff0f8b501f4846610f99da01130a49c96db9962bfd9be20670658cf276cc308be08").into(), - hex!("8effe3fb27c9f76bbd78687b743b52e6f3330eddc81bc9006ca81fd640f149d73630af578694f4530833c2151522dcc1").into(), - hex!("a3d327f48eb34998a3b19a745bca3fade6a71360022c9180efb60d5a6f4126c3f4dfa498f45b9a626ca567fdd66ffbff").into(), - hex!("a59a59db246f981e9c8e54aba52898c714d9787fef8969a6d8677fe6dec82950ff22a1364393b579f3e596cdf5bcd7b1").into(), - hex!("a15ebe9ab6de62a4d1ff30b7fc58acfb14ea54d7fa513cbcb045af3070db22bf9c1e987fa26c0c54356b9e38fa412626").into(), - hex!("b58396bce7d32ba6c70adbd37156d859e153c1932d2b0c7c874a1182ba831439e80d6fc6d7d88a870e193f515aef2264").into(), - hex!("b666dae42ea858c9b7d903ea3ca5279f619c71ac6e3fda7469e2bbba08c7e8e12d6a3c35ff2c6383673b1b7c21db5e0e").into(), - hex!("8eaaa21c8955f15bbcfd5756421a045e7b4825576379cc6229fe9751f7a7738b90be19ba52261db01c1e13af955675b0").into(), - hex!("8027bc62b59f9f15613e38da74ccc71fc3eaee26f096d187c613068195ce6eb64176013f2d86b00c4b0b6a7c11b9a9e5").into(), - hex!("8275eb1a7356f403d4e67a5a70d49e0e1ad13f368ab12527f8a84e71944f71dd0d725352157dbf09732160ec99f7b3b0").into(), - hex!("b8c41c09c228da62a548e49cfa107630166ac5c1469abf6d8aab55938ed1d142d5ddbc4f1043eed9496e9002cac99945").into(), - hex!("912750d2f1b21756662a400236f797b8ba76c73e5af95941a8c6ef9427838c4826715c80942cf8cb7ed01566bc490754").into(), - hex!("862af7dbb38ad7293a4e598cb52a8ac84dacee3d9bf007b5cb6a18a1acead0aa33f6dba796ce630e632c97aeb7100d68").into(), - hex!("890def696fc04bbb9e9ed87a2a4965b896a9ae127bc0e1cc515549b88ddbcbc02647e983561cab691f7d25cf7c7eb254").into(), - hex!("b835ffaf54c8b878d3c4262ca2bf5e6be2c691adced622b35d998ed72e1467ba907f4fde8d64ce43b43a8196f48e55db").into(), - hex!("a6d7e65bf9f889532090ae4f9067bb63f15b21f05f22c2540ff1bb5b0b5d98f205e150b1b1690e9aa13d0dee37222143").into(), - hex!("8ebfbcaccddd2489c4a29a374a2babc26987c3312607eadb2c4b0a53a17de97107c54eab34def09144b3098c082c286b").into(), - hex!("900b9972180a2c8753f5ff49fdd2cfe18c700d9927b3c3e16deb6376ad6ee665c698be72d4837b94911a0b4c183cb140").into(), - hex!("aa9679c01ecf1f1452c54688e01cb25bf157bde6b09b1ed460b8c175d65eba439c7ad4b7c1d72415f5622f3fbc068dc8").into(), - hex!("887a4277ee8754733f3692a90416eeac1ebee52ff23173a827f0ba569bd84efd806eb9139049f66cc577e370d3f0962d").into(), - hex!("951b27456e2af80436608aadec54ebd03bda37fa58452631da63bc5ff3eecb5ffb73d356b19f6c9c4225fcb0da8fda20").into(), - hex!("9104b5af82dbca914370eadb5518b26bee7ed7edeca74b741585ba8b249204e2c998bd47a02cef4335e236f8efafef94").into(), - hex!("8757e9a6a2dac742ab66011c53fa76edb5ebc3c2fbd9a7265529a3e5608b5c24b4482fed095725e9b8fed5a8319c17a4").into(), - hex!("a7acf82999de75f231fd80770bcb0f4c720d6b1e4a2558fa1ce854382fda92beb89fea5b5d229dad85fafee7a9e98329").into(), - hex!("8fb74891a8642f25a55b5eda5818367aac2fdf9663ad1e3dbc0166b484c0cda581b243cc75131167f1afa9caaf6705a0").into(), - hex!("897d7a19b70dcef1af006df3365981d73068c81f18017f32fb9966599481496efd5f6caceef943b31c52750c46d9590d").into(), - hex!("87ac804ccfe7f1fa156b8666664a397236832569f8945e11d4688a9e43ada4d4104efb3fda750f48ef655a29357c5e7d").into(), - hex!("af18cf1e3d094b4d8423da072f98b3023d296f6a1f2a35d500f02bde522bb81dc65e9741c5bc74f7d5613bd78ce6bc03").into(), - hex!("9752561179783f336937757b619b2fdcb9dfce05aa3c4fce6d582dc966182eb85ab4ccb63e7e1736a7c5fad9d33cccd2").into(), - hex!("89e19b665ce7f6617884afaf854e88bb7b501ecdd195a5662c79802d721f5340eca8c48341ad1d6c78f519f82e5a9836").into(), - hex!("94402d05dbe02a7505da715c5b26438880d086e3130dce7d6c59a9cca1943fe88c44771619303ec71736774b3cc5b1f6").into(), - hex!("a76adeddf2454d131c91d5e2e3a464ef5d3c40ee6a2ab95e70ef2e49e0920d24f9b09276250ed7b29851affbdbc7885a").into(), - hex!("8934e9a3feababa12ed142daa30e91bd6d28b432d182ac625501fe1dc82f973c67f0fe82d39c9b1da3613bb8bfe2f77b").into(), - hex!("a5c11337eb91ce0e9b6d61bbdadea0a063beee1bc471cc02dc1d81c5dd2095315c400cbc6c33d23c77e98bba6bdf5439").into(), - hex!("92d00e64ed711951aeb852908aeb6fd379ea516872dd512384b1e773ef078e52e6d618beb202d437d2a46bcb78087f7a").into(), - hex!("97f1a7370b4f5acf83b466f519da361c366915f560385dd7eff9d53700ad81b25c9862bc71d35428e82372a5ae555ea0").into(), - hex!("95614544f65808f096c8297d7cf45b274fc9b2b1bd63f8c3a95d84393f1d0784d18cacb59a7ddd2caf2764b675fba272").into(), - hex!("8d474636a638e7b398566a39b3f939a314f1cf88e64d81db0f556ca60951ec1dca1b93e3906a6654ed9ba06f2c31d4ea").into(), - hex!("b87e5f481b938ac8a481b775cc58be2a06604549e3c810fc4734bab76099e5c617f0243c4c140cb7dd6d36a6dc2286bf").into(), - hex!("806efb61d1c948efc10dbf9bef30197d1c269e5e7fcf20a84367b26223d33fade413a0bbf4e33f0d1f1a00967289015e").into(), - hex!("880b99e77a6efb26c0a69583abb8e1e09a5307ac037962ddf752407cacaf8f46b5a67faf9126bdbcb9b75abf854f1c89").into(), - hex!("82ffe4de0e474109c9d99ad861f90afd33c99eae86ea7930551be40f08f0a6b44cad094cdfc9ed7dd165065b390579d0").into(), - hex!("941cd102228aa81ef99506313a4492a17c506e7169808c6b14dd330164e9e8b71b757cbe6e1bb02184372a8c26f7ad1f").into(), - hex!("ae96dc808c316a677977831bad1e529ef965dadb5d6aea25ab008fe7bb1543e596e33052cfbe4279fa060201199d2c34").into(), - hex!("a2053719da2b7501dab42011ae144b3c8d72bd17493181bf3ae79a678068dc3ee2f19d29a60b5a323692c3f684f96392").into(), - hex!("b17171939519d90e243d41839c3c5ce7ac7e6a978e4a7e56b2c8e6a2b1b587c7eacea47f2e31a55d88555d252c810ebd").into(), - hex!("a958987c2b3c84df8176b600f5b75a8badef9653c71eff967e76648937def38826eaab4027a639f4f300b20019166250").into(), - hex!("854aafa329e2b2563355641eba95f2aba5b33d443ab16f5e342048f97d97c4e2812ff27c6f4180b8110272f3151be690").into(), - hex!("94d4a1e3a3d28a948f14d1507372701ac6fc884a4905405a63663e170831578a2719714ef56f920baa0ca27954823e39").into(), - hex!("826be957cf66db958028fa95655b54b2337f78fb6ef26bd29e2e3a64b130b90521333f31d132c04779e4b23a6b6cd951").into(), - hex!("8261f7e644b929d18197b3a5dcbba5897e03dea3f6270a7218119bd6ec3955591f369b693daff58133b62a07f4031394").into(), - hex!("84926cf2265981e5531d90d8f2da1041cb73bdb1a7e11eb8ab21dbe94fefad5bbd674f6cafbcaa597480567edf0b2029").into(), - hex!("8fb51e3ef3c1047ae7c527dc24dc8824b2655faff2c4c78da1fcedde48b531d19abaf517363bf30605a87336b8642073").into(), - hex!("8ba45888012549a343983c43cea12a0c268d2f7884fcf563d98e8c0e08686064a9231ae83680f225e46d021a4e7959bb").into(), - hex!("973ab82026d360e2cf5676d883906186bc61b43f60767ca58f11d0995e40780b163961e6e096299ccf1c86175203abde").into(), - hex!("b77416ea9a6b819e63ae427057d5741788bd6301b02d180083c7aa662200f5ebed14a486efae63c3de81572fe0d92a9c").into(), - hex!("820cc2ac3eed5bce7dc72df2aa3214e71690b91445d8bb1634c0488a671e3669028efbe1eae52f7132bde29b16a020b7").into(), - hex!("a6b434ac201b511dceeed63b731111d2b985934884f07d65c9d7642075b581604e8a66afc7164fbc0eb556282e8d83d2").into(), - hex!("b81821a79c9148b41d24d85dc997336a1e1719da0e31e42af30812b97a5af31708ca3e7bc2e803c3751cff23af5c509d").into(), - hex!("a013cc5e3fbb47951637426581c1d72764556798f93e413e1317849efd60f3ecb64c762f92544201eb5d6cfb68233050").into(), - hex!("b5f32034d0f66bcbccefe2a177a60f31132d98c0899aa1ffff5ebf807546ff3104103077b1435fa6587bfe3e67ac0266").into(), - hex!("86ca8ed7c475d33455fae4242b05b1b3576e6ec05ac512ca7d3f9c8d44376e909c734c25cd0e33f0f6b4857d40452024").into(), - hex!("b781956110d24e4510a8b5500b71529f8635aa419a009d314898e8c572a4f923ba643ae94bdfdf9224509177aa8e6b73").into(), - hex!("a3f9dcc48290883d233100b69404b0b05cf34df5f6e6f6833a17cc7b23a2612b85c39df03c1e6e3cd380f259402c6120").into(), - hex!("a104d4bad69f1720307ed12363d1ec97952acfe09d9e3650034c33f3f20c763271ebe0d5b50b1d3bd15c469f4573b09d").into(), - hex!("94bbc6b2742d21eff4fae77c720313015dd4bbcc5add8146bf1c4b89e32f6f5df46ca770e1f385fdd29dc5c7b9653361").into(), - hex!("951aa38464912a29df2101c60771d6de7fadb63f2db3f13527f8bdacb66e9e8a97aaac7b81b19e3d1025b54e2c8facff").into(), - hex!("919b5187af7dae210f151dc64a9cbd396d1ae04acadebf542a7123004efc7ce00d6e14c170d876fbc64dc1b5d141a5f4").into(), - hex!("88e1e459ee5aeb8b36ed004f6d03da296101106fbe1b18f9bbf63e92321db51670c34050fd3b7dc56a4bad76403823ee").into(), - hex!("86b3ec14a8ffb811a0ecc3771f600d8b08c098537d100fba66def19e7ee4d1c397a311977bf37e6cd2d47a8a2ee8c223").into(), - hex!("898c4873bd356ba8015f6f686d57088fa8f79f38a187a0ef177a6a5f2bc470f263454ee63d0863b62fca37e5a0292987").into(), - hex!("b471c72bd2971353f4b44248b8e6cf5316812861a88ccfc20fd0d89a5e010428c387228b2f6f14c12f79e31afc9d0753").into(), - hex!("8b7cb5b8de09a6dfceddcbaa498bc65f86297bcf95d107880c08854ed2289441a67721340285cfe1749c62e8ef0f3c58").into(), - hex!("983cb6bbfe83bce8326e699e83fca01ea2958c09808c703cac97a0ea777e5a5f3f5bba9169a47732de7459a3c7af47d2").into(), - hex!("8235a3f09078dd34ce2fc17cc625e061298713b113dda12d354b3d2ba80e11c443b1dd59c9eb5a29513a909645ae97d4").into(), - hex!("8bb51b380a8a52d61a94e7b382ff6ce601260fa9b8c5d616764a3df719b382ec43aec9266444a16951e102d8b1fb2f38").into(), - hex!("9579973ee2559da09b327c62b1cc0177f2859872885dca709e24dcfbb9bdf9224a6d26869aafce498f44c0e6bd8a996c").into(), - hex!("842ba3c847c99532bf3a9339380e84839326d39d404f9c2994821eaf265185c1ac87d3dc04a7f851df4961e540330323").into(), - hex!("99dad12f78e1a554f2163afc50aa26ee2a3067fc30f9c2382975d7da40c738313eaae7adbc2521f34c1c708f3a7475b7").into(), - hex!("b96e3ff8bdae47aa13067c29318b1e96a7fe3941869c17ce6662183b7b064bf261e1cea03e2a4643c993728a2606b5b5").into(), - hex!("955bc897171aa65d0159aa6e5d51855833f83d8bd5e65f93ad26c27781171783f3988a12bf987472edb39994bd071ea5").into(), - hex!("a59249e4dfb674dfdc648ae00b4226f85f8374076ecfccb43dfde2b9b299bb880943181e8b908ddeba2411843e288085").into(), - hex!("ac2955c1d48354e1f95f1b36e085b9ea9829e8de4f2a3e2418a403cb1286e2599ba00a6b82609dd489eda370218dcf4c").into(), - hex!("b2eedff11e346518fa54e161be1d45db77136b724d497e337a55edfc896417de3a180bf90dd5f9d92c19db48e8574760").into(), - hex!("976eb5543e043b88d87fda18634470911dfe0e0cabab874ca38c1009e64d43026d9637d39dcd777bc7f809bbfc3e2110").into(), - hex!("8ea5f88a79f4eb9e7c0b6b29f8ef2d1cc4c15ed0ed798ab11a13d28b17ab99278d16cd59c3fa8217776c6dfae3aedf88").into(), - hex!("b7f146a357e02a63cd79ca47bf93998b193ce1174446953f12fa751f85dc2a54c9ed00c01a9308509152b3bad21d7230").into(), - hex!("87fd7e26a0749350ebdcd7c5d30e4b969a76bda530c831262fc98b36be932a4d025310f695d5b210ead89ee70eb7e53b").into(), - hex!("b9445bafb56298082c43ccbdabac4b0bf5c2f0a60a3f9e65916af4108d773d62ffc898a35b0b8efb72ea846e214faa02").into(), - hex!("b106c6d13ca17a4c8ea599306e84918127cf2de21027ac3fe5a57d35cf6f3b1d7671c70b866f6e02168ae4e7adb56860").into(), - hex!("9276e8051bed8f5dbfc6b35765aac577dd9351d9d6ac1bb14496bd98091005b9a4737b213e347336413743f681f5043b").into(), - hex!("aefc682f8784b18d36202a069269be7dba8ab67ae3543838e6d473fbc5713d103abcc8da1729a288503b786baac182d3").into(), - hex!("97578474be98726192cb0eac3cb9195a54c7315e9c619d5c44c56b3f98671636c383416f73605d4ea7ca9fbeff8dd699").into(), - hex!("99c34f9bd0fcb18b3d931e562988cf91886a417f8678f22651bf3cf138df2bbec3f675de90f62dda769e0eda03d72b7e").into(), - hex!("a0047e03c89a95248543618e6b7ca2c7aad7acda3c9f85771ec5c93fa898c651e8b2ea3b6b799d8cd592290a986cdd7d").into(), - hex!("993726e0b1c2277b97b83c80192e14b67977bf21b6ebcde2bda30261aa1897251cd2e277cfcb6193517f1eb156d2fe86").into(), - hex!("974a5180e55eab23d4c973fbee6ad1010335161ecdb849fe6520b34c1f96530a4faff80bd738fe281019b79d968c472c").into(), - hex!("8f1d90034f998018c3f4b5947b40b139fcead2e40aa80fdec6a4337c60e9d5ff1923dda7f0b5b1731ff16f55027d41bf").into(), - hex!("a7d9ae9621dd1f3da3cd2d435e891cc3579c4c0d60d6a4565cac86c315cea21a9ad883559fe7b897ae6e05f1aa989ad9").into(), - hex!("800f6be579b31ea950a50be65f7de8f678b23b7466579c01ac26ebf9c19599fb2b446da40ad4fc92c6109fcd6793303f").into(), - hex!("86fa3d4b60e8282827115c50b1b49b29a371b52aa9c9b8f83cd5268b535859f86e1a60aade6bf4f52e234777bea30bda").into(), - hex!("a80ac2a197002879ef4db6e2b1e1b9c239e4f6c0f0abf1cc9b9b7bf3da7e078a21893c01eaaab236a7e8618ac146b4a6").into(), - hex!("b4bf70468eff528bf8815a8d07080a7e98d1b03da1b499573e0dbbd9846408654535657062e7a87a54773d5493fc5079").into(), - hex!("ae0e15a09238508b769de83b30582cc224b31cd854d04fdb7b8008d5d8d936dbdd3f4a70fff560a8be634c141772561b").into(), - hex!("936f7e20c96b97548fef667aa9fa9e6cfdc578f392774586abe124e7afc36be3a484735e88cc0d6de6d69cf4548b1227").into(), - hex!("8163eea18eacc062e71bb9f7406c58ebe1ce42a8b93656077dd781c2772e37775fe20e8d5b980dd52fdad98b72f10b71").into(), - hex!("86a6560763e95ba0b4c3aa16efd240b1873813386871681d075266511063b2f5077779a4fe49ffc35e1f320b613b8c94").into(), - hex!("b156d9d22722bb6e3b75b3b885b64642fa510ba7e6057657cd61bac43fb9c284d05bb09e2d4b78a2a4ddada85da9c702").into(), - hex!("9779ca2759dbed8081f0cbbfffcb3b842ba335e3ae48a60c5e5c77c7a2a0623e4c415ec3a023cc4e216885fcbac3ce52").into(), - hex!("b8137fd57ce7d3cfaf8bdbaa28704734d567d0e7a2d87fb84716722c524bb93acb2c1284249027f3c87bccc264c01f4e").into(), - hex!("8cf06b34e7021e9401eb705dde411ecf7e7e7185f8c0b0aeed949097df31812a9fdd4db7d18f9383a8a5a8d2d58fa176").into(), - hex!("8c65aa29a9ee9066b81cf24cf9e0beca3e8e8926e3df22d5ff1236297e158cc8bc7970a2c7016009cc4efa8f14b14347").into(), - hex!("ac7e49f2059e99ff65505742978f8d61a03f73f40141a2bd46fde5a2346f36ce5366e01ed7f0b7e807a5ce0730e9eaa9").into(), - hex!("a1c25eb9b73723982be78180770aa63c5f7b23c2e54a2ed7e75a860c4512d273008066f1124ac8a43c60fe1e2a8bf03c").into(), - hex!("9310722e360a5652737362f6b9cb6e9c3969a0c9bb79b488b3c7d19d9e8c42ebd841df346258ded2e393895c99b413cf").into(), - hex!("893272a63650b08e5b8f9b3f17f8547b456192ad649c168bafd7166b4c08c5adf795c508b88fd2425f7be8334592afb2").into(), - hex!("b576c49c2a7b7c3445bbf9ba8eac10e685cc3760d6819de43b7d1e20769772bcab9f557df96f28fd24409ac8c84d05c4").into(), - hex!("af17532b35bcb373ce1deebce1c84abe34f88a412082b97795b0c73570cb6b88ea4ba52e7f5eb5ca181277cdba7a2d6d").into(), - hex!("8b8813bd2c07001a4d745cd6d9491bc2c4a9177512459a75dc2a0fa989680d173de638f76f887de3303a266b1ede9480").into(), - hex!("ab73a043ccdfe63437a339e6ee96ef1241264e04dd4d917f6d6bc99396006de54e1e156d38596ba3d15cb1aaa329f8f5").into(), - hex!("b67146b202afec0132ac0070c005cf664081e860339f8f4d45ac3e630dda05560936e646673e652d08cecd8d18fc64da").into(), - hex!("a750404e9d4b1a48f767d2b6aa699200c92c3b8102597f8c5c1dbaaf08112a0587c05801dfebb3612fb6dfd76ddc9ccb").into(), - hex!("b0d4231814e40e53ab4eed8333d418a6e2e4bd3910148b610dec5f91961df1ad63f4661d533137a503d809ea1ad576fa").into(), - hex!("81fc724846b5781f3736795c32b217458bb29972af36cc4483dd98ab91680d3d9bc18842db2661487d3a85430dc9e326").into(), - hex!("a5cf6f4fd67aecb845eebc8d7304c98c69806d774d4c468350f7f82ff0f5baeecc56837705e39432a8d246aa2a7075ed").into(), - hex!("a71d2c8374776f773bad4de6edfc5f3ff1ea41f06eb807787d3fba5b1f0f741aae63503dbca533e7d4d7d46ab8e4988a").into(), - hex!("825359cfe68ad6a75578a94be6419179e0aa088170b6c20fc5c249dc3be7a260d687c93d8d8a343c7c72c2ed6a716de3").into(), - hex!("b6aeb7a9b934a54e811921494f271d5d717924c561cd7a23ab3ef3dd3e86184d211c53c418f0746cdb3a12a26a334fc8").into(), - hex!("8c6fc89428c74f0c025e980c5a1e576deadf8685f57136e50600175fa2d19389c853d532bb45a3e22b4a879fab1fcb0d").into(), - hex!("ae95ddcf3db88f6b107dcf5d8aa907b2035e0250f7d664027656146395a794349d08a6a306ce7317b728ca83f70f3eaf").into(), - hex!("8c03fb67dd8c11034bd03c74a53a3d55a75a5752ea390bd2e7f74090bf30c271541b83c984d495871d32c98018088939").into(), - hex!("b8d68610fdee190ec5a1f4be4c4f750b00ad78d3e9c96b576c6913eab9e7a81e1d6d6a675ee3c6efac5d02ed4b3c093a").into(), - hex!("87d4b20bbe2dcd4f65f4e1087f58532d5140b39a5288e1a63fc0b7e97a6a56946eafdd90ba09300c3d1fef6356ac6b7c").into(), - hex!("83e264b1d3d4622826ab98d06f28bbbd03014cc55a41aaf3f2a30eec50430877d62b28c9d6d4be98cb83e1e20f3b13db").into(), - hex!("97ffcbf88b668cde86b2839c7f14d19cb7f634a4cf05d977e65f3cd0e8051b2670e521ae74edc572d88201cff225e38a").into(), - hex!("91efdbcaad9931312d7c41d24de977f94d7f3f7b88090a1f72d9a097a1e30cc805c5ea16180f463022d9b26b8863f958").into(), - hex!("a4b507a4bc2bc424297bf8968bf385fae3acc686cff4b7933b4f5b6ef3149995393d5331dbac4b629e8adce01a91a4cc").into(), - hex!("a76a26c30d8abbbd4bf982bb8bd2066a2ec823a5eb6fbe37c664e67efbe2f72d8ce2d00223b900699149f8441bff5ada").into(), - hex!("b3a5497365bd40a81202b8a94a5e28a8a039cc2e639d73de289294cbda2c0e987c1f9468daba09ea4390f8e4e806f3c8").into(), - hex!("a09b2a07d861e01645accfb088f7f9ad524186bd439712775459a60f8a1fbbd43ee084e4d6e23ffce06daa189cd1e654").into(), - hex!("a41cf5d678a007044005d62f5368b55958b733e3fdde302ba699842b1c4ecc000036eda22174a8e0c6d3e7ef93663659").into(), - hex!("a698b04227e8593a6fed6a1f6f6d1eafe186b9e73f87e42e7997f264d97225165c3f76e929a3c562ec93ee2babe953ed").into(), - hex!("8bc66e370296649989a27117c17fbc705d5ac2bda37c5dad0e4990d44fcc40d3e1872945f8b11195538af97961b5c496").into(), - hex!("8bff10f91b8c0abb6c9542588da17fa0118ffda4c82626a754887e333d7d69661b3ae4e400da15c49565f8d10a77d0d7").into(), - hex!("ac715c7b3d794860a61d9c7bd224a2b14a6023f696afa30345aad2ce0a6ea6dbc142f34af1ffe7f783542851a28e8ece").into(), - hex!("91c5e0b9146fe5403fcc309b8c0eede5933b0ab1de71ab02fac6614753caac5d1097369bdeed3a101f62bbcae258e927").into(), - hex!("8553748da4e0b695967e843277d0f6efeb8ba24b44aa9fa3230f4b731caec6ed5e87d3a2fcd31d8ee206e2e4414d6cf4").into(), - hex!("ac722bd742374f925185ea7d4d62d7510b2d8a6ebf5c750af6ce83e2d8a28c95a3e298870ec8254ab2d1d0aa2a063c60").into(), - hex!("b083c4cefb555576bb37b71f30532822cb4b1e1998e35cb00ffb80ca14e2853193c16a6756417853d4a74d625744dd76").into(), - hex!("85745bd84c92ddfc55df11fe134cf70e3c340aa1c7cdd6188a03308cf3a840f4f19629f9730b2e6426424989ff03000d").into(), - hex!("845b4531dee808b583645f56fa98cbdecce3ea100db60524b64f68e29866173791f01137714f4dc7fb8612f7f7943263").into(), - hex!("93f03495d53c781be8b76e37e68b64aa260523004eff6455ddc8a8552af39854e5181f8c5365812b1f65926534fba5dd").into(), - hex!("801c126abff96fe9b042be8869d2907d0c6963a79901f9db46577a445418b7465a1f4b346933d433e539536a9a2df01c").into(), - hex!("952cf6782b0ad3e85625391cc5f486a16bb5b1f8ea20defcb6857bd7d068dcd2701bc7ed5c3b773a869180d9042f772b").into(), - hex!("b3b6eccb2ec8509b4eea8392877887180841ab5794c512b2447be5df7165466d7e293696deaabf063173e5f2238ce763").into(), - hex!("b63fd45023f850985813a3f54eceaccb523d98d4c2ba77310a21f396e19a47c4f655f906783b4891de32b61a05dc7933").into(), - hex!("a113b889be5dcc859a7f50421614a51516b3aadc60489a8c52f668e035c59d61640da74ba1a608856db4ff1fa1fe2dfd").into(), - hex!("87fec026beda4217b0a2014a2e86f5920e6113b54ac79ab727da2666f57ff8a9bc3a21b327ad7e091a07720a30c507c9").into(), - hex!("a3ee8fd53158dad3b6d9757033abf2f3d1d78a4da4022643920c233711ff5378ac4a94eadcaf0416fdcca525391d0c64").into(), - hex!("8d6bed5f6b3f47b1428f00c306df550784cd24212ebac7e6384a0b1226ab50129c0341d0a10d990bd59b229869e7665a").into(), - hex!("b549cef11bf7c8bcf4bb11e5cdf5a289fc4bf145826e96a446fb4c729a2c839a4d8d38629cc599eda7efa05f3cf3425b").into(), - hex!("982691766a549df56436acd0fe76da78132e027515f27174c10d117bfcc20ed73fc31f5465bd7a22a101094fe913e221").into(), - hex!("985af1d441b93fa2a86c86b6d7b70b16973d3971e4e89e093b65f0ae626d702202336869af8e3af3923e287547d5384b").into(), - hex!("994b7baecc8bb68d270a3a88c58e4054afdbd713b4472f9522b27c1762c637ef8f013d745ce9d1dc8fc4d986d4c9338c").into(), - hex!("827dabda84c7f7b1adc0f5ca0fccf0729e9d7f78e1ffa7c5e9c4f66610ff0ab776c880b00c77137cf7abe14df977febc").into(), - hex!("acd17cba1203748b55bd9d7b940a16bb7c02988c93007a80b87e0bdb049b91f5ecce577e3e4ea68a0abe998a72cd300d").into(), - hex!("989fa046d04b41fc95a04dabb7ab8b64e84afaa85c0aa49e1c6878d7b2814094402d62ae42dfbf3ac72e6770ee0926a8").into(), - hex!("99dc48a054f448792523dcdeec819e1b928b1bd66f60f457261f0554f8532eedd7152792df70ae5316ab2f9c02a57cdc").into(), - hex!("ab33c65587ecb3278325948c706aed26547e47ed2b4bc027e9119bb37bec67ddf5489fbc30304ef6c80699c10662d392").into(), - hex!("ae89e41d8cfbf26057a4078f8a5146978e658801b08814190cbce017d79beaeb71558231a72bde726fa592fb0828c01c").into(), - hex!("a9901df92e2d3abbb25f3bf4b913692c4cd57da327b01c8ee2362c02fbefcf66cdb792c17a81dcbde3c9b9dba313e4a1").into(), - hex!("8ee41011424da5e2ecea941cbf069ea32420749f2519434d3d8f9725ac789753404687a6745cffe4bd5dfc8fec71a719").into(), - hex!("8cfcdfa192b17321be4e447204e1a49ecaadca70a3b5dd96b0c70ab64d1a927d1f8c11a7e596367e5fa34e2307af86fc").into(), - hex!("b8a0003e949cf994b1bb25e270cb61358200c93b1c6f611a041cf8536e2e0de59342453c5a8d13c6d4cc95ed8ce058f3").into(), - hex!("adc806dfa5fbf8ce659aab56fe6cfe0b9162ddd5874b6dcf6d658bd2a626379baeb7df80d765846fa16ad6aad0320540").into(), - hex!("a83b036b01e12cadd7260b00a750093388666aff6d9b639e2ce7dfc771504ef8b2090da28ec4613988f2ec553d1d749e").into(), - hex!("825aca3d3dfa1d0b914e59fc3eeab6afcc5dc7e30fccd4879c592da4ea9a4e8a7a1057fc5b3faab12086e587126aa443").into(), - hex!("845a4a09941f48677e6c03699770f9a56ba72695089e432a6f232294dd8da6d34e394116a9a87f3b0902c78332af9439").into(), - hex!("b2f168afc35ed9b308ab86c8c4aaf1dcd6833ce09153bb5e124dad198b006e86a941832d387b1bd34b63c261c6b88678").into(), - hex!("a094cca9d120d92c0e92ce740bc774a89667c6f796b438b0d98df0b7aef0935d8c915d5b0dad4b53e383dc9f095c29fa").into(), - hex!("956ecb233b3529b2d9cb80ae49e48667f2a3120e4a0d7131d1e9ec36db3a59dc2ef2a579cbb99d6f14880ca83f02b64c").into(), - hex!("906cde18b34f777027d0c64b16c94c9d8f94250449d353e94972d42c94dd4d915aa1b6c73a581da2986e09f336af9673").into(), - hex!("824c8a1399ab199498f84e4baa49ff2c905cf94d6ac176e27ec5e2c7985140dbaa9cc6303d906a07ab5d8e19adf25d8a").into(), - hex!("889a5cf9315383bf64dfe88e562d772213c256b0eed15ce27c41c3767c048afe06410d7675e5d59a2302993e7dc45d83").into(), - hex!("95791fb6b08443445b8757906f3a2b1a8414a9016b5f8059c577752b701d6dc1fe9b784bac1fa57a1446b7adfd11c868").into(), - hex!("99049e9a23c59bb5e8df27976b9e09067d66e4a248926d28171d6c3fdd1ab338944a8b428b2eaae5e491932c68711c7c").into(), - hex!("95c810431c8d4af4aa2b889f9ab3d87892c65a3df793f2bfd35df5cfdb604ca0129010fa9f8acae594700bece707d67f").into(), - hex!("841d77b358c4567396925040dffe17b3b82c6f199285ac621b2a95aa401ddb2bc6f07ebd5fa500af01f64d3bb44de2df").into(), - hex!("90c402a39cd1237c1c91ff04548d6af806663cbc57ff338ed309419c44121108d1fbe23f3166f61e4ab7502e728e31fd").into(), - hex!("968d44188e2d9d1508b0659e96d6dabd0b46aa22df8d182e977c7f59e13aa05d5da09f293f14f6f2ee1b996071cd2f25").into(), - hex!("8ae9585caa3c73e679fe9b00f2c691732f7b7ca096e22d88c475a89d4d55cb9fba3cd0fe0cedd64ce75c591211664955").into(), - hex!("94b81d5ad72efb4dd60867e71afcd8e87e1f24bf958d42fc07db66f6185a1e610987ab9ceef63109a36fe5544a0cf826").into(), - hex!("8499a8c3d67d1f6eccf1c69274393dc498cff862ea8e6c11ffb8107ae190d258ddc1d294f2a8f050488df0212063ece2").into(), - hex!("921109a390e4d7fbc94dff3228db755f71cb00df70a1d48f92d1a6352f5169025bb68bcd04d96ac72f40000cc140f863").into(), - hex!("b464d763e5ef724ab7ee13a60015df5c9a7809a79188ff6a7e0d5e5400febd42ad7330406a59704a44a08f2289d659c8").into(), - hex!("96f1a36134e0d4137a7fe8bbb354f50aaa67f28f194ae2fdbe8be3eb24596678d8c9287765ee90c1f2778d0d607931e0").into(), - hex!("b031d93b8f119211af76cfafee7c157d3759b2167ee1495d79ad5f83647d38248b4345917309ef1a10ecaa579af34760").into(), - hex!("88a7dc337d89324f025f686f37d21240c7da9a1cb802259ea8d8a83e246dcc2adceca7ca3534bc7bf8f3ae1cbeafb5c0").into(), - hex!("b30e022b8a563655074e08e123b5f96956bbf0fe221cc629c5fedd2764a66b475916ceb98867f935b4a47212e53ae9f3").into(), - hex!("ab6e3180dae399d41243f23545e5e6d118844f9b8edba502a3503fd1162ed826f9fc610889a1d685d374b6c21e86067d").into(), - hex!("96cf5760c79cfc830d1d5bd6df6cfd67596bef24e22eed52cee04c290ad418add74e77965ea5748b7f0fb34ee4f43232").into(), - hex!("a5817c74a394b0359a4376ef7e9e8f7dfa6a7829602da225074fb392b715e1fd52c50cae0f128a7006f28b22f233fbf5").into(), - hex!("a50ab79cf3f6777a45f28d1b5cdad2c7ea718c60efeeb4c828d6307b29ef319445e6a9f98aa90f351c78b496575150c1").into(), - hex!("8b300dea07e73dd2f07b05d477e51f8424589f6b2fa6f461240e1322a3a7ab5bf227b74544bb5d66a297702cdbf6c6bf").into(), - hex!("b13b5cb86dc8b8fe87125f1a51fe98db36bdde4f600401408b75059a44e70b1bbfefd874e539691f3f1bf6f54db883c8").into(), - hex!("8d06205cd66703ce6776b38b98c32b27f45c7b3f65ea2d05e2b702c24d553f51c69bf0b17e8db7382475e3d370d2e8d6").into(), - hex!("a11a7496c712734aec80738e30d2bf245758b34245076149854eb209fa6403be8bb0d4e515becc881b7f3610749260c0").into(), - hex!("9615800f8c95f95bf25055ae079b964e0a64fa0176cc98da272662014f57e7cd2745929daf838df0094b9f54be18b415").into(), - hex!("b19ca6e55f349bbb2dc3e429520ff5b2e817972470794f35c1aac8c118b37a694cfcc875b6d72225343799825d2f5c39").into(), - hex!("a650864b7eb6769aaf0625c254891447351e702e40d2be34dfd25f3b5367370de354318d8935ba18db7929270455ae6a").into(), - hex!("a649208372f44f32eb1cd895de458ca1b8be782746356f08ac8ef629429d0780a0799fcff85736e19aead0b79bfff261").into(), - hex!("89461cb2dadf51d6f1208b0965c8eabec895d7b19b7d90d3c6e49dbe75a75c30fd26db3dfb169dd46a4342280225032a").into(), - hex!("b5d6f664ec92e5343792d5d6b629919c5fd8cfb874677df2264daf02bcd9d12facf9b859d5402839c9022396e20d260b").into(), - hex!("a7179d338fe5a0e4669364a364e17f8d00cb6c59a80a069afd5f4f14510df2eee90c07826553e4f7fe46d28f72b2903e").into(), - hex!("8ded37d67b5368619a090266e9b5585fbff60319a90a4244a3c3342641f5bfa5130998dd97d7a42505cd896c29255530").into(), - hex!("a3fd63e87a00b48ba46a646a26187ae6dcb16779721973ada13a545853e2e51b5e4df04630d670884ad4a2304cc60c67").into(), - hex!("92761b7e31f0c758b3b1f5b43a194b25aabec668101946eb6511132863d3afb9d18f833d43a8338d0e7bc78d8689e523").into(), - hex!("ab8a8769c754008a7976b6799e81d7bfe97413d0a79b90715703c1f8f567675463ec93aabee59277121fc4df88b5c7a9").into(), - hex!("b354d0d1bd942f79002a2eaf37eb99dab650170e7040c13c824803ed7c1670dc910ccae13bbe58bde003829b140b45ea").into(), - hex!("b9eed89e003894ad2cc9d9b93a45247e1367ac69a00b0ed5e3280c1188b4cb90eb870d449b83a852a798bd02f9d0c813").into(), - hex!("b900a55013d0427e5da6b21611d6ae3e648f54f794cb099b2d2beebae0a957477a94dc415e8ec5e68e9029ce50d43843").into(), - hex!("afbf44071c2c905f7c8ef396eaed7f13deb7a91719cb5e8b9226aaceb876d81a10076383edc6216bc2f5c38a480b2957").into(), - hex!("80bdb82b7d583bf1e41653966b0ba3b4fec0e7df2ff08e3fa06fd9064bca0364263e075e1582741a5243bde786c9c32e").into(), - hex!("a841fe9ff26db21ade698f6dbfba025d90ae9f81f02af9e008fa0a429b993fb04d06acb93e40a9f81c78f73334555a17").into(), - hex!("8cd49711b42af58a5aae75a38fea9ddc5e4183c467a3159b5b0629f01ba548513c577456d34c861911e85782e52c3b1b").into(), - hex!("a322b5d2a6e3cb98b8aaa4c068e097188affef5dec2f08c3e9ce29e73687340d4e5a743a8be5f10e138f9cabbe0c7211").into(), - hex!("942772b7c7c47d4e5957ccf1d6f1450070930af3e2b7eaab0dd7699372445df0cc910e6c0efcf501887dd1adabdaee23").into(), - hex!("9834f66e5c946c3a8241ca2bbde046a7e88072124911d5d15c037a95b61e82b88b5c2058fa4a3721537dee39dee5da18").into(), - hex!("a90cc5b9c4d84f36962d0d55d5bc123dbe5ec5f4fe7b6bf0d009028b3cf14e36c11bc5365391cb4ae548d5eb04fe371b").into(), - hex!("a7c2174eea2b66b2a71cc8095fae39c423a353c7d5020ec2d0551317a66202fcf082c6119ba768755523fff49791bb4e").into(), - hex!("ab92b2a177dfa55d202a653532f0e04d1339ca301aebe6a0e8419bf45be3e573b6b9ae4d3d822cc8279367a3d2c39b06").into(), - hex!("8a9ad977988eb8d98d9f549e4fd2305348a34e6874674bcd6e467c793bba6d7a2f3c20fa44aabbf7151ca53ecb1612f6").into(), - hex!("a7d1676816e81a752267d309014de1772b571b109c2901dc7c9810f45417faa18c81965c114be489ed178e54ac3687a1").into(), - hex!("a575be185551c40eb8edbdb21a0df381c801b6e99467fcf5882dd7cb34916960ce47ac732c1920ad3218f497b690cef4").into(), - hex!("b50c306f78143b37986e68efa10dbe1fb047d58562e9b5c5439b341dd8f1896c7ae586afac0a3213759784a905c1caaa").into(), - hex!("b31e89b4a034c1b73d43b3d63ea3bddea682a6a5327eff389c70b13e9e72185b0327682a0cb1ff3c4a4f8ba08b13d898").into(), - ], - aggregate_pubkey: hex!("948a4b8d91bd29969cd4470b1bc24d34586d38e73d5be71c98a9894899471a5f708747563276b4b6d2716fdb72860267").into(), - }, - next_sync_committee_branch: vec![ - hex!("cb3fea582872d90706ddc6d029bac0d791ea75d43c3ab04f056f62a11b89d27b").into(), - hex!("f26b4bb68eb7e6906c8ef4a9958398a48e4450bf9c8a462fafa4fde51cd5628f").into(), - hex!("690925f92c1d322d2ff2a5636539094825dfd2c9bf7538fe111b2358e03a71de").into(), - hex!("51d977e358166401c7cd3f6185468c1a8c69a4c3d8577535dd583bc427692e02").into(), - hex!("88d2089aaf2f6fd8f6e4ae499c6fe33cc34289eb9310780861e772204f07b670").into(), - ], - }), - finalized_header: BeaconHeader{ - slot: 4055040, - proposer_index: 854, - parent_root: hex!("8adf3b288deb17566a553fa7a06a2f63f4ac4cea4868af4d89ddca41f73ae9b9").into(), - state_root: hex!("595e9ebaaa23f027672b4d2a33173a22b2839baac709c7f8e66d3219f492ee9f").into(), - body_root: hex!("acf37b466d4f6b5d1db5b6ffe5d77c13972d116c2b0809de924427fd597d391a").into(), - }, - finality_branch: vec![ - hex!("00ef010000000000000000000000000000000000000000000000000000000000").into(), - hex!("3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb").into(), - hex!("a2e2a28c0bb0ad56c25f3c461a4bfe4f3b3b894bc0105a62e85f43a4ae1adc3f").into(), - hex!("690925f92c1d322d2ff2a5636539094825dfd2c9bf7538fe111b2358e03a71de").into(), - hex!("51d977e358166401c7cd3f6185468c1a8c69a4c3d8577535dd583bc427692e02").into(), - hex!("88d2089aaf2f6fd8f6e4ae499c6fe33cc34289eb9310780861e772204f07b670").into(), - ], - block_roots_root: hex!("7054ba439f83e9b2223911e25fad48eb28f5c362d94c0de2455a45436cc93897").into(), - block_roots_branch: vec![ - hex!("c99a842c81d0b956eef988dbcd90499457d61f942375c6cbf67262909b708db5").into(), - hex!("5d32345aeb10aa3ede4be021d2231dac47cc2074f74b72466f0b042e69adf70f").into(), - hex!("b69608a2377956c1a39c3423d3399ccfb12307623c9df6358f5fcfca64a80102").into(), - hex!("cefd9b668e49ece82bd4b0ee2f1efc88ecaf0d9af464fb622735663aaf106c4c").into(), - hex!("c113ad1c971779b15c64772ab69cd775edfb926a60447974913bb6f58fbd12fb").into(), - ], - }) -} - -pub fn make_finalized_header_update() -> Box { - Box::new(Update { - attested_header: BeaconHeader { - slot: 4058720, - proposer_index: 1088, - parent_root: hex!("37c7398a391c71da07258b48f41d4caaaf891fdf558e110b9c25db716fa8ff55").into(), - state_root: hex!("6cf68a66c993f1c27f499e054a5fbd7c0e625c34ea0057fda9691c561e990002").into(), - body_root: hex!("109e4c0c647d42dba0c8c6569997c51b5bcfc1a33475b1433ded6353f48423ff").into(), - }, - sync_aggregate: SyncAggregate{ - sync_committee_bits: hex!("ffffffffff7bfdfffff7fffff1effffef7f9ffbdfdffffffdffbfffbbf7ffffffffffefdf7ffbeffdffef7bfffffffffffbffffffffffbffffffffffffffdfda"), - sync_committee_signature: hex!("b5727bad1db101b6f0fd7ec4cb79b43dae90366fe0cae31a62439388eb03ebd75732cee3bde51f814203a4c0f5b23898120cd0870f0e662bdf0f85a048b534d9a906e6d32a65df019059d34f724221075734ec2849c09679febecf6929934f09").into(), - }, - signature_slot: 4058721, - next_sync_committee_update: None, - finalized_header: BeaconHeader { - slot: 4058656, - proposer_index: 810, - parent_root: hex!("bb6cfda1e02c3117d9fa41c1e1594ce0645352a073ad8b474f83c148e0d9954f").into(), - state_root: hex!("f938f0f0cba85234afbaace20545134c70b35e6ff9f74d944b0fea309109f3cf").into(), - body_root: hex!("cf6a7a6f653cb64b2b910278a478339b34eb08abf00e0766d10c7a8fe9bdb139").into(), - }, - finality_branch: vec![ - hex!("71ef010000000000000000000000000000000000000000000000000000000000").into(), - hex!("3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb").into(), - hex!("a2e2a28c0bb0ad56c25f3c461a4bfe4f3b3b894bc0105a62e85f43a4ae1adc3f").into(), - hex!("aa2bad8cf9b0433d3d79bc5b95c067048b018d1d2ffd0c66db6e7cf86e0a314e").into(), - hex!("027f238235d07ac9757543c19deabe1d553d6fc110e8bea4b037b1fab263b4dc").into(), - hex!("7dfa1cc1907e8927295f78a770bf86b28f5c2bddcac38beb3b4beb265ff5608f").into(), - ], - block_roots_root: hex!("4a5a57fb0769443f6472f59dbb78d7a9a69ff61d09aa89d5da645d634ec46a14").into(), - block_roots_branch: vec![ - hex!("a09ad7f3afd681bb6fd54abba339549f3b601beedea79a5b7d448b1cf1e1613e").into(), - hex!("acdfd4d5eba154f118a84af7a2d17ba6100fcd9c24fc235e927f584a5b56e32f").into(), - hex!("36ca106eac009ed605e680415b105b3a6591830c38034511f300aae44802235f").into(), - hex!("171561a9e1afb413132d0f4d3cbbd810766c151be32ec9f2d609f40aef9e2588").into(), - hex!("7cd963eba3fb57ee5ce37ee4b621d24fc14d642e32f48dc48ade528e11458ab9").into(), - ] - }) -} - -pub fn make_execution_header_update() -> Box { - Box::new(ExecutionHeaderUpdate { - header: BeaconHeader { - slot: 4058654, - proposer_index: 1039, - parent_root: hex!("758fa0a54047c0221b3107423e78b8910514ba7a0c4250401dac77108dce2ff8").into(), - state_root: hex!("53c79320b4b7649e39a9f07903f4fc68a7cfe7a81cb2e30293dd7b00ee13f69a").into(), - body_root: hex!("a76a7f037f12ee070dcb273d9787b13ff0cf17420a39564a101789318a157ec3").into(), - }, - ancestry_proof: Some(AncestryProof { - header_branch: vec![ - hex!("bb6cfda1e02c3117d9fa41c1e1594ce0645352a073ad8b474f83c148e0d9954f").into(), - hex!("b44967bd8ff799126cad993ff7369f7a28d60281304d0c7c058e6721b6ce4c61").into(), - hex!("0009710ef2467f95542c2e8e7a7249282c08f62aedbe7d21ae4a7af04e1a890d").into(), - hex!("7bc5dc20638cfe1cfd5d2547c3efbed4cfb533c76c27d41f723ed876ab9edc3a").into(), - hex!("6dcd59a8a041cf2591921417cb8133f0ff5af9bfe1f1ab491e75a751adc9c9e1").into(), - hex!("3f25a2852042c7bf2c421bf16c0b9373c1d27ccb1eca4088f8191712481261be").into(), - hex!("d1f9cfe1f04031459e5c45f47b2a49c780cabb8ca5b8d76461db2b88c337ed76").into(), - hex!("8c37e3119bf7d3cb8208e832669261b0eda1b3c7b11d321760ba1c0649f61416").into(), - hex!("1783d3b7041ecb78d9e1f913b82bd335229ca1f2cc5d3cc8dd28c94152e887b4").into(), - hex!("e39fc366c951c7cb2100308b0a9417581c46812a7d7e89f516c19863f7686f96").into(), - hex!("3c29b6d9b8715dbe5d6831364229efc91ad56ae69e93cb119d5ef4bdc53fcb37").into(), - hex!("3cf6fe5e8d91dbaa77e6befa81e04fb25a3e089317d83ff35fc8adfbbf2aab5a").into(), - hex!("b41c97cf3b1b4b5bf2999dfb1b3eaeac5c1b12205e9ab0809988e3779d119047").into(), - ], - finalized_block_root: hex!("b4802863fc1d32778211ce6aac8109c73c516a003213f4f5333c80472d08fe4e").into(), - }), - execution_header: ExecutionPayloadHeader { - parent_hash: hex!("9cffcba69c88a619483e13864704dde5db80e05f8d49018f615395ce09cd24ab").into(), - fee_recipient: hex!("ff58d746a67c2e42bcc07d6b3f58406e8837e883").into(), - state_root: hex!("6a4aafc93626778475a416721104229035e91f0db788d0099b57e756cd272f0a").into(), - receipts_root: hex!("e1ce670bdcf9acf4c62fee845cd7e81eabbb6db9ddbff56130020c6cf999a45d").into(), - logs_bloom: hex!("a000980408008000328c1458805c005048b84812c134200090b40428568108a0648090105085100301844800090802484420800d020282019002040d083004031a20420240a4a8900a43296938c040802040220170860210910020036b8c482228c004440300021c82c0400110402a10800582424001c00000828310210020a18130504020790dca716194100880ea5501149104002bc05e189080901c4001010e0a040658a410072021230a5224265030082404000aa11f28162e216636000408842103d41010760972060060000500c20130b000000065401483200081a84934f020020120009618002269c884724616040000840e18080300024490000230").into(), - prev_randao: hex!("5d9ac7ea788ecb534e98bc9079fa0bef199011dadadedaee5dc40e2cd702d664").into(), - block_number: 5025098, - gas_limit: 30000000, - gas_used: 13802943, - timestamp: 1704437448, - extra_data: hex!("476f65726c69205365706f6c69612d4265706f6c696120513966").into(), - base_fee_per_gas: U256::from(19959019915_u64), - block_hash: hex!("795021134c2b7f9c00b498ff7b0971dbbe061561868f702d8ca68a05e5eb5a99").into(), - transactions_root: hex!("3cb7c92fde5d511cc90cd67e375c4388794f4c01e375e8e8a06d003b5593fd12").into(), - withdrawals_root: hex!("5f5155fd8e5cd24b7ecb1e039792b0caff01dfda2990786d9ffc88325b5d1ea8").into(), - }, - execution_branch: vec![ - hex!("85ff3d1c2bc3dcdd5543bcd29a1224c6a8c24875224fbb1e3b69f0515ffaacda").into(), - hex!("336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e").into(), - hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71").into(), - hex!("fe1fa7acd413c54ebd394126ade19fc624ad9e4c60792d54ff3d60b07076b76d").into(), - ], - }) -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_minimal.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_minimal.rs deleted file mode 100755 index b9476a0fb080..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/fixtures_minimal.rs +++ /dev/null @@ -1,248 +0,0 @@ -// Generated, do not edit! -// See README.md for instructions to generate -use crate::{CheckpointUpdate, ExecutionHeaderUpdate, Update}; -use hex_literal::hex; -use primitives::{ - updates::AncestryProof, BeaconHeader, ExecutionPayloadHeader, NextSyncCommitteeUpdate, - SyncAggregate, SyncCommittee, -}; -use sp_core::U256; -use sp_std::{boxed::Box, vec}; - -pub fn make_checkpoint() -> Box { - Box::new(CheckpointUpdate { - header: BeaconHeader { - slot: 152, - proposer_index: 7, - parent_root: hex!("7ecd45ee8bbacb20c6818eb46740b0f8d2fbd5af964e0dd844d3aa49ca75ce26").into(), - state_root: hex!("0859c78c54a2ecf1af0aecc05f3c8ba9274d1df500bfc4e6a7194c0235f55def").into(), - body_root: hex!("561bec3e5b200ee1bf6b60b5858ca2d7766ac9327b46355c070afafae8fca2ba").into(), - }, - current_sync_committee: SyncCommittee { - pubkeys: [ - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - ], - aggregate_pubkey: hex!("8fe11476a05750c52618deb79918e2e674f56dfbf12dbce55ae4386d108e8a1e83c6326f5957e2ef19137582ce270dc6").into(), - }, - current_sync_committee_branch: vec![ - hex!("c6dd41df7b4978b7ee7479dcbfdbfa9fb56d1464afe9806bfd6f527e9d1c69a4").into(), - hex!("b3824f305318071010d4f4d9505f9fc102cdd57f1c03cf4540e471b157f98e3f").into(), - hex!("66677299731d34be9d4dea7c0e89d8eae81b8dffa3c6218152484a063b1064a1").into(), - hex!("ef53c2b02cdb7f44fb37ea75f4c48c5086604a26be9635f88b1138f961f87773").into(), - hex!("1a3f86a88fb2ec99cb1d7b0f35227c0f646490773bac523c30fc7eccf87c0f84").into(), - ], - validators_root: hex!("270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69").into(), - block_roots_root: hex!("8ad7487f0e79a6cf67ce49916f74e5b272be9e38ea5f8a6a588eaa89ea7f858e").into(), - block_roots_branch: vec![ - hex!("90683050cb3f3b04b2a89c206365747bef4c42154feb5d3f4198dfd48b2067ae").into(), - hex!("34f521b45630273930475b8a4350fe2c71c804878ebcd89064eb1dc24a85e468").into(), - hex!("81e166eaeaff5df2d3a5df306c78af075106cbf63c2f1b50ab67eec2dbb0f5ce").into(), - hex!("857526b3bf20de3ec6e57565dd593304f83e47541cc18d7c2d5b4c9f2724ba14").into(), - hex!("1b4bedd5ecc523599da000387f5e33ffe5324b8e234c43ee702de8ccc88d713f").into(), - ], - }) -} - -pub fn make_sync_committee_update() -> Box { - Box::new(Update { - attested_header: BeaconHeader { - slot: 144, - proposer_index: 2, - parent_root: hex!("74e7da3093f79414b5ab593d1c12ba63767db7f4af62672fa1be641331c338e0").into(), - state_root: hex!("92a08dc74f6af7bfcd428aa1677d58f36fefc159c0134b312c186a69fcd00496").into(), - body_root: hex!("51506a8230d40d065a29ad01197c983b9b5d4b9abd26d3c48773941f4e6f482d").into(), - }, - sync_aggregate: SyncAggregate{ - sync_committee_bits: hex!("ffffffff"), - sync_committee_signature: hex!("92cbff711040bcc4a81616edbadbe712ea3ac4939c3d3121a4561b4b3950e2e5b09809606b79fdad2ce20fdef413120a04f02dc65149ca9b6ecab2a94ac4087062df4ab03e161ae56fa6fee4ba40af29c3b4327e21e846f98144cab30684d197").into(), - }, - signature_slot: 145, - next_sync_committee_update: Some(NextSyncCommitteeUpdate { - next_sync_committee: SyncCommittee { - pubkeys: [ - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - hex!("a8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac").into(), - hex!("81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e").into(), - hex!("b89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b").into(), - hex!("88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e").into(), - hex!("9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373").into(), - hex!("ab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34").into(), - hex!("a3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b").into(), - hex!("a99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c").into(), - ], - aggregate_pubkey: hex!("8fe11476a05750c52618deb79918e2e674f56dfbf12dbce55ae4386d108e8a1e83c6326f5957e2ef19137582ce270dc6").into(), - }, - next_sync_committee_branch: vec![ - hex!("c243f5286cbf6c3c5f58ef6e1734a737bf96cfc0adbf2ee88d4a996f8dfc7097").into(), - hex!("6ae16cb8ea57014c75a9469485bc024bb1e64676656cb069753bf091e58de88f").into(), - hex!("1afa3c77cd75040c1bbbc5d1b7c07e65eeee44fbc659b64ccd55b4ba579038ae").into(), - hex!("89b14216f60859ae366de066eeff4c7b69f8b5738c5b70cdfab4b3a976f9f12f").into(), - hex!("b7d8fa1e64e6d6339a7c68a81e20daab65804777b93a04236fa503b575c2f1a9").into(), - ], - }), - finalized_header: BeaconHeader{ - slot: 128, - proposer_index: 3, - parent_root: hex!("3774d6a479fc6f71ccaff3f8a1881c424b0319e96a7da15f87e3b750ba50dae5").into(), - state_root: hex!("85937007c564046bcc147d53b1d2d78941e2787ec059bee191420369a7f80447").into(), - body_root: hex!("c8f31c33ffaeef2d534363b7ef9ec391f90c17bc5bbe439cf0dcf0de8eeb4d7d").into(), - }, - finality_branch: vec![ - hex!("1000000000000000000000000000000000000000000000000000000000000000").into(), - hex!("10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7").into(), - hex!("c2374959a44ad09eb825ada636c430d530e656d7f06dccbcf2ca8b6dc834b188").into(), - hex!("1afa3c77cd75040c1bbbc5d1b7c07e65eeee44fbc659b64ccd55b4ba579038ae").into(), - hex!("89b14216f60859ae366de066eeff4c7b69f8b5738c5b70cdfab4b3a976f9f12f").into(), - hex!("b7d8fa1e64e6d6339a7c68a81e20daab65804777b93a04236fa503b575c2f1a9").into(), - ], - block_roots_root: hex!("b10da1bbb1c0dcb01637b9e3dcb710d1013dc42a002bd837d5b4effa0ac995c9").into(), - block_roots_branch: vec![ - hex!("9c62693fd336e4b3ca61d3cbe9caeb85f1f1b59ef50aeddfce53dc7321d6058b").into(), - hex!("364947a6574f4acc97888e1fddb5ec718859d54cd7e3db98cda8db4dbea82ded").into(), - hex!("10a61d26b0c1b5b89cf5b82b965f772a1b6ae852fbd13a986c5c63bf12b99244").into(), - hex!("506ed8ca9908af4b5acb4cfdec6dd968acf38346c16385abca360c9976411c3e").into(), - hex!("ada571922caf3dde48e19f1482df8d17dd6bb05e525c016c8cf6796a5d7f4a00").into(), - ], - }) -} - -pub fn make_finalized_header_update() -> Box { - Box::new(Update { - attested_header: BeaconHeader { - slot: 184, - proposer_index: 5, - parent_root: hex!("13548d0b72ef2b352ba73a53274ad02e9310d8417d4782bf9cdad877da549595").into(), - state_root: hex!("cbd5e841afef5103a613bb9a89199d39c40751af1af7cabadfa8e1fd49c4be09").into(), - body_root: hex!("c9b5074ac3043ae2ad6da067b0787d61b6f1611b560ef80860ce62564534a53a").into(), - }, - sync_aggregate: SyncAggregate{ - sync_committee_bits: hex!("ffffffff"), - sync_committee_signature: hex!("80628825caef48ef13b4ffda96fcee74743609fe3537b7cd0ca8bc25c8a540b96dfbe23bdd0a60a8db70b2c48f090c1d03a25923207a193724d98e140db90ab692cd00ec2b4d3c0c4cbff13b4ab343e0c896e15cba08f9d82c392b1c982a8115").into(), - }, - signature_slot: 185, - next_sync_committee_update: None, - finalized_header: BeaconHeader { - slot: 168, - proposer_index: 1, - parent_root: hex!("bb8245e89f5d7d9191c559425b8522487d98b8f2c9b814a158656eaf06caaa06").into(), - state_root: hex!("98b4d1141cfc324ce7095417d81b28995587e9a50ebb4872254187155e6b160c").into(), - body_root: hex!("c1a089291dbc744be622356dcbdd65fe053dcb908056511e5148f73a3d5c8a7e").into(), - }, - finality_branch: vec![ - hex!("1500000000000000000000000000000000000000000000000000000000000000").into(), - hex!("10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7").into(), - hex!("c2374959a44ad09eb825ada636c430d530e656d7f06dccbcf2ca8b6dc834b188").into(), - hex!("97a3662f859b89f96d7c6ce03496c353df5f6c225455f3f2c5edde329f5a94d1").into(), - hex!("4c4720ad9a38628c6774dbd1180d026aceb0be3cb0085d531b1e09faf014328a").into(), - hex!("c3d59497774f8f1c13fda9f9c6b4f773efabbac8a24d914dc7cf02874d5f5658").into(), - ], - block_roots_root: hex!("dff54b382531f4af2cb6e5b27ea905cc8e19b48f3ae8e02955f859e6bfd37e42").into(), - block_roots_branch: vec![ - hex!("8f957e090dec42d80c118d24c0e841681e82d3b330707729cb939d538c208fb7").into(), - hex!("4d33691095103fbf0df53ae0ea14378d721356b54592019050fc532bfef42d0c").into(), - hex!("bc9b31cd5d18358bff3038fab52101cfd5c56c75539449d988c5a789200fb264").into(), - hex!("7d57e424243eeb39169edccf9dab962ba8d80a9575179799bbd509c95316d8df").into(), - hex!("c07eeb9da14bcedb7dd225a68b92f578ef0b86187724879e5171d5de8a00be3a").into(), - ] - }) -} - -pub fn make_execution_header_update() -> Box { - Box::new(ExecutionHeaderUpdate { - header: BeaconHeader { - slot: 166, - proposer_index: 7, - parent_root: hex!("da28a205118aaf4aa69a3fb4eb7a565541b7172cc77771ec886b54b6f5bc10f3").into(), - state_root: hex!("179a6249c3e86ebcc9c71a0fc604a825a5fb5dd1602177681c54dc7e09af4265").into(), - body_root: hex!("e1290e50d64f043594bcac66824b04eb3047ae4174188e40106235183f47074c").into(), - }, - ancestry_proof: Some(AncestryProof { - header_branch: vec![ - hex!("bb8245e89f5d7d9191c559425b8522487d98b8f2c9b814a158656eaf06caaa06").into(), - hex!("ab498fef414d709fcac589217246527b82c25706fa800f21d543c83a0ccc59a2").into(), - hex!("de054acbf636cf9f1692137f78179381b5b0328b49fbc4d324eb8e897b41f52c").into(), - hex!("c472fde1df644788c92208467ff5aad686ce55bab1570917e8de1922296666fd").into(), - hex!("11a71c67676c72696c452d875318501cd50968106f72fb611bfe5952285516f8").into(), - hex!("6d2bd2b6cd84ddadc89df27f3f7f9141bb88c742a30123c77eefebef9d5f6667").into(), - ], - finalized_block_root: hex!("be7d9cc4483ed0065fc7c32e2a783ca3782d8dbd7bfe899fd7c0bcee82f11629").into(), - }), - execution_header: ExecutionPayloadHeader { - parent_hash: hex!("96b27b6e0919c19a70c4a2f7136fd59d2e63a3ba0453a86775add3f2dd681cea").into(), - fee_recipient: hex!("0000000000000000000000000000000000000000").into(), - state_root: hex!("b847ee60946ebdb5bd92c22385da44b8a9aea4c6779f1a1402cc06e22b76fb4a").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").into(), - prev_randao: hex!("e6c6665aa502e12dd8f5937da2eb7f7fe7a78bc9a900c9321412b8ddd4d72325").into(), - block_number: 166, - gas_limit: 68022694, - gas_used: 0, - timestamp: 1704700423, - extra_data: hex!("d983010d05846765746888676f312e32312e318664617277696e").into(), - base_fee_per_gas: U256::from(7_u64), - block_hash: hex!("1871ded7b2b8b4b5b358c904104704811b15aeefc24e49daa2a1a68176d6553a").into(), - transactions_root: hex!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1").into(), - withdrawals_root: hex!("28ba1834a3a7b657460ce79fa3a1d909ab8828fd557659d4d0554a9bdbc0ec30").into(), - }, - execution_branch: vec![ - hex!("276d006ecfe51451787321ef00417b194e90b35d4106bd7d51372f39918a4531").into(), - hex!("336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e").into(), - hex!("db56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71").into(), - hex!("6b8ff91d1be713c644ef9b3e5b77323897930c342fd12615c0d2142bee5cd1d7").into(), - ], - }) -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/mod.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/mod.rs deleted file mode 100644 index 807d4de14eed..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/mod.rs +++ /dev/null @@ -1,166 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; -mod util; - -use crate::Pallet as EthereumBeaconClient; -use frame_benchmarking::v2::*; -use frame_system::RawOrigin; - -#[cfg(feature = "beacon-spec-minimal")] -mod fixtures_minimal; -#[cfg(feature = "beacon-spec-minimal")] -use fixtures_minimal::*; - -#[cfg(not(feature = "beacon-spec-minimal"))] -mod fixtures_mainnet; -#[cfg(not(feature = "beacon-spec-minimal"))] -use fixtures_mainnet::*; - -use primitives::{ - fast_aggregate_verify, prepare_aggregate_pubkey, prepare_aggregate_signature, - verify_merkle_branch, -}; -use util::*; - -#[benchmarks] -mod benchmarks { - use super::*; - - #[benchmark] - fn force_checkpoint() -> Result<(), BenchmarkError> { - let checkpoint_update = make_checkpoint(); - let block_root: H256 = checkpoint_update.header.hash_tree_root().unwrap(); - - #[extrinsic_call] - _(RawOrigin::Root, Box::new(*checkpoint_update)); - - assert!(>::get() == block_root); - assert!(>::get(block_root).is_some()); - - Ok(()) - } - - #[benchmark] - fn submit() -> Result<(), BenchmarkError> { - let caller: T::AccountId = whitelisted_caller(); - let checkpoint_update = make_checkpoint(); - let finalized_header_update = make_finalized_header_update(); - let block_root: H256 = finalized_header_update.finalized_header.hash_tree_root().unwrap(); - EthereumBeaconClient::::process_checkpoint_update(&checkpoint_update)?; - - #[extrinsic_call] - submit(RawOrigin::Signed(caller.clone()), Box::new(*finalized_header_update)); - - assert!(>::get() == block_root); - assert!(>::get(block_root).is_some()); - - Ok(()) - } - - #[benchmark] - fn submit_with_sync_committee() -> Result<(), BenchmarkError> { - let caller: T::AccountId = whitelisted_caller(); - let checkpoint_update = make_checkpoint(); - let sync_committee_update = make_sync_committee_update(); - EthereumBeaconClient::::process_checkpoint_update(&checkpoint_update)?; - - #[extrinsic_call] - submit(RawOrigin::Signed(caller.clone()), Box::new(*sync_committee_update)); - - assert!(>::exists()); - - Ok(()) - } - - #[benchmark] - fn submit_execution_header() -> Result<(), BenchmarkError> { - let caller: T::AccountId = whitelisted_caller(); - let checkpoint_update = make_checkpoint(); - let finalized_header_update = make_finalized_header_update(); - let execution_header_update = make_execution_header_update(); - let execution_header_hash = execution_header_update.execution_header.block_hash; - EthereumBeaconClient::::process_checkpoint_update(&checkpoint_update)?; - EthereumBeaconClient::::process_update(&finalized_header_update)?; - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone()), Box::new(*execution_header_update)); - - assert!(>::contains_key(execution_header_hash)); - - Ok(()) - } - - #[benchmark(extra)] - fn bls_fast_aggregate_verify_pre_aggregated() -> Result<(), BenchmarkError> { - EthereumBeaconClient::::process_checkpoint_update(&make_checkpoint())?; - let update = make_sync_committee_update(); - let participant_pubkeys = participant_pubkeys::(&update)?; - let signing_root = signing_root::(&update)?; - let agg_sig = - prepare_aggregate_signature(&update.sync_aggregate.sync_committee_signature).unwrap(); - let agg_pub_key = prepare_aggregate_pubkey(&participant_pubkeys).unwrap(); - - #[block] - { - agg_sig.fast_aggregate_verify_pre_aggregated(signing_root.as_bytes(), &agg_pub_key); - } - - Ok(()) - } - - #[benchmark(extra)] - fn bls_fast_aggregate_verify() -> Result<(), BenchmarkError> { - EthereumBeaconClient::::process_checkpoint_update(&make_checkpoint())?; - let update = make_sync_committee_update(); - let current_sync_committee = >::get(); - let absent_pubkeys = absent_pubkeys::(&update)?; - let signing_root = signing_root::(&update)?; - - #[block] - { - fast_aggregate_verify( - ¤t_sync_committee.aggregate_pubkey, - &absent_pubkeys, - signing_root, - &update.sync_aggregate.sync_committee_signature, - ) - .unwrap(); - } - - Ok(()) - } - - #[benchmark(extra)] - fn verify_merkle_proof() -> Result<(), BenchmarkError> { - EthereumBeaconClient::::process_checkpoint_update(&make_checkpoint())?; - let update = make_sync_committee_update(); - let block_root: H256 = update.finalized_header.hash_tree_root().unwrap(); - - #[block] - { - verify_merkle_branch( - block_root, - &update.finality_branch, - config::FINALIZED_ROOT_SUBTREE_INDEX, - config::FINALIZED_ROOT_DEPTH, - update.attested_header.state_root, - ); - } - - Ok(()) - } - - #[cfg(feature = "beacon-spec-minimal")] - impl_benchmark_test_suite!( - EthereumBeaconClient, - crate::mock::minimal::new_tester(), - crate::mock::minimal::Test - ); - #[cfg(not(feature = "beacon-spec-minimal"))] - impl_benchmark_test_suite!( - EthereumBeaconClient, - crate::mock::mainnet::new_tester(), - crate::mock::mainnet::Test - ); -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/util.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/util.rs deleted file mode 100644 index 7e5ded6e1f0d..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/benchmarking/util.rs +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{ - decompress_sync_committee_bits, Config, CurrentSyncCommittee, Pallet as EthereumBeaconClient, - Update, ValidatorsRoot, Vec, -}; -use primitives::PublicKeyPrepared; -use sp_core::H256; - -pub fn participant_pubkeys( - update: &Update, -) -> Result, &'static str> { - let sync_committee_bits = - decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits); - let current_sync_committee = >::get(); - let pubkeys = EthereumBeaconClient::::find_pubkeys( - &sync_committee_bits, - (*current_sync_committee.pubkeys).as_ref(), - true, - ); - Ok(pubkeys) -} - -pub fn absent_pubkeys(update: &Update) -> Result, &'static str> { - let sync_committee_bits = - decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits); - let current_sync_committee = >::get(); - let pubkeys = EthereumBeaconClient::::find_pubkeys( - &sync_committee_bits, - (*current_sync_committee.pubkeys).as_ref(), - false, - ); - Ok(pubkeys) -} - -pub fn signing_root(update: &Update) -> Result { - let validators_root = >::get(); - let signing_root = EthereumBeaconClient::::signing_root( - &update.attested_header, - validators_root, - update.signature_slot, - )?; - Ok(signing_root) -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mainnet.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mainnet.rs deleted file mode 100644 index 3d22ad82cec0..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mainnet.rs +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pub const SLOTS_PER_EPOCH: usize = 32; -pub const SECONDS_PER_SLOT: usize = 12; -pub const EPOCHS_PER_SYNC_COMMITTEE_PERIOD: usize = 256; -pub const SYNC_COMMITTEE_SIZE: usize = 512; -pub const SYNC_COMMITTEE_BITS_SIZE: usize = SYNC_COMMITTEE_SIZE / 8; -pub const SLOTS_PER_HISTORICAL_ROOT: usize = 8192; -pub const IS_MINIMAL: bool = false; -pub const BLOCK_ROOT_AT_INDEX_DEPTH: usize = 13; diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/minimal.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/minimal.rs deleted file mode 100644 index affa86db9761..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/minimal.rs +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pub const SLOTS_PER_EPOCH: usize = 8; -pub const SECONDS_PER_SLOT: usize = 6; -pub const EPOCHS_PER_SYNC_COMMITTEE_PERIOD: usize = 8; -pub const SYNC_COMMITTEE_SIZE: usize = 32; -pub const SYNC_COMMITTEE_BITS_SIZE: usize = SYNC_COMMITTEE_SIZE / 8; -pub const SLOTS_PER_HISTORICAL_ROOT: usize = 64; -pub const IS_MINIMAL: bool = true; -pub const BLOCK_ROOT_AT_INDEX_DEPTH: usize = 6; diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mod.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mod.rs deleted file mode 100644 index d20743b846e4..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/config/mod.rs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use primitives::merkle_proof::{generalized_index_length, subtree_index}; -use static_assertions::const_assert; - -pub mod mainnet; -pub mod minimal; - -#[cfg(feature = "beacon-spec-minimal")] -pub use minimal::*; - -#[cfg(not(feature = "beacon-spec-minimal"))] -pub use mainnet::*; - -// Generalized Indices - -// get_generalized_index(BeaconState, 'block_roots') -pub const BLOCK_ROOTS_INDEX: usize = 37; -pub const BLOCK_ROOTS_SUBTREE_INDEX: usize = subtree_index(BLOCK_ROOTS_INDEX); -pub const BLOCK_ROOTS_DEPTH: usize = generalized_index_length(BLOCK_ROOTS_INDEX); - -// get_generalized_index(BeaconState, 'finalized_checkpoint', 'root') -pub const FINALIZED_ROOT_INDEX: usize = 105; -pub const FINALIZED_ROOT_SUBTREE_INDEX: usize = subtree_index(FINALIZED_ROOT_INDEX); -pub const FINALIZED_ROOT_DEPTH: usize = generalized_index_length(FINALIZED_ROOT_INDEX); - -// get_generalized_index(BeaconState, 'current_sync_committee') -pub const CURRENT_SYNC_COMMITTEE_INDEX: usize = 54; -pub const CURRENT_SYNC_COMMITTEE_SUBTREE_INDEX: usize = subtree_index(CURRENT_SYNC_COMMITTEE_INDEX); -pub const CURRENT_SYNC_COMMITTEE_DEPTH: usize = - generalized_index_length(CURRENT_SYNC_COMMITTEE_INDEX); - -// get_generalized_index(BeaconState, 'next_sync_committee') -pub const NEXT_SYNC_COMMITTEE_INDEX: usize = 55; -pub const NEXT_SYNC_COMMITTEE_SUBTREE_INDEX: usize = subtree_index(NEXT_SYNC_COMMITTEE_INDEX); -pub const NEXT_SYNC_COMMITTEE_DEPTH: usize = generalized_index_length(NEXT_SYNC_COMMITTEE_INDEX); - -// get_generalized_index(BeaconBlockBody, 'execution_payload') -pub const EXECUTION_HEADER_INDEX: usize = 25; -pub const EXECUTION_HEADER_SUBTREE_INDEX: usize = subtree_index(EXECUTION_HEADER_INDEX); -pub const EXECUTION_HEADER_DEPTH: usize = generalized_index_length(EXECUTION_HEADER_INDEX); - -pub const MAX_EXTRA_DATA_BYTES: usize = 32; -pub const MAX_LOGS_BLOOM_SIZE: usize = 256; -pub const MAX_FEE_RECIPIENT_SIZE: usize = 20; - -pub const MAX_BRANCH_PROOF_SIZE: usize = 20; - -/// DomainType('0x07000000') -/// -pub const DOMAIN_SYNC_COMMITTEE: [u8; 4] = [7, 0, 0, 0]; - -pub const PUBKEY_SIZE: usize = 48; -pub const SIGNATURE_SIZE: usize = 96; - -const_assert!(SYNC_COMMITTEE_BITS_SIZE == SYNC_COMMITTEE_SIZE / 8); diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/functions.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/functions.rs deleted file mode 100644 index 751e63c7f86a..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/functions.rs +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::config::{ - EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH, SYNC_COMMITTEE_BITS_SIZE, - SYNC_COMMITTEE_SIZE, -}; - -/// Decompress packed bitvector into byte vector according to SSZ deserialization rules. Each byte -/// in the decompressed vector is either 0 or 1. -pub fn decompress_sync_committee_bits( - input: [u8; SYNC_COMMITTEE_BITS_SIZE], -) -> [u8; SYNC_COMMITTEE_SIZE] { - primitives::decompress_sync_committee_bits::( - input, - ) -} - -/// Compute the sync committee period in which a slot is contained. -pub fn compute_period(slot: u64) -> u64 { - slot / SLOTS_PER_EPOCH as u64 / EPOCHS_PER_SYNC_COMMITTEE_PERIOD as u64 -} - -/// Compute epoch in which a slot is contained. -pub fn compute_epoch(slot: u64, slots_per_epoch: u64) -> u64 { - slot / slots_per_epoch -} - -/// Sums the bit vector of sync committee participation. -pub fn sync_committee_sum(sync_committee_bits: &[u8]) -> u32 { - sync_committee_bits.iter().fold(0, |acc: u32, x| acc + *x as u32) -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/impls.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/impls.rs deleted file mode 100644 index 300431d87707..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/impls.rs +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use snowbridge_core::inbound::{ - VerificationError::{self, *}, - *, -}; -use snowbridge_ethereum::Receipt; - -impl Verifier for Pallet { - /// Verify a message by verifying the existence of the corresponding - /// Ethereum log in a block. Returns the log if successful. The execution header containing - /// the log should be in the beacon client storage, meaning it has been verified and is an - /// ancestor of a finalized beacon block. - fn verify(event_log: &Log, proof: &Proof) -> Result<(), VerificationError> { - log::info!( - target: "ethereum-client", - "💫 Verifying message with block hash {}", - proof.block_hash, - ); - - let header = >::get(proof.block_hash).ok_or(HeaderNotFound)?; - - let receipt = match Self::verify_receipt_inclusion(header.receipts_root, proof) { - Ok(receipt) => receipt, - Err(err) => { - log::error!( - target: "ethereum-client", - "💫 Verification of receipt inclusion failed for block {}: {:?}", - proof.block_hash, - err - ); - return Err(err) - }, - }; - - log::trace!( - target: "ethereum-client", - "💫 Verified receipt inclusion for transaction at index {} in block {}", - proof.tx_index, proof.block_hash, - ); - - event_log.validate().map_err(|_| InvalidLog)?; - - // Convert snowbridge_core::inbound::Log to snowbridge_ethereum::Log. - let event_log = snowbridge_ethereum::Log { - address: event_log.address, - topics: event_log.topics.clone(), - data: event_log.data.clone(), - }; - - if !receipt.contains_log(&event_log) { - log::error!( - target: "ethereum-client", - "💫 Event log not found in receipt for transaction at index {} in block {}", - proof.tx_index, proof.block_hash, - ); - return Err(LogNotFound) - } - - log::info!( - target: "ethereum-client", - "💫 Receipt verification successful for {}", - proof.block_hash, - ); - - Ok(()) - } -} - -impl Pallet { - /// Verifies that the receipt encoded in `proof.data` is included in the block given by - /// `proof.block_hash`. - pub fn verify_receipt_inclusion( - receipts_root: H256, - proof: &Proof, - ) -> Result { - let result = verify_receipt_proof(receipts_root, &proof.data.1).ok_or(InvalidProof)?; - - match result { - Ok(receipt) => Ok(receipt), - Err(err) => { - log::trace!( - target: "ethereum-client", - "💫 Failed to decode transaction receipt: {}", - err - ); - Err(InvalidProof) - }, - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/lib.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/lib.rs deleted file mode 100644 index c99458441a5c..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/lib.rs +++ /dev/null @@ -1,841 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Ethereum Beacon Client -//! -//! A light client that verifies consensus updates signed by the sync committee of the beacon chain. -//! -//! # Extrinsics -//! -//! ## Governance -//! -//! * [`Call::force_checkpoint`]: Set the initial trusted consensus checkpoint. -//! * [`Call::set_operating_mode`]: Set the operating mode of the pallet. Can be used to disable -//! processing of conensus updates. -//! -//! ## Consensus Updates -//! -//! * [`Call::submit`]: Submit a finalized beacon header with an optional sync committee update -//! * [`Call::submit_execution_header`]: Submit an execution header together with an ancestry proof -//! that can be verified against an already imported finalized beacon header. -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod config; -pub mod functions; -pub mod impls; -pub mod types; -pub mod weights; - -#[cfg(any(test, feature = "fuzzing"))] -pub mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -use frame_support::{ - dispatch::DispatchResult, pallet_prelude::OptionQuery, traits::Get, transactional, -}; -use frame_system::ensure_signed; -use primitives::{ - fast_aggregate_verify, verify_merkle_branch, verify_receipt_proof, BeaconHeader, BlsError, - CompactBeaconState, CompactExecutionHeader, ExecutionHeaderState, ForkData, ForkVersion, - ForkVersions, PublicKeyPrepared, SigningData, -}; -use snowbridge_core::{BasicOperatingMode, RingBufferMap}; -use sp_core::H256; -use sp_std::prelude::*; -pub use weights::WeightInfo; - -use functions::{ - compute_epoch, compute_period, decompress_sync_committee_bits, sync_committee_sum, -}; -pub use types::ExecutionHeaderBuffer; -use types::{ - CheckpointUpdate, ExecutionHeaderUpdate, FinalizedBeaconStateBuffer, SyncCommitteePrepared, - Update, -}; - -pub use pallet::*; - -pub use config::SLOTS_PER_HISTORICAL_ROOT; - -pub const LOG_TARGET: &str = "ethereum-client"; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[derive(scale_info::TypeInfo, codec::Encode, codec::Decode, codec::MaxEncodedLen)] - #[codec(mel_bound(T: Config))] - #[scale_info(skip_type_params(T))] - pub struct MaxFinalizedHeadersToKeep(PhantomData); - impl Get for MaxFinalizedHeadersToKeep { - fn get() -> u32 { - // Consider max latency allowed between LatestFinalizedState and LatestExecutionState is - // the total slots in one sync_committee_period so 1 should be fine we keep 2 periods - // here for redundancy. - const MAX_REDUNDANCY: u32 = 2; - config::EPOCHS_PER_SYNC_COMMITTEE_PERIOD as u32 * MAX_REDUNDANCY - } - } - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - #[pallet::constant] - type ForkVersions: Get; - /// Maximum number of execution headers to keep - #[pallet::constant] - type MaxExecutionHeadersToKeep: Get; - type WeightInfo: WeightInfo; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - BeaconHeaderImported { - block_hash: H256, - slot: u64, - }, - ExecutionHeaderImported { - block_hash: H256, - block_number: u64, - }, - SyncCommitteeUpdated { - period: u64, - }, - /// Set OperatingMode - OperatingModeChanged { - mode: BasicOperatingMode, - }, - } - - #[pallet::error] - pub enum Error { - SkippedSyncCommitteePeriod, - /// Attested header is older than latest finalized header. - IrrelevantUpdate, - NotBootstrapped, - SyncCommitteeParticipantsNotSupermajority, - InvalidHeaderMerkleProof, - InvalidSyncCommitteeMerkleProof, - InvalidExecutionHeaderProof, - InvalidAncestryMerkleProof, - InvalidBlockRootsRootMerkleProof, - HeaderNotFinalized, - BlockBodyHashTreeRootFailed, - HeaderHashTreeRootFailed, - SyncCommitteeHashTreeRootFailed, - SigningRootHashTreeRootFailed, - ForkDataHashTreeRootFailed, - ExpectedFinalizedHeaderNotStored, - BLSPreparePublicKeysFailed, - BLSVerificationFailed(BlsError), - InvalidUpdateSlot, - /// The given update is not in the expected period, or the given next sync committee does - /// not match the next sync committee in storage. - InvalidSyncCommitteeUpdate, - ExecutionHeaderTooFarBehind, - ExecutionHeaderSkippedBlock, - Halted, - } - - /// Latest imported checkpoint root - #[pallet::storage] - #[pallet::getter(fn initial_checkpoint_root)] - pub(super) type InitialCheckpointRoot = StorageValue<_, H256, ValueQuery>; - - /// Latest imported finalized block root - #[pallet::storage] - #[pallet::getter(fn latest_finalized_block_root)] - pub(super) type LatestFinalizedBlockRoot = StorageValue<_, H256, ValueQuery>; - - /// Beacon state by finalized block root - #[pallet::storage] - #[pallet::getter(fn finalized_beacon_state)] - pub(super) type FinalizedBeaconState = - StorageMap<_, Identity, H256, CompactBeaconState, OptionQuery>; - - /// Finalized Headers: Current position in ring buffer - #[pallet::storage] - pub(crate) type FinalizedBeaconStateIndex = StorageValue<_, u32, ValueQuery>; - - /// Finalized Headers: Mapping of ring buffer index to a pruning candidate - #[pallet::storage] - pub(crate) type FinalizedBeaconStateMapping = - StorageMap<_, Identity, u32, H256, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn validators_root)] - pub(super) type ValidatorsRoot = StorageValue<_, H256, ValueQuery>; - - /// Sync committee for current period - #[pallet::storage] - pub(super) type CurrentSyncCommittee = - StorageValue<_, SyncCommitteePrepared, ValueQuery>; - - /// Sync committee for next period - #[pallet::storage] - pub(super) type NextSyncCommittee = - StorageValue<_, SyncCommitteePrepared, ValueQuery>; - - /// Latest imported execution header - #[pallet::storage] - #[pallet::getter(fn latest_execution_state)] - pub(super) type LatestExecutionState = - StorageValue<_, ExecutionHeaderState, ValueQuery>; - - /// Execution Headers - #[pallet::storage] - pub type ExecutionHeaders = - StorageMap<_, Identity, H256, CompactExecutionHeader, OptionQuery>; - - /// Execution Headers: Current position in ring buffer - #[pallet::storage] - pub type ExecutionHeaderIndex = StorageValue<_, u32, ValueQuery>; - - /// Execution Headers: Mapping of ring buffer index to a pruning candidate - #[pallet::storage] - pub type ExecutionHeaderMapping = StorageMap<_, Identity, u32, H256, ValueQuery>; - - /// The current operating mode of the pallet. - #[pallet::storage] - #[pallet::getter(fn operating_mode)] - pub type OperatingMode = StorageValue<_, BasicOperatingMode, ValueQuery>; - - #[pallet::call] - impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::force_checkpoint())] - #[transactional] - /// Used for pallet initialization and light client resetting. Needs to be called by - /// the root origin. - pub fn force_checkpoint( - origin: OriginFor, - update: Box, - ) -> DispatchResult { - ensure_root(origin)?; - Self::process_checkpoint_update(&update)?; - Ok(()) - } - - #[pallet::call_index(1)] - #[pallet::weight({ - match update.next_sync_committee_update { - None => T::WeightInfo::submit(), - Some(_) => T::WeightInfo::submit_with_sync_committee(), - } - })] - #[transactional] - /// Submits a new finalized beacon header update. The update may contain the next - /// sync committee. - pub fn submit(origin: OriginFor, update: Box) -> DispatchResult { - ensure_signed(origin)?; - ensure!(!Self::operating_mode().is_halted(), Error::::Halted); - Self::process_update(&update)?; - Ok(()) - } - - #[pallet::call_index(2)] - #[pallet::weight(T::WeightInfo::submit_execution_header())] - #[transactional] - /// Submits a new execution header update. The relevant related beacon header - /// is also included to prove the execution header, as well as ancestry proof data. - pub fn submit_execution_header( - origin: OriginFor, - update: Box, - ) -> DispatchResult { - ensure_signed(origin)?; - ensure!(!Self::operating_mode().is_halted(), Error::::Halted); - Self::process_execution_header_update(&update)?; - Ok(()) - } - - /// Halt or resume all pallet operations. May only be called by root. - #[pallet::call_index(3)] - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operating_mode( - origin: OriginFor, - mode: BasicOperatingMode, - ) -> DispatchResult { - ensure_root(origin)?; - OperatingMode::::set(mode); - Self::deposit_event(Event::OperatingModeChanged { mode }); - Ok(()) - } - } - - impl Pallet { - /// Forces a finalized beacon header checkpoint update. The current sync committee, - /// with a header attesting to the current sync committee, should be provided. - /// An `block_roots` proof should also be provided. This is used for ancestry proofs - /// for execution header updates. - pub(crate) fn process_checkpoint_update(update: &CheckpointUpdate) -> DispatchResult { - let sync_committee_root = update - .current_sync_committee - .hash_tree_root() - .map_err(|_| Error::::SyncCommitteeHashTreeRootFailed)?; - - // Verifies the sync committee in the Beacon state. - ensure!( - verify_merkle_branch( - sync_committee_root, - &update.current_sync_committee_branch, - config::CURRENT_SYNC_COMMITTEE_SUBTREE_INDEX, - config::CURRENT_SYNC_COMMITTEE_DEPTH, - update.header.state_root - ), - Error::::InvalidSyncCommitteeMerkleProof - ); - - let header_root: H256 = update - .header - .hash_tree_root() - .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - - // This is used for ancestry proofs in ExecutionHeader updates. This verifies the - // BeaconState: the beacon state root is the tree root; the `block_roots` hash is the - // tree leaf. - ensure!( - verify_merkle_branch( - update.block_roots_root, - &update.block_roots_branch, - config::BLOCK_ROOTS_SUBTREE_INDEX, - config::BLOCK_ROOTS_DEPTH, - update.header.state_root - ), - Error::::InvalidBlockRootsRootMerkleProof - ); - - let sync_committee_prepared: SyncCommitteePrepared = (&update.current_sync_committee) - .try_into() - .map_err(|_| >::BLSPreparePublicKeysFailed)?; - >::set(sync_committee_prepared); - >::kill(); - InitialCheckpointRoot::::set(header_root); - >::kill(); - - Self::store_validators_root(update.validators_root); - Self::store_finalized_header(header_root, update.header, update.block_roots_root)?; - - Ok(()) - } - - pub(crate) fn process_update(update: &Update) -> DispatchResult { - Self::cross_check_execution_state()?; - Self::verify_update(update)?; - Self::apply_update(update)?; - Ok(()) - } - - /// Cross check to make sure that execution header import does not fall too far behind - /// finalised beacon header import. If that happens just return an error and pause - /// processing until execution header processing has caught up. - pub(crate) fn cross_check_execution_state() -> DispatchResult { - let latest_finalized_state = - FinalizedBeaconState::::get(LatestFinalizedBlockRoot::::get()) - .ok_or(Error::::NotBootstrapped)?; - let latest_execution_state = Self::latest_execution_state(); - // The execution header import should be at least within the slot range of a sync - // committee period. - let max_latency = config::EPOCHS_PER_SYNC_COMMITTEE_PERIOD * config::SLOTS_PER_EPOCH; - ensure!( - latest_execution_state.beacon_slot == 0 || - latest_finalized_state.slot < - latest_execution_state.beacon_slot + max_latency as u64, - Error::::ExecutionHeaderTooFarBehind - ); - Ok(()) - } - - /// References and strictly follows - /// Verifies that provided next sync committee is valid through a series of checks - /// (including checking that a sync committee period isn't skipped and that the header is - /// signed by the current sync committee. - fn verify_update(update: &Update) -> DispatchResult { - // Verify sync committee has sufficient participants. - let participation = - decompress_sync_committee_bits(update.sync_aggregate.sync_committee_bits); - Self::sync_committee_participation_is_supermajority(&participation)?; - - // Verify update does not skip a sync committee period. - ensure!( - update.signature_slot > update.attested_header.slot && - update.attested_header.slot >= update.finalized_header.slot, - Error::::InvalidUpdateSlot - ); - // Retrieve latest finalized state. - let latest_finalized_state = - FinalizedBeaconState::::get(LatestFinalizedBlockRoot::::get()) - .ok_or(Error::::NotBootstrapped)?; - let store_period = compute_period(latest_finalized_state.slot); - let signature_period = compute_period(update.signature_slot); - if >::exists() { - ensure!( - (store_period..=store_period + 1).contains(&signature_period), - Error::::SkippedSyncCommitteePeriod - ) - } else { - ensure!(signature_period == store_period, Error::::SkippedSyncCommitteePeriod) - } - - // Verify update is relevant. - let update_attested_period = compute_period(update.attested_header.slot); - let update_has_next_sync_committee = !>::exists() && - (update.next_sync_committee_update.is_some() && - update_attested_period == store_period); - ensure!( - update.attested_header.slot > latest_finalized_state.slot || - update_has_next_sync_committee, - Error::::IrrelevantUpdate - ); - - // Verify that the `finality_branch`, if present, confirms `finalized_header` to match - // the finalized checkpoint root saved in the state of `attested_header`. - let finalized_block_root: H256 = update - .finalized_header - .hash_tree_root() - .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - ensure!( - verify_merkle_branch( - finalized_block_root, - &update.finality_branch, - config::FINALIZED_ROOT_SUBTREE_INDEX, - config::FINALIZED_ROOT_DEPTH, - update.attested_header.state_root - ), - Error::::InvalidHeaderMerkleProof - ); - - // Though following check does not belong to ALC spec we verify block_roots_root to - // match the finalized checkpoint root saved in the state of `finalized_header` so to - // cache it for later use in `verify_ancestry_proof`. - ensure!( - verify_merkle_branch( - update.block_roots_root, - &update.block_roots_branch, - config::BLOCK_ROOTS_SUBTREE_INDEX, - config::BLOCK_ROOTS_DEPTH, - update.finalized_header.state_root - ), - Error::::InvalidBlockRootsRootMerkleProof - ); - - // Verify that the `next_sync_committee`, if present, actually is the next sync - // committee saved in the state of the `attested_header`. - if let Some(next_sync_committee_update) = &update.next_sync_committee_update { - let sync_committee_root = next_sync_committee_update - .next_sync_committee - .hash_tree_root() - .map_err(|_| Error::::SyncCommitteeHashTreeRootFailed)?; - if update_attested_period == store_period && >::exists() { - let next_committee_root = >::get().root; - ensure!( - sync_committee_root == next_committee_root, - Error::::InvalidSyncCommitteeUpdate - ); - } - ensure!( - verify_merkle_branch( - sync_committee_root, - &next_sync_committee_update.next_sync_committee_branch, - config::NEXT_SYNC_COMMITTEE_SUBTREE_INDEX, - config::NEXT_SYNC_COMMITTEE_DEPTH, - update.attested_header.state_root - ), - Error::::InvalidSyncCommitteeMerkleProof - ); - } - - // Verify sync committee aggregate signature. - let sync_committee = if signature_period == store_period { - >::get() - } else { - >::get() - }; - let absent_pubkeys = - Self::find_pubkeys(&participation, (*sync_committee.pubkeys).as_ref(), false); - let signing_root = Self::signing_root( - &update.attested_header, - Self::validators_root(), - update.signature_slot, - )?; - // Improvement here per - // suggested start from the full set aggregate_pubkey then subtracting the absolute - // minority that did not participate. - fast_aggregate_verify( - &sync_committee.aggregate_pubkey, - &absent_pubkeys, - signing_root, - &update.sync_aggregate.sync_committee_signature, - ) - .map_err(|e| Error::::BLSVerificationFailed(e))?; - - Ok(()) - } - - /// Reference and strictly follows DispatchResult { - let latest_finalized_state = - FinalizedBeaconState::::get(LatestFinalizedBlockRoot::::get()) - .ok_or(Error::::NotBootstrapped)?; - if let Some(next_sync_committee_update) = &update.next_sync_committee_update { - let store_period = compute_period(latest_finalized_state.slot); - let update_finalized_period = compute_period(update.finalized_header.slot); - let sync_committee_prepared: SyncCommitteePrepared = (&next_sync_committee_update - .next_sync_committee) - .try_into() - .map_err(|_| >::BLSPreparePublicKeysFailed)?; - - if !>::exists() { - ensure!( - update_finalized_period == store_period, - >::InvalidSyncCommitteeUpdate - ); - >::set(sync_committee_prepared); - } else if update_finalized_period == store_period + 1 { - >::set(>::get()); - >::set(sync_committee_prepared); - } - log::info!( - target: LOG_TARGET, - "💫 SyncCommitteeUpdated at period {}.", - update_finalized_period - ); - Self::deposit_event(Event::SyncCommitteeUpdated { - period: update_finalized_period, - }); - }; - - if update.finalized_header.slot > latest_finalized_state.slot { - let finalized_block_root: H256 = update - .finalized_header - .hash_tree_root() - .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - Self::store_finalized_header( - finalized_block_root, - update.finalized_header, - update.block_roots_root, - )?; - } - - Ok(()) - } - - /// Validates an execution header for import. The beacon header containing the execution - /// header is sent, plus the execution header, along with a proof that the execution header - /// is rooted in the beacon header body. - pub(crate) fn process_execution_header_update( - update: &ExecutionHeaderUpdate, - ) -> DispatchResult { - let latest_finalized_state = - FinalizedBeaconState::::get(LatestFinalizedBlockRoot::::get()) - .ok_or(Error::::NotBootstrapped)?; - // Checks that the header is an ancestor of a finalized header, using slot number. - ensure!( - update.header.slot <= latest_finalized_state.slot, - Error::::HeaderNotFinalized - ); - - // Checks that we don't skip execution headers, they need to be imported sequentially. - let latest_execution_state: ExecutionHeaderState = Self::latest_execution_state(); - ensure!( - latest_execution_state.block_number == 0 || - update.execution_header.block_number == - latest_execution_state.block_number + 1, - Error::::ExecutionHeaderSkippedBlock - ); - - // Gets the hash tree root of the execution header, in preparation for the execution - // header proof (used to check that the execution header is rooted in the beacon - // header body. - let execution_header_root: H256 = update - .execution_header - .hash_tree_root() - .map_err(|_| Error::::BlockBodyHashTreeRootFailed)?; - - ensure!( - verify_merkle_branch( - execution_header_root, - &update.execution_branch, - config::EXECUTION_HEADER_SUBTREE_INDEX, - config::EXECUTION_HEADER_DEPTH, - update.header.body_root - ), - Error::::InvalidExecutionHeaderProof - ); - - let block_root: H256 = update - .header - .hash_tree_root() - .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - - match &update.ancestry_proof { - Some(proof) => { - Self::verify_ancestry_proof( - block_root, - update.header.slot, - &proof.header_branch, - proof.finalized_block_root, - )?; - }, - None => { - // If the ancestry proof is not provided, we expect this header to be a - // finalized header. We need to check that the header hash matches the finalized - // header root at the expected slot. - let state = >::get(block_root) - .ok_or(Error::::ExpectedFinalizedHeaderNotStored)?; - if update.header.slot != state.slot { - return Err(Error::::ExpectedFinalizedHeaderNotStored.into()) - } - }, - } - - Self::store_execution_header( - update.execution_header.block_hash, - update.execution_header.clone().into(), - update.header.slot, - block_root, - ); - - Ok(()) - } - - /// Verify that `block_root` is an ancestor of `finalized_block_root` Used to prove that - /// an execution header is an ancestor of a finalized header (i.e. the blocks are - /// on the same chain). - fn verify_ancestry_proof( - block_root: H256, - block_slot: u64, - block_root_proof: &[H256], - finalized_block_root: H256, - ) -> DispatchResult { - let state = >::get(finalized_block_root) - .ok_or(Error::::ExpectedFinalizedHeaderNotStored)?; - - ensure!(block_slot < state.slot, Error::::HeaderNotFinalized); - - let index_in_array = block_slot % (SLOTS_PER_HISTORICAL_ROOT as u64); - let leaf_index = (SLOTS_PER_HISTORICAL_ROOT as u64) + index_in_array; - - ensure!( - verify_merkle_branch( - block_root, - block_root_proof, - leaf_index as usize, - config::BLOCK_ROOT_AT_INDEX_DEPTH, - state.block_roots_root - ), - Error::::InvalidAncestryMerkleProof - ); - - Ok(()) - } - - /// Computes the signing root for a given beacon header and domain. The hash tree root - /// of the beacon header is computed, and then the combination of the beacon header hash - /// and the domain makes up the signing root. - pub(super) fn compute_signing_root( - beacon_header: &BeaconHeader, - domain: H256, - ) -> Result { - let beacon_header_root = beacon_header - .hash_tree_root() - .map_err(|_| Error::::HeaderHashTreeRootFailed)?; - - let hash_root = SigningData { object_root: beacon_header_root, domain } - .hash_tree_root() - .map_err(|_| Error::::SigningRootHashTreeRootFailed)?; - - Ok(hash_root) - } - - /// Stores a compacted (slot and block roots root (hash of the `block_roots` beacon state - /// field, used for ancestry proof)) beacon state in a ring buffer map, with the header root - /// as map key. - fn store_finalized_header( - header_root: H256, - header: BeaconHeader, - block_roots_root: H256, - ) -> DispatchResult { - let slot = header.slot; - - >::insert( - header_root, - CompactBeaconState { slot: header.slot, block_roots_root }, - ); - >::set(header_root); - - log::info!( - target: LOG_TARGET, - "💫 Updated latest finalized block root {} at slot {}.", - header_root, - slot - ); - - Self::deposit_event(Event::BeaconHeaderImported { block_hash: header_root, slot }); - - Ok(()) - } - - /// Stores the provided execution header in pallet storage. The header is stored - /// in a ring buffer map, with the block hash as map key. The last imported execution - /// header is also kept in storage, for the relayer to check import progress. - pub fn store_execution_header( - block_hash: H256, - header: CompactExecutionHeader, - beacon_slot: u64, - beacon_block_root: H256, - ) { - let block_number = header.block_number; - - >::insert(block_hash, header); - - log::trace!( - target: LOG_TARGET, - "💫 Updated latest execution block at {} to number {}.", - block_hash, - block_number - ); - - LatestExecutionState::::mutate(|s| { - s.beacon_block_root = beacon_block_root; - s.beacon_slot = beacon_slot; - s.block_hash = block_hash; - s.block_number = block_number; - }); - - Self::deposit_event(Event::ExecutionHeaderImported { block_hash, block_number }); - } - - /// Stores the validators root in storage. Validators root is the hash tree root of all the - /// validators at genesis and is used to used to identify the chain that we are on - /// (used in conjunction with the fork version). - /// - fn store_validators_root(validators_root: H256) { - >::set(validators_root); - } - - /// Returns the domain for the domain_type and fork_version. The domain is used to - /// distinguish between the different players in the chain (see DomainTypes - /// ) and to ensure we are - /// addressing the correct chain. - /// - pub(super) fn compute_domain( - domain_type: Vec, - fork_version: ForkVersion, - genesis_validators_root: H256, - ) -> Result { - let fork_data_root = - Self::compute_fork_data_root(fork_version, genesis_validators_root)?; - - let mut domain = [0u8; 32]; - domain[0..4].copy_from_slice(&(domain_type)); - domain[4..32].copy_from_slice(&(fork_data_root.0[..28])); - - Ok(domain.into()) - } - - /// Computes the fork data root. The fork data root is a merkleization of the current - /// fork version and the genesis validators root. - fn compute_fork_data_root( - current_version: ForkVersion, - genesis_validators_root: H256, - ) -> Result { - let hash_root = ForkData { - current_version, - genesis_validators_root: genesis_validators_root.into(), - } - .hash_tree_root() - .map_err(|_| Error::::ForkDataHashTreeRootFailed)?; - - Ok(hash_root) - } - - /// Checks that the sync committee bits (the votes of the sync committee members, - /// represented by bits 0 and 1) is more than a supermajority (2/3 of the votes are - /// positive). - pub(super) fn sync_committee_participation_is_supermajority( - sync_committee_bits: &[u8], - ) -> DispatchResult { - let sync_committee_sum = sync_committee_sum(sync_committee_bits); - ensure!( - ((sync_committee_sum * 3) as usize) >= sync_committee_bits.len() * 2, - Error::::SyncCommitteeParticipantsNotSupermajority - ); - - Ok(()) - } - - /// Returns the fork version based on the current epoch. The hard fork versions - /// are defined in pallet config. - pub(super) fn compute_fork_version(epoch: u64) -> ForkVersion { - Self::select_fork_version(&T::ForkVersions::get(), epoch) - } - - /// Returns the fork version based on the current epoch. - pub(super) fn select_fork_version(fork_versions: &ForkVersions, epoch: u64) -> ForkVersion { - if epoch >= fork_versions.capella.epoch { - return fork_versions.capella.version - } - if epoch >= fork_versions.bellatrix.epoch { - return fork_versions.bellatrix.version - } - if epoch >= fork_versions.altair.epoch { - return fork_versions.altair.version - } - - fork_versions.genesis.version - } - - /// Returns a vector of public keys that participated in the sync committee block signage. - /// Sync committee bits is an array of 0s and 1s, 0 meaning the corresponding sync committee - /// member did not participate in the vote, 1 meaning they participated. - /// This method can find the absent or participating members, based on the participant - /// parameter. participant = false will return absent participants, participant = true will - /// return participating members. - pub fn find_pubkeys( - sync_committee_bits: &[u8], - sync_committee_pubkeys: &[PublicKeyPrepared], - participant: bool, - ) -> Vec { - let mut pubkeys: Vec = Vec::new(); - for (bit, pubkey) in sync_committee_bits.iter().zip(sync_committee_pubkeys.iter()) { - if *bit == u8::from(participant) { - pubkeys.push(*pubkey); - } - } - pubkeys - } - - /// Calculates signing root for BeaconHeader. The signing root is used for the message - /// value in BLS signature verification. - pub fn signing_root( - header: &BeaconHeader, - validators_root: H256, - signature_slot: u64, - ) -> Result { - let fork_version = Self::compute_fork_version(compute_epoch( - signature_slot, - config::SLOTS_PER_EPOCH as u64, - )); - let domain_type = config::DOMAIN_SYNC_COMMITTEE.to_vec(); - // Domains are used for for seeds, for signatures, and for selecting aggregators. - let domain = Self::compute_domain(domain_type, fork_version, validators_root)?; - // Hash tree root of SigningData - object root + domain - let signing_root = Self::compute_signing_root(header, domain)?; - Ok(signing_root) - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/mock.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/mock.rs deleted file mode 100644 index 217d37db8dfa..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/mock.rs +++ /dev/null @@ -1,284 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate as ethereum_beacon_client; -use crate::config; -use frame_support::parameter_types; -use hex_literal::hex; -use pallet_timestamp; -use primitives::{CompactExecutionHeader, Fork, ForkVersions}; -use snowbridge_core::inbound::{Log, Proof}; -use sp_core::H256; -use sp_runtime::traits::{BlakeTwo256, IdentityLookup}; -use std::{fs::File, path::PathBuf}; - -#[cfg(feature = "beacon-spec-minimal")] -const SPEC: &str = "minimal"; -#[cfg(not(feature = "beacon-spec-minimal"))] -const SPEC: &str = "mainnet"; - -fn load_fixture(basename: String) -> Result -where - T: for<'de> serde::Deserialize<'de>, -{ - let filepath: PathBuf = - [env!("CARGO_MANIFEST_DIR"), "tests", "fixtures", &basename].iter().collect(); - serde_json::from_reader(File::open(filepath).unwrap()) -} - -pub fn load_execution_header_update_fixture() -> primitives::ExecutionHeaderUpdate { - let basename = format!("execution-header-update.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn load_checkpoint_update_fixture( -) -> primitives::CheckpointUpdate<{ config::SYNC_COMMITTEE_SIZE }> { - let basename = format!("initial-checkpoint.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn load_sync_committee_update_fixture( -) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - let basename = format!("sync-committee-update.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn load_finalized_header_update_fixture( -) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - let basename = format!("finalized-header-update.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn load_next_sync_committee_update_fixture( -) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - let basename = format!("next-sync-committee-update.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn load_next_finalized_header_update_fixture( -) -> primitives::Update<{ config::SYNC_COMMITTEE_SIZE }, { config::SYNC_COMMITTEE_BITS_SIZE }> { - let basename = format!("next-finalized-header-update.{}.json", SPEC); - load_fixture(basename).unwrap() -} - -pub fn get_message_verification_payload() -> (Log, Proof) { - ( - Log { - address: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(), - topics: vec![ - hex!("1b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ad").into(), - hex!("00000000000000000000000000000000000000000000000000000000000003e8").into(), - hex!("0000000000000000000000000000000000000000000000000000000000000001").into(), - ], - data: hex!("0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000").into(), - }, - Proof { - block_hash: hex!("05aaa60b0f27cce9e71909508527264b77ee14da7b5bf915fcc4e32715333213").into(), - tx_index: 0, - data: (vec![ - hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb").to_vec(), - hex!("d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c185510").to_vec(), - hex!("b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646").to_vec(), - ], vec![ - hex!("f90131a0b601337b3aa10a671caa724eba641e759399979856141d3aea6b6b4ac59b889ba00c7d5dd48be9060221a02fb8fa213860b4c50d47046c8fa65ffaba5737d569e0a094601b62a1086cd9c9cb71a7ebff9e718f3217fd6e837efe4246733c0a196f63a06a4b0dd0aefc37b3c77828c8f07d1b7a2455ceb5dbfd3c77d7d6aeeddc2f7e8ca0d6e8e23142cdd8ec219e1f5d8b56aa18e456702b195deeaa210327284d42ade4a08a313d4c87023005d1ab631bbfe3f5de1e405d0e66d0bef3e033f1e5711b5521a0bf09a5d9a48b10ade82b8d6a5362a15921c8b5228a3487479b467db97411d82fa0f95cccae2a7c572ef3c566503e30bac2b2feb2d2f26eebf6d870dcf7f8cf59cea0d21fc4f68ab05bc4dcb23c67008e92c4d466437cdd6ed7aad0c008944c1855108080808080808080").to_vec(), - hex!("f851a0b9890f91ca0d77aa2a4adfaf9b9e40c94cac9e638b6d9797923865872944b646a060a634b9280e3a23fb63375e7bbdd9ab07fd379ab6a67e2312bbc112195fa358808080808080808080808080808080").to_vec(), - hex!("f9030820b9030402f90300018301d6e2b9010000000000000800000000000020040008000000000000000000000000400000008000000000000000000000000000000000000000000000000000000000042010000000001000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000002000000000000000000000000200000000000000200000000000100000000040000001000200008000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000f901f5f87a942ffa5ecdbe006d30397c7636d3e015eee251369ff842a0c965575a00553e094ca7c5d14f02e107c258dda06867cbf9e0e69f80e71bbcc1a000000000000000000000000000000000000000000000000000000000000003e8a000000000000000000000000000000000000000000000000000000000000003e8f9011c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000001b8a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004b000f000000000000000100d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec701345772617070656420457468657210574554481235003511000000000000000000000000000000000000000000f858948cf6147918a5cbb672703f879f385036f8793a24e1a01449abf21e49fd025f33495e77f7b1461caefdd3d4bb646424a3f445c4576a5ba0000000000000000000000000440edffa1352b13227e8ee646f3ea37456dec701").to_vec(), - ]), - } - ) -} - -pub fn get_message_verification_header() -> CompactExecutionHeader { - CompactExecutionHeader { - parent_hash: hex!("04a7f6ab8282203562c62f38b0ab41d32aaebe2c7ea687702b463148a6429e04") - .into(), - block_number: 55, - state_root: hex!("894d968712976d613519f973a317cb0781c7b039c89f27ea2b7ca193f7befdb3").into(), - receipts_root: hex!("cf0d1c1ba57d1e0edfb59786c7e30c2b7e12bd54612b00cd21c4eaeecedf44fb") - .into(), - } -} - -#[cfg(feature = "beacon-spec-minimal")] -pub mod minimal { - use super::*; - - use sp_runtime::BuildStorage; - - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime!( - pub enum Test { - System: frame_system::{Pallet, Call, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; - } - - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type OnSetCode = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type MaxConsumers = frame_support::traits::ConstU32<16>; - type Nonce = u64; - type Block = Block; - } - - impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = (); - type WeightInfo = (); - } - - parameter_types! { - pub const ExecutionHeadersPruneThreshold: u32 = 10; - pub const ChainForkVersions: ForkVersions = ForkVersions{ - genesis: Fork { - version: [0, 0, 0, 1], // 0x00000001 - epoch: 0, - }, - altair: Fork { - version: [1, 0, 0, 1], // 0x01000001 - epoch: 0, - }, - bellatrix: Fork { - version: [2, 0, 0, 1], // 0x02000001 - epoch: 0, - }, - capella: Fork { - version: [3, 0, 0, 1], // 0x03000001 - epoch: 0, - }, - }; - } - - impl ethereum_beacon_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; - type WeightInfo = (); - } - - // Build genesis storage according to the mock runtime. - pub fn new_tester() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); - ext - } -} - -#[cfg(not(feature = "beacon-spec-minimal"))] -pub mod mainnet { - use super::*; - - type Block = frame_system::mocking::MockBlock; - use sp_runtime::BuildStorage; - - frame_support::construct_runtime!( - pub enum Test { - System: frame_system::{Pallet, Call, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - EthereumBeaconClient: ethereum_beacon_client::{Pallet, Call, Storage, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; - } - - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type OnSetCode = (); - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type MaxConsumers = frame_support::traits::ConstU32<16>; - type Nonce = u64; - type Block = Block; - } - - impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = (); - type WeightInfo = (); - } - - parameter_types! { - pub const ChainForkVersions: ForkVersions = ForkVersions { - genesis: Fork { - version: [144, 0, 0, 111], // 0x90000069 - epoch: 0, - }, - altair: Fork { - version: [144, 0, 0, 112], // 0x90000070 - epoch: 50, - }, - bellatrix: Fork { - version: [144, 0, 0, 113], // 0x90000071 - epoch: 100, - }, - capella: Fork { - version: [144, 0, 0, 114], // 0x90000072 - epoch: 56832, - }, - }; - pub const ExecutionHeadersPruneThreshold: u32 = 8192; - } - - impl ethereum_beacon_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; - type WeightInfo = (); - } - - // Build genesis storage according to the mock runtime. - pub fn new_tester() -> sp_io::TestExternalities { - let t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext = sp_io::TestExternalities::new(t); - let _ = ext.execute_with(|| Timestamp::set(RuntimeOrigin::signed(1), 30_000)); - ext - } -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/tests.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/tests.rs deleted file mode 100644 index d6346d3aafe3..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/tests.rs +++ /dev/null @@ -1,1045 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{ - functions::compute_period, pallet::ExecutionHeaders, sync_committee_sum, verify_merkle_branch, - BeaconHeader, CompactBeaconState, Error, ExecutionHeaderBuffer, FinalizedBeaconState, - LatestExecutionState, LatestFinalizedBlockRoot, NextSyncCommittee, SyncCommitteePrepared, -}; - -use crate::mock::{ - get_message_verification_header, get_message_verification_payload, - load_checkpoint_update_fixture, load_execution_header_update_fixture, - load_finalized_header_update_fixture, load_next_finalized_header_update_fixture, - load_next_sync_committee_update_fixture, load_sync_committee_update_fixture, -}; - -#[cfg(feature = "beacon-spec-minimal")] -pub use crate::config::minimal::*; -#[cfg(feature = "beacon-spec-minimal")] -pub use crate::mock::minimal::*; - -#[cfg(not(feature = "beacon-spec-minimal"))] -pub use crate::config::mainnet::*; -#[cfg(not(feature = "beacon-spec-minimal"))] -pub use crate::mock::mainnet::*; - -use frame_support::{assert_err, assert_noop, assert_ok}; -use hex_literal::hex; -use primitives::{ - CompactExecutionHeader, ExecutionHeaderState, Fork, ForkVersions, NextSyncCommitteeUpdate, -}; -use rand::{thread_rng, Rng}; -use snowbridge_core::{ - inbound::{VerificationError, Verifier}, - RingBufferMap, -}; -use sp_core::H256; -use sp_runtime::DispatchError; - -/// Arbitrary hash used for tests and invalid hashes. -const TEST_HASH: [u8; 32] = - hex!["5f6f02af29218292d21a69b64a794a7c0873b3e0f54611972863706e8cbdf371"]; - -/* UNIT TESTS */ - -#[test] -pub fn sum_sync_committee_participation() { - new_tester().execute_with(|| { - assert_eq!(sync_committee_sum(&[0, 1, 0, 1, 1, 0, 1, 0, 1]), 5); - }); -} - -#[test] -pub fn compute_domain() { - new_tester().execute_with(|| { - let domain = EthereumBeaconClient::compute_domain( - hex!("07000000").into(), - hex!("00000001"), - hex!("5dec7ae03261fde20d5b024dfabce8bac3276c9a4908e23d50ba8c9b50b0adff").into(), - ); - - assert_ok!(&domain); - assert_eq!( - domain.unwrap(), - hex!("0700000046324489ceb6ada6d118eacdbe94f49b1fcb49d5481a685979670c7c").into() - ); - }); -} - -#[test] -pub fn compute_signing_root_bls() { - new_tester().execute_with(|| { - let signing_root = EthereumBeaconClient::compute_signing_root( - &BeaconHeader { - slot: 3529537, - proposer_index: 192549, - parent_root: hex!( - "1f8dc05ea427f78e84e2e2666e13c3befb7106fd1d40ef8a3f67cf615f3f2a4c" - ) - .into(), - state_root: hex!( - "0dfb492a83da711996d2d76b64604f9bca9dc08b6c13cf63b3be91742afe724b" - ) - .into(), - body_root: hex!("66fba38f7c8c2526f7ddfe09c1a54dd12ff93bdd4d0df6a0950e88e802228bfa") - .into(), - }, - hex!("07000000afcaaba0efab1ca832a15152469bb09bb84641c405171dfa2d3fb45f").into(), - ); - - assert_ok!(&signing_root); - assert_eq!( - signing_root.unwrap(), - hex!("3ff6e9807da70b2f65cdd58ea1b25ed441a1d589025d2c4091182026d7af08fb").into() - ); - }); -} - -#[test] -pub fn compute_signing_root() { - new_tester().execute_with(|| { - let signing_root = EthereumBeaconClient::compute_signing_root( - &BeaconHeader { - slot: 222472, - proposer_index: 10726, - parent_root: hex!( - "5d481a9721f0ecce9610eab51d400d223683d599b7fcebca7e4c4d10cdef6ebb" - ) - .into(), - state_root: hex!( - "14eb4575895f996a84528b789ff2e4d5148242e2983f03068353b2c37015507a" - ) - .into(), - body_root: hex!("7bb669c75b12e0781d6fa85d7fc2f32d64eafba89f39678815b084c156e46cac") - .into(), - }, - hex!("07000000e7acb21061790987fa1c1e745cccfb358370b33e8af2b2c18938e6c2").into(), - ); - - assert_ok!(&signing_root); - assert_eq!( - signing_root.unwrap(), - hex!("da12b6a6d3516bc891e8a49f82fc1925cec40b9327e06457f695035303f55cd8").into() - ); - }); -} - -#[test] -pub fn compute_domain_bls() { - new_tester().execute_with(|| { - let domain = EthereumBeaconClient::compute_domain( - hex!("07000000").into(), - hex!("01000000"), - hex!("4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95").into(), - ); - - assert_ok!(&domain); - assert_eq!( - domain.unwrap(), - hex!("07000000afcaaba0efab1ca832a15152469bb09bb84641c405171dfa2d3fb45f").into() - ); - }); -} - -#[test] -pub fn verify_merkle_branch_for_finalized_root() { - new_tester().execute_with(|| { - assert!(verify_merkle_branch( - hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - &[ - hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - hex!("5f6f02af29218292d21a69b64a794a7c0873b3e0f54611972863706e8cbdf371").into(), - hex!("e7125ff9ab5a840c44bedb4731f440a405b44e15f2d1a89e27341b432fabe13d").into(), - hex!("002c1fe5bc0bd62db6f299a582f2a80a6d5748ccc82e7ed843eaf0ae0739f74a").into(), - hex!("d2dc4ba9fd4edff6716984136831e70a6b2e74fca27b8097a820cbbaa5a6e3c3").into(), - hex!("91f77a19d8afa4a08e81164bb2e570ecd10477b3b65c305566a6d2be88510584").into(), - ], - crate::config::FINALIZED_ROOT_INDEX, - crate::config::FINALIZED_ROOT_DEPTH, - hex!("e46559327592741956f6beaa0f52e49625eb85dce037a0bd2eff333c743b287f").into() - )); - }); -} - -#[test] -pub fn verify_merkle_branch_fails_if_depth_and_branch_dont_match() { - new_tester().execute_with(|| { - assert!(!verify_merkle_branch( - hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - &[ - hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - hex!("5f6f02af29218292d21a69b64a794a7c0873b3e0f54611972863706e8cbdf371").into(), - hex!("e7125ff9ab5a840c44bedb4731f440a405b44e15f2d1a89e27341b432fabe13d").into(), - ], - crate::config::FINALIZED_ROOT_INDEX, - crate::config::FINALIZED_ROOT_DEPTH, - hex!("e46559327592741956f6beaa0f52e49625eb85dce037a0bd2eff333c743b287f").into() - )); - }); -} - -#[test] -pub fn sync_committee_participation_is_supermajority() { - let bits = - hex!("bffffffff7f1ffdfcfeffeffbfdffffbfffffdffffefefffdffff7f7ffff77fffdf7bff77ffdf7fffafffffff77fefffeff7effffffff5f7fedfffdfb6ddff7b" - ); - let participation = primitives::decompress_sync_committee_bits::<512, 64>(bits); - assert_ok!(EthereumBeaconClient::sync_committee_participation_is_supermajority(&participation)); -} - -#[test] -pub fn sync_committee_participation_is_supermajority_errors_when_not_supermajority() { - new_tester().execute_with(|| { - let participation: [u8; 512] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, - 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - ]; - - assert_err!( - EthereumBeaconClient::sync_committee_participation_is_supermajority(&participation), - Error::::SyncCommitteeParticipantsNotSupermajority - ); - }); -} - -#[test] -pub fn execution_header_pruning() { - new_tester().execute_with(|| { - let execution_header_prune_threshold = ExecutionHeadersPruneThreshold::get(); - let to_be_deleted = execution_header_prune_threshold / 2; - - let mut stored_hashes = vec![]; - - for i in 0..execution_header_prune_threshold { - let mut hash = H256::default(); - thread_rng().try_fill(&mut hash.0[..]).unwrap(); - EthereumBeaconClient::store_execution_header( - hash, - CompactExecutionHeader::default(), - i as u64, - hash, - ); - stored_hashes.push(hash); - } - - // We should have stored everything until now - assert_eq!({ ExecutionHeaders::::iter().count() }, stored_hashes.len()); - - // Let's push extra entries so that some of the previous entries are deleted. - for i in 0..to_be_deleted { - let mut hash = H256::default(); - thread_rng().try_fill(&mut hash.0[..]).unwrap(); - EthereumBeaconClient::store_execution_header( - hash, - CompactExecutionHeader::default(), - (i + execution_header_prune_threshold) as u64, - hash, - ); - - stored_hashes.push(hash); - } - - // We should have only stored upto `execution_header_prune_threshold` - assert_eq!( - ExecutionHeaders::::iter().count() as u32, - execution_header_prune_threshold - ); - - // First `to_be_deleted` items must be deleted - for i in 0..to_be_deleted { - assert!(!ExecutionHeaders::::contains_key(stored_hashes[i as usize])); - } - - // Other entries should be part of data - for i in to_be_deleted..(to_be_deleted + execution_header_prune_threshold) { - assert!(ExecutionHeaders::::contains_key(stored_hashes[i as usize])); - } - }); -} - -#[test] -fn compute_fork_version() { - let mock_fork_versions = ForkVersions { - genesis: Fork { version: [0, 0, 0, 0], epoch: 0 }, - altair: Fork { version: [0, 0, 0, 1], epoch: 10 }, - bellatrix: Fork { version: [0, 0, 0, 2], epoch: 20 }, - capella: Fork { version: [0, 0, 0, 3], epoch: 30 }, - }; - new_tester().execute_with(|| { - assert_eq!(EthereumBeaconClient::select_fork_version(&mock_fork_versions, 0), [0, 0, 0, 0]); - assert_eq!(EthereumBeaconClient::select_fork_version(&mock_fork_versions, 1), [0, 0, 0, 0]); - assert_eq!( - EthereumBeaconClient::select_fork_version(&mock_fork_versions, 10), - [0, 0, 0, 1] - ); - assert_eq!( - EthereumBeaconClient::select_fork_version(&mock_fork_versions, 21), - [0, 0, 0, 2] - ); - assert_eq!( - EthereumBeaconClient::select_fork_version(&mock_fork_versions, 20), - [0, 0, 0, 2] - ); - assert_eq!( - EthereumBeaconClient::select_fork_version(&mock_fork_versions, 32), - [0, 0, 0, 3] - ); - }); -} - -#[test] -fn find_absent_keys() { - let participation: [u8; 32] = [ - 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - ]; - let update = load_sync_committee_update_fixture(); - let sync_committee_prepared: SyncCommitteePrepared = - (&update.next_sync_committee_update.unwrap().next_sync_committee) - .try_into() - .unwrap(); - - new_tester().execute_with(|| { - let pubkeys = EthereumBeaconClient::find_pubkeys( - &participation, - (*sync_committee_prepared.pubkeys).as_ref(), - false, - ); - assert_eq!(pubkeys.len(), 2); - assert_eq!(pubkeys[0], sync_committee_prepared.pubkeys[0]); - assert_eq!(pubkeys[1], sync_committee_prepared.pubkeys[7]); - }); -} - -#[test] -fn find_present_keys() { - let participation: [u8; 32] = [ - 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 1, 0, - ]; - let update = load_sync_committee_update_fixture(); - let sync_committee_prepared: SyncCommitteePrepared = - (&update.next_sync_committee_update.unwrap().next_sync_committee) - .try_into() - .unwrap(); - - new_tester().execute_with(|| { - let pubkeys = EthereumBeaconClient::find_pubkeys( - &participation, - (*sync_committee_prepared.pubkeys).as_ref(), - true, - ); - assert_eq!(pubkeys.len(), 4); - assert_eq!(pubkeys[0], sync_committee_prepared.pubkeys[1]); - assert_eq!(pubkeys[1], sync_committee_prepared.pubkeys[8]); - assert_eq!(pubkeys[2], sync_committee_prepared.pubkeys[26]); - assert_eq!(pubkeys[3], sync_committee_prepared.pubkeys[30]); - }); -} - -#[test] -fn cross_check_execution_state() { - new_tester().execute_with(|| { - let header_root: H256 = TEST_HASH.into(); - >::insert( - header_root, - CompactBeaconState { - // set slot to period 5 - slot: ((EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH) * 5) as u64, - block_roots_root: Default::default(), - }, - ); - LatestFinalizedBlockRoot::::set(header_root); - >::set(ExecutionHeaderState { - beacon_block_root: Default::default(), - // set slot to period 2 - beacon_slot: ((EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH) * 2) as u64, - block_hash: Default::default(), - block_number: 0, - }); - - assert_err!( - EthereumBeaconClient::cross_check_execution_state(), - Error::::ExecutionHeaderTooFarBehind - ); - }); -} - -/* SYNC PROCESS TESTS */ - -#[test] -fn process_initial_checkpoint() { - let checkpoint = load_checkpoint_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::force_checkpoint( - RuntimeOrigin::root(), - Box::new(checkpoint.clone()) - )); - let block_root: H256 = checkpoint.header.hash_tree_root().unwrap(); - assert!(>::contains_key(block_root)); - }); -} - -#[test] -fn process_initial_checkpoint_with_invalid_sync_committee_proof() { - let mut checkpoint = load_checkpoint_update_fixture(); - checkpoint.current_sync_committee_branch[0] = TEST_HASH.into(); - - new_tester().execute_with(|| { - assert_err!( - EthereumBeaconClient::force_checkpoint(RuntimeOrigin::root(), Box::new(checkpoint)), - Error::::InvalidSyncCommitteeMerkleProof - ); - }); -} - -#[test] -fn process_initial_checkpoint_with_invalid_blocks_root_proof() { - let mut checkpoint = load_checkpoint_update_fixture(); - checkpoint.block_roots_branch[0] = TEST_HASH.into(); - - new_tester().execute_with(|| { - assert_err!( - EthereumBeaconClient::force_checkpoint(RuntimeOrigin::root(), Box::new(checkpoint)), - Error::::InvalidBlockRootsRootMerkleProof - ); - }); -} - -#[test] -fn submit_update_in_current_period() { - let checkpoint = load_checkpoint_update_fixture(); - let update = load_finalized_header_update_fixture(); - let initial_period = compute_period(checkpoint.header.slot); - let update_period = compute_period(update.finalized_header.slot); - assert_eq!(initial_period, update_period); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(update.clone()) - )); - let block_root: H256 = update.finalized_header.hash_tree_root().unwrap(); - assert!(>::contains_key(block_root)); - }); -} - -#[test] -fn submit_update_with_sync_committee_in_current_period() { - let checkpoint = load_checkpoint_update_fixture(); - let update = load_sync_committee_update_fixture(); - let init_period = compute_period(checkpoint.header.slot); - let update_period = compute_period(update.finalized_header.slot); - assert_eq!(init_period, update_period); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert!(!>::exists()); - assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update))); - assert!(>::exists()); - }); -} - -#[test] -fn submit_update_in_next_period() { - let checkpoint = load_checkpoint_update_fixture(); - let sync_committee_update = load_sync_committee_update_fixture(); - let update = load_next_finalized_header_update_fixture(); - let sync_committee_period = compute_period(sync_committee_update.finalized_header.slot); - let next_sync_committee_period = compute_period(update.finalized_header.slot); - assert_eq!(sync_committee_period + 1, next_sync_committee_period); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(sync_committee_update.clone()) - )); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(update.clone()) - )); - let block_root: H256 = update.finalized_header.clone().hash_tree_root().unwrap(); - assert!(>::contains_key(block_root)); - }); -} - -#[test] -fn submit_update_with_invalid_header_proof() { - let checkpoint = load_checkpoint_update_fixture(); - let mut update = load_sync_committee_update_fixture(); - let init_period = compute_period(checkpoint.header.slot); - let update_period = compute_period(update.finalized_header.slot); - assert_eq!(init_period, update_period); - update.finality_branch[0] = TEST_HASH.into(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert!(!>::exists()); - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::InvalidHeaderMerkleProof - ); - }); -} - -#[test] -fn submit_update_with_invalid_block_roots_proof() { - let checkpoint = load_checkpoint_update_fixture(); - let mut update = load_sync_committee_update_fixture(); - let init_period = compute_period(checkpoint.header.slot); - let update_period = compute_period(update.finalized_header.slot); - assert_eq!(init_period, update_period); - update.block_roots_branch[0] = TEST_HASH.into(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert!(!>::exists()); - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::InvalidBlockRootsRootMerkleProof - ); - }); -} - -#[test] -fn submit_update_with_invalid_next_sync_committee_proof() { - let checkpoint = load_checkpoint_update_fixture(); - let mut update = load_sync_committee_update_fixture(); - let init_period = compute_period(checkpoint.header.slot); - let update_period = compute_period(update.finalized_header.slot); - assert_eq!(init_period, update_period); - if let Some(ref mut next_sync_committee_update) = update.next_sync_committee_update { - next_sync_committee_update.next_sync_committee_branch[0] = TEST_HASH.into(); - } - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert!(!>::exists()); - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::InvalidSyncCommitteeMerkleProof - ); - }); -} - -#[test] -fn submit_update_with_skipped_period() { - let checkpoint = load_checkpoint_update_fixture(); - let sync_committee_update = load_sync_committee_update_fixture(); - let mut update = load_next_finalized_header_update_fixture(); - update.signature_slot += (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH) as u64; - update.attested_header.slot = update.signature_slot - 1; - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(sync_committee_update.clone()) - )); - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::SkippedSyncCommitteePeriod - ); - }); -} - -#[test] -fn submit_update_with_sync_committee_in_next_period() { - let checkpoint = load_checkpoint_update_fixture(); - let update = load_sync_committee_update_fixture(); - let next_update = load_next_sync_committee_update_fixture(); - let update_period = compute_period(update.finalized_header.slot); - let next_update_period = compute_period(next_update.finalized_header.slot); - assert_eq!(update_period + 1, next_update_period); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert!(!>::exists()); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(update.clone()) - )); - assert!(>::exists()); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(next_update.clone()) - )); - let last_finalized_state = - FinalizedBeaconState::::get(LatestFinalizedBlockRoot::::get()).unwrap(); - let last_synced_period = compute_period(last_finalized_state.slot); - assert_eq!(last_synced_period, next_update_period); - }); -} - -#[test] -fn submit_update_with_sync_committee_invalid_signature_slot() { - let checkpoint = load_checkpoint_update_fixture(); - let mut update = load_sync_committee_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - - // makes a invalid update with signature_slot should be more than attested_slot - update.signature_slot = update.attested_header.slot; - - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::InvalidUpdateSlot - ); - }); -} - -#[test] -fn submit_update_with_skipped_sync_committee_period() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_update = load_next_finalized_header_update_fixture(); - let checkpoint_period = compute_period(checkpoint.header.slot); - let next_sync_committee_period = compute_period(finalized_update.finalized_header.slot); - assert_eq!(checkpoint_period + 1, next_sync_committee_period); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(finalized_update)), - Error::::SkippedSyncCommitteePeriod - ); - }); -} - -#[test] -fn submit_update_execution_headers_too_far_behind() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let execution_header_update = load_execution_header_update_fixture(); - let next_update = load_next_sync_committee_update_fixture(); - - new_tester().execute_with(|| { - let far_ahead_finalized_header_slot = finalized_header_update.finalized_header.slot + - (EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH * 2) as u64; - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_ok!(EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - )); - - let header_root: H256 = TEST_HASH.into(); - >::insert( - header_root, - CompactBeaconState { - slot: far_ahead_finalized_header_slot, - block_roots_root: Default::default(), - }, - ); - LatestFinalizedBlockRoot::::set(header_root); - - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(next_update)), - Error::::ExecutionHeaderTooFarBehind - ); - }); -} - -#[test] -fn submit_irrelevant_update() { - let checkpoint = load_checkpoint_update_fixture(); - let mut update = load_next_finalized_header_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - - // makes an invalid update where the attested_header slot value should be greater than the - // checkpoint slot value - update.finalized_header.slot = checkpoint.header.slot; - update.attested_header.slot = checkpoint.header.slot; - update.signature_slot = checkpoint.header.slot + 1; - - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::IrrelevantUpdate - ); - }); -} - -#[test] -fn submit_update_with_missing_bootstrap() { - let update = load_next_finalized_header_update_fixture(); - - new_tester().execute_with(|| { - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::NotBootstrapped - ); - }); -} - -#[test] -fn submit_update_with_invalid_sync_committee_update() { - let checkpoint = load_checkpoint_update_fixture(); - let update = load_sync_committee_update_fixture(); - let mut next_update = load_next_sync_committee_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - - assert_ok!(EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update))); - - // makes update with invalid next_sync_committee - >::mutate(>::get(), |x| { - let prev = x.unwrap(); - *x = Some(CompactBeaconState { slot: next_update.attested_header.slot, ..prev }); - }); - next_update.attested_header.slot += 1; - next_update.signature_slot = next_update.attested_header.slot + 1; - let next_sync_committee = NextSyncCommitteeUpdate::default(); - next_update.next_sync_committee_update = Some(next_sync_committee); - - assert_err!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(next_update)), - Error::::InvalidSyncCommitteeUpdate - ); - }); -} - -#[test] -fn submit_execution_header_update() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let execution_header_update = load_execution_header_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_ok!(EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update.clone()) - )); - assert!(>::contains_key( - execution_header_update.execution_header.block_hash - )); - }); -} - -#[test] -fn submit_execution_header_update_invalid_ancestry_proof() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let mut execution_header_update = load_execution_header_update_fixture(); - if let Some(ref mut ancestry_proof) = execution_header_update.ancestry_proof { - ancestry_proof.header_branch[0] = TEST_HASH.into() - } - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - ), - Error::::InvalidAncestryMerkleProof - ); - }); -} - -#[test] -fn submit_execution_header_update_invalid_execution_header_proof() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let mut execution_header_update = load_execution_header_update_fixture(); - execution_header_update.execution_branch[0] = TEST_HASH.into(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - ), - Error::::InvalidExecutionHeaderProof - ); - }); -} - -#[test] -fn submit_execution_header_update_that_skips_block() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let execution_header_update = load_execution_header_update_fixture(); - let mut skipped_block_execution_header_update = load_execution_header_update_fixture(); - skipped_block_execution_header_update.execution_header.block_number = - execution_header_update.execution_header.block_number + 2; - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_ok!(EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update.clone()) - )); - assert!(>::contains_key( - execution_header_update.execution_header.block_hash - )); - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(skipped_block_execution_header_update) - ), - Error::::ExecutionHeaderSkippedBlock - ); - }); -} - -#[test] -fn submit_execution_header_update_that_is_also_finalized_header_which_is_not_stored() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let mut execution_header_update = load_execution_header_update_fixture(); - execution_header_update.ancestry_proof = None; - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - ), - Error::::ExpectedFinalizedHeaderNotStored - ); - }); -} - -#[test] -fn submit_execution_header_update_that_is_also_finalized_header_which_is_stored_but_slots_dont_match( -) { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let mut execution_header_update = load_execution_header_update_fixture(); - execution_header_update.ancestry_proof = None; - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - - let block_root: H256 = execution_header_update.header.hash_tree_root().unwrap(); - - >::insert( - block_root, - CompactBeaconState { - slot: execution_header_update.header.slot + 1, - block_roots_root: Default::default(), - }, - ); - LatestFinalizedBlockRoot::::set(block_root); - - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - ), - Error::::ExpectedFinalizedHeaderNotStored - ); - }); -} - -#[test] -fn submit_execution_header_not_finalized() { - let checkpoint = load_checkpoint_update_fixture(); - let finalized_header_update = load_finalized_header_update_fixture(); - let update = load_execution_header_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - assert_ok!(EthereumBeaconClient::submit( - RuntimeOrigin::signed(1), - Box::new(finalized_header_update) - )); - - >::mutate(>::get(), |x| { - let prev = x.unwrap(); - *x = Some(CompactBeaconState { slot: update.header.slot - 1, ..prev }); - }); - - assert_err!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(update) - ), - Error::::HeaderNotFinalized - ); - }); -} - -/* IMPLS */ - -#[test] -fn verify_message() { - let header = get_message_verification_header(); - let (event_log, proof) = get_message_verification_payload(); - let block_hash = proof.block_hash; - - new_tester().execute_with(|| { - >::insert(block_hash, header); - assert_ok!(EthereumBeaconClient::verify(&event_log, &proof)); - }); -} - -#[test] -fn verify_message_missing_header() { - let (event_log, proof) = get_message_verification_payload(); - - new_tester().execute_with(|| { - assert_err!( - EthereumBeaconClient::verify(&event_log, &proof), - VerificationError::HeaderNotFound - ); - }); -} - -#[test] -fn verify_message_invalid_proof() { - let header = get_message_verification_header(); - let (event_log, mut proof) = get_message_verification_payload(); - proof.data.1[0] = TEST_HASH.into(); - let block_hash = proof.block_hash; - - new_tester().execute_with(|| { - >::insert(block_hash, header); - assert_err!( - EthereumBeaconClient::verify(&event_log, &proof), - VerificationError::InvalidProof - ); - }); -} - -#[test] -fn verify_message_invalid_receipts_root() { - let mut header = get_message_verification_header(); - let (event_log, proof) = get_message_verification_payload(); - let block_hash = proof.block_hash; - header.receipts_root = TEST_HASH.into(); - - new_tester().execute_with(|| { - >::insert(block_hash, header); - assert_err!( - EthereumBeaconClient::verify(&event_log, &proof), - VerificationError::InvalidProof - ); - }); -} - -#[test] -fn verify_message_invalid_log() { - let header = get_message_verification_header(); - let (mut event_log, proof) = get_message_verification_payload(); - let block_hash = proof.block_hash; - event_log.topics = vec![H256::zero(); 10]; - - new_tester().execute_with(|| { - >::insert(block_hash, header); - assert_err!( - EthereumBeaconClient::verify(&event_log, &proof), - VerificationError::InvalidLog - ); - }); -} - -#[test] -fn verify_message_receipt_does_not_contain_log() { - let header = get_message_verification_header(); - let (mut event_log, proof) = get_message_verification_payload(); - let block_hash = proof.block_hash; - event_log.data = hex!("f9013c94ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0f863a01b11dcf133cc240f682dab2d3a8e4cd35c5da8c9cf99adac4336f8512584c5ada000000000000000000000000000000000000000000000000000000000000003e8a00000000000000000000000000000000000000000000000000000000000000002b8c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000068000f000000000000000101d184c103f7acc340847eee82a0b909e3358bc28d440edffa1352b13227e8ee646f3ea37456dec70100000101001cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c0000e8890423c78a0000000000000000000000000000000000000000000000000000000000000000").to_vec(); - - new_tester().execute_with(|| { - >::insert(block_hash, header); - assert_err!( - EthereumBeaconClient::verify(&event_log, &proof), - VerificationError::LogNotFound - ); - }); -} - -#[test] -fn set_operating_mode() { - let checkpoint = load_checkpoint_update_fixture(); - let update = load_finalized_header_update_fixture(); - let execution_header_update = load_execution_header_update_fixture(); - - new_tester().execute_with(|| { - assert_ok!(EthereumBeaconClient::process_checkpoint_update(&checkpoint)); - - assert_ok!(EthereumBeaconClient::set_operating_mode( - RuntimeOrigin::root(), - snowbridge_core::BasicOperatingMode::Halted - )); - - assert_noop!( - EthereumBeaconClient::submit(RuntimeOrigin::signed(1), Box::new(update)), - Error::::Halted - ); - - assert_noop!( - EthereumBeaconClient::submit_execution_header( - RuntimeOrigin::signed(1), - Box::new(execution_header_update) - ), - Error::::Halted - ); - }); -} - -#[test] -fn set_operating_mode_root_only() { - new_tester().execute_with(|| { - assert_noop!( - EthereumBeaconClient::set_operating_mode( - RuntimeOrigin::signed(1), - snowbridge_core::BasicOperatingMode::Halted - ), - DispatchError::BadOrigin - ); - }); -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/types.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/types.rs deleted file mode 100644 index 5dcefea9f80f..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/types.rs +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pub use crate::config::{ - SLOTS_PER_HISTORICAL_ROOT, SYNC_COMMITTEE_BITS_SIZE as SC_BITS_SIZE, - SYNC_COMMITTEE_SIZE as SC_SIZE, -}; -use frame_support::storage::types::OptionQuery; -use snowbridge_core::RingBufferMapImpl; - -// Specialize types based on configured sync committee size -pub type SyncCommittee = primitives::SyncCommittee; -pub type SyncCommitteePrepared = primitives::SyncCommitteePrepared; -pub type SyncAggregate = primitives::SyncAggregate; -pub type CheckpointUpdate = primitives::CheckpointUpdate; -pub type Update = primitives::Update; -pub type NextSyncCommitteeUpdate = primitives::NextSyncCommitteeUpdate; - -pub use primitives::ExecutionHeaderUpdate; - -/// ExecutionHeader ring buffer implementation -pub type ExecutionHeaderBuffer = RingBufferMapImpl< - u32, - ::MaxExecutionHeadersToKeep, - crate::ExecutionHeaderIndex, - crate::ExecutionHeaderMapping, - crate::ExecutionHeaders, - OptionQuery, ->; - -/// FinalizedState ring buffer implementation -pub(crate) type FinalizedBeaconStateBuffer = RingBufferMapImpl< - u32, - crate::MaxFinalizedHeadersToKeep, - crate::FinalizedBeaconStateIndex, - crate::FinalizedBeaconStateMapping, - crate::FinalizedBeaconState, - OptionQuery, ->; diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/src/weights.rs b/bridges/snowbridge/parachain/pallets/ethereum-client/src/weights.rs deleted file mode 100644 index e1a5578f4661..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/src/weights.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! Autogenerated weights for ethereum_beacon_client -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-09-27, STEPS: `10`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("/tmp/snowbridge/spec.json"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/snowbridge -// benchmark -// pallet -// --chain -// /tmp/snowbridge/spec.json -// --execution=wasm -// --pallet -// ethereum_beacon_client -// --extrinsic -// * -// --steps -// 10 -// --repeat -// 10 -// --output -// pallets/ethereum-client/src/weights.rs -// --template -// templates/module-weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for ethereum_beacon_client. -pub trait WeightInfo { - fn force_checkpoint() -> Weight; - fn submit() -> Weight; - fn submit_with_sync_committee() -> Weight; - fn submit_execution_header() -> Weight; -} - -// For backwards compatibility and tests -impl WeightInfo for () { - fn force_checkpoint() -> Weight { - Weight::from_parts(97_263_571_000_u64, 0) - .saturating_add(Weight::from_parts(0, 3501)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(9)) - } - fn submit() -> Weight { - Weight::from_parts(26_051_019_000_u64, 0) - .saturating_add(Weight::from_parts(0, 93857)) - .saturating_add(RocksDbWeight::get().reads(8)) - .saturating_add(RocksDbWeight::get().writes(4)) - } - fn submit_with_sync_committee() -> Weight { - Weight::from_parts(122_461_312_000_u64, 0) - .saturating_add(Weight::from_parts(0, 93857)) - .saturating_add(RocksDbWeight::get().reads(6)) - .saturating_add(RocksDbWeight::get().writes(1)) - } - fn submit_execution_header() -> Weight { - Weight::from_parts(113_158_000_u64, 0) - .saturating_add(Weight::from_parts(0, 3537)) - .saturating_add(RocksDbWeight::get().reads(5)) - .saturating_add(RocksDbWeight::get().writes(4)) - } -} diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.mainnet.json deleted file mode 100755 index 97d498e2d9ec..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.mainnet.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "header": { - "slot": 4058654, - "proposer_index": 1039, - "parent_root": "0x758fa0a54047c0221b3107423e78b8910514ba7a0c4250401dac77108dce2ff8", - "state_root": "0x53c79320b4b7649e39a9f07903f4fc68a7cfe7a81cb2e30293dd7b00ee13f69a", - "body_root": "0xa76a7f037f12ee070dcb273d9787b13ff0cf17420a39564a101789318a157ec3" - }, - "ancestry_proof": { - "header_branch": [ - "0xbb6cfda1e02c3117d9fa41c1e1594ce0645352a073ad8b474f83c148e0d9954f", - "0xb44967bd8ff799126cad993ff7369f7a28d60281304d0c7c058e6721b6ce4c61", - "0x0009710ef2467f95542c2e8e7a7249282c08f62aedbe7d21ae4a7af04e1a890d", - "0x7bc5dc20638cfe1cfd5d2547c3efbed4cfb533c76c27d41f723ed876ab9edc3a", - "0x6dcd59a8a041cf2591921417cb8133f0ff5af9bfe1f1ab491e75a751adc9c9e1", - "0x3f25a2852042c7bf2c421bf16c0b9373c1d27ccb1eca4088f8191712481261be", - "0xd1f9cfe1f04031459e5c45f47b2a49c780cabb8ca5b8d76461db2b88c337ed76", - "0x8c37e3119bf7d3cb8208e832669261b0eda1b3c7b11d321760ba1c0649f61416", - "0x1783d3b7041ecb78d9e1f913b82bd335229ca1f2cc5d3cc8dd28c94152e887b4", - "0xe39fc366c951c7cb2100308b0a9417581c46812a7d7e89f516c19863f7686f96", - "0x3c29b6d9b8715dbe5d6831364229efc91ad56ae69e93cb119d5ef4bdc53fcb37", - "0x3cf6fe5e8d91dbaa77e6befa81e04fb25a3e089317d83ff35fc8adfbbf2aab5a", - "0xb41c97cf3b1b4b5bf2999dfb1b3eaeac5c1b12205e9ab0809988e3779d119047" - ], - "finalized_block_root": "0xb4802863fc1d32778211ce6aac8109c73c516a003213f4f5333c80472d08fe4e" - }, - "execution_header": { - "parent_hash": "0x9cffcba69c88a619483e13864704dde5db80e05f8d49018f615395ce09cd24ab", - "fee_recipient": "0xff58d746a67c2e42bcc07d6b3f58406e8837e883", - "state_root": "0x6a4aafc93626778475a416721104229035e91f0db788d0099b57e756cd272f0a", - "receipts_root": "0xe1ce670bdcf9acf4c62fee845cd7e81eabbb6db9ddbff56130020c6cf999a45d", - "logs_bloom": "0xa000980408008000328c1458805c005048b84812c134200090b40428568108a0648090105085100301844800090802484420800d020282019002040d083004031a20420240a4a8900a43296938c040802040220170860210910020036b8c482228c004440300021c82c0400110402a10800582424001c00000828310210020a18130504020790dca716194100880ea5501149104002bc05e189080901c4001010e0a040658a410072021230a5224265030082404000aa11f28162e216636000408842103d41010760972060060000500c20130b000000065401483200081a84934f020020120009618002269c884724616040000840e18080300024490000230", - "prev_randao": "0x5d9ac7ea788ecb534e98bc9079fa0bef199011dadadedaee5dc40e2cd702d664", - "block_number": 5025098, - "gas_limit": 30000000, - "gas_used": 13802943, - "timestamp": 1704437448, - "extra_data": "0x476f65726c69205365706f6c69612d4265706f6c696120513966", - "base_fee_per_gas": 19959019915, - "block_hash": "0x795021134c2b7f9c00b498ff7b0971dbbe061561868f702d8ca68a05e5eb5a99", - "transactions_root": "0x3cb7c92fde5d511cc90cd67e375c4388794f4c01e375e8e8a06d003b5593fd12", - "withdrawals_root": "0x5f5155fd8e5cd24b7ecb1e039792b0caff01dfda2990786d9ffc88325b5d1ea8" - }, - "execution_branch": [ - "0x85ff3d1c2bc3dcdd5543bcd29a1224c6a8c24875224fbb1e3b69f0515ffaacda", - "0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e", - "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", - "0xfe1fa7acd413c54ebd394126ade19fc624ad9e4c60792d54ff3d60b07076b76d" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.minimal.json deleted file mode 100644 index 3e17c14f4adb..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/execution-header-update.minimal.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "header": { - "slot": 3622, - "proposer_index": 7, - "parent_root": "0x254c9215f6cce83e21b9776afb482181639602d3cb58cf99452a6a4a4f603930", - "state_root": "0xea98df6d30817d63f3e54ea118e2b1ba8675753c72dec1661c503d4eb43f9bdd", - "body_root": "0x765a0616a31d38e0ca2d10f6e8b234dd3d07e16aa929bcbc4de775c93f1972fd" - }, - "ancestry_proof": { - "header_branch": [ - "0x7690506882ac8c5f01d00f3ade06439259a3a0261ef5d61ec44920678b4104e6", - "0xf01aa0fdd7c9ef7b1affb7854fe8cbcc5c70643ee5b83e032faa702a0675a8cb", - "0x273a7b300b75ffa2c765af50680aa836299264f2107f38010278822313181801", - "0x30fe73a3bae6a31af32656ab759a4b67d27a213e01012b96cc4fedd0f2e77c75", - "0x7246cb3a35f13a1f0bbf907887985bb5382c45f2aa1699dbca48a0a82d5330af", - "0x5e7270e88a22dd4a905b2e76da2c8c358baeddd34de6c64a71bb1c80070ab717" - ], - "finalized_block_root": "0xa6fdc5df11c1759d11c9f0353a666715e5677e9ffd7d414e44cff0970553f1c9" - }, - "execution_header": { - "parent_hash": "0x6c9657f1267ad6040ea017ff6d02b55c4ba25cb092b8326d321dd98d01d1ee64", - "fee_recipient": "0x0000000000000000000000000000000000000000", - "state_root": "0x01f975f7cdff9b0a8844304aa59062fe18af0fef4636539312dfe20d238600ba", - "receipts_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "prev_randao": "0xcdfcab74bc26b3f4311afdc72d2d21d33a4b045187a01fa208a9d687a6d1d25c", - "block_number": 3622, - "gas_limit": 30000000, - "gas_used": 0, - "timestamp": 1685722543, - "extra_data": "0xd983010b02846765746888676f312e31392e358664617277696e", - "base_fee_per_gas": 7, - "block_hash": "0x38c80e0e26cb80730df627d32f50266bd0fe32fb12b7606300ad81aa2b4033db", - "transactions_root": "0x7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1", - "withdrawals_root": "0x28ba1834a3a7b657460ce79fa3a1d909ab8828fd557659d4d0554a9bdbc0ec30" - }, - "execution_branch": [ - "0x005b8d55b34b4323bfd4773c28b09eb53bc87959e65411ccd23728c7e42d5ff2", - "0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e", - "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", - "0x7061330dada1ba1c602ba98f647a441885460ed0db00483fea1282385dfab84b" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.mainnet.json deleted file mode 100755 index 49434dee72d3..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.mainnet.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "attested_header": { - "slot": 4058720, - "proposer_index": 1088, - "parent_root": "0x37c7398a391c71da07258b48f41d4caaaf891fdf558e110b9c25db716fa8ff55", - "state_root": "0x6cf68a66c993f1c27f499e054a5fbd7c0e625c34ea0057fda9691c561e990002", - "body_root": "0x109e4c0c647d42dba0c8c6569997c51b5bcfc1a33475b1433ded6353f48423ff" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffffff7bfdfffff7fffff1effffef7f9ffbdfdffffffdffbfffbbf7ffffffffffefdf7ffbeffdffef7bfffffffffffbffffffffffbffffffffffffffdfda", - "sync_committee_signature": "0xb5727bad1db101b6f0fd7ec4cb79b43dae90366fe0cae31a62439388eb03ebd75732cee3bde51f814203a4c0f5b23898120cd0870f0e662bdf0f85a048b534d9a906e6d32a65df019059d34f724221075734ec2849c09679febecf6929934f09" - }, - "signature_slot": 4058721, - "next_sync_committee_update": null, - "finalized_header": { - "slot": 4058656, - "proposer_index": 810, - "parent_root": "0xbb6cfda1e02c3117d9fa41c1e1594ce0645352a073ad8b474f83c148e0d9954f", - "state_root": "0xf938f0f0cba85234afbaace20545134c70b35e6ff9f74d944b0fea309109f3cf", - "body_root": "0xcf6a7a6f653cb64b2b910278a478339b34eb08abf00e0766d10c7a8fe9bdb139" - }, - "finality_branch": [ - "0x71ef010000000000000000000000000000000000000000000000000000000000", - "0x3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb", - "0xa2e2a28c0bb0ad56c25f3c461a4bfe4f3b3b894bc0105a62e85f43a4ae1adc3f", - "0xaa2bad8cf9b0433d3d79bc5b95c067048b018d1d2ffd0c66db6e7cf86e0a314e", - "0x027f238235d07ac9757543c19deabe1d553d6fc110e8bea4b037b1fab263b4dc", - "0x7dfa1cc1907e8927295f78a770bf86b28f5c2bddcac38beb3b4beb265ff5608f" - ], - "block_roots_root": "0x4a5a57fb0769443f6472f59dbb78d7a9a69ff61d09aa89d5da645d634ec46a14", - "block_roots_branch": [ - "0xa09ad7f3afd681bb6fd54abba339549f3b601beedea79a5b7d448b1cf1e1613e", - "0xacdfd4d5eba154f118a84af7a2d17ba6100fcd9c24fc235e927f584a5b56e32f", - "0x36ca106eac009ed605e680415b105b3a6591830c38034511f300aae44802235f", - "0x171561a9e1afb413132d0f4d3cbbd810766c151be32ec9f2d609f40aef9e2588", - "0x7cd963eba3fb57ee5ce37ee4b621d24fc14d642e32f48dc48ade528e11458ab9" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.minimal.json deleted file mode 100644 index c6473529b10c..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/finalized-header-update.minimal.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "attested_header": { - "slot": 3640, - "proposer_index": 5, - "parent_root": "0xf062fcec9c3379a08e6add37a834b1e39af395fc343973e44957ecebbf2ecddd", - "state_root": "0xb1581cb62fe376e305e02f26463153f5dfb804d8df97ef40fc315c1bc30731ba", - "body_root": "0x98461abcc6d130b7bcb9430292c8a269ea9f01082685347e2968d892f716067c" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffff", - "sync_committee_signature": "0x925c6e4b67890a7e28a7ca19853f88247e92014b9d233ac9058efd4f3827f0055db308debe17596e635b93727b5a851e1366ca801f30b03fdec722f45011504702a27646488b5ab5e3428fe7b4d4a50132f374612f66e45d68db27c568f96f08" - }, - "signature_slot": 3641, - "next_sync_committee_update": null, - "finalized_header": { - "slot": 3624, - "proposer_index": 7, - "parent_root": "0x7690506882ac8c5f01d00f3ade06439259a3a0261ef5d61ec44920678b4104e6", - "state_root": "0x3726ebb8d9973977a71a8389caf5fc5830eeb8cd4fdfbbc7b0c4e6ca3e6a4090", - "body_root": "0x0f9a3f0fa5a4ffaf7c10504c86f23e7d554366ffd069fe958a160b253c3fd409" - }, - "finality_branch": [ - "0xc501000000000000000000000000000000000000000000000000000000000000", - "0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7", - "0x83c3d5360d254f4a44be712c1f433e88e810b6d1e0e789e90bada9e36126b857", - "0x97245fa01a89a6d7b4542cd731fef699f58b2bbaabdd6f641334c9e9eeae3a20", - "0xc3d19c773f66ab94bc2106d5e75a3205398dd6e94b6f8a5716f347741eb9fc5a", - "0x9e5040e56d765c1add56779a716be7497be27cba37f866cd8d34418d55e48715" - ], - "block_roots_root": "0x29a54625749fa25f9e36df14a3baa335c58246bba2f8c7eb8b1ec2e4908e2fd0", - "block_roots_branch": [ - "0x53616f9298818a8423c98adc47c92aaf82f0c5c911dc4ee5f88ba6d3022341c1", - "0x5d2f1c4bce6f63f26cbe3fbf480281c04a6b14bea74350a88ee945354ecbd79d", - "0x8333eefc7eaa4d10091e2014b3aae2bf6bd2d10c22c67100e189f8ab6caab261", - "0x3edfa69130bc193dec47c27a5903f03d5262b75899b69c0e95ac1816a664a3e7", - "0x5e046000f85aede8d4c28140b27778488d4ad21b1e16e345055d07ee53f2711b" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.mainnet.json deleted file mode 100755 index 1f0f837f596c..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.mainnet.json +++ /dev/null @@ -1,542 +0,0 @@ -{ - "header": { - "slot": 4058624, - "proposer_index": 631, - "parent_root": "0x4abadda13b61df8d40fcb061d1ec15d0fb7bc5144252bb54c57b41893b642bf3", - "state_root": "0x6fe9fa01a04dcdeaa64eba04a72fa6dbadc8596dc5ec1fff2ef343520fe722e1", - "body_root": "0x6cd83df0ee7669e06e64496a1d2be083bc3bb9f2da17e9b1e62979d200328106" - }, - "current_sync_committee": { - "pubkeys": [ - "0xa13bf1fc1826b61cceefcc941c5a4865cefdfa6c91e5223308fa6a0aa6e7b13a0499a63edf5d9fff48fdeae83e38dcbf", - "0xb3285148b91dab139b053442bdd14d627ba1e1250fe469f0f2df854b6e6ff4a18671ae3879ec9f7d8091f99f092162e9", - "0xb00d95908e72c6051478a422eb2231b5f797c2fa5c696ed1e6b9c9996ba1d8236f512443f18c01ce63312c38fa383fd4", - "0xa866633b4293e726accf6e97ac90c1898cac83e8531a25b50ae99f0ecb477a692e6a5f2488447ccd83ed869ab5abc406", - "0xa308ed8737b3a9346ff20dc9f112efccc193472e6fde6aa218ceae11e288bbd2c35fa45c1d8bb238696a96767cd68b46", - "0x81534e2a182da0c6831479c7e722953d267ba9c63a204ac96a178b1dc90d0a6ba8737002688ba5f102eda5669249f114", - "0x87c5670e16a84e27529677881dbedc5c1d6ebb4e4ff58c13ece43d21d5b42dc89470f41059bfa6ebcf18167f97ddacaa", - "0xb37334c41a3456b73b61d0eb0777260af9c2e400bbec0e0c0fdb45c39ce0dd19f021d9760f35da801f20486c6be30e9e", - "0xab73a043ccdfe63437a339e6ee96ef1241264e04dd4d917f6d6bc99396006de54e1e156d38596ba3d15cb1aaa329f8f5", - "0x8983fdebbeba6e3cc3ee1c9feb24faaeee712356975e359b0ddca3f7c9c7448132d665f54a4629002252d3fcf375f7b0", - "0xa03c1e287ccc4d457f5e71e9dc769294835945561e6f236ac7de210d2e614eee8a85e21dfb46e2143c68de22ccee8660", - "0x8e6b888197010ebadd216da35b9716daa8675d93b3c33a96a19fd9ca42624f6b430b2ff115cd0f5b717341605dda24bf", - "0x8fb51e3ef3c1047ae7c527dc24dc8824b2655faff2c4c78da1fcedde48b531d19abaf517363bf30605a87336b8642073", - "0x893272a63650b08e5b8f9b3f17f8547b456192ad649c168bafd7166b4c08c5adf795c508b88fd2425f7be8334592afb2", - "0xa90c42266ca0a65976fb4dc18465b0a44a63ed3b2747cae74e46e3ccf158f98384e2e86c852e7c5556b083b3ded9d243", - "0xb67c621d9b6313a9f6744dfcdd77d4e9cb4bd413fb5e3199cdcd7f675fc39f1ba492860749bfddf98f4088756e844a98", - "0xa9760afaa51002be0948acf7aebd90ec4e60e0dba8456e445aea93408a0468b62bb6da4984b92f8f6061561c9d56f4c4", - "0x981b2d7c56ff38f1d02c5d7a7f8bfe71daaf94d48c3bc93e8083a0a23c1ae1ff05f90312deb09b35d4513c1ffa573d86", - "0x9515dedf061e654d58a43e4e525a63ad2a6274ea6f20b1d624a6ba7d3062ed68a0226eee6951ab8464906c52ba5556b0", - "0x901f724ee1891ca876e5551bd8f4ad4da422576c618465f63d65700c2dd7953496d83abe148c6a4875a46a5a36c218cf", - "0xa8d152e5d94b75cb9e249230db21af31de4d4f3d4ef60ccbf2212babf69aed2a38435a993ee2f13cca410ad55a4875ab", - "0x875ebfe737cea438e967d70ceaffb4360cce28ecc76c8c4ee612c47fb6b3e89af03c66981571066107323f49a6242772", - "0xa798a0371e8cc4dc42ccd79934b0db5a3a59f18a0ae09f2eb172596428fcb3f00312e783d6fd21cbc1610317f44e08cb", - "0x99c629c9cd603a9344b04d22d2bcc06cf45ebf62d97f968df19c73c7a50f4f6a2a2cc7fb633f509f961edfb94fbab94e", - "0x854410e6fb856da8b997ebf28ae2415ce6e1f9f6a4579fad15b5df61709c924a925397b33fe67c89ffad6143a39d756a", - "0xa3969926aa2e52f1a48ac53074b764648b4c71bd43430944679628463cd68398f700d874c14503b53756be451c8ba284", - "0x8ee8873de7cd28a54ba2c63a80b63399effed76b154e96ed26e7c0668b9f2476e298688b6a00c4b2ab9d020a897695d7", - "0xad54241ba3de6a4426c788690d3f78d2eb678814edc49d3fb988d7fc752e43512972567bb384bcc1b18d083d15e376da", - "0x942bee9ee880ac5e2f8ba35518b60890a211974d273b2ae415d34ce842803de7d29a4d26f6ee79c09e910559bdcac6d3", - "0x96b478b1e5e49d4ea3fd97c4846ae0f781dcc9f9ff61ee022ca92c3d8dfba89c513c46e8bb38b73e6b678a79b9b12177", - "0xaad9577501d7f3a5dbac329f2c1fe711710869cc825740f365488fc55a278d687bb72423560f7cb2cbd60546a82ea1e6", - "0x8aa3d9dad1c122b9aed75e3cc94b3a9dab160fa4cad92ebab68a58c0151a5d93f0f6b40b86fba00e63d45bd29a93b982", - "0xa12fc78b8d3334a3eb7b535cd5e648bb030df645cda4e90272a1fc3b368ee43975051bbecc3275d6b1e4600cc07239b0", - "0xab01a7b13c967620d98de736b8ff23d856daa26d5cd8576993ee02a5d694332c0464ed018ebffcd5c71bab5cada850ce", - "0x96cf5760c79cfc830d1d5bd6df6cfd67596bef24e22eed52cee04c290ad418add74e77965ea5748b7f0fb34ee4f43232", - "0x9443e6ba4400fb3370c573cd7e33f05e1475f9cf1d6adb905bee3aff8f1452d8d384c8a72c9110070f35c6aad940bba6", - "0x95c60b5561e53cfc26d620be90f84199ffd6dd9687c1be3a547048e7cba10a0be9bb6da000e7521cbd488d0901d48ee9", - "0xab69cf79750436d310dc3c5e96c2b97003f4394f31dfa8a9ac420595dc7b4d96dad5787d93347ba2bc6f196c241a3dbf", - "0x9145ee1fb6e84114c903819db94fa5a72bcbc15fcb8a7fd8eefba23b156cc46309281dcf78b48a2847b3754f7d7d7a79", - "0xb118f77f99ac947df97e7682f0fb446175185b842380af4ee7394531e4f93002c72b41a57a7c1b923a4f24b10924c84f", - "0xa4aabd1890ebf35423565dbff3477a09eea4e35f5a26ed449eab38e0a21fb89e9ddfe3a2003cddc457db648a1b5891a3", - "0x8ff5d2e6c98b1fea70cb36ea8ed497fd1233b9418948ac58c6c379ed35fb10f8253ef188c909d5e77e81b5b8e2a4ad17", - "0xa23f076306c120dccf69d7d2ac7f83a377a72d35bf448f88feff8b6dba9307fdabf34452e30b87407b2258b9edfd1174", - "0x87d2217eb05d657aba7b048cf3c661b463e78e51135a5b937e71975ff5102e596434720f02349c73415decb88418cb0d", - "0x8bb51b380a8a52d61a94e7b382ff6ce601260fa9b8c5d616764a3df719b382ec43aec9266444a16951e102d8b1fb2f38", - "0xb0053550040ab3a3996cba5caf9ad5718867b5f5df273ed8c6520761571f03a94e50b5f8a6a8c42d725383cce97d3cae", - "0xae50f93230983a82e732903d6ed50a506d678f35b6b4a4b3686a92b12aeb9d34cb095e8562b0900125bbced0359b37de", - "0x8bfa106ada4914419bf1d8900c5981dd5b90c3023196d7e918d62879fc3a575bd0a25f939366f7fd2240df6108b069ec", - "0xb3a5497365bd40a81202b8a94a5e28a8a039cc2e639d73de289294cbda2c0e987c1f9468daba09ea4390f8e4e806f3c8", - "0xb4f583e10aa9af79b4ebd647e0fffe1c720112727e5ffac4313f236737491fceeee194537786c561cd5777b453e5b03c", - "0x826be957cf66db958028fa95655b54b2337f78fb6ef26bd29e2e3a64b130b90521333f31d132c04779e4b23a6b6cd951", - "0xaace45334070c51cc8b3579598d4cd8cda2153bba51f56e3b1fe5e135c83ef70503c322756b9cad9d3cd28f1ecfc8227", - "0x94bb68c8180496472262455fd6ab338697810825fa4e82fc673f3ac2dacfd29ee539ac0bfe97eb39d4ef118db875bab6", - "0xb560c33950a355119845f63defb355807e56773f636fb836f7746155fad070e384fc1091b8e5c057e4cbc7da9275ecf7", - "0x820cc2ac3eed5bce7dc72df2aa3214e71690b91445d8bb1634c0488a671e3669028efbe1eae52f7132bde29b16a020b7", - "0x9244703338879e3ea00663dcde8f11095de3e38df9277d8c2acc26e72021c222ae40bcc91228789fdf0b69acc3144783", - "0x8d474636a638e7b398566a39b3f939a314f1cf88e64d81db0f556ca60951ec1dca1b93e3906a6654ed9ba06f2c31d4ea", - "0x889a5cf9315383bf64dfe88e562d772213c256b0eed15ce27c41c3767c048afe06410d7675e5d59a2302993e7dc45d83", - "0xb544c692b046aad8b6f5c2e3493bc8f638659795f06327fff1e9f4ffc8e9f7abdbf4b7f6fcdfb8fe19654d8fa7d68170", - "0xaefc682f8784b18d36202a069269be7dba8ab67ae3543838e6d473fbc5713d103abcc8da1729a288503b786baac182d3", - "0xa0f2092ac34d2363614fb2f57fc7b72db247eb1fa53f395881ce6b4aacd6fb920d6dc59507701d487288102e4c4fa389", - "0xb33de3de106be61481ccb7f07a7a63cf4d1674010e462388fb8ab5ea08f444ed7a277905207e0b3aa2f00bb9efca984f", - "0x84173aeaf3d96368dc7ca1ad5e5575da279113567e5815a364a0356a720c5e08cb58ca1fdd891924f4871d3eaae5de40", - "0xb6d6482ad7b9b412ffbefbbdcc28eb3d091b1291f54f77bdd53c4ac85f705c454940f466dc272dde7b03c26f0cd6ecb3", - "0xa2053719da2b7501dab42011ae144b3c8d72bd17493181bf3ae79a678068dc3ee2f19d29a60b5a323692c3f684f96392", - "0x8296f8caf58316af535def398a43357e48cb3b1e674b857eba1bd1b970da3dd045e22fe6d17dee4e9117f62ece3ec31c", - "0x84faf4d90edaa6cc837e5e04dc67761084ae24e410345f21923327c9cb5494ffa51b504c89bee168c11250edbdcbe194", - "0x879aea8f09dec92f354e31aa479d00cb77457d363de2d9a51ddf7d734061b6f83d6345cf33dbef22004cd23dd6c4b760", - "0xb8fca0f7bc276f03c526d42df9f88c19b8dc630ad1299689e2d52cd4717bbe5425479b13bdf6e6337c48832e4cd34bb5", - "0xb2a01dc47dd98f089f28eee67ba2f789153516b7d3b47127f430f542869ec42dd8fd4dc83cfbe625c5c40a2d2d0633ea", - "0xa19f2ce14e09ece5972fe5af1c1778b86d2ab6e825eccdb0ac368bb246cfe53433327abfe0c6fa00e0553863d0a8128e", - "0x95d1f944b0c53eb3e9fcd5632713602bbb9195b87a172a370ae2df98504612a55f3968615a39b569ce6a0fe9fb559be7", - "0xae36ab11be96f8c8fcfd75382bb7f4727511596bc08c25814d22f2b894952489d08396b458f7884d6b3c0adb69856a6d", - "0x824d0dc002e158adef06fc38d79b01553be5a3903566029cf0beddb2248b11da40e66feb168e8e3e2a63ea033a75f382", - "0x8f9f85ae6377414fcf8297ed45a736210cd3803f54f33116b0f290b853dc61e99ea08f3c422ed9bc6bdc2f42ab4f56ba", - "0x86c53fc078846c3d9bc47682506f8285ba4551475921fd388b96291741970c34b8de4210202e40d2de4acb6e2892072b", - "0x853184f246d098139230962e511585368b44d46a115c5f06ccaeef746773951bead595fb6246c69975496bac61b42a4f", - "0xb91b4260e2884bae9778fe29a2c1e4525e4663ec004159def5d47320de304c96d2a33ad7a670e05acf90cbba3efdd4d9", - "0x83492e27e07e35c0836aee6bee95d040b8d3e82db6f94a3917d07797800f7200f5dbc6c9596c6c3c70f8f470b65a9b6e", - "0xb1bb33607d10ea8c954064ecb00c1f02b446355ef73763a122f43b9ea42cd5650b54c5c9d1cfa81d4a421d17a0a451aa", - "0x99cb1728157a1b7cdd9607cf15911bbcb56b64d52fb0d0117b457853a81ec55913f977850f26e188fa2652579efe9ddf", - "0x8b7cb5b8de09a6dfceddcbaa498bc65f86297bcf95d107880c08854ed2289441a67721340285cfe1749c62e8ef0f3c58", - "0xb97447233c8b97a8654749a840f12dab6764209c3a033154e045c76e0c8ed93b89788aac5cd1e24ed4a18c36de3fbf60", - "0xb4790910e2cbef848448f24f63e9dd4a1b122cf65feecf152d5fde282ad6fcc6ea3f9cc23178baf85612020795e4b13a", - "0x81fc724846b5781f3736795c32b217458bb29972af36cc4483dd98ab91680d3d9bc18842db2661487d3a85430dc9e326", - "0xa154892ff23b284040e623bba940a6a1ef1207b8b089fc699cb152b00bcce220464502cfa1dfb5a2f62e6f3960cdf349", - "0xaf3f765fd293c253072b33a780ed68933f78d7e079d9a2079b6232755bedf6ebcbce9ba65c01f695602fa8ee17899867", - "0x97578474be98726192cb0eac3cb9195a54c7315e9c619d5c44c56b3f98671636c383416f73605d4ea7ca9fbeff8dd699", - "0x917c4fd52538d34c26ccdd816e54ebea09517712aa74cec68a2e3d759c6a69b5ccb4089ad1e0b988e916b2ce9f5c8918", - "0x8cf3c29531a17489a5f8232d56c5251ffddc95be3ff7ff61472e19fb38c5eaec841ef3b1ee36756b3dd8ff71ae199982", - "0x96d4b9b411319e531bab6af55c13f0adb1dd6b4286784ff807f283e7990dc368c16d536fc5db3d992deb4b0278914e6f", - "0x8903f7e0c9764ce844b15d84feea04406dc66b195a5f82ff4027f27361e11cf368538137d139368f5a6f42876b04f056", - "0xa4047173b5906c9b4292aaee1e91d9080ae74b1d3eb990449ed1f96bf22c3ee80f4915361e5bf7dccce24ae1618dae77", - "0xa4c4b96071e7bc92e41defba3507ddf423d93f3a94271b1f9812dfc4660e4c9fd24e0dd7aef324c46deb8d7a7c97eaa4", - "0x8289b65d6245fde8a768ce48d7c4cc7d861880ff5ff1b110db6b7e1ffbfdc5eadff0b172ba79fd426458811f2b7095eb", - "0xab4119eef94133198adb684b81f5e90070d3ca8f578c4c6c3d07de592a9af4e9fa18314db825f4c31cea1e2c7c62ed87", - "0xa3ffc3dad920d41ec3f4c39743ef571bcabb4430465d9aa811d0f0a7daa12bee4ed256527d16a6e937bf709ebb560ebd", - "0x8553748da4e0b695967e843277d0f6efeb8ba24b44aa9fa3230f4b731caec6ed5e87d3a2fcd31d8ee206e2e4414d6cf4", - "0xb15e1b4ac64bafbc4fdfead9aeff126bf102fdd125c1c914f7979680ec1715fbeccf3dc35c77d284421ec1371ed8bc32", - "0x9377aab082c8ae33b26519d6a8c3f586c7c7fccc96ec29a6f698b67d72d9266ad07378ba90d18e8c86a2ec77ecc7f137", - "0xb71c11828ecad7731136cb1f5b80392a4add8d62f8866a781fdde797a201ebf6d483b2348aacbea2061a5108933b757d", - "0x86793899ef71740ab2ec221d0085701f7909251b1cf59a276c8d629492f9ef15fc0b471beedc446a25b777391ab00718", - "0x8100b48ac2785477a123a7967bfcea8bacef59391680a411692880098a08771ff9786bd3b8dfb034cae00d5a7665621c", - "0x8b027c14affe47f83ee59b504d83b2fd2d9303de2c03ee59d169bb199d9f4bd6533d7f8c812dd7a6f1e8155e3e185689", - "0x9615800f8c95f95bf25055ae079b964e0a64fa0176cc98da272662014f57e7cd2745929daf838df0094b9f54be18b415", - "0x951aa38464912a29df2101c60771d6de7fadb63f2db3f13527f8bdacb66e9e8a97aaac7b81b19e3d1025b54e2c8facff", - "0xa0e68d24f784fcb2b71acc2d5871285623c829d0e939146b145e04908b904468a67c07a2f156e6b17bf531adc5777c4b", - "0x86a533b02ae929f67c301649a2d58651b98cdffe731b63fa32aa1013c271634bbb088c0d02865913c11bbb1bf57c0e12", - "0x81f145ebb9a5674a5b052d0e9059acc8f8ab612dd9f54d43ff620202606e19a86a9b284dc6480d555a030e5fefee8c50", - "0xa698b04227e8593a6fed6a1f6f6d1eafe186b9e73f87e42e7997f264d97225165c3f76e929a3c562ec93ee2babe953ed", - "0xb3180ded54610b1b3a2db7db539197ced6a75e9bb381d1f4b802ca7cd450f5418522ad2bee3df1956ed63ff1ffe95dc1", - "0x86fa3d4b60e8282827115c50b1b49b29a371b52aa9c9b8f83cd5268b535859f86e1a60aade6bf4f52e234777bea30bda", - "0x97d076617cf0a64ab3d1f030cfd72a303b6b252c0a7b96157ff7fc8af5970f00d14492c46e8f6f37caafe837d0dc95c7", - "0xac2c98a0ab3f9d041fc115d9be4a6c77bd2219bb4b851cbee0d9257a4de5791251735b5b8fad09c55d16eb0d97080eff", - "0xace7fda25c2fb7c18710603c16a0ff0f963352d1582a42a20c9f5603c66f485df8383465c35c31e8379b4cb2ec15b4c4", - "0xa07b35ec8d6849e95cbd89645283050882209617a3bb53eae0149d78a60dbf8c1626d7af498e363025896febdba86ee7", - "0xb2fc4478830f2ae4234569346d80b59899247c609b75bd2190a896498539e1f30dca5edbad69f0224918d09f0d7eb332", - "0x84926cf2265981e5531d90d8f2da1041cb73bdb1a7e11eb8ab21dbe94fefad5bbd674f6cafbcaa597480567edf0b2029", - "0xb5f32034d0f66bcbccefe2a177a60f31132d98c0899aa1ffff5ebf807546ff3104103077b1435fa6587bfe3e67ac0266", - "0x938206740a33d82ffda3e01598216324731335d367965aa0b740486d60ba2e86a4ecd546851046a61a4b0fc88295b5cb", - "0xad2b1ab32161e37ee553e3787f05f9281073d7ef7d0ae035daa353bc83da8ef8c76c99ad2928463c7c708f7404020476", - "0x94f4720c194e7ea4232048b0af18b8a920fde7b82869e2abcc7e14a9906530be1ef61132884bb159df019e66d83a0315", - "0xa26dd9b28564c3d95679aca03e3432ac26e287f80e870714c5946b05538b3cb43bba7b85c16bceb5430e81b7a04c1b1d", - "0x8ef0930db046c45ca5c69d565d54681d2b6d249e27092736aee582b29de3aac3fd96e1066a57cadd851b4e5334261594", - "0x92096ebf98ebac5c82345d3ef0db0f5a14af23ceea73279087426b281d6701997fe131fe65a7df7d624b4ff91d997ae8", - "0x81c850f419cf426223fc976032883d87daed6d8a505f652e363a10c7387c8946abee55cf9f71a9181b066f1cde353993", - "0x97070a33393a7c9ce99c51a7811b41d477d57086e7255f7647fd369de9d40baed63ce1ea23ad82b6412e79f364c2d9a3", - "0xa99cde5c7c85ae291c74c893e598cc0e6eb2dda2a81dbb504a638eb21dd2c41d6e5caf7baa29e3c1c32e94dca0d791f1", - "0x937ccbf8cd19b82af2755b4856cfcca3d791e33ae37e4881982ea89d3b21d205a9402d754fac63037243e699484d21f6", - "0xad7dca7640444f1268f03b67544815d4366c6a4a2f0d25ee78f3361c63095416216fd31aa0bcce7448cdd7ba73a6344e", - "0x84991ca8ef255610ebc6aff6d66ea413a768e4d3a7764750fd02b5cd4735d41df399b36e87647fc83cf73421a39d09e9", - "0x91215fc3f7243638733fe293dab7029e0c4275550102acf5f1638773cf8f8ef2c53ffa5bdfc1b602c269a2b5ab164b7a", - "0xaa6cfb3a25f4d06c3ce1e8fd87496a74a5b951ab72557472a181a2e278c5e982d290dd4facf40bd2f4f8be62263dadb0", - "0xac9f29ad08aaf27581fe1f12e210ad4ac6011507fe3100763a4120f9e439f3c6d191f3fb55aadf58bd865cfd4406c68e", - "0x87c6cb9ca628d4081000bc6c71425b95570291eb32ef2cf62416bd1ce3666eb2ce54accd69f79d506cefbfe6feb5a1da", - "0x93042dd42e56671155bb40d85d9d56f42caf27bd965c6a7a7948b39089dba8487d4d5fd30522dba6ba392964e3ffd590", - "0xa76adeddf2454d131c91d5e2e3a464ef5d3c40ee6a2ab95e70ef2e49e0920d24f9b09276250ed7b29851affbdbc7885a", - "0x92a488068e1b70bf01e6e417f81e1dc3bcec71d51e7eabbc53b6736e8afdb8b67d191940fe09c55783be9210e1cbd73c", - "0x8180ffffb5abe78c38f2a42a3b7f1a408a6d70d3f698d047d5f1eef3018068256110fcb9fb028c8bdccbc22c0a4c3a20", - "0xa50ab79cf3f6777a45f28d1b5cdad2c7ea718c60efeeb4c828d6307b29ef319445e6a9f98aa90f351c78b496575150c1", - "0xa4632399c1a813e41fb2055ef293466098ea7752a9d3722d019aa01620f8c5ecdc5954f176c6c0901a770cbe6990eb11", - "0x83bf5055d6332009c060fd50b8dc698d42b764b079c90a1fad8a83101f8dd1cc27acb27dc9d1c25ac8d3db4107471b4a", - "0x8c432e044af778fb5e5e5677dbd29cd52d6574a66b09b0cd6e2a5812e71c91559c3f257587bfc557b4b072a822973a60", - "0x8368a0f17c8427beb71dbf11a09a2fe8495a33f08c29c74a9a996a88aa01c0a09f9555abeb1ef1592cab99a9e05875cf", - "0xa8795e7f4c4c5d025ead0077c3aa374daaf9858f1025c0d3024d72f5d6c03355ae6ac7418bf0757fe49c220acff89f7f", - "0xa6d9f67ca319ea9de50c3fed513269b83fa067977adfd1e9d9ee07ad61b2ac1de64a39d7b6897ab55870cf982fe481dd", - "0x86b3a4ea9b1fde00cce79d5ae480353d60cb6ddce363c535bbbc3e41a4b8e39fcf2978eb430091ae1b10420d43193971", - "0x90fb5cac22a22fb8a6b619f1eacd95873be974d4d5d1f7080e523bb9b4b2644eda7340d780bd1ea8ce36407ca0410fea", - "0xb5036d4c241685bcd67156e4ab0eba42b97f639947d54b17af2c88fbcc5fc57359c7df4bc7f8df955a524fb1501a6fda", - "0xb1c56f028f31f0ff86bdf55788703b4d809becaf3e4d9d349f1b660a07d2f15e127eb72a0e2a5a2742313785a3de43a5", - "0xa3e909196f447e492200cc67000c5d7f0f585fb98e966cf9bf08257597fea8d92a90ceb054d4b5553d561330b5d0c89a", - "0x87cac423d0847ee3547f45ac5babf53bddb154814e291f368cbb62ddd4f2c6f18d77a1c39fddb482befe1a0e77d5b7fd", - "0x8605b88ce23190b1fa9d389b15e6907417239a72b97673d1479c4ccb8f4515c7921d14537775c74e738a9c3f122b1443", - "0x87587504e819bc7f0349705a05c15e8504fd6b2c25c3fd264096cdb7aaa22d8078da776215925d9d775a7f9355b6f0c0", - "0xafba279768f0f928b864645aa4e491e9c949bf3dab57efa24eeaa1a9a7d4d5a53c840019354068e64c65a2f5889b8f3c", - "0x86b1cdd26ea9a3ae04d31a0b34aa3edc9e8d038437152214d195381173e79e4ccf7f8f0ce9801086724a1c927c20e4c8", - "0x812d3ded3a3c9e58eecf13a29bb4cc13b01b2a0af322423a29bb0e4f6d9021d1d87ac4af7a2a6b88d34f44a8bc1b3c55", - "0xa988cfed9f481bc98beb5fc188ed3f6893a3ebba27c3ebace669792f6abf0997727023c3b6930a6421224f5b257b8b49", - "0xa38c974b57da968f0c4611f5d85d8014fd48594c8cd763ef2f721cfd2c738e828d41ff029e3591d7447e3125641db8ef", - "0x880b4ef2b278e1b2cccf36a3b5b7fbce94f106ed9fa2820cb9099a7a540a57e9fdeef5c0fb0a743049828fc2b8c46163", - "0x96e7d1bbd42195360267c2a324b4d9bccad3231ed8a7f070278472a90371867e2ef2c29c9979a1ec6e194893afd992df", - "0xa92beb343caf6a945990adcf84302c55d1fccdef96c34a21f2c00d3e206a9b2c6c6b412f66e5d4fafe26ef6446cde705", - "0xaa48afa77d5a81cd967b285c0035e941ca6d783493e1840d7cbc0f2829a114ace9146a8fbe31ecbd8e63e9b3c216a8c5", - "0x893a2d97ae067202c8401f626ab3938b135110105b719b94b8d54b56e9158665e96d8096effe9b15c5a40c6701b83c41", - "0xb614910b247c6ade31001b0435686c3026b425b9bff80b6c23df81c55968633349e1408a9a5a9398a7d5d6ed5d9d3835", - "0x991c660e4d476ad92aa32ef2c5b27669ab84026eeb5ca70af69bbbcd8ebc0a8fec17843423306edc78b4436629d55c25", - "0xb926a21f555c296603dc9e24e176243199a533914f48994b20abca16f19c30cfd0baf319268139fe3f83ce69afdc324d", - "0x8e70e4867d2731901d603928d72bbeb34b2e0339a4f5cf06e7a771640717421b4ea039c61dde951582a28c2ff152ff70", - "0x95aafa379cc6a2b4bdd0cad30b7f0a47839952af41f584219ec201c6c4d54610eb2c04b67b29080acb8cecc5e7543fbc", - "0x8465bd8be9bd9c2c6116d4ae44ec6618c109cb9aaee2d241e7a6ed906d398ef15a6fc18bc8b1d3398184241405954bba", - "0xb455f751232de0a48440d09983f4f4718b6169907979c9f282acf7177ab5b1f338fe1f2acd8d0bee4b4aad61d0340839", - "0x970df2314849c27daa16c6845f95b7be178c034d795b00a5b6757cc2f43c4c8d8c2e4d082bec28d58dd4de0cb5718d61", - "0x8d52413f981bc611427ad0534d25e914113d0ebcd6960aab6421608bec6648b89ae4b2ca2153c57d3cf4f1f37212aa5c", - "0xb7ac87da14b783914ab2e914fb7b536893b7a650cdc5baa1f3b4aca9da77b93a3336671335250e6467a8cd4aa8dc61e9", - "0xb37a2ec9dec3d7d9cbc911fa1e5310a47d23a841d02c8b99a923991c73fc0185d130a494748c64f2b5a4c07bcd06920e", - "0x86108b661fb2c363adcca84c114c83346413df748b959015c018452cfac14890bf585dc0a646d68727cc3cdfd2b61897", - "0x8421044f794a1bcb497de6d8705f57faaba7f70632f99982e1c66b7e7403a4fb10d9ef5fb2877b66da72fd556fd6ffb0", - "0x84d2eb008578aebd6f01254b7e46584c1524e6fd7a5a2ae5fa0ea560865ca50d52290cf2d12dd20b042f402e62181b4d", - "0x8d6bed5f6b3f47b1428f00c306df550784cd24212ebac7e6384a0b1226ab50129c0341d0a10d990bd59b229869e7665a", - "0x80e30cabe1b6b4c3454bc8632b9ba068a0bcfd20ce5b6d44c8b1e2e39cbe84792fd96c51cf45cf9855c847dc92ce9437", - "0xb7e74ab2b379ceb9e660087ee2160dafe1e36926dfab1d321a001a9c5adde6c60cd48c6da146d8adfa2bd33162eeaf1a", - "0xa2b1ea43f51460b3cb83657b4e296944658945d3ad6ae7b392e60f40829ba1da6a812d89f0380474578cbd0ab09801ac", - "0x91ead7dacf43905eb5d4b179af29f945479ed074126bad3b5a2bbc1663af5f664fe53a36684e9389ab5819e53f1344fc", - "0x927c030d5a69f0908c08f95715f7a8d1e33bed5e95fc4cfb17f7743cb0262755b1e6b56d409adcfb7351b2706c964d3b", - "0x883f38af3b2c1d50f6e7c515a5e02468d76890f6e669f7acd2df89365862fa65877095deb001b4e2868bc5b59439dbb1", - "0xa0ebae60a998907a19baa396ae5a82bfe6aa22cf71bfca4e1b4df7d297bd9367bbeb2463bda37aa852ad8fd51803e482", - "0x8ae80eeaed3fc456f8a25c2176bd09f52a2546d45d77a70f48a9e30aa29e35ff561c510ae1f64e476e4a0f330b9fdbdd", - "0xa7be457b8bc1bfde4865a35b7b1826118edba213b0f0d3cf5d877267cc1559cabe61cefb1e300142a978c29676036179", - "0xaf51da717d2a45ab96fad5d9317ea867ec4c6a411af6fabd72e568230099a04c036a0f114158815b1a75da6474dc892a", - "0xb549cef11bf7c8bcf4bb11e5cdf5a289fc4bf145826e96a446fb4c729a2c839a4d8d38629cc599eda7efa05f3cf3425b", - "0x8d264fbfeeebb6c4df37ff02224e75e245e508f53fb3446192cd786ecf10d0f704c4fc2e53e7f7318ae1407e46fc0fb8", - "0xac3195143035cdb4ddcd5f93c150035d327addee5503ea2087b1a10b2f73b02453ddd1a94d8e7d883e365f9f0e3c38c9", - "0xacbb398ea9d782388c834cf7b3d95b9ff80ee2a8d072acae8f9979595910849e657889b994531c949d2601b3ce7b235d", - "0x811e6a5478f708495addbb1445a2ef23e39ee90287f3a23ecd3d57d4b844e4f85b828bae8fa0f1893dfcc456f86f7889", - "0x8cde690247d4831dfe312145ae879f4e53cb26641b3a3bb9eb4d590c56c11ece3cfe77180bd809468df5cddaea4f5ab1", - "0xb42578df29a9eb23bed91db6a1698df49654d2bc1b0d7973b2a7e300e9cf32e0e6ac464d463d4d26e394e7598239c4bf", - "0x97ffcbf88b668cde86b2839c7f14d19cb7f634a4cf05d977e65f3cd0e8051b2670e521ae74edc572d88201cff225e38a", - "0xa322b5d2a6e3cb98b8aaa4c068e097188affef5dec2f08c3e9ce29e73687340d4e5a743a8be5f10e138f9cabbe0c7211", - "0xa076ea1084b7a1a33115ef62d6524f36e7820579868763a6ed1f8bce468f150cbfbf0ed04be2487aaa34100d828b0db6", - "0x944259a56e3b4f745996289912740281bde47e22705f142c2a483ffd701e780f51a01b177d2494dc8db9e69157f45d44", - "0x91cb79d52951d1b901e4a686bf4ad587e31db57ea5af6ffeb93eeafae3929879c386ddec860f803c2dc61055437e6bee", - "0x91efdbcaad9931312d7c41d24de977f94d7f3f7b88090a1f72d9a097a1e30cc805c5ea16180f463022d9b26b8863f958", - "0xb26f5ed09f7d5bb640ec94ddd1df0b76466f69a943b4699f53d45296d5d6b8010bb61477539bc377d1a673d89074d22f", - "0x80822499f96a1a8c0048f01f389dfcaaa5d8269c332dbb507fe46f270bcfd5f67c53f827fd867221592dbde77b6b37ab", - "0x8860ba25d5530cb8585975d8013a1c2d5b0f0f96066044fdc43ed13488ae44e379c624ff6993a18cb6e037809d7985e7", - "0x999d1c44e14184349064415ae28a149b3b11aba5baab6792744378d14df554a3625fac82038eaca920064822294dd513", - "0xa62c2e7c692403e874a16e08e46a067e19dd561993ca07ff79cecb53c753763b3e49d372638c96c0a8c921bfa0798a0c", - "0xa1c84730a5c41dcab9a5ef9e1508a48213dbc69b00c8f814baf3f5e676355fc0b432d58a23ad542b55b527a3909b3af6", - "0xa1c0c317e6e352e16e25c140820b927161ce5d2c4c2e10bca3057ba4d46b4f42ad7aba20de86dad9fc6368ea92695268", - "0x85c216e314eb7bd8ba02e092c90e132bc4bafb21c6a0fbe058b0dd4272cb76f183b83c6783fc321786065ff78c95f952", - "0x8e8f63ec8f4f1f7fcc61f893b671710c3c17f9d2d26c5c6ca40e671bd4b252bc0cc1655e6780d2ddcf2915d8f623b9a4", - "0xaaeb0005d77e120ef764f1764967833cba61f2b30b0e9fed1d3f0c90b5ad6588646b8153bdf1d66707ac2e59fd4a2671", - "0x92ff79402d5005d463006e0a6991eaacc3136c4823487d912cc7eec1fe9f61caf24cd10022afdab5f6b4f85bfb3eee4f", - "0xa32a5bd9b7bec31dd138c44d8365186b9323afbba359550414a01e1cdb529426bfa0b6f7daaf3536e9402821faa80003", - "0x845982c2672fdd44b33d2e56ad676e704c02f756b09e8765bea42b924c14724484567b55f0db42ac20cb70a7f5201c14", - "0x89cd9f6ae7d9a9ff2b4db916ba3af9fe700fcfbd16577bf73a965af938e8cf633020466b0298d3c31300360aa6851af2", - "0x8fa2d7b22af8e6b82679ebdfa13efdcb34289a554653ea6c1b16efb9f957f7fe64df787e7b03d8cdc8a732b91c916bd1", - "0x94f327bc57ed1ce88ce4504b4810cc8af5bd21a7e07b280a7866ce08e39b6cf7a6560bf73a5f10671271624cd7893970", - "0x90f4476224b64c2a5333198a4300ece8b3a59ae315469b23fd98dadcdceaaf38642d2076e9cd0bfacc515306f807819f", - "0xae0db78548261216ad7d6a7ed4e6089ee17b3fa311494b2f2c559e215cd3de7e5f3a781a49dcff428a8a61c2a4f49a19", - "0xa83371f44e007c708dc4bcafa7bd3581f9080a4583c9be88624265014fd92f060127e628de5af3c442a25f049c7e7766", - "0xb471c72bd2971353f4b44248b8e6cf5316812861a88ccfc20fd0d89a5e010428c387228b2f6f14c12f79e31afc9d0753", - "0x8962afddcb1a26cc8ccd3c993109e79a4dd747ca473b8b5ef93d9c2e71d29623b834ac945074acf118248e3ae7878a6c", - "0xaa0940e4e5586e79a3d97397c8aff3d112c6f759d2efac29366acc5b5c6a7cfef8d50516bf309da8b787de265dc8deda", - "0xa211120e1bb3b10138df1fa58efb009a298b8771f884b82bb3de15822b1252124a68f3980f96122a775fb96f05ddc3d5", - "0xa1047401598b1e6e2613d746bb4689e0406eccdbadf319a6609a3261cd09deec215d90eba6d0ddc50dd3787d60104e7f", - "0x96791b2b8066b155de0b57a2e4b814bc9b6b7c5a1db3d2475a2183b09f9dcd9c6f273e2b0c922a23d1cf049a6ce602a3", - "0x91013e0d537fb085a49bf1aa3b727239b3e2c1d74c0f52050ff066982d23d5ee6104e70b533047b685e8b1529a0f14dc", - "0xaa65c11071be23c9bddaa5203f3166e5cf043efe5fb8f4b26f8a9cabe71db701a450e79eb001c401da5752755d9cf1af", - "0x8645cc44d180c18a6d8f57ba57bae05879451997533cfe558cad4d3d586caec877e348915e32a09ee73483283c4df744", - "0x8eafbb7002f5bc4cea23e7b1ba1ec10558de447c7b3e209b77f4df7b042804a07bb27c85d76aea591fa5693542c070de", - "0x919c81bd1f3d9918e121e4793690f9ddd96c925ae928536322d4b98132f21979c1f34731d393f0ae6e0871af4355a8ad", - "0x98181e9291622f3f3f72937c3828cee9a1661ca522250dfbbe1c39cda23b23be5b6e970faf400c6c7f15c9ca1d563868", - "0x8f44c43b80a3c5f488118859fab054745cfe5b0824821944b82fcf870fda6d93489ea9ca4220c24db2f4ad09c6080cb7", - "0xa683d4865ddcc099f7b698153007b92f853b80f49b3be75163ea8cd1f8ff584b43a68e68de3ae61cda8ad4b41f355c87", - "0x942772b7c7c47d4e5957ccf1d6f1450070930af3e2b7eaab0dd7699372445df0cc910e6c0efcf501887dd1adabdaee23", - "0x805c06e565ee67cab0cbccb92b6656fdb240b430766eade3c6b0a0b1b93c840e2b4f028601451dca135c783239463880", - "0x84d3e2a06e16ced26094b356a16a4fb6aad50ad9ab23ef804a5852a33ef0bff76f3c5fbf7beb062376c2e669cb598679", - "0x803df08aa745cc3c0a799f3a91bb6ed423cd520c9d255d36c21bed1a0c3b12e8cad32f54da09dadca97683e9548fba91", - "0xaa2c3ef95b8d4265f01666129646004b6950d3e8ce74b4ca12aa3b90fbb445079a569178df772c272463a44d48922b8f", - "0xb0a4c136fb93594913ffcebba98ee1cdf7bc60ad175af0bc2fb1afe7314524bbb85f620dd101e9af765588b7b4bf51d0", - "0x93e4c18896f3ebbbf3cdb5ca6b346e1a76bee6897f927f081d477993eefbc54bbdfaddc871a90d5e96bc445e1cfce24e", - "0x89019e9550648962420984e9fd03597a854ae824567d9aa6cd5db01a4616b4e1477230f2d1362a2d307e2425a3eeb898", - "0x861b710d5ec8ce873e921655a2ca877429e34d432643f65d50e8b2669929be40a9ce11c6353b0ada1fe115e45396b2b7", - "0x88554c83648ea97dac83d806cd81d92531980346b208d281fba489da15a0084fd4d9a00591d1ca67aad3c5793685d55f", - "0x851fcadebee06930186f35293feefd40d7daedec9b94e6fe5967536c2c0e4cc68f58d3f5fbc76f1e77b90c9580074f98", - "0xb96a11048c7c327709d52e72e6f6ed0b7653329a374ea341ad909311b5b303e5629d6dcf11dcdb195e8c7592ceefac21", - "0x836075979eaf386ff6cb459cfd48fed171ae812b0ac3b38dc24dd8ca905cac1c600be717d4a0defa0a854f40cfaf8c33", - "0x90fc170529bcc0b80c46a53fffd8323fd2cc5cfa9b75ea4d36db21bd1f198335ad2bfa87f8990cf9cd9fd7989ecca718", - "0xb7eb6a49bf8f942dd8c37c41c1b35df43e4536e07ca9f4c1cfbbf8a8c03f84c54c1a0d8e901c49de526900aeac0f922f", - "0xaf6911edd6c7ad30f905a0a3f78634808832fdeb4206b006934822d673bcced8e378779261b3c4b772b34b8871987f57", - "0xa74d240d0d7ea0afe68813fab55388d77e75eca0519d21771dcb7170cedb11dc14b237b26c5ae1f7f728b52e5ec0f02d", - "0xa7b86e4f1366da44fd59a3ee68018a99c23ba3588789463bd88b0177a9b94030b58cb879a506e64421af966f261eaa86", - "0xad8d94e46cc02a1c0ad27105e8f672ec15b8296051801f1918d0bd470625686e8e8a0abde8f6852b846ee8d9132b26bc", - "0x980508c4d1e655cc6200f89a884b3a25c0c05708a3e4a101205c4fd901c3e20a943071a6300bb2614be41a139d4ef1df", - "0xb0173651b4ba0590b1d2f0265183f3729b5bb09893523ca12c4936120cbe5ef0d9b98733734407d99fdc766792ff10ac", - "0xabf72ec0280d56971e599b3be7915f5f224c0ccde2c440237e67b95489f0c9154ace04b7763db228473715f68053f071", - "0xb404beebf60026ca6843f2953cfcdee494d495c8e2d18865147102ef29a8f0ee470961d2246fe5a450c622d20ca51d53", - "0x89461cb2dadf51d6f1208b0965c8eabec895d7b19b7d90d3c6e49dbe75a75c30fd26db3dfb169dd46a4342280225032a", - "0xa61cb5b148cb7ff34775dead8efa7d54d7141182356bf614070dfaa710ebf07a4dfb684dad151db60c0f8261c30a4f40", - "0x83a798f47a4f62dcb8b531d463b0fd4a876d47a8ca990710290549255033c909de709471b4e823a60bf94d8baf8b5acf", - "0xa23431589f3a25070a188deead9adb0ed423d6b00af267f3f125cdd4391c1527909b5cfa88130dc4b67915f5002128fa", - "0x8d77e65ba6250fe18c54ce70d0ba4571a7d3e68a8b169055cd208e4434b35a4297e154775c73e7dfba511faadb2598c5", - "0x90e5db75f3787b819df471712f87b6f3281437090f5db7a2c21b07164446292a414c687e41de2d1ca00786b093239c64", - "0xb382fa28670a5e14dc954b2db8ace250c73df71ab095304bd8ee28f455ab26cc54f82775a831428e110d1a3a2af709bb", - "0xa58d2fb1c2612d28c54fafa7f2e1e6c336c24435abdb53e1be9dce9aebecbf7468a348b872549535ac18aa003f83ea87", - "0x9545f94c4e9056e360dd999985f8ad06210556fa6f07cff77136a2460605afb0ff1fb1d1a2abe4a4e319fd6c29fff80f", - "0x93121aa60f904a48e624e00f5410cf8c8925d2b0719f90c20e00cba584626f833de7c8a18dbfa6a07df24b916156bfc0", - "0xaa3446aac25f6c23ea16e8f7d19c58d187746ef3c2ac7d8fdf9bdc329409a07589ec8eebafbe2b156e7ba60addc15af8", - "0xb964f50011f03135e993739e2e63a71933ba4583040b3af96c7e2dce874226518f7b68f622c4a1d78b9c3ec671d33ad7", - "0x8cb5cb7cba886af58acadc5a4348524b1395a39dc51196316d759a9b72d9fc0fe45b706e264393a13ff911f0d15de45c", - "0xb50c306f78143b37986e68efa10dbe1fb047d58562e9b5c5439b341dd8f1896c7ae586afac0a3213759784a905c1caaa", - "0x97825edba8410e8bcb85c5943628c02ea95ee7595f559c030b94395c0d1d0d84c38eca199fce9c1992e572b5029b124c", - "0xb0922acd6da2a95b36de6d0755316594a7e2e32ea774792dc314e8c3cd76d9f1d69df38231e166e24bd42c664f4fbac7", - "0xae5ea228c1b91ef23c245928186fbafa1275ff1817535018d7d2d913abff0fd76bf41fd04a96d816f2f1891bd16e9264", - "0xb106c6d13ca17a4c8ea599306e84918127cf2de21027ac3fe5a57d35cf6f3b1d7671c70b866f6e02168ae4e7adb56860", - "0xa044cd5a3b727dc1cb59875e4025718375d12e706fffcdb48874e51a675dc2cabb209670192e408cdced5aeac65192e4", - "0xab1cc44983e46a6ea2430aa6616ab28614f43624665e3e6ae31a9357c0c5434f34e56c720906e184327693cc4ebe1fa2", - "0x890def696fc04bbb9e9ed87a2a4965b896a9ae127bc0e1cc515549b88ddbcbc02647e983561cab691f7d25cf7c7eb254", - "0xa86be58fef115445b909dffac6f51da3fe9214afd9c31fd564bb8f39b1dc3cb895b1222f2c63226b54b60b278ec45edb", - "0x8757e9a6a2dac742ab66011c53fa76edb5ebc3c2fbd9a7265529a3e5608b5c24b4482fed095725e9b8fed5a8319c17a4", - "0xa7e0ddbae16e4491822684c0da3affecbbd17ef96c5c491ac093c6eb4e162fc7854c367535e296fd3d6265c2ed1210bb", - "0x941fe0dabcdb3225a625af70a132bc1e24ccab1f8331dde87db3e26cbee710b12b85535e46b55de7f5d1c67a52ddd5c8", - "0xa24d05b51c7c128bb49979cbd9019e6618545d95275a44b5c3d1d03e71bf2ebffdf43fff50c30846ec27d279043cef4e", - "0xb526f40d519e7a8f2c81b69f71b3e2ef079028004c0448ba0608296c2787972491ec6d05ed6a8fbd5ef2da76325a93cb", - "0x87ca4fa85a257adf7e21af302437e0fa094e09efced2d7ebab6cf848e6a77ae7bfc7cf76079117f6ed6eded9d79ce9cb", - "0x9276e8051bed8f5dbfc6b35765aac577dd9351d9d6ac1bb14496bd98091005b9a4737b213e347336413743f681f5043b", - "0xa7741c52498e0a24db3ce7699882de8f462a2b3ed5e9f77dc7200cbdf46b6cdd923b1128759909d6dddd64700c4c20c5", - "0xab5b363ed9551e32042e43495a456e394cbc6d53b15d37a8859850162608bdf36d3d4564b88fdbaf36ff391bb4090b8c", - "0x838ff6630dc3908a04c51fb44a29eca5a0d88330f48c1d0dd68b8890411a394fd728f14215482b03477d33f39645dceb", - "0x997d3b82e4753f1fc3fc2595cfe25b22ac1956d89c0950767c6b9de20623d310b1d84aaa72ab967ef1ea6d397e13524b", - "0x85416cf3eef63d5530062d6f031aeddad101c7f1aea3bccb826c73f8a25d5d963caefd789a6b9832bd4ed459f268ae64", - "0x9194bc45e11d7276ed1c9ef3ad5a33d6a27372f5568563ca8ee213e2e7029dee404ab5acbaecaef698129798d35fd895", - "0xa4828a003513ab887082390262a932a7e8c5e25431824b7b4cc10fccba73265c0e5ee5b315ccef13906d971644913806", - "0xb907ec84b6ae5729d36e2acd585a350acacdeef148bcc5dc4a91edb57505526462bd4371574865541d8bb0d786a29b2f", - "0xaa5d1c1f0a7f6b9b3c3734f85864aa60bddad5121450218d76d82edefd2602685a820965c56d7eefe789d5115cb41e01", - "0xad28fe70a8606f87bcb5d6f44e1fca499c24bcee791971f599ffef1f403dc7aec2ab6ebed73c1f8750a9b0ff8f69a1e6", - "0xa641eaa149c366de228a2833907ad60eea423dd3edf47e76042fdf6f5dc47a5b5fc1f1b92c8b96c70e6d8a68d3b8896c", - "0xabac08f4df786b2d524f758bca43b403b724d12601dc0a8362b7a2779d55b060c6682a5618fffea2e4def169fcbd2bfb", - "0x8658a15df961c25648fd444bdf48a8f7bb382d9212c0c65d56bf9cdb61aab3bd86604c687fb682260dbc0ad2dc84bf01", - "0xac7983d50ec447b65e62ed38054d8e8242c31b40030f630098ce0a4e93536da9179c3f3ae0b34a0b02aad427a97ee60d", - "0xb8877a00a24b0ffcb2bd3fce8a8ba327d8ee2e98d85531cb61fec21fd49cd1696491cd51024a9c3820cf06a77cacf04b", - "0xae075b66e5f211c2149c45b211d1297bbc1d9e6497cb3315363c492a9a51ae5b9d0a28bfecd755d68553736901ac6606", - "0xafdc091a224486e7bfac169e6a7b4e008d2d04144508a337fd93b6f4d385ee3f0d927b1f5c1cd79a15e0fd6078e45dd4", - "0xb75c28941ee3f91b3535b4eaa0fb17b59ca65b5256601a1f6d0cf2bb4d66837fd16e51d6942856679012a5730a66e519", - "0x84a6edac5ac68a7ca837c46d5ada8fab136748b6c3a3b9165dbbc231ec386b15328e4ef7d69a15d4cf354135348a4ee4", - "0xb01ee30d120b97e7b60ea89b9b6c537cdf20b6e36337e70d289ed5949355dd32679dc0a747525d6f2076f5be051d3a89", - "0xa80deb10bba4bc7e729145e4caf009a39f5c69388a2a86eaba3de275b441d5217d615554a610466a33cfe0bbe09ef355", - "0x8d6e3df29419bd0da1deba52c1feebe37744108685b49ca703e1b76fb4d612e3959d3b60b822506e5c0aac50b2f5eee2", - "0xa373408beb5e4e0d3ebd5ca3843fe39bb56b77a5d3d2121d4a7a87f9add3ec7376388e9d4b8da0ba69164850cb4b077d", - "0xae0beb452af7479134a7fbc31a5f59d248e8a67d4c7f73a0e30a51db9cd33a1da3f0ae947fa7e5983aea1343e7daf06a", - "0xaa103a329b699d4102f948101ce5fae27226419f75d866d235da8956f11367e71db5c0a179dd63007ed53f7eec333aaa", - "0xa094cca9d120d92c0e92ce740bc774a89667c6f796b438b0d98df0b7aef0935d8c915d5b0dad4b53e383dc9f095c29fa", - "0xa4d88467136b99d6e55603b3665b6da0f7fb27c7759687f7e6977b6230272773d7b95049d999538c008f310c05ed948a", - "0xa23710308d8e25a0bb1db53c8598e526235c5e91e4605e402f6a25c126687d9de146b75c39a31c69ab76bab514320e05", - "0xa36d6952c2d7f88bf28032a76ed46c4dabbf1901a46efc50deb798d1b44adf7e0210fbdf2473a1ba408b5c98d76943e5", - "0xab45f5b756ec6e0b98d0d4301c87675a0a1f0b1178b8a9780c1ab23e482cd821834835afa1de890962212159e464b10a", - "0xb800be1788175a01a9228b0d3e7eb4302484a2654eb2a86c0f0900b593da0a436ef031ac230e2b05e968b33e90a342ce", - "0x8cc8d279ec08d0a5a2a09ad07fabb0122eb65f48da2571d83f86efa2c1c5bc51b04ae94b145f0a8ef19a3988638b9380", - "0xb4cd409256819e8e4627edbba90ec40b7da17a57f95749104d90db0364f5007b1accc816f4d51a0dbe5ffbcb737cb37e", - "0x99365fe5ab8ea8bd768ae7181a6ba49b79d240f512ce309b02f09d465fea276298ff55b5b9cb5b4162a901b390606024", - "0xad77fcac9753efba7a9d9ef8ff4ec9889aa4b9e43ba185e5df6bf6574a5cf9b9ad3f0f3ef2bcbea660c7eef869ce76c8", - "0xad2456725ac3aeb0e4ca5c0502a8abb4dbd8a8897d9d91e673fea6a0cffd64d907b714b662d73c0877b98d4ab3ce6a89", - "0xac8436e33619e2907659741d66082acbda32612d245fcc8ae31e55f99703fac1a15657342fa66751d3be44fc35d71c36", - "0xb0eecd04c8d09fd364f9ca724036995c16ba6830d6c13a480b30eb2118c66c019cfdc9dacce6bfd8215abe025733e43d", - "0x9439b663e4104d64433be7d49d0beaae263f20cfac0b5af402a59412056094bd71f0450bc52a294fc759ca8a3fddfee9", - "0xb72de0187809aaea904652d81dcabd38295e7988e3b98d5279c1b6d097b05e35ca381d4e32083d2cf24ca73cc8289d2b", - "0x93706f8d7daca7c3b339538fb7087ddbf09c733662b55c35f2a71073f4a17c91741955d4d549c2ee6c22eaa84193c1ad", - "0x926dc729e135f1f0bff4662ee3d6823a64597fe189b763ada34f246e77705fd4e062d85506a338e9fa98c4d225a3b27a", - "0x93f03495d53c781be8b76e37e68b64aa260523004eff6455ddc8a8552af39854e5181f8c5365812b1f65926534fba5dd", - "0x9834f66e5c946c3a8241ca2bbde046a7e88072124911d5d15c037a95b61e82b88b5c2058fa4a3721537dee39dee5da18", - "0x92ec1aeb2aa24c51cd5f724972c8b6095e77b237d83f93ed34ca0bc91a1dbf1ad95adccc59e0f0abbfef33f331f3298c", - "0x94402d05dbe02a7505da715c5b26438880d086e3130dce7d6c59a9cca1943fe88c44771619303ec71736774b3cc5b1f6", - "0x8368bb9b9bb2e17730c42ed1100eb870c88a8431601312aa8cb1e738cdb9ca2704dfd432cf1703c0db043259819631dc", - "0xa35189a105401f0cfba4b43be21723486c04659e5a01e67c43e8f9911030810b878beee696f04f63d314ccfe97ebb790", - "0x93ccd8c5f82374e0bef6562e16576f742d79b6f400e3485ef36e148088b61fbd882c3d2bb38ab0b43fa1dac77f31d543", - "0xb85d9a426a23ca9ee582bc16c203a9352dcc5f85440e46979de80eb572384479b697dc964cafd9457d9f34eeb77bb72a", - "0xaefb70e89dbf4456e077690509afcdcabf975416ff2fa16777fdf90b3abd3f5dcd865c43f1ebe6f8a669edc7f3bd6ad8", - "0x8eb03001ac9e22c6956a682ed458e650785c36d23ddbcd51ac4d9cc991325c02519ff1958987a08eb29ff56ff6e2c293", - "0xab4a1ffef7e001723c71f5d28f3dd030a06c42d91773733d117247bbf9c01cd66fca2cff8c6ce04c4bfb68dfcdd851f2", - "0xa9ef845ab489f61dbfdcd71abcc29fc38f3494a00243b9c20b9cd0dd9e8a0f23304df84939b9652cdf5542d9b3ee085e", - "0xb5726aee939d8aee0d50bf15565f99e6d0c4df7388073b4534f581f572ad55893c5566eab1a7e22db8feeb8a90175b7d", - "0x9953a7cbc152f101a60e3e381f2af17ebe7401e16ef6462d132b8f0f6c6a18837914a1299d1605f9f289b9561112f4bb", - "0xa0c9b944a338325f5efb675c9c12619fb43c8e25e80d38d6140e31d5070573b1a0ed9bb52576e4f22f37d0292d36a648", - "0x8bfd6a173a56b73480cc950ef266a18933ecafc86915a7453ded09efd8a0cf4466101f1373f05d48eae3e7fc5c0f7f54", - "0x983fc1ddf17f9756c9cecc00b39bb2ad432587a5c6d1c3296a383b9f539c9afe84c6c818447a709c0b686ba26ce5ea3e", - "0x94bbc6b2742d21eff4fae77c720313015dd4bbcc5add8146bf1c4b89e32f6f5df46ca770e1f385fdd29dc5c7b9653361", - "0xb26b4d483bca73d3f3a976bb595a0e40f9a42094e0febbad3a1874934be1939a1b362ee4ea14a4f5cbfa9b1392796a12", - "0x8dbe8fcbcc414eb352245c52549973f73d987012de9d5f2b2f55dfdc43cf8cc9ea6b147abf149817f80f9e15aea566c6", - "0x9604da21e23c994a0a875ad5e0d279c79210f7a7de5c9699fac4aebbd76d39b703eeec5dd5efc9ad6b9dc58936089ddc", - "0x8934e9a3feababa12ed142daa30e91bd6d28b432d182ac625501fe1dc82f973c67f0fe82d39c9b1da3613bb8bfe2f77b", - "0x85f2ed3ffb03e50c8f22553b8e6349be6244d893aa37a7c6dbd221e9e121579e5a04466e60d6b4d3567bc747b1fc1e9f", - "0xab0ad421f6fd056687b4fa5e99dff97bd08840b7c4e00435eb9da80e0d7d071a447a22f8e5c1c5e93a9c729e5b875a1e", - "0x841d77b358c4567396925040dffe17b3b82c6f199285ac621b2a95aa401ddb2bc6f07ebd5fa500af01f64d3bb44de2df", - "0x83f21dfe0272a5a8682c3c7814c5e0e4db6a9098f1fa80fda725f77ea81fdfd2fa36b0c8db013503a89bd035f86306fa", - "0x95c98e3b6b62f84edf7f297cae93ee5f82593478877f92fb5bf43fd4422c3c78e37d48c1ee7ca474f807ab3e848d4496", - "0x81c3a8c00cfe4e82f3d8cb48de7d4926d5ec2f7689f9cb85c1886a23758bc107a4bc6e978601c3519156a169d0bf6779", - "0x8e956ca6050684b113a6c09d575996a9c99cc0bf61c6fb5c9eaae57b453838821cc604cf8adb70111de2c5076ae9d456", - "0x83474776ef2341051b781a8feaf971915b4a1034fa30a9232c4bf4b1bd0b57bc069c72c79510acef92e75da6f6b8843d", - "0xb41780d9d67e9e8b81b1f62d25c0c72ecfda659d2bfe6825edb70ecd0e0724250ac364e7be521cdc112ba638f16360d4", - "0x842ba3c847c99532bf3a9339380e84839326d39d404f9c2994821eaf265185c1ac87d3dc04a7f851df4961e540330323", - "0xaf17532b35bcb373ce1deebce1c84abe34f88a412082b97795b0c73570cb6b88ea4ba52e7f5eb5ca181277cdba7a2d6d", - "0xb9574edb9567f07f85c7c2e6ca6c02d90ad7c7b87d49796f1e2fb7240ad071fb755cf13ca8678668a56217c62df168eb", - "0x82212706111fb1cf5def02b5b0eb7ae9e6ea42b4c7a2b9fcacb7aec928326edb9ac940850dd933f2822f6cf519de0d50", - "0x9579973ee2559da09b327c62b1cc0177f2859872885dca709e24dcfbb9bdf9224a6d26869aafce498f44c0e6bd8a996c", - "0xa102c2ade15ea2f2b0cbc7dbd8c1171de0c8092fc4ecef84b5fd2bae7424aea8be1629f851c75e4d1d0e96104e54bfbc", - "0xa5d7e847ce7793386e17fe525f82aabb790d5417c3c6e3f6312f8e5ff52efa8b345c1ff60c4c9bf7636f5ff17b7a0061", - "0xb4b80d7fbdb1dbf1567dfb30d8e814e63de670839a8f6ff434fe171416599fef831b8e978d6498851b8a81e0bc8dfb85", - "0xb6e6277b86cd5284299ced867d37ab98090ac44a94deef6898aeadd177e64605440c15b9609c07e71fe54c95b61873b0", - "0x8135a0633082e4465090d6930b770340e82366bc5c37be6ef6dd105f85acf63361e17de8b5fcab4c82e9f9b4029954b7", - "0x864d5d9858cd881eecb0dde5e3e0c6c5de623cd9ef619e87b82fd25c5edf45a1a025b1dc763c27c5f4d520fd564b464a", - "0x8784a8fa62e0ce23283386175007bb781a8ec91b06fd94f22a20cd869929de37259847a94a0f22078ab14bb74709fac6", - "0x8adb748d5fa5c22ce4c76a1debf394b00d58add9f4e08524cf9c503f95981b36b8d0cb2dfaef0d59d07768e555733ecc", - "0xb76cb8cb446eb3cb4f682a5cd884f6c93086a8bf626c5b5c557a06499de9c13315618d48a0c5693512a3dc143a799c07", - "0xb2af1f7ece1fd640c205a09614122d69d5d2e81a7618bedefd6dbb91c7f432679be4ced1e6dddd3de323bd44991931c5", - "0xb950b457c34bfdfdd9d6da9628d41749ccae03659518a04b56487bf1b4c0681b719ec5230c0b0fd5dd710894df6aa2f8", - "0xb21785008910a949804d1291e7533752641d31beae3cb518806488f81d58c38a5efe5ed9534ac692e68c3121e2f9d97d", - "0xa9b120a77d70c1cbc0178a12d97a78b2dd0b98d0584e8e780b937800ceb18c90eaa1f0a83c5b50e34cae1c20468f004f", - "0x998c9ee20d33f96a2388b1df642aa602bc8900ba335e8810baab17060c1eace4bc5203672c257b9ae750008b707b0aa1", - "0xa7d1676816e81a752267d309014de1772b571b109c2901dc7c9810f45417faa18c81965c114be489ed178e54ac3687a1", - "0xb409f87f0632aae9bc081345b17a50a767ba4198f9ac9d352246fb3bebd29ed53c9d6f148c2f318c2eb12846b0aac4cb", - "0xb40a3bae2b08c13db00f993db49e2042be99cde3d6f4f03d9991e42297933d6049394c659e31f316fcb081b60461dabf", - "0x8c1de4264e04ff7e8282faf81c0bfb5943656451be52170211cb7adf4ff21bccbb789400735579c622f69982fcb8e9c6", - "0x8085c60b6b12ac8a5be8a7e24977663125c34827842aa3b2730854ab199dd0d2eaa93084c9599f0939be8db6758b198b", - "0x972cfaefda96f5edfe0614c01533b76153118712c1c02c505008204a5be2aa438675d97f43384199517b1c08c7c9fdb2", - "0xa1e47798a782a024da340d6d6a1b1e5e15a0f2d8668adf349ca375086964414a563cc1eea3226ae637f87e78c0a630b3", - "0x8171f20c020faae112bb92ca213c1df5b1050151496c70db5c5319212bada83b120d515bd7d8b24736090c574e1b7203", - "0xafe779a9ca4edc032fed08ee0dd069be277d7663e898dceaba6001399b0b77bbce653c9dc90f27137b4278d754c1551a", - "0xa5a07bf219432e9c80c38596c93560b49c7de287f31e30b7a06fcb4d15982add4a24085adbc5b753c462be989c64c96d", - "0x9210be290176d7e8a5005d27e7ed825067b1c678b174bc8180f92b5c03b6c3d1822356edba84f460caf6bf5275cd7efb", - "0xa95bec86a7c8417a8df3a0158199327ba0924d3b7dd94cd7c1ef8489b10270ae64b8537ed39cd3699a48942bfc80c35d", - "0xad9725114b01152fff134c1a8ccb8d171b8cd11685ef6815b76f442d757d130bab9ef4c9845e66f4aa0237ee2b525c20", - "0x8018499ef720e28759133033833edfe17ed23e42f99058bb79fe844ddee823cfdc43916be2dc9724d18f9726e6f1b409", - "0x809c7a08fbef7caf4c137cd639f2e47a8ca60d13bca3990eac51ac2a9e4442cd1a1473bebb63c61d595b586525d7b027", - "0x9793a74fa578ace75b083578277a1ae8766d41a5c508b0f1135fb97dff1d0826002393a7276b18cbc4b3c5671360ce0b", - "0xa6d7e65bf9f889532090ae4f9067bb63f15b21f05f22c2540ff1bb5b0b5d98f205e150b1b1690e9aa13d0dee37222143", - "0x99c935fe18699bca9852200c292690a2b834bac508890c4ee9af1aa6999a8d590bf6a3a274bb55d5a73f1b7095d10f37", - "0x860f5649c5299211728a36722a142bf1aa7cbbfbd225b671d427c67546375de96832c06709c73b7a51439b091249d34f", - "0x9104ac7ad13b441c6b2234a319e1c54e7f172c9a3efcb8c5fab0ac1d388b01895a9a208f59910bc00fb998b0adab1bc3", - "0xa3b109249ac2900806f0f39338da72d4f2cc6d1ac403b59834b46da5705cf436af8499fa83717f954edb32312397c8d9", - "0xb9893f7a47af457a9efd90ddc0c0ef383ab34e9c1284e617c126965cd9f0de5c54ee8b7b5208ff190366fe445e9c1325", - "0xb77416ea9a6b819e63ae427057d5741788bd6301b02d180083c7aa662200f5ebed14a486efae63c3de81572fe0d92a9c", - "0x8b20a852fc8f0b7cdbbd808c04a0cfd2fbccbdc0cb2361434f0d96341c8bde6155695977768d563b95746dcb4339fe2c", - "0x96b15806d9009962fa07f8c32e92e3bc30be4ded0645ab9f486962a1b317e313830992179826d746ea26d4d906bdb7b6", - "0xb0d69b3861ca6791632ec8a87114b463e0da571bc076c22a8f0d9e88a1a5eaef24683f3efa8f34900d0112412e3dc4fa", - "0xb01a30d439def99e676c097e5f4b2aa249aa4d184eaace81819a698cb37d33f5a24089339916ee0acb539f0e62936d83", - "0xb19ca6e55f349bbb2dc3e429520ff5b2e817972470794f35c1aac8c118b37a694cfcc875b6d72225343799825d2f5c39", - "0xb7ea5e0d3cfcf0570204b0371d69df1ab8f1fdc4e58688ecd2b884399644f7d318d660c23bd4d6d60d44a43aa9cf656d", - "0xa778da56ddfe4a383816b43b027464d7a28689fc4a6b35b36883d3f36d9c41f0177bdbfc8f258afe8da90f02d3b64fea", - "0x910fd030feb5538f538e5ba74b9bd017d889ed6d2a797be9c26d2be8caeba7a473006102de27e87755742ba34e445bca", - "0xb49593ea6040ce82cfb5aa2881a4b0c42b78aa9fc8467d79c8e4a8ae4ee7355842841c8e1cc0558362047ed80de44fd3", - "0xb07447c7e87459315fcbda3fb86fef27f98373b1246e2ce367e26afd87f6d698a438501fdc13cc5de9eef8d545aab768", - "0x8a9f7e8d45f11c4bfb0921c6008f3c79ff923452bcfa7769beb3222f1f37dcb861be979e6eae187f06cf26af05e8ee5b", - "0x8ebfbcaccddd2489c4a29a374a2babc26987c3312607eadb2c4b0a53a17de97107c54eab34def09144b3098c082c286b", - "0x93be3d4363659fb6fbf3e4c91ac25524f486450a3937bc210c2043773131f81018dbc042f40be623192fbdd174369be2", - "0x8cf8412bd48b21b008f0207b1f430ed96bc6512c3712dffbbecb66e493e33698c051b27a2998c5bddd89d6c373d02d06", - "0xa5562fbaa952d4dcfe234023f969fa691307a8dfa46de1b2dcff73d3791d56b1c52d3b949365911fdff6dde44c08e855", - "0xa8c167b93023b60e2050e704fcaca8951df180b2ae17bfb6af464533395ece7ed9d9ec200fd08b27b6f04dafa3a7a0bd", - "0x93e4d7740847caeeaca68e0b8f9a81b9475435108861506e3d3ccd3d716e05ced294ac30743eb9f45496acd6438b255d", - "0x8016d3229030424cfeff6c5b813970ea193f8d012cfa767270ca9057d58eddc556e96c14544bf4c038dbed5f24aa8da0", - "0xab7eff4ef8696db334bce564bc273af0412bb4de547056326dff2037e1eca7abde039a51953948dd61d3d15925cd92f6", - "0xa3f9dcc48290883d233100b69404b0b05cf34df5f6e6f6833a17cc7b23a2612b85c39df03c1e6e3cd380f259402c6120", - "0x8b476b3b065a3b95a3d11ec60a749c2258ddcc5885bfb50b8a086d3fd1e49ff73e1dde733b8981c3d2d206aa0c87b09b", - "0xaf3e694ad71684f7214f86bed85149db039971e1c362119b979a135255aa226128802e58e2caaeaf8d89304371dd0440", - "0xaa19a75f21a14ad5f170e336a0bd07e0c98b9f5d71f91e784d1dc28a5f5eb6870a4eb35bb41edcf9e6efe982ae5c2c5b", - "0xb9528983419ab5766596683faebb3592982a76b68593f810186b4e5f94f6de60830739ad8dcc164c601d575b84bd2700", - "0x88e7a12a90428bb45bcf4b01442c11607433211fc2f9bee9545304eb66e0b4b5339360160bc782e185391385da7c5ad7", - "0xa4c4df0e29db19ab4c82dd6ca8570b337d15b59c7d84577a7a444a8f762ff16ff5ab3e4203a1d6b60a23ff949a93ea81", - "0x8f11ee58ef82b1bbd2240d3f548d8681e22bed5ce118d605bed4523b4bb39899ac78e15337daab92666750dfcaf32aff", - "0x8d3cba4d10f94bd3406a341c903ad144cfcfe6b61678d5c03084a56b4413bc30bd20d7a9fd5d839dbb565cc9b2aa99fe", - "0xab8a8769c754008a7976b6799e81d7bfe97413d0a79b90715703c1f8f567675463ec93aabee59277121fc4df88b5c7a9", - "0xb201b0546f19c5db88df9c684cf55ed623bdb43927d06051bd595497df741feb1485961f64e8d3d1811d9e2e9e1e54ad", - "0xa04016e9e13ad845763cfe44af4e29fecf920b4aa42f581715fc34fb9ca27776feee45c82093c7274839eef1838b10c4", - "0x8f84cba7ceb7652023fc8ebde4b00ecde1f550935bab12feb630d6f49517b4148f3cde184bf55d4f6ec99a849fc6f862", - "0xa2248409026f35c3da8bc4d5c02315066df8fca44ff5a358cc42b5c88bdf6866dc133617c697bff004b1ef20ec4b5748", - "0xa52c5a63b55a8001b6b67c5db4fd5e95923052f03618369312896ed9892d99354aebc0dee8c3b365bafa29e211a5c3f9", - "0x8c9fefe233d0d657349b7efcdc368f5aaead27071d224af780874751e7d241f6b88f7650fbb4133043b24bbebc12aa48", - "0x86ceb649a337a5a79c17b496993ca07fa93b38a582367ca04f3dfec5cef8f268d4e8080e5a76b150f5be1b177ef6984e", - "0x87dcb537e38cefa32e629ae669da42e809b5afcabdeeef244b72ce057fc18584a1e8c3f073d5d33775232707f0cc59ca", - "0xa020404547407be6d42856780a1b9cf46b5bc48122902880909bdcf45b204c083f3b03447c6e90d97fd241975566e9bf", - "0xa1beb9f673409ec678020ea4dcbe65177aa18e2932ceb9cfb33fccb94b9a8ccb664f71647d58b3c8b2bdbbffbc02d5f7", - "0xae47b31c5b62b38ee886ee04945649054369018dd6543c91f0138464af489a32c1fea339e0e0cbe82e3e8b9f2ef3918c", - "0xb18c41c0f827f6d8656d3fb93c90b663eb2eac034923972f8842cb30e96c32842b3fbc1127930e1ba4322d5b6641f04d", - "0xa6d6ef51a361df2e8f1d993980e4df93dbbb32248a8608e3e2b724093936f013edabb2e3374842b7cce9630e57c7e4dd", - "0xa49da42c27d019a21cc6489ada7b712b98c4ede28ba25dbcfa916acef48446a2baf73e03a48be763378a09774d4a03fc", - "0x8b62902fb2855300580e94830a4bc825d997ede33bf356fe3b7c08d6a8bd85a37879433fc6bee58f9b44ca280f4e8dfd", - "0xaf9d13103868c854821ba518907b067cfba025d739125f1e9cce0a04fffc3a2a1f25506c1209a0cfe1d6c1572c229ff0", - "0x8910f41db6952c25dfbf6b6b5ba252a2d999c51537d35a0d86b7688bb54dcb6f11eb755a5dce366113dfb2f6b56802b7", - "0xb551d1ce88cbf4ffbdcb0113a6e319513bd676d0078dd4e6a6f23ad336c1d0fb47a4e427bdedbe0fc8f152353971f81d", - "0xb8876bda1e709ab16e1347a1107852a7898a334a84af978de39920790b4d82eb0739cbfc34da1c7154dd6e9f7674759c", - "0xa7d9ae9621dd1f3da3cd2d435e891cc3579c4c0d60d6a4565cac86c315cea21a9ad883559fe7b897ae6e05f1aa989ad9", - "0xaac995a41c14d379853ef18ffc854ad62ad77061ca9bdf5029cab3d6c2630de114e777a7fc3322455939d5205ed59c55", - "0x999cec6a31d9b2f280017ddd59138014829fa34cab58e6c35a5014ec364b84712441e7a2f717cf2f0de8d5451e250924", - "0xb1f43b498cba1797f9793dc794a437500c3c44a8a4b59f9125a4d358afa304fc05b88ac31ed40b6eb68f0396b60cb7cd", - "0x93ba2e000bdb7269818d390bc4232992d280e69abebe2db2ecb6fcb1390d323238c9793574509bc1fa34051ac1928f07", - "0xa64808a2d15c30460651c200a09b50fc83e9d84d87abc156d06cee73b76fbd74e6d64424cb5bb83d3f16b21bdb7ae9d2", - "0xa75bcd04fcb44ce5cbab7eef6649155ec0bef46202e4eb86c88b4ced65e111f764ee7fb37e9f68e38067040fedf715ee", - "0xb95fc0ec39596deee2c4363f57bb4786f5bb8dfb345c1e5b14e2927be482615971d0d81f9a88b3389fac7079b3cb2f46", - "0xaef456af90354ff88039d2dde02b0f5a6790aa762b23e0a9da8c6ec92c3b8b3320687bb21666608b4a22615843afd1ef", - "0xb38be9ada17ced704a34a7498c4fd6ba2503f6bd886b693d4712267847efa887a26e7da5d60f8bc5014b92bca8b3a12d", - "0x991a7c93f06d50ec6a4340c6751b73eb5825bad02a954e44e1e2d424af928819ebbb590c6129ce35b3f1e908e2152f33", - "0x84888f2efd897a2aca04e34505774f6f4d62a02a5ae93f71405f2d3b326366b4038854458fd6553d12da6d4891788e59", - "0x941e2e3ba414a371a11c3fe92cabf688ff363da6230ec7c83ac7303f652a19ebc89cc494427c456d0c2ae84c72053f73", - "0x925f3bb79c89a759cbf1fabdaa4d332dfe1b2d146c9b782fe4a9f85fee522834e05c4c0df8915f8f7b5389604ba66c19", - "0x941c8962debd2756f92a6a0451a2bf7fbc01f32ed03d0823dffd4a61186628a4c3c7c482b18589ff65e4c449fa35c2a4", - "0x88ce41025aa153a94f91f22e7b96f9342b5e0e1d76274fc70c4df7d08f66d9f7ac86e55a1c6e77693b8b01b2b38bf900", - "0x8f142bde50abe4dac8e059003db41610436d5ca60d2dfe2660ecaa5f9628aeb8b5d443e1b57662076f77363c89a1479d", - "0xb2affe048c187d311a185503d8958cacbe03796edf79bc32e8533941004d9178bd2e376e627e1ba61ed43850c0c455cf", - "0x8f7bbaaac458bada6d852fe665c87c646133bab16c0d5136c3dc922095b9d647d93a9de7671cb7bfd4cbd138ae0709d1", - "0xb76f598fd5c28d742bc1a81af84f35f1284d62239989f1025e9eba9bece2d746a52f246f9bb6bcfde888b9f7b67fc4f6", - "0xa4c665a3e4e25a7af51e433c978573841bfa2c75c075e17dd1f43b2f0369249f3d3a46ff51051e8ce7da528b0fa98d16", - "0x81e0992e7c1c54c21cac32e36b90b25e1e5b72aac99c953c3c4d019eced64d7e316cbc0840204a4a51a4ad17d8b1d508", - "0x96d7a69eaf2761bf0e5ebcd607b134d5dedba8e262ca1d6d3e8fbf23e6419a8ce1bbe4cd23b9e4b5f80db54a802a9795", - "0xb2235bdf60dde5d0d78c72cb69e6e09153b0154efdbab97e1bc91f18d3cec4f660a80311fe6a1acd419a448ab65b18f1", - "0x838d5eee51f5d65c9ed1632d042bb7f88161f3789e6bb461318c5400eaf6728e7ba0f92c18e1a994aa4743145c96164b", - "0xacfbac397ae2ff23b31bb27b90788fd0fd51a50f8e8c9f4b31be8499194252014f0b1972b204aeb9c2836a20beb3c868", - "0xad85789bb62b60e9768bd330a31a16f711b6018445af6a47646f318f12df8d4d256ad00d1ed7c3afa4e98fef73c6c610", - "0xb2349265be33d90aaf51362d015ce47c5ffe33e9e6e018c8c6e39336d9327ccdd13d25e792eb33b43ed89a162f6ac2fd", - "0xaa458aaca6ecb43b6e45ea72d02682e5a7dc8dc22782669a0628e1638e73999319f011803f4ec8cf072467bf2c49c629", - "0xb9e6c9f2562e90bd3008669a42151538b70faf028cc5bbc09fd6ab3febc626df911fcc65744a2ad793ecaf3f91a1f701", - "0xa37185bd96faa526dfd3ddaff89b1eb29ceb4597bfc7e346bff9d6b3225b9ca87cbce0db94f05243c7232ead5f6607e8", - "0x824fde65f1ff4f1f83207d0045137070e0facc8e70070422369a3b72bbf486a9387375c5ef33f4cb6c658a04c3f2bd7e", - "0xb0ed68167a67490bd7d7d49e83341606d6e6fdd99b82e46747c2190d270719f81c5f5f8733646c246260f438a695aa3a", - "0xa87c2f13f2a824b7e2c39cfb63ca7b94ae6a11ade0c6b8e83f5092b933fa8b6157a5d2f09c23081f49d35cc85f5db36c", - "0x88f5e795cb36ab22bdcff01caca0e9d04db463c3d88cf656c3a0e0f5ac864b7092c738758b4c8f3b65e31995c6aaf267", - "0xac66f3a7041586ac1576e33598f01921e16d99afbf4249c3350f0ee1654de98bd37a61c243eb6a18a942db529e36af0d", - "0xaca69a4095567331a665e2841210655636a3273d7b7590e021925fe50757617898e1883532f9cfd46428c2e3d854f9f7", - "0x946d585d7aa452d37a8c89d404757c3cce2adf2410e18613483c19199abd88f7a12e206f87a43f6009e42f4e31ed20c0", - "0x9722c1079db7e2e1c49756288a02302b43b8fd92d5671585ac1ea7491123742a2744a526c12c9a0b4c4a80f26342a3a6", - "0xb80e8516598c59dddcf13fdb7a42d8f5a52c84e01bd6a39880f4acaefe8e4b8f09cc1b1a2423cd5121f4952201f20078", - "0x85bca2f86423a09014b562f7dc613246bedffdcb3aa41fee02270c13e6b00c8d6704dcbfbafc5997df6a90c7fc08c29f", - "0xa36dad4f7cba9f4cc843fe40f6240e1973a4c412cae29b4a68712598523cfaecb05272fc47d30772bf06906b5a26e282", - "0xa3d8610c2522d330df02511710e52b1d9bdc9f2b156deca12b1bf754266caeac4f449ed965d9863558df43ce9ae65a44", - "0xb3e313e79d905a3cc9cc8a86bd4dba7286fb641c2f93706adb3b932443e32eff2cbed695beeb26d93101c53d5f49d7db", - "0x88d8a32231ff2bfc39f1f9d39ccf638727b4ead866660b1b8bfbdf59c5ab4d76efddd76930eff49ea0af048b2e396b6c", - "0xa90d9502a9785e55c199630456fcb1e794bbeb0f5f8c022e66f238a0789998b126cf9911fd0b7d463b7706dc6f9ec128", - "0x8c627caf25eae6764501b9eff35aa90bd4f24952cad712aae20344579e83ecd104ad1f7915edc4f9023b17fddbdb4cd7", - "0x87d4b20bbe2dcd4f65f4e1087f58532d5140b39a5288e1a63fc0b7e97a6a56946eafdd90ba09300c3d1fef6356ac6b7c", - "0xa18f4464cf5cebade8ee280fa00e0917cbf1743aeb0dacc748ab68773b909e30dc60f40fdef3041b5f082e650985f7a6", - "0xa6ae4fd03fbb4e2150795f75a241ab3a95c622b4615f553bab342a1803b86b1c1a2fc93bd92ee12786bf2de22d455786", - "0xa89bc7548ea245ce9556eeee3fba98a3256f87499f54a7c5eec0c43b9fb4ef2fe8f6810867ed0df814a88ee100c245af", - "0x97f1a7370b4f5acf83b466f519da361c366915f560385dd7eff9d53700ad81b25c9862bc71d35428e82372a5ae555ea0", - "0x825359cfe68ad6a75578a94be6419179e0aa088170b6c20fc5c249dc3be7a260d687c93d8d8a343c7c72c2ed6a716de3", - "0xaa9b9cc039d147677aedd1e47ad9013fcc0da0164070ff7305b18e5786c7fac0471368637a3adbb78f3af174a5c1592a", - "0xa61687511b627bde7b3977e9a34cb7fddc2aaa509a7b99b6b6c7b97133845c721e1e69f99758698d82cca265d8703610", - "0x8853c582e86cf916750d670a621246a63c7fd78f68c556642053bcdfa7937de58885d728209736b7d5521b591387e9a7", - "0x82b8c013f24fe64b8e0337ae8b6a682cae336b8404eafc1404744f80f765efdb8b2873d1d3f31141e8dfe4d93346ac56", - "0x866ec39b9eda580d96bc2bff76af5cd4887b6788675149ab33bfefe38db82ad01b8d64c6b60704210918f3564cde1110", - "0x81337ebe90d6942d8b61922ea880c4d28ebc745ddc10a1acc85b745a15c6c8754af1a73b1b3483b6a5024b783510b35c", - "0x807c510df25c0ba10d4aa06a462e02f050c69a977c64c071401ab74f9ac1e60788aa504743b4cc1982da835ff9ac2541", - "0x96b1c82b85cdb8a7026fd3431bea9cd008f0261ee7f4179f4e69a399872837ab836a14e2dd45f5448d54800a4ae7c7f2", - "0xa48b1031ca2f5a5acb4dbdd0e9a2b4e9add5ccfc0b17d94818273c8df11e825193fade364e0aec10f1ff91d57d03a52f" - ], - "aggregate_pubkey": "0xa825959280c88c6716f6df807204feb84d745dfbee3cb3474ce81a1ef0c4cd142e5ca962a0335e68b7b4266769d631b8" - }, - "current_sync_committee_branch": [ - "0xbcfe80e1d24fbdad7bc058b011403a4c26cb56967654494cde51517f888023f4", - "0x4710ae46156553fee6231622052f7fb2f6945cdb59a5501cef824b1925c87445", - "0x6df62e05ef3e1ac92c659c3a519b8fa651d1b649c2b46fda58c48cdeffe8337c", - "0xd26ff22ef5958a707a8d98eb1ffaaf1f9f412e816c04b79f5434cb1792ccf608", - "0x90d5e61f0af673ab4d8b3ab0b978d05142a8295a163b198e6dea9d8c8f1c6d89" - ], - "validators_root": "0xd8ea171f3c94aea21ebc42a1ed61052acf3f9209c00e4efbaaddac09ed9b8078", - "block_roots_root": "0x5078f286fa90b88a09dcccd4ac72f6c3615b77c0ab3132508cb8c0c07b20282d", - "block_roots_branch": [ - "0x558b658b1230e225ac3adce3daf0b066ed0484b4a768d55b74ba81579ca0e5d0", - "0x2cbb27d38065ff3f230247af918e67d1998b67bc7e2ce6c244bab7146e16b8ad", - "0xc63bfc96585f424385e3b4b39ce46e957017b716c54d105eb7e07c841d1d4309", - "0xe662b38f57427b58c46b09980db3856f17e56b60b36bd5471823b0f2cc1b6467", - "0x8b3bd99618b1e50cf284b4c3b03d0cc272312bce377d585eded77154aa5580a5" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.minimal.json deleted file mode 100644 index a7e48f459019..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/initial-checkpoint.minimal.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "header": { - "slot": 3616, - "proposer_index": 7, - "parent_root": "0x6c5e8c7b32b7bfbb250fa8fd7bc348d7325fb2bfc869e4c506af6802fcad87f4", - "state_root": "0x3e467e3429a1ae36572fe3fe1c953381242e950254cf97c7527a8cea8aa6c9de", - "body_root": "0x7da749680d2b0b4f779047fcfe7d0c13d247f6d23478817fe9c6fbe07993adb2" - }, - "current_sync_committee": { - "pubkeys": [ - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c" - ], - "aggregate_pubkey": "0x8fe11476a05750c52618deb79918e2e674f56dfbf12dbce55ae4386d108e8a1e83c6326f5957e2ef19137582ce270dc6" - }, - "current_sync_committee_branch": [ - "0x46af3f54acbea439b63aa5bb699c8f25ff584b23912366788f7c8e95011ce324", - "0x41dcb71ec3b3940399118d28e09fdc58a8e33b818b8c5cbb933c59929504ca08", - "0xfa53febb29348e3493a50c0e7c6d35796bf69c54dfc6f42f7600612789d0ed6d", - "0x5e7ea1693066b604fc60d4657b43e7a4aafd3f4f54d9a740d2abe765e92d8385", - "0x16c9bca64a82e80c23817bfec345d088e0adc3865e392965c1244f97979f816a" - ], - "validators_root": "0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69", - "block_roots_root": "0x00f6bbdeac1e1a922a9bf0e78720c0bffe558d8195e8ede8cb72bbd295f242f2", - "block_roots_branch": [ - "0x7a61086fb9e53ab4dd87243d6288c51793696168a73773277630da5b20bf6091", - "0x60733905cdc5dd65d05161bb3138eecc47d6d6057ab36b0d36cf5a3200484143", - "0x86d7de634ae45de5b3cbbc562dd976de7d06a3d96f83147413536e6b108c7a39", - "0x0ada571c9e0da6fce8dd13e6d9ce173768521ac32e0af456634556176789fa6e", - "0x2341538fd0aafbc1ff0f513545e5dcd4b8905dc9e00d6173480c18a4e8086ebc" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.mainnet.json deleted file mode 100755 index 3440749102a7..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.mainnet.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "attested_header": { - "slot": 4066880, - "proposer_index": 1904, - "parent_root": "0xcab3b6fe3ca0c3ec6f9a8290d1cb3ade42b019f399dca754060518eda41fd429", - "state_root": "0xc47d2d0ec566de4bd41082ee14aa6294c05f264a4fb6a73766c75df917b57a55", - "body_root": "0x5dc66f1cdd8fe849e0aa63b096a8083c16b00814f37edd213819852cc43317d6" - }, - "sync_aggregate": { - "sync_committee_bits": "0x9fffefffffbfebfffffffeffffffbfffffdfffbffffff7ffffff7fddfffffaffcfeffff7ff3e6ffefffffbfffffdefbffdffffffbffffefffffff7ffffbfdffe", - "sync_committee_signature": "0x9146a1a3cc2520a69415103446e2c30676fcd164ef2beb42933bf4beb753f5e94f28fdcb6296e3ceda302b2a93c716d515a890894365a36ed535e099da76c7e585b8d6ed5fc2ec3c316049b14da844add39bc79cd3829a455f552438669ab70c" - }, - "signature_slot": 4066881, - "next_sync_committee_update": null, - "finalized_header": { - "slot": 4066816, - "proposer_index": 1396, - "parent_root": "0x17d77d07327f42b16d6d87a06c6ab5e56ce02e3ebc65ed2d28a64dd0c3a33d15", - "state_root": "0x9b498175419bce5a027c432fbb844f35138dc00083540a04ec0f54c77eaf061d", - "body_root": "0x6650167595152e94d0741c7a7b64d2c10ed01b0d11519f7d0c615c8a60dfae2e" - }, - "finality_branch": [ - "0x70f0010000000000000000000000000000000000000000000000000000000000", - "0x3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb", - "0x452c63d803b8bf301447a73b2f7a747e49f37f9c9a096d8ddb6c8302666b809e", - "0xdfebfd48ce69c56abd05de8266c76478936901404ac3869f0c068c5cfd33b301", - "0x6f1a65d993b2f461764934642be084a68bccee505bd3adc20cc69e151bc6330a", - "0xbd65074f41adb20717d733e64d219d832064b6417b90f22de6d065cbbd6b3d83" - ], - "block_roots_root": "0x4729dbb81e8ebbbae1acc10857551a3991fd5da08c27dbd304b62673edcd46a0", - "block_roots_branch": [ - "0xa3c286182434bdd4d55be8ef6e7212917dc272c204a4daff2d0244fa993d86cd", - "0x00d2df4cb3c0b06bb4f2722f975d6630a7f3c2a1ff12d635e2109f08379e3922", - "0x135a357782eb8f46d14db6e62bd3e9ad611d01f16a3e573cad9ea0c53010bdc7", - "0xdb944338cc4e7b11242b39bd83159afb122504a1934569bb500a4228b884b8c6", - "0xd381920000999813479b975b7cf0e5663b52c3ab06bb6ac66e723731e8f41e9b" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.minimal.json deleted file mode 100755 index 8f1ddc827c1f..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-finalized-header-update.minimal.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "attested_header": { - "slot": 3696, - "proposer_index": 1, - "parent_root": "0x04a63c5dfb726c31a32a72c1c426ff89e21363223d7096486b629f1d58abe5d8", - "state_root": "0xbe20e69420cbf9400224ec5edeb0843776a2ccf945e9a3ba9311ae812cad1e30", - "body_root": "0x1d2acd1748f1c58096d1edc8badd3a1d7e1dc3c33bcb9229e4c03f3a84efeadb" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffff", - "sync_committee_signature": "0xafa79bc0f3c731ab1eb6aeafc582a7dd1c100ea471df3af6ff485b58661b3ef8077264dea0b60df9aec2d3ca8ddab6770fc9d061462e5a6dc718146085425f863d00921c42413805cb5b4c5175f36f2087cfed740bb7d57e8d5b48352643cd5b" - }, - "signature_slot": 3697, - "next_sync_committee_update": null, - "finalized_header": { - "slot": 3680, - "proposer_index": 7, - "parent_root": "0x4d8f4fc47ad3eb045bd20cae13af6df02f96a3f8d7c8a285190ba10cfe2b84cf", - "state_root": "0xd498766d77277fe16a6a4609ab3ac3a6e9887d162d8dfffdfc9cc4ae833e4127", - "body_root": "0x9ba73bc9a4907cac0b887550e2b01a63dcc70473753ffcc243d33394cc64b4c0" - }, - "finality_branch": [ - "0xcc01000000000000000000000000000000000000000000000000000000000000", - "0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7", - "0x142061c4bc3673bf774cb8c7b6085057bd0ca85672b43afa2d9581b0b6a44e54", - "0x48b8cd8ca9d9563e30c1cca2a854cd7f75eb4cb013d10809b3138a72d94ea0c5", - "0x9b39523d05013ac7cbb9f43e5d6f9dc033b12aa1d6d6edd994ddc4f5efe7be9d", - "0x066c9aa26107bc8cb28bc73e518da6cc865ec1d67516b6ca24663b6b7ae3cb21" - ], - "block_roots_root": "0xb15aa2483811d8c5616cb93710f4fcb809d97443caac9de163f943a30f385db6", - "block_roots_branch": [ - "0xf7a43ad317417daa4c2a1e93c54895895a824ef1e43320eb44eab16673da5a61", - "0xe4b8d640660f765c2ef4dc886025dc8e54c6e70b66192582f42837ed5e9d8d41", - "0x841f113dc81e76419b6cdec8b0cf2fc20f9381492ed3c79e9b49179b4d3eacbc", - "0xeb5fdc4d8b5282b653ecbc9caa93bcfe482f6d6a32cbb0d9eb011bef947579bb", - "0x1f328cc5640efb191ae6aa86223b1aa9d083b26ac3e1fa3c071327bb09dc5727" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.mainnet.json deleted file mode 100755 index c445bfb48a23..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.mainnet.json +++ /dev/null @@ -1,563 +0,0 @@ -{ - "attested_header": { - "slot": 4063296, - "proposer_index": 944, - "parent_root": "0x3e8712719bae71b519a25b7eeea9b412acb882ba6bbeeadc596b1682838cb6a6", - "state_root": "0x16add3b722d0b9075e7a3fe9cef6d237698053edeffe1b95f5b59a31f1bb4f1c", - "body_root": "0x724f1d72cbacde14baf82d273d3c4eafbbda3a56cb0f641cbfe76a426657327c" - }, - "sync_aggregate": { - "sync_committee_bits": "0x9fffefffffbfebfffffffeffffffbfffffdfffbffffff7ffffff7fddfffffaffcfeffff7ff3e6ffefffffbfffffdefbffdffffffbffffefffffff7ffffbfdffe", - "sync_committee_signature": "0xb2f86b054283455ef620757c13531ef64baaf8899527864aee1b86301c62c72b6c979865579e04880790c1ea418b53a717d7b8b85c70fda1760b2436ee04a25b13a8906d6aea8e94facef2444f33e4d5b4e91439adb981900c253186e742f1ec" - }, - "signature_slot": 4063297, - "next_sync_committee_update": { - "next_sync_committee": { - "pubkeys": [ - "0x936749ff47e5be307546564a5a4615bd8df52e2590034b2db19846939af3595a79ccabf0f6ff52ca46b9a1de3efd47a5", - "0x93fda62b785757b465e6f396f74674d5b95a08c938cf694e66beed7d2f317a4c9d736cb54d7c221d61e8cb3d64dca3ab", - "0xa39e96e33076fbb49c35a58b6e386d22fa7378337bb8b0d47699264f78e5ae8dc143f1f6d5f8b371deafc5c875adb60a", - "0xb5f69b7614fe07889b58142d7b438186d70214ff4cb209b6f271a3bf2bcdef5e6f1c7e95dbf5f2785aa471f0294cd029", - "0x987dd977d6b8d27c4065b61b3c078ec9ce3871fec02844ed00f5ad28c42f9cedecbe830ddd19e11a5c879b01eb0f8f80", - "0x9969ab62009b6aa81734579346766937d22ba73c008d24bebc183d1b3d3cfabc90b47f41b29bc6e23d70165594c2e774", - "0x840ac0e104b22eaebcaa1e49be43689f45434a6c5ddb71eec577323f38836ada5464b317fa3862773132166f2ac0a536", - "0xaf96a83f97ed0696fd29e59daa24e1857e16371f67089d08129f9c236753ea68c93590dce4d32c9e9818a21014da6f0d", - "0x8779a0376579008d0daa99895f548dd091b3abab37e91efc9cabf08835068c983ab0927e7c8eb0396eb83a5e0a713c56", - "0x99289672bfc48d2fbfd51a32d0d7f9d03fff37b8269ce45cbae1e9a091ee3983774d053efe8eae2f2d3f22a9eb532457", - "0xb60df25a7ac1ad14aef7e8809c4bfc190b715f94f14b0534cc2e4015ff6c322883cbdc5309e05d67dca4bc641c69725a", - "0x8c22f1f2a530879a93e744397fa6acca57b01fb62b62188ffa7487464815c605e1520ff4bb18e832753893649ab80d62", - "0xb3acfe8f25eb5153b880a03e07760f7fa30beca475843581b4878ac0412cd2038117f25a48c152e6d60ec16e4b1e9a45", - "0x8163eea18eacc062e71bb9f7406c58ebe1ce42a8b93656077dd781c2772e37775fe20e8d5b980dd52fdad98b72f10b71", - "0x8100b48ac2785477a123a7967bfcea8bacef59391680a411692880098a08771ff9786bd3b8dfb034cae00d5a7665621c", - "0x83bbd31e799ac14686085868e8ea7587c7c7969c7015bfe45fd8e3a3847ad5338005f9cdf58396b2ea833c4af98bd9ca", - "0xa59249e4dfb674dfdc648ae00b4226f85f8374076ecfccb43dfde2b9b299bb880943181e8b908ddeba2411843e288085", - "0x9793a74fa578ace75b083578277a1ae8766d41a5c508b0f1135fb97dff1d0826002393a7276b18cbc4b3c5671360ce0b", - "0xa734a3c947be4c7e6704639d4400aec2ccf5f1af0901b41a29e336afb37c53bf168774939ce51f32d4496bce1a32e612", - "0xb96a11048c7c327709d52e72e6f6ed0b7653329a374ea341ad909311b5b303e5629d6dcf11dcdb195e8c7592ceefac21", - "0xb3b7af9258af054362d461a74fcfeb6dcf3a37b6e33b6df32f8317d50d8be8e1970818a6e41c8232b89e1c8f964c6c1d", - "0x907c827a4fb5f698bf0e6f10ca07741c5b8e3ecb26aa53f938ba34ceb50c01be80c4afc5ac4358a5fda88eadea0cbe73", - "0x84173aeaf3d96368dc7ca1ad5e5575da279113567e5815a364a0356a720c5e08cb58ca1fdd891924f4871d3eaae5de40", - "0x92127d55535bf59f2b00511c82f74afe90529d4abfbaca6e53515d63303fe52b4b22383fb026a2a3f88e96d2bd235f6a", - "0xa9f261d19934fd26458421551e91f484d7a1522a7e7adbfb28f6371102a7650a5ae6efd49d9e33b03aefde647d134ce6", - "0x880b4ef2b278e1b2cccf36a3b5b7fbce94f106ed9fa2820cb9099a7a540a57e9fdeef5c0fb0a743049828fc2b8c46163", - "0xaace45334070c51cc8b3579598d4cd8cda2153bba51f56e3b1fe5e135c83ef70503c322756b9cad9d3cd28f1ecfc8227", - "0x97578474be98726192cb0eac3cb9195a54c7315e9c619d5c44c56b3f98671636c383416f73605d4ea7ca9fbeff8dd699", - "0xac5c01c51dac6ee1cb365c9b03f09906d9b7b9b4d1b73c44d9e8e06823025d7070f242898a975420bc87d6372382cab8", - "0xa9a591fdd18aec8746435eeead0a54bb88e055f55e91ffdd9bc663ce0bc2937fb296034ebb959d6adcf9af94bbd2f49b", - "0xb495404544c9335d5f184cd6873299a93174905fa34c14092f67d9b8545e71fab29545bc337e380dffcb533f7390e9cd", - "0xa3b7fabaabd4c2e555dce46add6c56851b68308c1bb7253576a9f32eda141522317b5c00a28b384ead3a880b8e7e40dc", - "0xae0beb452af7479134a7fbc31a5f59d248e8a67d4c7f73a0e30a51db9cd33a1da3f0ae947fa7e5983aea1343e7daf06a", - "0xa9d9a295590641b2b09d8473b50c0f6e036e1a009dcd1a0b16d84406763b4b078d5de6ca90898232e34f7f7bf147f61c", - "0xa5fe3dfb5031517bb8db0d5ade1e9f438e84bcf23221de003b03d2a2f4ea97629e81c79abc3769bdb8c69a512c189b91", - "0xb614910b247c6ade31001b0435686c3026b425b9bff80b6c23df81c55968633349e1408a9a5a9398a7d5d6ed5d9d3835", - "0xa19e7db50604f6b82cc28bc97135025459c8eac107a1c482919df10b8be2e4f24fceb93b963c0b8ac9f402e2f6ebf387", - "0xabf7da952c9d8f75fcc67fa7969fac0b26d4dc3e022961ed674ce85d734f11620a950fb1fb0ef830fba1d8b5bc3eced4", - "0xb382fa28670a5e14dc954b2db8ace250c73df71ab095304bd8ee28f455ab26cc54f82775a831428e110d1a3a2af709bb", - "0xb284286dd815e2897bb321e0b1f52f9c917b9ef36c9e85671f63b909c0b2c40a8132910325b20a543640b01dc63b48da", - "0xa2b1ea43f51460b3cb83657b4e296944658945d3ad6ae7b392e60f40829ba1da6a812d89f0380474578cbd0ab09801ac", - "0x8b886448cbbbeb40be3e71ccee251632186dccb51697f69eb5c746000b4327fd85be3a58fbd49f1df642a37f6388a8f2", - "0x9161ba220130eea190932ecdad9f114e385a31ec51c71cc8de451ffe5e75abcda37227c6a77f7090d4d8bbf134421bca", - "0xa24d05b51c7c128bb49979cbd9019e6618545d95275a44b5c3d1d03e71bf2ebffdf43fff50c30846ec27d279043cef4e", - "0x8cd1c73b7fe915e7169d351f88ade0f810d6a156fe20e4b52c7a697c3d93459e6d6c2f10dc1c6ec4114beae3e0a8c45a", - "0xb95e3032192bdc064306c683982d885f0ded8b907a532f15526a257ffeff2c8bdd7a2334c10d74b1484909b2e3ae0e47", - "0xac754a42f279472760bd36dd0cf36f5ec685e7fc2970c275811a70cd05843f94fe21745dddbd54135144edf1793aa0cc", - "0xb26b4d483bca73d3f3a976bb595a0e40f9a42094e0febbad3a1874934be1939a1b362ee4ea14a4f5cbfa9b1392796a12", - "0xa841594e74b66935efd295a6c06e2be03cc8c187b277cbf5cd2f590630d4812801ad55f3e502736d126441a2f22f1867", - "0xa845a8a3299f8e5fcf72358521a114c6077251e62ff6a885003f7281b0e1ee33715d9ca0b0082fbf7cb9d452d531c38c", - "0xa7b86e4f1366da44fd59a3ee68018a99c23ba3588789463bd88b0177a9b94030b58cb879a506e64421af966f261eaa86", - "0x85822227f6a96d3b6d6f5cf943e9fb819c8eaf42a9aa0bdd1527055442b1caf672522762831b2dac397af37a1c5ed702", - "0xb455f751232de0a48440d09983f4f4718b6169907979c9f282acf7177ab5b1f338fe1f2acd8d0bee4b4aad61d0340839", - "0xb97b2f1b2d6d744f2322812825ea1cf91453dfe1bbbb2678776e40e7d0fe682239d0dc8053f94d97e5a9678232b7a71f", - "0x815f53751f6d3e7d76c489f3c98d2b49214938cac8c2b417e2d17bb13446c285fa76fd32a97e9c4564a68f4faa069ad2", - "0x8ed7790f87f6975e0f3e501901b0bec1778c88bf39588989014c5dda76c2163732e7e5703c9cb2c1a6144ffdac5dcbab", - "0xb6cacc458ca5a0f04836c5640d34c70cab34cb5c87df28579a0d5e2c72edbc092814bdbe902747ebe3ce36808d8f4dac", - "0xab7c058199294c02e1edf9b790004f971cb8c41ae7efd25592705970141cdd5318e8eb187959f1ac8bf45c59f1ead0d9", - "0x99365fe5ab8ea8bd768ae7181a6ba49b79d240f512ce309b02f09d465fea276298ff55b5b9cb5b4162a901b390606024", - "0xb1afaefc9fb0e436c8fb93ba69feb5282e9f672c62cbb3a9fc56e5377985e9d8d1b8a068936a1007efa52ef8be55ce9c", - "0xb37334c41a3456b73b61d0eb0777260af9c2e400bbec0e0c0fdb45c39ce0dd19f021d9760f35da801f20486c6be30e9e", - "0x95757096c132e7f6c096d7b93a5a0d2594d5e609b9f13c4a9f878e95a389fa1a111b185dc1fd8f7d98b737dcf8d2af60", - "0x8f71f8edae59d6936846d8b50da29520f69b339f574ba9156d3d5f0cd4a279d36bad7ca7eb724dd48aefc4ca9ce26bdc", - "0xac2c98a0ab3f9d041fc115d9be4a6c77bd2219bb4b851cbee0d9257a4de5791251735b5b8fad09c55d16eb0d97080eff", - "0xa09f11d2bc6000d12a42b545ddc29c1973944a39787c5f27c96d4f6aa0d9c8fa9c479f2ed327fbd30376df3fa5b7d2a8", - "0xaa19a75f21a14ad5f170e336a0bd07e0c98b9f5d71f91e784d1dc28a5f5eb6870a4eb35bb41edcf9e6efe982ae5c2c5b", - "0x92a488068e1b70bf01e6e417f81e1dc3bcec71d51e7eabbc53b6736e8afdb8b67d191940fe09c55783be9210e1cbd73c", - "0x95cf2e038c790ce7a2960add7ab44804375f04ec6829f8cc63793dfe9fc48c7471079f81b932726509394fd3d46a52e9", - "0x87fdca39618051c4b3f03c816b13df2d4cd4c7c564e3d8693dcb58145b7b3b3db7884b0125b1e84d9bb82e91bed8bba3", - "0x815922ad356f490910e8cc3b0f7d3934b5e28c09711b5151ae8329876670f3de6d7a3a298fd97b580ac8f693305afb21", - "0x8bb4d08318386c91a0136d980a42da18c05743a5c52a861ce52a436e66a8ebe472dac7f7461db32ea5da59a23e9bd6c9", - "0xb0053550040ab3a3996cba5caf9ad5718867b5f5df273ed8c6520761571f03a94e50b5f8a6a8c42d725383cce97d3cae", - "0xa42c46a7e617d78b12053d7783f0d175fd9103db06d0c6982b38893a20b72fd8ad8501eacb3d47be06fd7c3ad89a8159", - "0x838ff6630dc3908a04c51fb44a29eca5a0d88330f48c1d0dd68b8890411a394fd728f14215482b03477d33f39645dceb", - "0x8ba45888012549a343983c43cea12a0c268d2f7884fcf563d98e8c0e08686064a9231ae83680f225e46d021a4e7959bb", - "0xa59a59db246f981e9c8e54aba52898c714d9787fef8969a6d8677fe6dec82950ff22a1364393b579f3e596cdf5bcd7b1", - "0x8722f3267a945f7123c1df8b6c2122456d81fed56e6369ba726b023c01c1f6738fc12e506e260d99e448fc920fd5e5af", - "0x89d356593ec09d838cd89306ce83c060ee797bf9eec8523f581cf263925699ef0f7161a790bd00bb09681534ed05ac82", - "0xb97fb8ebf2ee1bae5914cf96e5a07887ba41e712530eb2096ace318e989c0ad93060cfcf40507d927af6c7e945bcc289", - "0x88015bec478fd3ddff72efda0e8fc54b74faf804b0a3473cca38efbe5a7e6dc0be1cfe3dd62b8ac5a6a7a21971dcc58c", - "0x860c0eaee51b7de26e99033f352aa09c093943b59237f1313ecc35b0d711509bbe9f939c4bd646deb7de8103eea9ea13", - "0xaf9d13103868c854821ba518907b067cfba025d739125f1e9cce0a04fffc3a2a1f25506c1209a0cfe1d6c1572c229ff0", - "0xac7983d50ec447b65e62ed38054d8e8242c31b40030f630098ce0a4e93536da9179c3f3ae0b34a0b02aad427a97ee60d", - "0x8261f7e644b929d18197b3a5dcbba5897e03dea3f6270a7218119bd6ec3955591f369b693daff58133b62a07f4031394", - "0x8fa2d7b22af8e6b82679ebdfa13efdcb34289a554653ea6c1b16efb9f957f7fe64df787e7b03d8cdc8a732b91c916bd1", - "0x897eed8c65712e9b1ed8213abb85a6252ec30ab47eda4e36aeb8a72447ce7972861bc97957bc321714328c64af27544b", - "0x998c9ee20d33f96a2388b1df642aa602bc8900ba335e8810baab17060c1eace4bc5203672c257b9ae750008b707b0aa1", - "0x92378adc9d56996ce8ecdb9ed6510affccbcfd96712a23631edfd6ffdb1469847aa447db6b2bf61dad416ebcc5b7d1a7", - "0x83fc998e050cb1004fd016c7dc62885b07a95fc9b219fd6fde8ca2824c647f331f6b18ebdbd14569b906cd1ca1066189", - "0xa87c2f13f2a824b7e2c39cfb63ca7b94ae6a11ade0c6b8e83f5092b933fa8b6157a5d2f09c23081f49d35cc85f5db36c", - "0xa89bc7548ea245ce9556eeee3fba98a3256f87499f54a7c5eec0c43b9fb4ef2fe8f6810867ed0df814a88ee100c245af", - "0x8d52413f981bc611427ad0534d25e914113d0ebcd6960aab6421608bec6648b89ae4b2ca2153c57d3cf4f1f37212aa5c", - "0xb0a4c136fb93594913ffcebba98ee1cdf7bc60ad175af0bc2fb1afe7314524bbb85f620dd101e9af765588b7b4bf51d0", - "0xb7ac87da14b783914ab2e914fb7b536893b7a650cdc5baa1f3b4aca9da77b93a3336671335250e6467a8cd4aa8dc61e9", - "0xaaeb0005d77e120ef764f1764967833cba61f2b30b0e9fed1d3f0c90b5ad6588646b8153bdf1d66707ac2e59fd4a2671", - "0x8a60e066b13eabb372067a6b08704f3b6b98c0d468942738768127ebfcf122aef0ae2303f361c6338010fd371646769c", - "0xb7de6d7a4afb05984dce153e5570b104338265e45c8f0156f4d45c458f47add234a479e01c02d3c1817c170b5b65b100", - "0x983cb6bbfe83bce8326e699e83fca01ea2958c09808c703cac97a0ea777e5a5f3f5bba9169a47732de7459a3c7af47d2", - "0x8db19f6dd3789df179ab606508ca7e3da7967ad4340f630bda83df54c197d6bd3a14980c87fe10cbced7678c0c300ef1", - "0xb4e6bb207e08a1e096f6b27a5a60effc74fc8db0b6cdebc9ddbe88f434f4c8e0bd7fa77e015cc309db0f0922bd05b3f5", - "0x951d69f32685615df304c035151bd596d43bc3250f966e0c777544c506e3035d031afa4a3fcca1b85c41a4a041aefc01", - "0x942bee9ee880ac5e2f8ba35518b60890a211974d273b2ae415d34ce842803de7d29a4d26f6ee79c09e910559bdcac6d3", - "0xa0e68d24f784fcb2b71acc2d5871285623c829d0e939146b145e04908b904468a67c07a2f156e6b17bf531adc5777c4b", - "0x921da028f26a61a034f5425d6618eeb61adaa8ff10141bd65ac970adaefd3737a4bbd77d8a7a90cccfca35b0f4d585de", - "0xaf6911edd6c7ad30f905a0a3f78634808832fdeb4206b006934822d673bcced8e378779261b3c4b772b34b8871987f57", - "0xb044857d879d06e9be5dd70498b27a20aee758ef829d37d0ea12b92aa84b9d3c6194205368014d942ae0517cf6d0e201", - "0x8f90e72a54e6894d511061957162e753010812346afd4d90cfedb678b99ba1aacf2b6bd0e49b4b0e684da8082a048619", - "0x8317974fb1bdd174c7ef81a2a6478f887f44c1e8680c21730974e5c440846c4d43a76a3e90334b39508f507163e2ff8f", - "0x976eb5543e043b88d87fda18634470911dfe0e0cabab874ca38c1009e64d43026d9637d39dcd777bc7f809bbfc3e2110", - "0xb53fb1956a2a34a840de4ff0b5b1e0e2fb78a21ac8edbce6be6c26a4b4de6d37e9dce799110a802a344e8541912353d7", - "0x85bca2f86423a09014b562f7dc613246bedffdcb3aa41fee02270c13e6b00c8d6704dcbfbafc5997df6a90c7fc08c29f", - "0x8bca3560946189e4984126acb42153d8dad0b60e7f86518b55ea9ff7c899c9ec12821850943b6adeffbe9363bce4d217", - "0x952a95612aecce4321d2c17aabd2fb260b1cb41df5f76f5b82b46cf818d7a4f18e5e2944cddcd2280a993c0af4f834fe", - "0x9722c1079db7e2e1c49756288a02302b43b8fd92d5671585ac1ea7491123742a2744a526c12c9a0b4c4a80f26342a3a6", - "0x824c8a1399ab199498f84e4baa49ff2c905cf94d6ac176e27ec5e2c7985140dbaa9cc6303d906a07ab5d8e19adf25d8a", - "0x94bbc6b2742d21eff4fae77c720313015dd4bbcc5add8146bf1c4b89e32f6f5df46ca770e1f385fdd29dc5c7b9653361", - "0x90f7fa9a30d9f2812a20db97b3d03962a5b59719385c1881c61009e4c049809efe378b39cf74b64daa981358edd691de", - "0xa4632399c1a813e41fb2055ef293466098ea7752a9d3722d019aa01620f8c5ecdc5954f176c6c0901a770cbe6990eb11", - "0xac79f5491dbbd0eb47669225e781f94b98d04947cbc55baf287365831c100248bd0b39c911ac09b518715ba1ef0602f3", - "0xb9574edb9567f07f85c7c2e6ca6c02d90ad7c7b87d49796f1e2fb7240ad071fb755cf13ca8678668a56217c62df168eb", - "0x889a5cf9315383bf64dfe88e562d772213c256b0eed15ce27c41c3767c048afe06410d7675e5d59a2302993e7dc45d83", - "0xa0b3dff15982a38a2f56d8c6cfc5c5543c045bf2db24571d23387ccab42abe2756f34d5f0bf6a426bbad3c358b8bdb00", - "0x8009dff405aada0798a6cb7f418f73017d7a569a7576aff51348b15913a5e639dd232657cd775cfa0dd811ae5e301241", - "0xb31949c4a21181a54928f25f8598ea3dfcacab697a5653beb288d218d312133e5a93f434010ffdab3f3ebd0b43b207dd", - "0xb46f481155df4c4d576e5d76f1d4054e1129cc49398533ed32d0f681701276cecad4759e47b818f20d6a087989449529", - "0x88158d759eafd2205c770f166829fd61e8f17b2c13f440777eaf45f4d88a6e2028bc507680ff435882d5fb462f813735", - "0xa922d48a2a7da3540dd65bda3a8b5fb1f1741604e2335de285ac814c69c40b5373d92bc1babd3e4b2d32993f251c70b5", - "0xb7efcb232d3b639921ce21e80744c293ea77e25982b609e8cc82bd3999a734ca04ca43f41d9c7c15d162e0bbc3152495", - "0x96b1c82b85cdb8a7026fd3431bea9cd008f0261ee7f4179f4e69a399872837ab836a14e2dd45f5448d54800a4ae7c7f2", - "0x8295f613c162159f368340ca0fc2fd7776f7ad64eeafbd132bd3be1f1c30b5fbdc5f107f12fb0cff15b12c08621f457f", - "0x89e3ff351ce4f0d43cbb6385bac30b37431b31c7c073bacedbe0a60af3dd372aca672c6c4b4d05d2c4b7a040e80f3ef5", - "0xb075db32979df905cef986cfcd6db823ac21dd4013cecfe088885390ff8acd18d76dec793b80db5f7779426127daed7b", - "0xa18f4464cf5cebade8ee280fa00e0917cbf1743aeb0dacc748ab68773b909e30dc60f40fdef3041b5f082e650985f7a6", - "0x8fb51e3ef3c1047ae7c527dc24dc8824b2655faff2c4c78da1fcedde48b531d19abaf517363bf30605a87336b8642073", - "0x93e4d7740847caeeaca68e0b8f9a81b9475435108861506e3d3ccd3d716e05ced294ac30743eb9f45496acd6438b255d", - "0x946d585d7aa452d37a8c89d404757c3cce2adf2410e18613483c19199abd88f7a12e206f87a43f6009e42f4e31ed20c0", - "0xa4cfe97f6e61e45577ed6ce6eb7d1d9aca9e323b79b30736b407000555bf3e2ecbffd6314585b09000f09ee8381903af", - "0x87c5670e16a84e27529677881dbedc5c1d6ebb4e4ff58c13ece43d21d5b42dc89470f41059bfa6ebcf18167f97ddacaa", - "0xac7e49f2059e99ff65505742978f8d61a03f73f40141a2bd46fde5a2346f36ce5366e01ed7f0b7e807a5ce0730e9eaa9", - "0xb471c72bd2971353f4b44248b8e6cf5316812861a88ccfc20fd0d89a5e010428c387228b2f6f14c12f79e31afc9d0753", - "0x86b3a4ea9b1fde00cce79d5ae480353d60cb6ddce363c535bbbc3e41a4b8e39fcf2978eb430091ae1b10420d43193971", - "0x8167484b6a9bcbdef21464cee959a7a6aab5ac92ccc46214f4a2ed520cfb4d4de8917f9b9bd6fad71e66c17bd831eeeb", - "0x86ca8ed7c475d33455fae4242b05b1b3576e6ec05ac512ca7d3f9c8d44376e909c734c25cd0e33f0f6b4857d40452024", - "0xb49379bbb9f954d2ef5574199607bc6b3aa2cc3b48dcc3745cc77406bba2a394929844fec1b87c4ce65cd0ca0f83062d", - "0xab6366a7c6da8ca8ea43a3479e50ecf9a1f3b20ec01b8eae1d2a21ba2223a4ce62615836377c6395580a079c284947d3", - "0x9175ec473efbfaa029aadf1584f986371ecbeccd82ff6a52d1f6c66f51d7395e0ad67a5e8bef0600ffdb348978913e6e", - "0x8cfcdfa192b17321be4e447204e1a49ecaadca70a3b5dd96b0c70ab64d1a927d1f8c11a7e596367e5fa34e2307af86fc", - "0x905a97217fae8cfdc4a006b644e91b097df28e02da2f19f77e18f4b0c4aac2538ea83919a722eee5c0ff315a1daf3cc7", - "0x94b2d97448b452a986c039df1cfd651da59249b649182941556018af4ab61d2c6af82a29e69599153316f9b262efbcb5", - "0xb0eecd04c8d09fd364f9ca724036995c16ba6830d6c13a480b30eb2118c66c019cfdc9dacce6bfd8215abe025733e43d", - "0xb4d07d50fbc9634e5f4aeb884974068ea6b94e67e4527207f5f9c41a244943347d69d3c73af74d8de9ab3659d06c6d6a", - "0x8e54267871d8d3ce2a080e48786be3d97e5fc9404156436dc2a37bf05a588470b7656383bd79d58746d1667ceac54344", - "0x8277508c9aa4d1938c83b48d05fe3a440bfb50c5be79b30da1ac1853d19ee062797be19521f94b038cb991b1237abc59", - "0xb4aa92a60de61ad089cb027ef19a211c720ec0e51743b1166e3d71bac08a9ffff2f0687e250c6a7e1db866f7c4ae8f29", - "0xb9299f950db8cafd236a17f141cd2ea9ff441730749bab3571211d207ccafbf5a3990dc137400c405086c4d2879ab91f", - "0x8c38ab2a9558ac41c6ef736a5560e5960102e92f710efac3f631367a3f6d7227e0813579f349e661116bb29b2163b296", - "0xa5c11337eb91ce0e9b6d61bbdadea0a063beee1bc471cc02dc1d81c5dd2095315c400cbc6c33d23c77e98bba6bdf5439", - "0x8d3cba4d10f94bd3406a341c903ad144cfcfe6b61678d5c03084a56b4413bc30bd20d7a9fd5d839dbb565cc9b2aa99fe", - "0xac9f0b44105cf77ad721b97b0f04a37fddb2bb62c345b0d22a29e2870b8964d7484aad30e454c74608ce9901043501a5", - "0x8be4830a391aace561decdfea6aa610696d292a9e6b56448c6a590027df9f6762668671775272bac46ea335391ae157d", - "0x8e662149e22ce32383461ceb489b912f3c6320293d6edf61499164beaab7a265ffb9de3e0af6c95ca824d800718e1506", - "0x88b49b1130f9df26407ff3f6ac10539a6a67b6ddcc73eaf27fe2a18fb69aa2aff0581a5b0eef96b9ddd3cb761bdbbf51", - "0xa41cf5d678a007044005d62f5368b55958b733e3fdde302ba699842b1c4ecc000036eda22174a8e0c6d3e7ef93663659", - "0xa663c57b72e8acac40127fd3af579dcf9aba05910b26ed1155888543223d6558ee8e1c07f0a0e634e532ef6c5e9cf17c", - "0xaa103a329b699d4102f948101ce5fae27226419f75d866d235da8956f11367e71db5c0a179dd63007ed53f7eec333aaa", - "0x86c53fc078846c3d9bc47682506f8285ba4551475921fd388b96291741970c34b8de4210202e40d2de4acb6e2892072b", - "0xa7e0ddbae16e4491822684c0da3affecbbd17ef96c5c491ac093c6eb4e162fc7854c367535e296fd3d6265c2ed1210bb", - "0x88f0f11d0c2bf51453077cce0d3191931e73b104ee5c524da57e4eac0a88965f58b4abe423c1073f75fe3d3c666a209a", - "0xae8af784224b434b4dfa9ae94481da4c425602097936623e8abb875f25deb907aa7530bce357786a26ed64ef53d5e6b3", - "0x9408bfab1e7ac8b8b888c623bc0438b3a3460aff12436d13888315f496fdb808e9dc00894f272f348ed6aa475f848c49", - "0xabcf138d9363a73131f5bca56679d15606216bae1647c59c2857cb56818a0529c1b4b45e382273c993d62b7bcd552ded", - "0xab37a400dafa918d28ef43294b18dabcb4dd942261832f9839e59e53747c7b1bc44230967a9610b261f3abbd648e3dd8", - "0xa73b3c9d16f6c63659179b74b1aa5a0f4447c683ba38f9fc112efaccde4835e5b92c2f7041fa82cd90b2c4932704b9ac", - "0xa3fd9d8bbdc98394883022299fd9793e0c4f374d8e40d6ce89b2869d3173cb6a5476371d6095dad068ff217729f60af4", - "0xb4c5aa21659b3ae37fde62233b0bf41182fdd57c22fb5f47a236048e725a0e8636b9a595b13d9ecdf18c445f156ad7ee", - "0xb3a5497365bd40a81202b8a94a5e28a8a039cc2e639d73de289294cbda2c0e987c1f9468daba09ea4390f8e4e806f3c8", - "0x8cd49711b42af58a5aae75a38fea9ddc5e4183c467a3159b5b0629f01ba548513c577456d34c861911e85782e52c3b1b", - "0x868c13bb6bec7d56afd4e518f2f02b857a58d224fbe698be0e00bc178c1858e6bf5f0f7824fa013d5c8dd6f6e4147974", - "0x86f5a9bdeebd38fef93bf20a7451ef4c851d63f08e025a59109c68b46f4c61069a6c8c5fe90eb5af36943acc35e62f51", - "0x90c402a39cd1237c1c91ff04548d6af806663cbc57ff338ed309419c44121108d1fbe23f3166f61e4ab7502e728e31fd", - "0xa21477f0b51d73b0816b4b411c12db1e3a83698113ff9299ab2827e8da59baa85dbcc70afb831f5b0c038e0470562f00", - "0x82d09556978fa09b3d110e6066c20db31da2e18de90f973930f752970046f2df96b2a0248fdd833cbc50abad5c756026", - "0x92a346a321cfd73214be02f084ac2ff417900a1392d134b538099c92e7fdb7ba2174e9929c51b5e45bc3bcf718414dd2", - "0xac4b39bb8f0f62666a50574632764f8b6a1dc98afba5a5dad4409c920a0c0d5d2b5c2506c3a0d2f8727b7b7dce2ba1a8", - "0x8296f8caf58316af535def398a43357e48cb3b1e674b857eba1bd1b970da3dd045e22fe6d17dee4e9117f62ece3ec31c", - "0xa931bb29b6200899e8a8c257166400eff9888594daa1e37501390a1d219b019ed1b730d921a8f6d6fe62dff7b86ee387", - "0x8ae9585caa3c73e679fe9b00f2c691732f7b7ca096e22d88c475a89d4d55cb9fba3cd0fe0cedd64ce75c591211664955", - "0xb4a86fb5b0049718caead1bc036833a2caeb88e1afadbbbcb0cd021d95e1f33fcc916f0b97fc1b9226c37050e3463796", - "0xa15e0cb96a463ab81e661ca44c619b71a159680bbc04707ea5a5867ff38b15416e3abe55d2fabdab9aede1f157dd37e1", - "0x8b3f8fc8d2ec7a8db6ecadb8be90f55c1be4871bde10eb18c1773dc45dce042d93baa65b75c4688eb4125b6b7965c2d3", - "0xa4f964d672fa5579479e939d2d5dad6a5dac6fca4bcbf7d5ebbe7489f3809131667b41c3472addfe766d83202ea29c1a", - "0x86f0253db0918337e4e128e8056d2c793562c6b5cce8ba43695a02eae7df12605309722fd1e3b8c02ac513a4a49894a5", - "0x89cdbd610e7f57e86438e50874c3c7ba85afa63f5adcab9e454b5c203e4da65d74bb7cac5995a8652d10a6e438a1c2b8", - "0xaf2dc13a599c834b9af1b54a4fa675c0db92e807cab3bfc825f2c5571b3bc2e1c213cff941cc8b1080d894036f9f73f8", - "0xa0899189bba608887c6cb729580e570ecce9ca7107865ebd30def867afaaa250bac407c30dbee11b7ef6cd423269a8fd", - "0xa22542a4a2ebde18cc6aa29d5dace8b4f6720703f519610dcf01e671018392aff15728e3764730840272c9cfb074b612", - "0x88ce41025aa153a94f91f22e7b96f9342b5e0e1d76274fc70c4df7d08f66d9f7ac86e55a1c6e77693b8b01b2b38bf900", - "0xb76cb8cb446eb3cb4f682a5cd884f6c93086a8bf626c5b5c557a06499de9c13315618d48a0c5693512a3dc143a799c07", - "0xa7741c52498e0a24db3ce7699882de8f462a2b3ed5e9f77dc7200cbdf46b6cdd923b1128759909d6dddd64700c4c20c5", - "0xa211120e1bb3b10138df1fa58efb009a298b8771f884b82bb3de15822b1252124a68f3980f96122a775fb96f05ddc3d5", - "0x92ff79402d5005d463006e0a6991eaacc3136c4823487d912cc7eec1fe9f61caf24cd10022afdab5f6b4f85bfb3eee4f", - "0xa48b1031ca2f5a5acb4dbdd0e9a2b4e9add5ccfc0b17d94818273c8df11e825193fade364e0aec10f1ff91d57d03a52f", - "0xa0af9e02a7620e7ff119c3650d59d80169edd0ad452062b0e3e429c038cdaa4f55a18495e459367aaeb6a92c98003191", - "0xa61687511b627bde7b3977e9a34cb7fddc2aaa509a7b99b6b6c7b97133845c721e1e69f99758698d82cca265d8703610", - "0xb9691fb57be7aeb9d43995b8022051f199978d6ad635e1623a1bc1754b250fb8a94985cdc1e623e98767690a417e92a0", - "0xa6d6ef51a361df2e8f1d993980e4df93dbbb32248a8608e3e2b724093936f013edabb2e3374842b7cce9630e57c7e4dd", - "0x9820d98ef31bab813a0124ce48cacb9d99b2c1c625c41cb3d6e0b21f604ee215d5f37505c86766531dc302622d889766", - "0xa35ee5c2d7800489723c78008b495e1742f0542dbb487172ef438f60424c81aa41c2397095821248066140662133f6f4", - "0xae95ddcf3db88f6b107dcf5d8aa907b2035e0250f7d664027656146395a794349d08a6a306ce7317b728ca83f70f3eaf", - "0xa36dad4f7cba9f4cc843fe40f6240e1973a4c412cae29b4a68712598523cfaecb05272fc47d30772bf06906b5a26e282", - "0xaefc682f8784b18d36202a069269be7dba8ab67ae3543838e6d473fbc5713d103abcc8da1729a288503b786baac182d3", - "0xb551d1ce88cbf4ffbdcb0113a6e319513bd676d0078dd4e6a6f23ad336c1d0fb47a4e427bdedbe0fc8f152353971f81d", - "0xa11a7496c712734aec80738e30d2bf245758b34245076149854eb209fa6403be8bb0d4e515becc881b7f3610749260c0", - "0xb38e558a5e62ad196be361651264f5c28ced6ab7c2229d7e33fb04b7f4e441e9dcb82b463b118e73e05055dcc9ce64b6", - "0x9437ce85146202d3815df7f341a182678665dfb74b96006dc9d6acc16110d00b4a02717b702a765566457710ff5a7280", - "0x813bafdf6a64a9c40ef774e6c8cad52b19008f1207fc41bd10ad59c870fda8089299dd057fc6da34818e7a35b5a363e9", - "0xa5a1f7d42220d3740b3f353de74469fbd3a75ceccb3c84d0a87e43444855be0c51116a32a56cb1980294724d36bdda16", - "0xb4b80d7fbdb1dbf1567dfb30d8e814e63de670839a8f6ff434fe171416599fef831b8e978d6498851b8a81e0bc8dfb85", - "0x971882d02ad64729cc87251b49effc0b8db9880c25083bfa0ff34e7394e691288c7cefbb5cfdc76d6677ffb9da765dba", - "0x8144a5c583a61f809f6a9f5ba97dbed42f4086de71af955f5df5774f66a3581335926663502d7cc7b5129216da225f9c", - "0xb2eedff11e346518fa54e161be1d45db77136b724d497e337a55edfc896417de3a180bf90dd5f9d92c19db48e8574760", - "0xa6b434ac201b511dceeed63b731111d2b985934884f07d65c9d7642075b581604e8a66afc7164fbc0eb556282e8d83d2", - "0x85ab3c57517e3c348e7ec13a878b9303ff9aad78ec95b13242e087ec41f05f4a19366ae169fda8afec5300065db58f2f", - "0xa51f7858f1a7832b743a114127ebee1cffe176c988d4cb2348e45d4ebc52b43f80432c7276c6a5f8bfe39a432d4412ee", - "0x9332251b4b56579b201a2fd9e777e4be80aa213bc986ed5d1187cada9b225a7ed18f1f5bf68c2839bf330e00b2d63f22", - "0xb87e5f481b938ac8a481b775cc58be2a06604549e3c810fc4734bab76099e5c617f0243c4c140cb7dd6d36a6dc2286bf", - "0x83ca733849830cb8fc2ef469e7e464fd94def561ce49ff0aa352a6ecd0e52c7aefcd69ab59f3d1ed2d5b8536d0a7895d", - "0x8302ad0f2234535b55b975c5dd752c8a555d278b85b9e04e83b1db3bb2ae06f082f134d55216b5cacbf80444e1d0af84", - "0x8c627caf25eae6764501b9eff35aa90bd4f24952cad712aae20344579e83ecd104ad1f7915edc4f9023b17fddbdb4cd7", - "0x91066bac5341cead3d2cb168fde7da62b3dcf933ff5c1d379a4dd424b218c4e2ebcce038cc342e758795ecd4dbb8b790", - "0xa17e8874e2c59a2bdc31cc67095a271d31d5a4852ccf2a82eb7c457a3ba8c87ee5beb93a65a8f7bd04d10247e63d6b84", - "0xa15ebe9ab6de62a4d1ff30b7fc58acfb14ea54d7fa513cbcb045af3070db22bf9c1e987fa26c0c54356b9e38fa412626", - "0xa2ee6c29efa982e9b9abd3c5e4f14b99d5d0369d7bfc3c8edae1ab927398dc8a147a89e127b3324d7f4e3a7494c5d811", - "0x8cde690247d4831dfe312145ae879f4e53cb26641b3a3bb9eb4d590c56c11ece3cfe77180bd809468df5cddaea4f5ab1", - "0x8dc3c6478fe0150a2cc11b2bfb1b072620335516ad322dc5a644676a4a6aee71a8680eafb37db9065b5aa2f37696de07", - "0xa35fe9443b05f6632b080d0812e71142dba534b328f7d77e165aa89b370c158be708fed2ab8d8b3c60a3f83d6b1c4fd7", - "0x8266f9cc52944d85c50ba04d421c0ecb7ceac774f4485bca84115772ade238fdb5f5bf93f1f6c5288b3a44af177042e5", - "0x995194ca593943e772c58944789a30f8a91f20e58059967fa65364e4357b3483b0f94a3fe34e133bcf967859c5bd026d", - "0x83117ec2e506e292ff4759c270b3bca2ac221fc044ee7d3a4fcdd424ff0f4b961d6d268f7b9fce9ff07d29a4cb6ee3fd", - "0xb0a47515752c15e4dbeaf9ee27fab3b5c0db82f5c685e8f716fd7d8764164944340430fe3db1a5679e6ffea5a16dd919", - "0x91babaea18cf8f1e56feb0b89f0a3956c6469bb963d63312431057093b0ea0240a36abc3b7ac160e644e826cceb62530", - "0x9302bb41f741deaa5f2b6e3bca1427a6cf98b7ec2bf7967b7c0595efa258427323a022ef12f23426ff7a7c318462f07a", - "0x9022541f84e48b655e74bf3da484179e0e0040827fc71e777b68f19bcfd0e103d385ef957692e7091fe713561f38035c", - "0xa3b109249ac2900806f0f39338da72d4f2cc6d1ac403b59834b46da5705cf436af8499fa83717f954edb32312397c8d9", - "0xa94ccbf61b3a857744aa1540fc6d633afb8ab3c92d07fceef90a0dc54ecd2133490cbaac8832b26cf2f4b956471f36fe", - "0xaa744c552b5fc41e1ac6ca53184df87a1b7e54d73500751a6903674041f5f36af25711e7bc8a6fbba975dc247ddad52d", - "0xb544c692b046aad8b6f5c2e3493bc8f638659795f06327fff1e9f4ffc8e9f7abdbf4b7f6fcdfb8fe19654d8fa7d68170", - "0x94179fcc1fa644ff8a9776a4c03ac8bff759f1a810ca746a9be2b345546e01ddb58d871ddac4e6110b948173522eef06", - "0xa3a7196fecd25e9cc7cac79c35365676e48c7be1493df255676adff2209c0719f2190ceff3ce008d08efa07c244c11a6", - "0xb746447b0c0d7165f965672d71c318f2c1052a5ac6ebe320b14165c9276c839ed822a9183ea6e6dae63a4f826d421d65", - "0xa66d5b1cf24a38a598a45d16818d04e1c1331f8535591e7b9d3d13e390bfb466a0180098b4656131e087b72bf10be172", - "0xac1af27a7c67b1c6c082f0fe733046f8b155a7d66caa8ccc40a53ac5a55a4903d598b5f80543ea52c25205b02959f4f5", - "0xa485a082dee2987e528d1897dfc5ee99c8de9cdc0c955fc38c404c16c35b71bccd08770c93102110547381a2eb9d3782", - "0x900b9972180a2c8753f5ff49fdd2cfe18c700d9927b3c3e16deb6376ad6ee665c698be72d4837b94911a0b4c183cb140", - "0xb8454e8438641340b7fc8ac55b869abe54806f873ec0f2d8fc5425a1ba76ed8471425440621763b6e9d834b6e5451b98", - "0xb3ed0906d97f72f0fd5fe01cbd06b77d61c69f059f1e87a143a5630073ab69ef8876bc2a5e261d467a7f00f0050388d5", - "0x90a908b47d0c29a2d0e7e65a212d7e1788454062f46458c519c7f2ccd794ff21d4c24b91acf42a71a509aff6544f676a", - "0xb07d7c3f1d486f5657d5935e3d67403024ffdcf25da5c460fdadc980d8d6b931de623c4f8a3da5eb6af346193eb36573", - "0x87c2989f377be3751da3bc19172c5987d21c095cc3d851ee5120f67a5b3986d387b058688d54336d8510c49c6a66d754", - "0x8e70e4867d2731901d603928d72bbeb34b2e0339a4f5cf06e7a771640717421b4ea039c61dde951582a28c2ff152ff70", - "0x8336744d8ef3a3bb3e9ed3d6b83e08cafffc76b7438adedd3a7358b32acec0e73a4635aa3166362ab4e158e68576255d", - "0xa70132fe0c9580ecce2e3c0d4a531cabe48bbf6e7d1c1daf9ed2f315e81705bf1616b4cfda1c903b074e239ac6ab4c47", - "0xa978fb8ce8253f58e1a87da354f06af989b0bafaafec2fb3100bee272dd8664d2690f8ada7dd4817bc8b06ffb1fe23f9", - "0x94274299f0faca1152cca89282c10d00b5d3679cd4b7b02e018f653257b778262fb3c6c49d0eb83ce388869c283c3c05", - "0xb8233d647876eafe2746c10c1b41d99beea28b2627ea2ecb67a3eb0d166fadbceee34dfe942aa4ecf39e0d55f9d6d2a6", - "0x980a54f9e9d88a7ec08d04edbdd7c9222e99f270b1e978ce7140cc67e38a2e60cc1034dc5b0deb5b60e10697d3bc7295", - "0x8553bfd1a163df0d8bb1424383552b85a1c0d288dc1f46fdde90ce2d9be7e2688d7d06e1d6be06252c7099588d3488e5", - "0x8e8e48992d0394fcb9a0c56bbd3797400128e28fe395ad9acf582919d66d11a4811a7187897e60ee2ab4842800c8c36c", - "0x8853eff72fa4c7b4eda77e448e12bc8ee75f5cb0f35b721c7ee8184cf030a11e3e0278a4e76b326416fd645a9645d901", - "0x88e1e459ee5aeb8b36ed004f6d03da296101106fbe1b18f9bbf63e92321db51670c34050fd3b7dc56a4bad76403823ee", - "0x890def696fc04bbb9e9ed87a2a4965b896a9ae127bc0e1cc515549b88ddbcbc02647e983561cab691f7d25cf7c7eb254", - "0x95915d8ff2df795e7baac5433887c39ec6bbb9281c5d3406a4a1a2008f96c6f266adad4824c6c46429a158e36f5e1210", - "0xaf917d086e2e327d8d9e37ff85702536d7b15f444310d4aa832a61d850c7c3f09d31b3f5fd2a073e7fd64601275b6fca", - "0xa448516054e31866b54f1951b9a03f0a54fb13d938b105e3f67396ed3fbb015f290a37fa538baeb077fb4f9ac86c8305", - "0x8e58219fde5e9525e525b16b5332ef27fb6269e08e8c0bd3c20abb89397864b2c5bb55f5b6e03e8f0a0e0b04e5f72b14", - "0xa798a0371e8cc4dc42ccd79934b0db5a3a59f18a0ae09f2eb172596428fcb3f00312e783d6fd21cbc1610317f44e08cb", - "0xa8cbb85e8f38734d95b9d69346cbcb169c149b9801d9da46df5e27b5ff8d0ab7b870c83db3fac32a90d02efe5fb8fb49", - "0xa63868892ce200c7d82d7ae041db371c91ce03282adf796c8b1a1652732ec77add0945727b110339a80596c367c97deb", - "0xa0133deca5ae8f1100df8db69920b2d0c31aa21bd3849dbaf4c264eaeaec8937ab8f982770ce1ea17e0e258910a56d02", - "0xab88f81dc77f09a2b62078e7baf4b6c7503925a7a077bb30d72f4baeff8225039c5333242e325e824f7192d4d132b596", - "0xad83b3c5e9a08161950b1df9261d332dda2602cc68e0f5ee75bfa7e03bbef9edfb4945ca1f139df1bcb8affe8ae025da", - "0xa52c5a63b55a8001b6b67c5db4fd5e95923052f03618369312896ed9892d99354aebc0dee8c3b365bafa29e211a5c3f9", - "0x973dcf44ab60f55f5d10a8753ea16db9faedd839466a130729538f3a0724f00f74b3ca1de16987d7c6e24e9467f62bc7", - "0x991a7c93f06d50ec6a4340c6751b73eb5825bad02a954e44e1e2d424af928819ebbb590c6129ce35b3f1e908e2152f33", - "0xaa48afa77d5a81cd967b285c0035e941ca6d783493e1840d7cbc0f2829a114ace9146a8fbe31ecbd8e63e9b3c216a8c5", - "0x8c01b901e1067a89471927d911246a8b2f1284e93be9913406d7c88aba784694317e22a0a7635583dae7db45cafb73ed", - "0x942772b7c7c47d4e5957ccf1d6f1450070930af3e2b7eaab0dd7699372445df0cc910e6c0efcf501887dd1adabdaee23", - "0xafc555559b435c585b61096a34a15b8ad8722b2d3306ac8cbf158b46c135b293b08a5f37b109b138350dbcd1e0da9f8e", - "0xadc806dfa5fbf8ce659aab56fe6cfe0b9162ddd5874b6dcf6d658bd2a626379baeb7df80d765846fa16ad6aad0320540", - "0x80bdb82b7d583bf1e41653966b0ba3b4fec0e7df2ff08e3fa06fd9064bca0364263e075e1582741a5243bde786c9c32e", - "0x8d5776148c65e35d717da1902d74727b3bee21ceba8d337d77738932865f1b851e810b91346f705880da6cac63183717", - "0xb9d24940937b6e50a1797cad9ca58d4b2b2d8987bb8ec056ca2f397a2bdbb7af7939c0f4bcdf5a3b6fc80f65f9d535ce", - "0x81d6fc2f01633e8eab3ba4d72588e14f45b00e68ab887bdd4ec5e8558965db21189310df973837106216777b07fc0805", - "0xaf03bc1e94067741bca4978b9cf065cc6852090fde3aaf822bbe0744705ebda5baac6ed20b31144db0391309e474ba48", - "0x8cf8412bd48b21b008f0207b1f430ed96bc6512c3712dffbbecb66e493e33698c051b27a2998c5bddd89d6c373d02d06", - "0xb9c8a3894365780842a2096da49e48f7e77f05972e2acdeae8e8fed8ddc52a1e2fd754547087bc9292cf0c868155fbcd", - "0x85c8e7e1d7ee3ed366b530c5c9fe0a353f2907d8b80b16d00391780c04e3f7e060d433539780457732864e334039474f", - "0x8a3987de0131b7461bbbe54e59f6cefe8b3f5051ed3f35e4ad06e681c47beee6614b4e1fba2baa84dff8c94080dddda0", - "0x852ab89dc28bc26f6300800d9a3046bccfb3fe1491f29030f1389f40ca452f6b8a2f6d1541c1e523f1b59f8730823488", - "0xb5726aee939d8aee0d50bf15565f99e6d0c4df7388073b4534f581f572ad55893c5566eab1a7e22db8feeb8a90175b7d", - "0xa356e5b70bc478c625e32a38d29f0a619fdeb665503eedc304d1bf34562d4b6814dfc30aee5aee94ca4bc6394e412765", - "0x8b476b3b065a3b95a3d11ec60a749c2258ddcc5885bfb50b8a086d3fd1e49ff73e1dde733b8981c3d2d206aa0c87b09b", - "0x9171a7b23f3dbb32ab35712912ebf432bcc7d320c1e278d652200b5d49ad13a49ec8e56a0c85a90888be44de11fc11b5", - "0xaeddb53c6daac757916039e0992ec5305814e9deb113773f5ecf10355cc3723848fd9c55e0a6ffb6bcff4ad65ed5eb3c", - "0xb576c49c2a7b7c3445bbf9ba8eac10e685cc3760d6819de43b7d1e20769772bcab9f557df96f28fd24409ac8c84d05c4", - "0x8a277710379ba4fababb423026d9db3d8dcd484b2ee812439eb91b4b5177d03433b7a4486e43efbf2d2ce8ccfeabf323", - "0x80e30cabe1b6b4c3454bc8632b9ba068a0bcfd20ce5b6d44c8b1e2e39cbe84792fd96c51cf45cf9855c847dc92ce9437", - "0x804c021152c3304853941847e80480fdaceba3b9676fbe018268cf77d1a1856966c2f9686bb4d4aa0c4118a7e85f83cc", - "0x901f724ee1891ca876e5551bd8f4ad4da422576c618465f63d65700c2dd7953496d83abe148c6a4875a46a5a36c218cf", - "0x90fb5cac22a22fb8a6b619f1eacd95873be974d4d5d1f7080e523bb9b4b2644eda7340d780bd1ea8ce36407ca0410fea", - "0xa34eba9a41f2307891af1825ed501b74278f67eaef4bc57cae5c0c46202c19fa0d9a5dd8b91325f6c151a0644762ef29", - "0xa5c225b7bd946deb3e6df3197ce80d7448785a939e586413208227d5b8b4711dfd6518f091152d2da53bd4b905896f48", - "0x84888f2efd897a2aca04e34505774f6f4d62a02a5ae93f71405f2d3b326366b4038854458fd6553d12da6d4891788e59", - "0xb897fa90529458bdf3cede5ced3f3823dfb9b6d93b96b81429bf05e8f1a80f7c857d458045cfee58296b3ccbc4119abb", - "0x8117fbcf61d946bee1ce3dff9e568b83716907acfde9b352c3521cfed44158874af8dd5b3906b4a6b49da2fb212ef802", - "0xb6e9fe9fa3d4c833c3beae7f798f30f07e3cdf6f6c8eb8e2b70cad51b37af2549dc9f2e7f97f194e5897d4dedb904a45", - "0xa7555d66719916a2be7a7f0c8b7001aa2925bcb79723f78288f10831f9cec64923228b0e4b89dfd4342de8f70ce03cb4", - "0xa10788831a0cb2c3d14d8bc214d92bee6e2a9e92c423d2974760d84a6872a9465d12b628f9bd8a6e777a7db6f509b3a0", - "0x946948e31311703f64d34dc6faaae992e39b7ced92ecdc01df9761e3819a6db1266be718fdf434fbec912da37d1986f1", - "0x8675d210e67eddb3cefeed200b9e205679d36d8dcad70f09e678d8d1b3eb1059d12542f3aca300f384504458a881dd60", - "0xaaa18df4ad95f7443955accf8ec206f46d4d8ad9f1adb07b143b4225590917ed7ae050fc329d54310d3d0b198cedaf0b", - "0xad77fcac9753efba7a9d9ef8ff4ec9889aa4b9e43ba185e5df6bf6574a5cf9b9ad3f0f3ef2bcbea660c7eef869ce76c8", - "0xb201b0546f19c5db88df9c684cf55ed623bdb43927d06051bd595497df741feb1485961f64e8d3d1811d9e2e9e1e54ad", - "0x836075979eaf386ff6cb459cfd48fed171ae812b0ac3b38dc24dd8ca905cac1c600be717d4a0defa0a854f40cfaf8c33", - "0xa0617db822d559764a23c4361e849534d4b411e2cf9e1c4132c1104085175aa5f2ce475a6d1d5cb178056945ca782182", - "0x9831b8c836114f6d8213170dde1e7f48d5113974878ae831fc9b4da03f5ed3636342008228b380fd50d4affe909eb54a", - "0x97b43a6d1a47a1c415278344dba0cdfa952663a71fdcaf58d313c161e479ab5d1b980d8870055cc8f0d283bec8f97425", - "0x9340bfc34ffab8c28b1870a4125c559978ac2b278f76f462b5c859a00c3ba3426b176dc2c689096ad575b4cd4dbb76ae", - "0x88ad79a0320a896415e15b827a89969b4590d4dfa269b662bdc8f4633618f67b249f7e35a35884b131772d08025bfc32", - "0xa0230bdf83cd469c7248074bec535eba8280cfde587d7c63d307149e9626bc7642b4bacc9beff2d8e8f6ea398dc0ade7", - "0x8934e9a3feababa12ed142daa30e91bd6d28b432d182ac625501fe1dc82f973c67f0fe82d39c9b1da3613bb8bfe2f77b", - "0x87fd7e26a0749350ebdcd7c5d30e4b969a76bda530c831262fc98b36be932a4d025310f695d5b210ead89ee70eb7e53b", - "0x83a9cd621beecac8baebf7df4f7ee17bf4b70aac31df816ec3efb5cfef2dc5c0bf959c5227df3a7ef4c2b8d1e1b658a8", - "0x9529ea4a51324ed4ecd855faea43846a223da8cbb494e5854cef700ebbcf4d76119cef16192e6b7c51f82ab79371756e", - "0xb15e1b4ac64bafbc4fdfead9aeff126bf102fdd125c1c914f7979680ec1715fbeccf3dc35c77d284421ec1371ed8bc32", - "0x8f1d90034f998018c3f4b5947b40b139fcead2e40aa80fdec6a4337c60e9d5ff1923dda7f0b5b1731ff16f55027d41bf", - "0x86b706c5d3c5aca72cb23ddfb6452bc70dd3b1a98c8539a7c32f760778b401cbe90ef86c12d0468892dbcbd9a268a38b", - "0x9752561179783f336937757b619b2fdcb9dfce05aa3c4fce6d582dc966182eb85ab4ccb63e7e1736a7c5fad9d33cccd2", - "0x8bb51b380a8a52d61a94e7b382ff6ce601260fa9b8c5d616764a3df719b382ec43aec9266444a16951e102d8b1fb2f38", - "0x8097b13908662d245820f3b045d8c2c665fe9a054e9c661323924ec86dfa713b36b0c787ad4dfdeb979318810e687a48", - "0xa09b2a07d861e01645accfb088f7f9ad524186bd439712775459a60f8a1fbbd43ee084e4d6e23ffce06daa189cd1e654", - "0x941e2e3ba414a371a11c3fe92cabf688ff363da6230ec7c83ac7303f652a19ebc89cc494427c456d0c2ae84c72053f73", - "0x820cc2ac3eed5bce7dc72df2aa3214e71690b91445d8bb1634c0488a671e3669028efbe1eae52f7132bde29b16a020b7", - "0xb5222582ed6604b9856a48039bd643340f4bf1bf0fc805e8453a9eb7630d6cea1452d28536706d6fa3ec16617617991c", - "0x938bbaa0ba14597067ff4c0a7cfc1529c44160d6f61cfad12246526d84fb7a1ba964d3bbb065a348cf7a98356ee15234", - "0xa83371f44e007c708dc4bcafa7bd3581f9080a4583c9be88624265014fd92f060127e628de5af3c442a25f049c7e7766", - "0x8c17ccc763fcdf2ba7e27ea643654e52f62a6e3943ba25f66e1003fd52f728e38bfd1036c0d50eb3e3e878378bcc2e9d", - "0x9517cd84390fbbfb7862ca3e0171750b4c75a15ceb6030673e76b6fc1ce61ac264f6dd1758d817662abfc50095550bd3", - "0x936f7e20c96b97548fef667aa9fa9e6cfdc578f392774586abe124e7afc36be3a484735e88cc0d6de6d69cf4548b1227", - "0x908d762396519ce3c409551b3b5915033cdfe521a586d5c17f49c1d2faa6cb59fa51e1fb74f200487bea87a1d6f37477", - "0x8ec38c68afdfb6ba019204039c2fb49a35467058f561f626fa87314d705fd615a7b9966576052be1b3690028d3c5c7bc", - "0xb790669f1acb10911e520198795b259a18471cb3ac03f3885b4fa40626d414e26025790296fd078ef5c3681ebe4689cf", - "0xb659c05488f778fca3c918505d2d849c667471af03369ad9fa29e37bac4cc9caa18e749c62fcff22856945a74ef51356", - "0x97ffcbf88b668cde86b2839c7f14d19cb7f634a4cf05d977e65f3cd0e8051b2670e521ae74edc572d88201cff225e38a", - "0x9888c250b4b60306f4ecb1babbf95d0b6dbf6186503b2024b134478d721fb782d801bafd126cc3247bcdb1ee9d66de85", - "0x941f73b2138b4347ecafcc7b8c3d03f2a54dc49f580394ed08f22b0878ee7cb63d42978f1d320c09e7dbc67648c06f8c", - "0xac3195143035cdb4ddcd5f93c150035d327addee5503ea2087b1a10b2f73b02453ddd1a94d8e7d883e365f9f0e3c38c9", - "0xab6b47627cf76d9552c723818db5ebee7734542436b50ffe15b3a96e8e7a6b54f9a0965de78405e16e309193f147108d", - "0xb7c66da483b18f08344fc3c27bdf4914dabbcefd7ee7672fab651d05127d85d25ce363b0c338d6eed55c4e31f57bcb35", - "0xa641eaa149c366de228a2833907ad60eea423dd3edf47e76042fdf6f5dc47a5b5fc1f1b92c8b96c70e6d8a68d3b8896c", - "0x805c06e565ee67cab0cbccb92b6656fdb240b430766eade3c6b0a0b1b93c840e2b4f028601451dca135c783239463880", - "0x8528cf6ed82d9f729f9aee83c3ef763d85649d46019c4ca7dfb58d7824c2003f88ddb2bc5a40c4d78d86e68b675f4e56", - "0xac2955c1d48354e1f95f1b36e085b9ea9829e8de4f2a3e2418a403cb1286e2599ba00a6b82609dd489eda370218dcf4c", - "0xb043156fcd02b75dbe940c763fa8e8a7c7f6d74c1d5395db5ce544af3b6097eab61686950535a810aa95889ced12f74d", - "0x8e7d1dc7beb2de660b7da19ebf4cfef3ebb6a3d6f2f367e2dc91105653226e859137879171dccc586c10d9c4cccee7b6", - "0xa278bea51af1de8bbd2319f3a37ab14abc3bc0289ed31aae44f38897a7b24263a4dde1cb037e1441217bec0ddcf47266", - "0x8afa23226c47083bba80ab1be55b48c90c6629135533e3e4c14057d19febeba7f8e2cabe617b28ce1f0bd97a06972f66", - "0x9865218b0eb281e547e693055456d1d0c598bfcd0138dddb5edd5f5ff66cc2d52465f3e70c0f321246036d7ed8c606d1", - "0xa3a6d1ee35cc0ed9290a135086b32f136028b320650e1f3443434af7ff52dd74c546ffe2a1bebfc329f1b52cd72aca34", - "0x812d3ded3a3c9e58eecf13a29bb4cc13b01b2a0af322423a29bb0e4f6d9021d1d87ac4af7a2a6b88d34f44a8bc1b3c55", - "0x8d7dc174aa361d046cf183dd202cbc12fed780d7053f7047e11af9aded336318bf9928aab73ebfc81ca86f12007077b6", - "0xa9fdc2209bbf48970a404de3d803c65b11be96ab5a165183d05ed6477b3a0c633c3d6f0cb8eefb430fddb5b5be8cf887", - "0x83a798f47a4f62dcb8b531d463b0fd4a876d47a8ca990710290549255033c909de709471b4e823a60bf94d8baf8b5acf", - "0xa8b0bb9e1f8b0508c7d6e7382676663d27fb27e3f1c0e991a295e59498f4a5dbcc4cf89c73d3d587fb3b8f5838153885", - "0x80414adc7e0a9cb961b1f31682c33d8e01e3b8cf2aa2c2a911ab9b1f54d5c4bf92e18466cacf9b80333112ab015136d2", - "0x82d2b1053f6610064f838b3aeec585878f86323cac357c4aed054d87595c7734729a737b29b57940884ee839e984d612", - "0x91efdbcaad9931312d7c41d24de977f94d7f3f7b88090a1f72d9a097a1e30cc805c5ea16180f463022d9b26b8863f958", - "0x90ab68c372fd01bb210fb94094adb27296b7144d964bb1dd807ea8f718181747356b0f9db3feda78dd7a596209099ab8", - "0xb40a3bae2b08c13db00f993db49e2042be99cde3d6f4f03d9991e42297933d6049394c659e31f316fcb081b60461dabf", - "0x94402d05dbe02a7505da715c5b26438880d086e3130dce7d6c59a9cca1943fe88c44771619303ec71736774b3cc5b1f6", - "0x8adb748d5fa5c22ce4c76a1debf394b00d58add9f4e08524cf9c503f95981b36b8d0cb2dfaef0d59d07768e555733ecc", - "0xa129c9cf33df42b5a98ad98be9d940207ae154c715d3bde701b7160dfe45304679fb0481a4f9dde242c22a9849fc2d9c", - "0xb3180ded54610b1b3a2db7db539197ced6a75e9bb381d1f4b802ca7cd450f5418522ad2bee3df1956ed63ff1ffe95dc1", - "0x80e1dbf3296bdfa98aeec1a7560682165d13bc628061bd3257f345aa1ba13f8bd1bea14f117af562be22118f5a8265af", - "0x8d286e63f64a3e24c2e4c2b91bafb7c6a71d9438a2ffd7288c58ec6de9db6194eaf671b39c5a462c8658ad3cfce46f85", - "0xb4f4ed1bd274a852189719a8808a8f214c8386e844ca9ba13161b75d04c74633b1d8a758ce0b23ccbce8052494c81c3f", - "0xb1a3e6baed1cc37b9a67f38648f4fe365d23fb982027ab4202c3392d5459d7995264c2e9bb8e821a3e75e71390b6dc7c", - "0xabd7248ae069d3a3a45b0ef4dd5d7d54b62994e578ea20bdd3b7876596673953b94c5b109a6e4b953b517544b915368f", - "0x9377aab082c8ae33b26519d6a8c3f586c7c7fccc96ec29a6f698b67d72d9266ad07378ba90d18e8c86a2ec77ecc7f137", - "0x959675679fb41dd62595d8266e796834c1207dd70750e304b1ce45d3fc215ceb5214d6651fc97a061b6a570eba35b811", - "0xace7fda25c2fb7c18710603c16a0ff0f963352d1582a42a20c9f5603c66f485df8383465c35c31e8379b4cb2ec15b4c4", - "0xaaf15335f1fa2a187f24f3db7966fcda52c2859113ed8f460167538f5cde43429750349f9714edda0adb6705d401d27c", - "0xab99038a2a6f9228d5d7e67f47107abaf06af293586c3a6ab1adaf02aae373e3434ae3e26bb617302b8e3a7ce5107bd0", - "0xb3119de346a02c87743faa4a20fb90e7eac404a6f81ac681d593171cb29c5f79d4d5ab761b66ec71d4a86f43e0b4165c", - "0x89255902846cb35c706f6e8869a9122527afcf8a8b8f5f81497b5b71c6a96c601e7185acc78646e2a7884d148eeea815", - "0x8c26d4ec9fc8728b3f0340a457c5c05b14cc4345e6c0b9b9402f73e882812999e2b29b4bffdcb7fe645171071e2add88", - "0x903b9bf66c147ddfddacce63c8f12f62e45638383bf91b50e2fef29013ce54a3fd8c3eccc9b8961d91ca2920ba5b0c1e", - "0xb7a2c83971c4e4132f3fcaf3c4374872de67ea5d89814492309cf924520a23787401f9621681fcf526154e80849a7e72", - "0xb74f6e53b56856f88f8607b1c4e6c9e54aec15c5bb891e7bab00e2a13caab3b1d6529bf0d72d4ce99714b8cb8b973f1a", - "0xab8a8769c754008a7976b6799e81d7bfe97413d0a79b90715703c1f8f567675463ec93aabee59277121fc4df88b5c7a9", - "0xb34d4d2e15079e7e80fdba30cddf4fc0e6c9a61f7ab06a6ea0a4e55fd5bf632c6d72e021d6264d935439d321de883bb6", - "0x927c030d5a69f0908c08f95715f7a8d1e33bed5e95fc4cfb17f7743cb0262755b1e6b56d409adcfb7351b2706c964d3b", - "0x95718b06017ba9d45894867fd67148645d25d9db2229aa89971f444641ba9db4c5c6f0785f3b25cf2cd7fadaa6adc5eb", - "0xb30faf88fe203495aa268503bc82576f76a27f8bc8c4125b4c6f6e5e7b6880d495481cc9454713e0833317fa07da9b5f", - "0xa9ee291de5997232c68c9f6c3b568b05f46bfedfa18eb3776699d98cc7c6320003b7d862564d07fd28fc3691d1d28b21", - "0x8e54c7270d2c7041796f202e929ae921fd0fcdc8ef1e6eae7e67d461114fd45ecc7fb78247c072222e48d1292a12acf9", - "0xb7f146a357e02a63cd79ca47bf93998b193ce1174446953f12fa751f85dc2a54c9ed00c01a9308509152b3bad21d7230", - "0x8aadfcf3562f1c357068323352cb1745349a27a7362358d869e617c2410db747149b993ee9e881e252ecdd42fd75f351", - "0x8068da6d588f7633334da98340cb5316f61fcab31ddfca2ab0d085d02819b8e0131eb7cdef8507262ad891036280702c", - "0x89ab1e5c2565f154f92c9b3554160832d176613f1a2f872b6ed62ed925a33fb0b40b71b7443eaaa15099ab24693c8d13", - "0x8e9bccb749e66fbe47296f5dec33bd86e52987516263240f35ce9a212dbcf71348b60a016f830f2acd05482962403542", - "0x8fb74891a8642f25a55b5eda5818367aac2fdf9663ad1e3dbc0166b484c0cda581b243cc75131167f1afa9caaf6705a0", - "0x8027bc62b59f9f15613e38da74ccc71fc3eaee26f096d187c613068195ce6eb64176013f2d86b00c4b0b6a7c11b9a9e5", - "0x8658a15df961c25648fd444bdf48a8f7bb382d9212c0c65d56bf9cdb61aab3bd86604c687fb682260dbc0ad2dc84bf01", - "0xaf76d2de3664f45ed4024f1b944cd316cf758393232bb07bc695e5eaa7f04e7e09007f29e83f62ef6fa25d1000113ca9", - "0xa3c4269e6fdb75882f0bb83529388fb8e08d025d00d869a2ceefdbd38a060e59535bca43012815444cb84021787f6c7c", - "0x8784a8fa62e0ce23283386175007bb781a8ec91b06fd94f22a20cd869929de37259847a94a0f22078ab14bb74709fac6", - "0xa99cde5c7c85ae291c74c893e598cc0e6eb2dda2a81dbb504a638eb21dd2c41d6e5caf7baa29e3c1c32e94dca0d791f1", - "0x802f512bd4a97487491c0e07ab8a94d5580c72212032e34c42b7039b860a7cf8f1e2e24b7185b80d3ee00a9cd4c92903", - "0xb12fd5f747c5223c5150dca2728bb3a363c5bdade5a9d1415642b2201c51aa6bba20a988c51bb6452fee7e05a8586b42", - "0x99caf2cbdd4427666fcfb506bb6956772e058150b0638eacd5db2e8869c8565c1ff2c63f308bc3143874e0f31446292e", - "0xa9d47cb4c69fde551b2648a2444091502a56a778212ab544ac75cc1bd14d0f043f4e31de47fce9a890ef5428cc28dd41", - "0x94240350a53e7715c178382b174c4f918d35cde875faeda528c2f32073085c6032b47fcf00240dc264621041c105e0e8", - "0xa413befdecf9441fa6e6dd318af49173f19e8b95b8d928ebe1cc46cacc78b1377afa8867083be473457cd31dfff88221", - "0xb7c4e55e2b48ba55a71f72387475886e5b4715100e93cd2ae09582fd37e5646b54bd93fba311b65c842bd0aae1424bc7", - "0xb7ea5e0d3cfcf0570204b0371d69df1ab8f1fdc4e58688ecd2b884399644f7d318d660c23bd4d6d60d44a43aa9cf656d", - "0xa7c2174eea2b66b2a71cc8095fae39c423a353c7d5020ec2d0551317a66202fcf082c6119ba768755523fff49791bb4e", - "0x991e0fc7fddd0e316cf4bfe20478f10c15b8bbb618e6be52a5095e457ca52db8adc008f47d4624b6cf4f7d6c2b94a29e", - "0xa7d76c88daa3ba893d4bd023e039e1f587565d317609cc9ddce73f2d3c4d6d9facee20fca31c85322f10fdf15267fbec", - "0xb880555398668dc7d064a18ba82d574999a93a6843423703aa8e543fc196607239de7a4258710b85563f2889eacdd0fb", - "0x903f569a8de771406b9fd36384f1fea20d5d79374b8d9af24b4814f96c44739193662aa47be857543fa101aa70ab205d", - "0xb9ee3b7b95db0122edd90b641de3c07fbf63a4f70fee5f72051cbe25c92d88444314d0489a5ecdb1805f4f149f462ee6", - "0x8ee41011424da5e2ecea941cbf069ea32420749f2519434d3d8f9725ac789753404687a6745cffe4bd5dfc8fec71a719", - "0x8a978ee4be90254fd7003ee1e76e5257462cbb14a64dbca0b32cea078908d7da47588a40ffeb42af11a83a304608c0f7", - "0xab73a043ccdfe63437a339e6ee96ef1241264e04dd4d917f6d6bc99396006de54e1e156d38596ba3d15cb1aaa329f8f5", - "0x9439b663e4104d64433be7d49d0beaae263f20cfac0b5af402a59412056094bd71f0450bc52a294fc759ca8a3fddfee9", - "0xa53d2a4bef5f3d412fed35ac375f632eb72a6650efe811e2131a6ddcb530f88044f65b80b7d739998115b9f961bbe391", - "0x88e7a12a90428bb45bcf4b01442c11607433211fc2f9bee9545304eb66e0b4b5339360160bc782e185391385da7c5ad7", - "0xa163470735c16f800bed412bf0190d7c85cb2d3d588ffce245ec8e8d4872c756a109367e293caf4f5c0ca1ad31f8be5d", - "0x897d7a19b70dcef1af006df3365981d73068c81f18017f32fb9966599481496efd5f6caceef943b31c52750c46d9590d", - "0x90f4476224b64c2a5333198a4300ece8b3a59ae315469b23fd98dadcdceaaf38642d2076e9cd0bfacc515306f807819f", - "0xa8d152e5d94b75cb9e249230db21af31de4d4f3d4ef60ccbf2212babf69aed2a38435a993ee2f13cca410ad55a4875ab", - "0x95aafa379cc6a2b4bdd0cad30b7f0a47839952af41f584219ec201c6c4d54610eb2c04b67b29080acb8cecc5e7543fbc", - "0xa8795e7f4c4c5d025ead0077c3aa374daaf9858f1025c0d3024d72f5d6c03355ae6ac7418bf0757fe49c220acff89f7f", - "0x85e2013728a13c41601d4f984f0420a124db40154a98bbe8fddc99e87188b4a1272d20360406a9dbae9e49bfe3f1c11c", - "0xb380ee52038a0b622cd7eccf4bd52966573fadde4fe8f70f43fa9c43a5a99b3eaf58335a1948b561f5b368ab4e0710f6", - "0xb43fdb2ba9128fd24721209e958be7b9c84dca08387c982723f93ed4a272f933823ae084f1b1399ff6271e0da6f5aa3f", - "0xab2053c376c6bd113b89fdb2ae3b8401aa891135345885730c61cac7813f69ea7d906c531be752e28657f73af92d1f4e", - "0xb586e67ae1826a1cdd651ac785e4b38f8a0e042f103a9b7dbb0035626d5dec3ded04a4e2cc09e63b4b01aebe304e40d7", - "0xa86be58fef115445b909dffac6f51da3fe9214afd9c31fd564bb8f39b1dc3cb895b1222f2c63226b54b60b278ec45edb", - "0x8016d3229030424cfeff6c5b813970ea193f8d012cfa767270ca9057d58eddc556e96c14544bf4c038dbed5f24aa8da0", - "0xa8b593de2c6c90392325b2d7a6cb3f54ec441b33ed584076cc9da4ec6012e3aaf02cec64cc1fd222df32bf1c452cc024", - "0x860d581af35d522b5eb5fddd92a98a6b4cc483fda00820d1ce4530e07892890c096e99b33976ca3550bb900e830ad3b6", - "0x82212706111fb1cf5def02b5b0eb7ae9e6ea42b4c7a2b9fcacb7aec928326edb9ac940850dd933f2822f6cf519de0d50", - "0xa98f68569ced00cf2c9f85fe0b4bcaabed0652b9fbe438bb5a86612a0addb5975e3b98395f2a4788639c602cf21a8494", - "0x8600e2031c9113ad2a75c19872b5efef85765b524f74de98baf4efe4a75c6be563e9e19622388fbe9afe58aa6017b930", - "0x8e825c03c8409a3302266dc5f47fbfc381dfbafbadc37bd8d40f079ca8963d4c5ae6ef0d0ba6aef2d4688736f5f6bb45", - "0x8bff10f91b8c0abb6c9542588da17fa0118ffda4c82626a754887e333d7d69661b3ae4e400da15c49565f8d10a77d0d7", - "0x8421044f794a1bcb497de6d8705f57faaba7f70632f99982e1c66b7e7403a4fb10d9ef5fb2877b66da72fd556fd6ffb0", - "0xb504cb87a024fd71b7ee7bed2833115567461d1ae8902cccd26809005c4a56078617ec5d3fa5b29a1c5954adc3867a26", - "0xb5f32034d0f66bcbccefe2a177a60f31132d98c0899aa1ffff5ebf807546ff3104103077b1435fa6587bfe3e67ac0266", - "0x9604659740f6d473bd2c470c6751f2a129328e74e01b23368f692ad9b6cce0fe1509c3f82e9f01019b72f6bf3a8e4600", - "0xa6ae4fd03fbb4e2150795f75a241ab3a95c622b4615f553bab342a1803b86b1c1a2fc93bd92ee12786bf2de22d455786", - "0x8f142bde50abe4dac8e059003db41610436d5ca60d2dfe2660ecaa5f9628aeb8b5d443e1b57662076f77363c89a1479d", - "0x919b0dca4050f3304144debd653bce45768355d2faa698b99de06ca6ab8573a285764904cafc9262352c87d9287f0545", - "0xabf28b692bed19ee9152d5f8ade776f0a42a9762ea5f37d80f47ff219fc0a8ebe5e6eb920453e1ced3ea5bba19ae5be7", - "0xb67146b202afec0132ac0070c005cf664081e860339f8f4d45ac3e630dda05560936e646673e652d08cecd8d18fc64da", - "0xaa25208385573caee2a4830f09e1cc9bd041cdb78d3ee27a4b011815a62d0d2e0295c222480947ae427b1578fb5509f5", - "0xa35d9d6d5dd5428cce7616842203b5fa3721cb4b20f50c0113f138604954fe0cf214ca3d065b578f921054b9efe823df", - "0xa1c0c317e6e352e16e25c140820b927161ce5d2c4c2e10bca3057ba4d46b4f42ad7aba20de86dad9fc6368ea92695268", - "0xb9ed23f3f26fc9f31e1e30e8ae88482352fab6ef79a2eb8939dc78110580708f482ba3ab306ed6e09030653b9704a80e", - "0xb15978155af006d231888257c6e4beac0d3b0782bcbc99e61802a5c031252f05213c9ee9465e6816d9702e4a21cb9571", - "0x8c9fefe233d0d657349b7efcdc368f5aaead27071d224af780874751e7d241f6b88f7650fbb4133043b24bbebc12aa48", - "0x92f0bf3257e775c5c469cd9a43249421c9fd223996aeda09654045b885a512e86bd834b2947aef216b4d9dd5f8f2e9aa", - "0x81ad5baedeacae12f19cc6d268779c791ddbdbae859d218806cf887b91e83bee3472740b0736877c81c5c1969eeccfec", - "0xa54e104339286d3ce8271828fbac20f6cf7afd3b72d9b194b7cbaf65f6612416117be492bf4aa88faf6ada56cf4b6462", - "0xac2c341f0054876d28393d5125c84b913e754bafdadf769ded764b8dcd4b042b5dbc19b6f40ce8eb45edf7639b3d62d3", - "0x8eebee05702bf1574b12597b72a86d5badef064879fa9d1b9aff5ab75e5c71d81d8bc404f2614085855d6ed87f581238", - "0xa5a07bf219432e9c80c38596c93560b49c7de287f31e30b7a06fcb4d15982add4a24085adbc5b753c462be989c64c96d", - "0xa3d31b20198f326eac488e88fc5b9171276d4934b0bc573c8b55b2abd26380d5296d5bbea281de91c0945f34b37f42bb", - "0xb928a1a20f078a50f9c67da1d909e6656c3980f20b96bb8d06c0cc42557ccd290ed64cd78f9c9ca090cfdb9327eebd89", - "0x8a0a4b295761aa6d2d1b988fb0c65b4338cc3ea48410cc673671ca029ba6c51fd4e101b54472eae93611faee53d4eb2f", - "0x935f616bc620ddcde07f28b19a66c996798792b953264d1471f686e84f3c6f125e2a3d3a7a535c4175973c7ed2e4bece", - "0xa80deb10bba4bc7e729145e4caf009a39f5c69388a2a86eaba3de275b441d5217d615554a610466a33cfe0bbe09ef355", - "0x8dca376df4847cb8fc2e54a31894c820860c30b5e123b76670a37435e950f53312f089a8e9bd713f68f59fd1bf09202f", - "0xa04016e9e13ad845763cfe44af4e29fecf920b4aa42f581715fc34fb9ca27776feee45c82093c7274839eef1838b10c4", - "0xb8a0003e949cf994b1bb25e270cb61358200c93b1c6f611a041cf8536e2e0de59342453c5a8d13c6d4cc95ed8ce058f3", - "0xa50ab79cf3f6777a45f28d1b5cdad2c7ea718c60efeeb4c828d6307b29ef319445e6a9f98aa90f351c78b496575150c1", - "0x8253e3b0b85538d01b0ca90b0a1656ad80ee576d0c3fa6349df58df92683b510e56c524fa6144f79a5525f41e4a2ed34", - "0x917721639b1bd13c33ad5b332e4486c4202ed28ddd9fe97b4d2367a87829c742c9e4bfb508827f4b8cadd0bdab99708f", - "0xb0b8c15d67a443907315ba3e94a89491dfbfd04ff9238d856f46cd49a3324788ddff3be9d61b2987f6f5a3c7d852133c", - "0xb2a4000ce0ddd3f0543ebfe4906570853a85350d75418a1ff2608099c069f03510df576ea0cbb406b7ae8e4f21576811", - "0x801c126abff96fe9b042be8869d2907d0c6963a79901f9db46577a445418b7465a1f4b346933d433e539536a9a2df01c", - "0x9530f92929f61f9afeea5737bded7aaff3078367aaf65b2c75f0f4263b6e90990a2bf64927774c4f0289120d49558d6f", - "0xa065363b9c4b731b08fd361081f93d987ad336475487dd28bbda2dca92b0b5da4edf326995a4ae923a4b2add7aa1df4d", - "0x85c216e314eb7bd8ba02e092c90e132bc4bafb21c6a0fbe058b0dd4272cb76f183b83c6783fc321786065ff78c95f952", - "0xa53658aaddc51e20752454dcbc69dac133577a0163aaf8c7ff54018b39ba6c2e08259b0f31971eaff9cd463867f9fd2f", - "0xa013cc5e3fbb47951637426581c1d72764556798f93e413e1317849efd60f3ecb64c762f92544201eb5d6cfb68233050", - "0xb7e5497eda543c02a7b3245eece98d21dd4c587b5a05f21b5c785756a0b875715782f706fbbfeaa0edaa6faa6b03d8eb", - "0x8ded37d67b5368619a090266e9b5585fbff60319a90a4244a3c3342641f5bfa5130998dd97d7a42505cd896c29255530", - "0xa9b120a77d70c1cbc0178a12d97a78b2dd0b98d0584e8e780b937800ceb18c90eaa1f0a83c5b50e34cae1c20468f004f", - "0xa22b351f139096f9ed5baafe27affde1351685765805d458381e392e0bfc51cbd8af5909b3a1da05d0d176877028eb32", - "0xa16938f556b8c11d110d95b8584cecef8b95ef349ea64b59df806cc62c52ee48074d0b3f18d84533e41583aefd6a9d43", - "0xb95fc0ec39596deee2c4363f57bb4786f5bb8dfb345c1e5b14e2927be482615971d0d81f9a88b3389fac7079b3cb2f46", - "0x89ca7b7aecbb224d04839d36e4b323ae613c548a942830317aa0d51a111cb40d7e6d98600dc1a51e5a32f437951d6c7c", - "0xb28df3e04bde4ec373171401dbd0546f4cb6fa8e9a4a8019aadc653d4e05e0b5b9a64417715dd87f6df9e7b3145f6659", - "0x89df46082b8dc997c3e33fa94fb6ebfd19af29d619ed4d861f8ffcf83d02b9077b9754d0667c2fceb7aa31ab5f806f65", - "0xb0c707313762e66c681b0efe03ca11a49791173c1e5d42b235c3370e98c37ca4393e6babaabc3933e3d54e72843337d8", - "0xa4bf094dcd71e1a8dccca76dc7887476154e673551f25b0ca90d6dac8b3b3a2241bc601afeeb1564bde0432db1972999", - "0x8f88615a86867c4add4c6dbd2c717a7d5c9e6450e9540b56de14c31d9ff84e2495aca3f1d5be51940c183c6ced9da2d4", - "0x81351fd284d6d07092875f366bc5e53bfd7944b81eece85eab71a00443d1d2a9fc0337aaf34c980f6778dd211caa9f64", - "0xaf7616b8f2f56dc68e3e8ae5dc5dbb4b027e53ce652860687f1b15b2f820ea0349baea5af4e3ba4d865429330d3383d8" - ], - "aggregate_pubkey": "0x90ad8bc2718e8464a78d43480f280d3ae08068ad88c2686227ec6a25f4393099e7e21b6200e83ba1a8fc34a9c08f5069" - }, - "next_sync_committee_branch": [ - "0xbcfe80e1d24fbdad7bc058b011403a4c26cb56967654494cde51517f888023f4", - "0x621312d94927fb6e3633ca6b4a8f61e8fbc72799bd54639043f1abe818ba816f", - "0x16fc985fc30e89dee4524512296e2a5438c4c68d8f035d3377cdbc2c7f9e1804", - "0x88c597da85b7b1a0ca4f2e149ecaa3eb869e60e78e5127db801706005d3d0d3a", - "0x7b3e52c66c24e912c1c7aa3207753cd882ec3c691354ede99ec716da5fa0fe3e" - ] - }, - "finalized_header": { - "slot": 4063232, - "proposer_index": 1311, - "parent_root": "0x9f5209af620727873d563ec0386856f5100df2278ee157f8b058021e29a2d0a9", - "state_root": "0x9cfb7a4ceeb31d6be6dba26dace0a074066152dbe507e328886be16e8b38bd9c", - "body_root": "0x9b934ad271680073ffce322e54a0ba990caafa9a0ab95195e4553aa5936d3f41" - }, - "finality_branch": [ - "0x00f0010000000000000000000000000000000000000000000000000000000000", - "0x3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb", - "0x452c63d803b8bf301447a73b2f7a747e49f37f9c9a096d8ddb6c8302666b809e", - "0x16fc985fc30e89dee4524512296e2a5438c4c68d8f035d3377cdbc2c7f9e1804", - "0x88c597da85b7b1a0ca4f2e149ecaa3eb869e60e78e5127db801706005d3d0d3a", - "0x7b3e52c66c24e912c1c7aa3207753cd882ec3c691354ede99ec716da5fa0fe3e" - ], - "block_roots_root": "0x31ed28275cbaae8300426740b8f08d2d31b0bebac67939a5f6507adc361458d3", - "block_roots_branch": [ - "0x7fb8181acdb3d8c6c5e2db5dafd701f1439abfaf2da9435818dae5cc47683035", - "0xc439004cf29049836d890c28867350dc62197484a9c97ca0fcd7be38904e826b", - "0x433cf8bf2df73fd85edc9445bd609ffff88cdf3eaea77b593e3aa48e6648666e", - "0xf092d3324350b4889c0a16d9c2ed940798360d33e5d82b32e0049b6b25cad0a8", - "0x565c0d114cdf1e419edfdcda9941aabc3d9bb8ebf07a4afea082ba1ec2083331" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.minimal.json deleted file mode 100755 index 8f1c8b9ce21c..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/next-sync-committee-update.minimal.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "attested_header": { - "slot": 3664, - "proposer_index": 4, - "parent_root": "0x15ac23a0c16bfa81e8595621118040c3e6cbddd4b09bae6fb39ba5fefd0258e8", - "state_root": "0x6fb81aa3827e7d580bb05b4df2686c9a49508bde2f8342fd75be609a23dd8362", - "body_root": "0x9906a1ae8065d268f8acb7f1b3119408d2f7f8e6e0764370c16ea3d15134981f" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffff", - "sync_committee_signature": "0xa9b5584ec9290a4ac6c5616639d031f9ab1064d63b4889f1da52f6f4d66b645fca48bbe2fe8484adb0c05c647edd694d0340cf684b8ccf8e34c6d8cf447cfcfdcb856f5abdcfd85ada5a4a04d4c8f6f40c6e99308893c3941485a436d6c8e5f7" - }, - "signature_slot": 3665, - "next_sync_committee_update": { - "next_sync_committee": { - "pubkeys": [ - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373" - ], - "aggregate_pubkey": "0x8fe11476a05750c52618deb79918e2e674f56dfbf12dbce55ae4386d108e8a1e83c6326f5957e2ef19137582ce270dc6" - }, - "next_sync_committee_branch": [ - "0x46af3f54acbea439b63aa5bb699c8f25ff584b23912366788f7c8e95011ce324", - "0x5b118fe110ee4a1b0cf9823bc189fb38eb55a7b49adbdafcf466ec7cd4b7fd68", - "0xc2f12fb91a61abedb47f62a98258960edca21f31494cdf59b47a1c721e3e98f8", - "0x16fdfd5e6b591b3140a76efa4593a9c4d105b9e5c62d6f44edbd24790657be50", - "0xc8175ab66690cc94c0a24452754addd62a06948de5db9814e813437a130de452" - ] - }, - "finalized_header": { - "slot": 3648, - "proposer_index": 1, - "parent_root": "0x991ee98a70e8f90bdd61d0f5554e53d37473e75e16af171f6d88f27d20223dae", - "state_root": "0x59b04d660ac772005a13a7dc1d5f99bb0d0292f3c422f04f7365198d70dd30de", - "body_root": "0x5151f035e146258e7327ad9cf1df13f8ddec7a7842c19993cf739358717b5565" - }, - "finality_branch": [ - "0xc801000000000000000000000000000000000000000000000000000000000000", - "0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7", - "0x142061c4bc3673bf774cb8c7b6085057bd0ca85672b43afa2d9581b0b6a44e54", - "0xc2f12fb91a61abedb47f62a98258960edca21f31494cdf59b47a1c721e3e98f8", - "0x16fdfd5e6b591b3140a76efa4593a9c4d105b9e5c62d6f44edbd24790657be50", - "0xc8175ab66690cc94c0a24452754addd62a06948de5db9814e813437a130de452" - ], - "block_roots_root": "0xe6e2adaaad45363d7112945ef670e21c66bcb3276dc450962ade1e8950230380", - "block_roots_branch": [ - "0x386ede102258966d4c23031c5a02de2af8180d475c4c1716b07fb5b9f142a817", - "0x35e6c89bc38d993a1957f8a9fb1fbeab7420688091ba2cd7ee7b19b7e187f7d6", - "0x99249309825cafef7e694c09c4fdf95eb4b1e8743d3b23f6959d9980ad2d69b0", - "0x5e028d1d905db6430f0ce4aafbc78f442047ec3a132b4e69557fdf804a4cfbf3", - "0xd34afeab37851937920243683a1c926c41c626aacb145718fce755782d4996dd" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.mainnet.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.mainnet.json deleted file mode 100755 index 22a44e3cf796..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.mainnet.json +++ /dev/null @@ -1,563 +0,0 @@ -{ - "attested_header": { - "slot": 4055104, - "proposer_index": 1862, - "parent_root": "0x5f44df1f70338aca4b3046f9e5b144bda8b27276320ca000077389d0aba35317", - "state_root": "0x9daecfedc819b45231bf93819a73efd4304ca79528032fae2e852ebbe514cfdf", - "body_root": "0xa33f5cdc6732684e6f248e5a7636c7e7bf705f0bf709098a46ba15c660b4fc65" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffffff7bfdfffff7fffff1effffef7f9ffbdfdffffffdffbfffbbf7ffffffffffefdf7ffbeffdffef7bfffffffffffbffffffffffbffffffffffffffdfda", - "sync_committee_signature": "0x880f147850ac0a94130b81f94203e2f69d512c929df8b954b6adc20cb1e8598aafadf366c074b590c0905d584dd980af18e0c8a837bbcadf6b4438507aa46ef95879c0acd9c2d273ccb13d93e4938e9c601f0dd466f53369ae94e1287955cae6" - }, - "signature_slot": 4055105, - "next_sync_committee_update": { - "next_sync_committee": { - "pubkeys": [ - "0xaedc2d47fa2662be6ab58ddd3682bd5e53f508162968fce8326c75f92fb3c1a25c4d4d0e6904f9b6cb1ccbaaa9dc28d8", - "0x8097b13908662d245820f3b045d8c2c665fe9a054e9c661323924ec86dfa713b36b0c787ad4dfdeb979318810e687a48", - "0x98aebd4bf15916512508a5fe89d814d5d76423c562cd3f0a0af504c8cde53be30f4df00e3ba0229cbf8528e198a0df11", - "0x86bba46d0031989d0f1baccea4174fc3fa0d595e60d35a464e86c33c233e2d6def84fced7a00f59afe397cf4fb5b67c5", - "0x845982c2672fdd44b33d2e56ad676e704c02f756b09e8765bea42b924c14724484567b55f0db42ac20cb70a7f5201c14", - "0x926dc729e135f1f0bff4662ee3d6823a64597fe189b763ada34f246e77705fd4e062d85506a338e9fa98c4d225a3b27a", - "0xb930ecc2a26183240f8da107e80979b59da4e05f090316d982815ed6151d7750490b85273187ec4e07eb221813a4f279", - "0x81564bee5a3bd09476f658cf7719326c353485e2f4fea58d110071c5dddd3cabc349a8d1ecea45d589ed4479952a2ba2", - "0xa66d5b1cf24a38a598a45d16818d04e1c1331f8535591e7b9d3d13e390bfb466a0180098b4656131e087b72bf10be172", - "0xb9b9b6113301bd2b409b71afa1ab9e31d22f84f8cb03badaa408e1d37032350094124e533de766622d7975a047fade6c", - "0x8eb3b3e3135720036c1120c4e8b8d405b00d002f2bdbe601a06f2c2fffb940a9966d18636ee34fc003dfef547d8f3b76", - "0x898deb30ede570d391266c81132a78239083aa9e27a9068e26a3bc14ff6468c3f2423484efb2f808b4996c16bfee0932", - "0xa90d9502a9785e55c199630456fcb1e794bbeb0f5f8c022e66f238a0789998b126cf9911fd0b7d463b7706dc6f9ec128", - "0xae8af784224b434b4dfa9ae94481da4c425602097936623e8abb875f25deb907aa7530bce357786a26ed64ef53d5e6b3", - "0xb544c692b046aad8b6f5c2e3493bc8f638659795f06327fff1e9f4ffc8e9f7abdbf4b7f6fcdfb8fe19654d8fa7d68170", - "0xac5c01c51dac6ee1cb365c9b03f09906d9b7b9b4d1b73c44d9e8e06823025d7070f242898a975420bc87d6372382cab8", - "0xa4632399c1a813e41fb2055ef293466098ea7752a9d3722d019aa01620f8c5ecdc5954f176c6c0901a770cbe6990eb11", - "0x85f7ae1a7a7c793c408750ddec2d7f58b985fc3cdf9fcf6b2192bc57092b8a271b2fb6ced0639baaffe0bec3203e568b", - "0xaaeb466f4316874c2107a0de38dafafa65ce50039c20723e8797815238011426f4e77e29fc573e7c6d2df85c1bbfefdd", - "0xa8fd63da16dd6a4aa1532568058d7f12831698134049c156a2d20264df6539318f65ec1e1a733e0f03a9845076bb8df8", - "0x93600f65c090814cee5cbd5f22f98e79c69e63510501a0be6a74b111e4c52441133fc1c198c7bf235f9005aeacf1d441", - "0xa69f0a66173645ebda4f0be19235c620c1a1024c66f90e76715068804b0d86a23dc68b60bca5a3e685cce2501d76de97", - "0xac6e7e9960207138d5b4b6a7f061756c01cc4a830e5988423d344f23544ed0eaa790aed63a22df375768f670cc9b9bd4", - "0x93042dd42e56671155bb40d85d9d56f42caf27bd965c6a7a7948b39089dba8487d4d5fd30522dba6ba392964e3ffd590", - "0x85bca2f86423a09014b562f7dc613246bedffdcb3aa41fee02270c13e6b00c8d6704dcbfbafc5997df6a90c7fc08c29f", - "0x9550072f64a48cb86bfa224d492be9a91e5a6c9def04b6a290b7a19d96981937d5a2c35de6515d1881bcb167f6e3d661", - "0x8d797819318cdf7b26405d1a327d80d4c289e56f830b28d4e303bcb019aeb0b3d69bfed58adcde8a2445dd5281b86af1", - "0x90c04eb3f3679cd630434418cb3a225a73254887692429960bd45b1613f85b2c14723cd8c7f1e875588ed82b7f5576b7", - "0x9953a7cbc152f101a60e3e381f2af17ebe7401e16ef6462d132b8f0f6c6a18837914a1299d1605f9f289b9561112f4bb", - "0xa9300a33927335f482dd0e44d0d57704ebeb278f732ae8301073cb7d5e457f02a0cb03268de71d284b8c23fb96947469", - "0x88554c83648ea97dac83d806cd81d92531980346b208d281fba489da15a0084fd4d9a00591d1ca67aad3c5793685d55f", - "0x9131874b09aa95ba186bcaa9e040fabc811b9c7b905b7dc79e902cf2bb5816d7ee39b0b55be609f22bc8c538760b2037", - "0x8368bb9b9bb2e17730c42ed1100eb870c88a8431601312aa8cb1e738cdb9ca2704dfd432cf1703c0db043259819631dc", - "0xb49379bbb9f954d2ef5574199607bc6b3aa2cc3b48dcc3745cc77406bba2a394929844fec1b87c4ce65cd0ca0f83062d", - "0x876afcd045c8a18967923733a3a43757652289b0974cd348238a693f30bb57f38664ecb97877a5e5f7d0185039a2bf54", - "0x8db19f6dd3789df179ab606508ca7e3da7967ad4340f630bda83df54c197d6bd3a14980c87fe10cbced7678c0c300ef1", - "0x997a91da55801acb6134d067ad65a9a44ead0b53d3871bb97b46ec36149d25e712d7230d38605479796190abd3d134b7", - "0xab1abf9cf630d6cbcac0c503df44603142ac81acd647784ae0e8fc97800ef04378bc9d7f2087f959ad4bbbeec65b8dfe", - "0x95718b06017ba9d45894867fd67148645d25d9db2229aa89971f444641ba9db4c5c6f0785f3b25cf2cd7fadaa6adc5eb", - "0x8ec38c68afdfb6ba019204039c2fb49a35467058f561f626fa87314d705fd615a7b9966576052be1b3690028d3c5c7bc", - "0xa5d72ac4cdcd847d67cb5a68c6141cde99a91303ca84165bbdc6fd7f643422faec783de60739e1b2753088280c90a68b", - "0xa778da56ddfe4a383816b43b027464d7a28689fc4a6b35b36883d3f36d9c41f0177bdbfc8f258afe8da90f02d3b64fea", - "0xa2ab566033062b6481eb7e4bbc64ed022407f56aa8dddc1aade76aa54a30ce3256052ce99218b66e6265f70837137a10", - "0xb9c347c1c350fb7ef6ee9ca6780cf0604f30e3a74e9d0234bca6b3e7faed26148f2b736d9fbff6b04f5b947fda458e8c", - "0x815f53751f6d3e7d76c489f3c98d2b49214938cac8c2b417e2d17bb13446c285fa76fd32a97e9c4564a68f4faa069ad2", - "0xb3f1319ae34ad1d59207288f01d3d7b7e1bad7733fb4a819a09b011d72a4d736bd3c7afeb74cf56da0e00cf712042ad2", - "0xabbfb501071148e98b6aa56308197356fd993c93e27fd58987eca82036c1ae0ea89f9fb1a06c82851234643904c58453", - "0xa0899189bba608887c6cb729580e570ecce9ca7107865ebd30def867afaaa250bac407c30dbee11b7ef6cd423269a8fd", - "0x88e7a12a90428bb45bcf4b01442c11607433211fc2f9bee9545304eb66e0b4b5339360160bc782e185391385da7c5ad7", - "0x82714b00a822c30b317ffc1d4ba163990cc1ffe5769f91906a7f71ad1f62b39865a5314433a4ab2ba762b1d62b01003e", - "0xa3a930dd70aeeaff0f2e3790927d5425db40467ee106261615de5fcb937bb1621be213ccd8b3a14d96c5908bedc2e421", - "0xb2902161b565dd5b8e8c54187b26f01741a39ea8bc1120598661bd367cf8fc73e21eda2f0f6f9ba2270c80a59ff5985e", - "0xb77cdf45f39bf85ab3e8c8afa602f159de8352188aba5378957d468315a2d2326daef83d8ac6b227f1e7a514488afbc6", - "0xa9e573274f5a131d6c7641bc0576a2621b6466a5bf2cecb21058160a854b1b9e0be176da2b6b9b3ed562fc36c5f09119", - "0x876561bba29e656b7122f1cb51a02dff1ac7d470217d8a4799c01e61816c4660eea91843a5a42502ddf842d2daeb0586", - "0xa0ebae60a998907a19baa396ae5a82bfe6aa22cf71bfca4e1b4df7d297bd9367bbeb2463bda37aa852ad8fd51803e482", - "0x84a6edac5ac68a7ca837c46d5ada8fab136748b6c3a3b9165dbbc231ec386b15328e4ef7d69a15d4cf354135348a4ee4", - "0x8b476b3b065a3b95a3d11ec60a749c2258ddcc5885bfb50b8a086d3fd1e49ff73e1dde733b8981c3d2d206aa0c87b09b", - "0xb48490c5a3bc9e66cdc78994f7c73e0f2724fec8a304b4147799e5142396df155ef7c42065ed6d2c0393d138fb4d2a0b", - "0x849ddbdc3ac55ff22a3b2f4bc51892fed694490ab4dd342165ac38c725c8b38921eaefe3c443962925fc3726aa41e236", - "0xb49c45d9da4aaa64967c28f1fd77b7f709f5a331b58823eb1613856fd8f92635135981830a287e8dbda3a0e0fc481c5b", - "0x93ccd8c5f82374e0bef6562e16576f742d79b6f400e3485ef36e148088b61fbd882c3d2bb38ab0b43fa1dac77f31d543", - "0x81522576ae4ec9358f1a16934cd1c1116de609634e68f552924a972101eb7215f037ab8e0582d7b13541537d55554d31", - "0xaad60e58a19598c5013b37e2e4adc6721eaa7e6e184960d1dc4e6f012246abbb58a047c0679064d5eaaaaff02de881e5", - "0xb4f034f2b53ff9989e8a0f12c1484c58ed7942432a429af58a6659feaf23f7d2bf20ff7b9a7e0a28a2e09c9a730681d8", - "0x88b2c68b425269850c1a4f4608aca194da5c641adeb99e2f7fb92e34b8245dff066e73bde072be60f7f2c3d3d13de3b6", - "0xa749ab53fc2662a0796489be84fcfa59bb723ff748bd8980df0cb4b3d1e2943845b0d7c67576fa0a33c8b0ff8a86932d", - "0xabd7248ae069d3a3a45b0ef4dd5d7d54b62994e578ea20bdd3b7876596673953b94c5b109a6e4b953b517544b915368f", - "0xa49da42c27d019a21cc6489ada7b712b98c4ede28ba25dbcfa916acef48446a2baf73e03a48be763378a09774d4a03fc", - "0xb3c36fa39f668bbc3fec028875a820057dbf96f727bb423280da96d5d50e885d23bc23fb73457bf79089691ce7663a7b", - "0x8dca376df4847cb8fc2e54a31894c820860c30b5e123b76670a37435e950f53312f089a8e9bd713f68f59fd1bf09202f", - "0x95d1f944b0c53eb3e9fcd5632713602bbb9195b87a172a370ae2df98504612a55f3968615a39b569ce6a0fe9fb559be7", - "0x8c9fefe233d0d657349b7efcdc368f5aaead27071d224af780874751e7d241f6b88f7650fbb4133043b24bbebc12aa48", - "0xa2ee6c29efa982e9b9abd3c5e4f14b99d5d0369d7bfc3c8edae1ab927398dc8a147a89e127b3324d7f4e3a7494c5d811", - "0xb7ea5e0d3cfcf0570204b0371d69df1ab8f1fdc4e58688ecd2b884399644f7d318d660c23bd4d6d60d44a43aa9cf656d", - "0xa07826925f401a7b4222d869bb8794b5714ef2fc66fba2b1170fcac98bed4ba85d976cf9ee268be8a349ae99e17ac075", - "0xb0a47515752c15e4dbeaf9ee27fab3b5c0db82f5c685e8f716fd7d8764164944340430fe3db1a5679e6ffea5a16dd919", - "0xb7de6d7a4afb05984dce153e5570b104338265e45c8f0156f4d45c458f47add234a479e01c02d3c1817c170b5b65b100", - "0xacd4d1e11f81f4833353b09d4473ec8b15b8ff31dbf39e97654f5338a26c4020306d51018f1f4b9c4efdb92992408a6e", - "0x80e09f3bf3ea87d48e04b53d8f3b43b7e53d61f445f8c8a5a35472b84f6bb4f58f17d9832f5881bb44fc06156151e5c5", - "0x98d6d46f603afebcbc561c130e416d5a588a7e6c1f17f89ed6e30538b7f8dbf4b3c75b8a3331425c4ca21e03fe8b57f3", - "0xab671eb947490c43fd05e42a787344b21af89babb705393c82748eaa0cfcf80bee498d275a1eaf1d647ca3b2923d76ea", - "0x80e1dbf3296bdfa98aeec1a7560682165d13bc628061bd3257f345aa1ba13f8bd1bea14f117af562be22118f5a8265af", - "0xaef456af90354ff88039d2dde02b0f5a6790aa762b23e0a9da8c6ec92c3b8b3320687bb21666608b4a22615843afd1ef", - "0xa5a07bf219432e9c80c38596c93560b49c7de287f31e30b7a06fcb4d15982add4a24085adbc5b753c462be989c64c96d", - "0x84d2eb008578aebd6f01254b7e46584c1524e6fd7a5a2ae5fa0ea560865ca50d52290cf2d12dd20b042f402e62181b4d", - "0xb8e5226ad3515627ae6840235f5f7b7ecd54e8f01079c324d126ec852f6665ebb77168b3f2b3b51580e04a6ff602d5b3", - "0x8c1de4264e04ff7e8282faf81c0bfb5943656451be52170211cb7adf4ff21bccbb789400735579c622f69982fcb8e9c6", - "0x90bfbe37ac3992432e68c95c0d4342a9712126d1f50089239c9f4f6c0c202b54334e08604d245b97dc8e8f6706f6992c", - "0xb0a771b9a0dd7e352d46c8efcc1834e610dd097711bf7117678a99d386890c93b9b901872d4dcacb6dcbcf3aea0883ea", - "0xa4eb903990bee2374b14fa66fc262d6821669537e9ba241c87b4b5c9e2b89b32fff4bfc28ab8471ef52e8eebc3e743d1", - "0xa6b74c706b33d3cae9b7adc5c7502ac98f7bf94a14d579d2bf77b613ae555634ad6fe631ba36dc14bf44526436355e24", - "0x8296f8caf58316af535def398a43357e48cb3b1e674b857eba1bd1b970da3dd045e22fe6d17dee4e9117f62ece3ec31c", - "0xa129c9cf33df42b5a98ad98be9d940207ae154c715d3bde701b7160dfe45304679fb0481a4f9dde242c22a9849fc2d9c", - "0x858b6f1bd3e68fc536bdf1f4bd96db032994eb76e71571e2d85af73b898478b82f9ab432732b0beebc0864ad8025ae33", - "0x8658a15df961c25648fd444bdf48a8f7bb382d9212c0c65d56bf9cdb61aab3bd86604c687fb682260dbc0ad2dc84bf01", - "0xa8d152e5d94b75cb9e249230db21af31de4d4f3d4ef60ccbf2212babf69aed2a38435a993ee2f13cca410ad55a4875ab", - "0x95757096c132e7f6c096d7b93a5a0d2594d5e609b9f13c4a9f878e95a389fa1a111b185dc1fd8f7d98b737dcf8d2af60", - "0xa22542a4a2ebde18cc6aa29d5dace8b4f6720703f519610dcf01e671018392aff15728e3764730840272c9cfb074b612", - "0x8f90e72a54e6894d511061957162e753010812346afd4d90cfedb678b99ba1aacf2b6bd0e49b4b0e684da8082a048619", - "0xb2affe048c187d311a185503d8958cacbe03796edf79bc32e8533941004d9178bd2e376e627e1ba61ed43850c0c455cf", - "0xb549d272a7f3180826a978d747507e4dc80d82784abb655cfcd3a69cc72e7d58c70febea1ce002a89852a8f934ea70fb", - "0xa9ef845ab489f61dbfdcd71abcc29fc38f3494a00243b9c20b9cd0dd9e8a0f23304df84939b9652cdf5542d9b3ee085e", - "0xaa744c552b5fc41e1ac6ca53184df87a1b7e54d73500751a6903674041f5f36af25711e7bc8a6fbba975dc247ddad52d", - "0xa802b9ffbd4f01b877791aba27da972be4bacacc64a1f45687be4af01b84bd4b83fe2ba1ea78e29d7683f6c777ab2543", - "0xb44d2d9510516c0abb4fc101241cf0e0223b179fb70686519628c27f0ef56381232961bc79a30f592ef093ffecbc4486", - "0xa684a09add047c0fe648d9c5618500d1816047168e055e8ac8c952c3544a462cc095b32fab07d939947a58fcb4ec7ba7", - "0xb5eb31e5cba0193e74968099ace5808dfc457c6f404f270fdc4949b60daa7607ba1811abab1bb19fccdad61d489b6657", - "0xa10f19657a9bc5a5c16ebab9f9fddc3f1d812749cd5d80cb331f51de651873ff899e0670f1b079b29a194572de387a17", - "0xaf61f03e3ceef5bef36afa29ba2edc7a3b01ca26cec2589edbc9d124dd46e41410e0e3afbae959c83a6f839bbcf8049a", - "0x8e6bbfe492ecbbb8dc8889d3dcd7037a58db605bc6bb79131a72a9b9c1bad630e75f5e5e0c1bc407e73f3d13b116739f", - "0x983fc1ddf17f9756c9cecc00b39bb2ad432587a5c6d1c3296a383b9f539c9afe84c6c818447a709c0b686ba26ce5ea3e", - "0x8d52413f981bc611427ad0534d25e914113d0ebcd6960aab6421608bec6648b89ae4b2ca2153c57d3cf4f1f37212aa5c", - "0xae075b66e5f211c2149c45b211d1297bbc1d9e6497cb3315363c492a9a51ae5b9d0a28bfecd755d68553736901ac6606", - "0xa02f7fec0661394399a82b2e3151009160b3f5392017ba579b301ed42c85100c295acbfed46b6c58a9d71796ed0930e6", - "0xa3a7196fecd25e9cc7cac79c35365676e48c7be1493df255676adff2209c0719f2190ceff3ce008d08efa07c244c11a6", - "0xa5fe3dfb5031517bb8db0d5ade1e9f438e84bcf23221de003b03d2a2f4ea97629e81c79abc3769bdb8c69a512c189b91", - "0x8cd9d7e953c7ae07ee785d68a999e702565960d376692d9ea468556ad141229b1f3bc97926818c078901f73ecc578e93", - "0x81d6fc2f01633e8eab3ba4d72588e14f45b00e68ab887bdd4ec5e8558965db21189310df973837106216777b07fc0805", - "0xb75ac3d5b3dad1edf40a9f6b5d8923a81872832eb3a38e515539cec871a353b07cb477f6d55cf15ba2815a70458aac32", - "0x94d3c9406dc6dd7241a726355643d706e46b35f1ffe4509ac43e97c64c07592821156ba02ec9a78978e66709995a0ac8", - "0xa3b109249ac2900806f0f39338da72d4f2cc6d1ac403b59834b46da5705cf436af8499fa83717f954edb32312397c8d9", - "0x8336744d8ef3a3bb3e9ed3d6b83e08cafffc76b7438adedd3a7358b32acec0e73a4635aa3166362ab4e158e68576255d", - "0x99b74edbac662fff69ba412de466a427a928ce2363c9e59dddd664f6fa50f2e1dd3d464701b01784aa224b3d96dedea3", - "0xb397ed7134f447d9bf1c511bf92f2d27d7b6d425b8b411365fbef696cff95c2175461cf5dd83d93bb700e50ebb99b949", - "0xa3e1fe11f38d3954a7f48c8b68ff956ea0b6f8a3e603fd258c9406ec2b685ff48241db5257179ea020a83c31dc963854", - "0x949cf015ce50e27cf5c2ff1b8e2e066679905ac91164e3423d3fb7e05c64429e77e432db0f549acb99f91fb134b6edad", - "0xa1c0c317e6e352e16e25c140820b927161ce5d2c4c2e10bca3057ba4d46b4f42ad7aba20de86dad9fc6368ea92695268", - "0x8d6e3df29419bd0da1deba52c1feebe37744108685b49ca703e1b76fb4d612e3959d3b60b822506e5c0aac50b2f5eee2", - "0xa15e0cb96a463ab81e661ca44c619b71a159680bbc04707ea5a5867ff38b15416e3abe55d2fabdab9aede1f157dd37e1", - "0xb6d6482ad7b9b412ffbefbbdcc28eb3d091b1291f54f77bdd53c4ac85f705c454940f466dc272dde7b03c26f0cd6ecb3", - "0x8391e3ad6ec2686bdc686671d579edac2d5efa8cf0923577df28fe0735e4d5103173d44452816e3c2b2a7fcc1fcc20d9", - "0x818202d7cb60e4148c71633ccbe1ce311de7b7ff93a1988e86ba29cc58037189f0f275b3323a6719dc9bdcfbc49c35c3", - "0xa7c0fcc422c6da878926cc6763ae6ec685a5d8fd1afe61269957be6bfb3f1705a8e4c6e6d85bd15636521f5a2ceb3a00", - "0x8f7bbaaac458bada6d852fe665c87c646133bab16c0d5136c3dc922095b9d647d93a9de7671cb7bfd4cbd138ae0709d1", - "0xb6e9fe9fa3d4c833c3beae7f798f30f07e3cdf6f6c8eb8e2b70cad51b37af2549dc9f2e7f97f194e5897d4dedb904a45", - "0xb455f751232de0a48440d09983f4f4718b6169907979c9f282acf7177ab5b1f338fe1f2acd8d0bee4b4aad61d0340839", - "0x8aadfcf3562f1c357068323352cb1745349a27a7362358d869e617c2410db747149b993ee9e881e252ecdd42fd75f351", - "0x91bf4c32fa8888d3829d3c33e12550d2ecb70762d5eeecd044d4902e4a7f8b7a2592cf6cb7736eb6bd9d312f85c2777c", - "0x859426bf6211e68924eefdb26cdc168ac0deab291aaff7036163997bff34d45809932f91e12d113784c05553ca773b15", - "0x81730b4bc5f755e5b99c321a6996c65e57ea2ebe6c0e4e404ed30920194fd76db65304635ad054a8b25bfd982cead47a", - "0xb26f5ed09f7d5bb640ec94ddd1df0b76466f69a943b4699f53d45296d5d6b8010bb61477539bc377d1a673d89074d22f", - "0xaa65c11071be23c9bddaa5203f3166e5cf043efe5fb8f4b26f8a9cabe71db701a450e79eb001c401da5752755d9cf1af", - "0xa019370ca799c2c98a605850910cf43531bfb616393039fdfc370848feedd3339b2427b750ccc91952b03a09f690e9ed", - "0x8f84cba7ceb7652023fc8ebde4b00ecde1f550935bab12feb630d6f49517b4148f3cde184bf55d4f6ec99a849fc6f862", - "0x838733220d1559c800cf1714db8a43a67a0c0d1d3a9fc1e2cdcf615d20406501e5146fe8b59bf64f4c5daa1a6d74f15c", - "0x9708cfcc9ff95cf23f544119e17518a338575018f153b1ef50118da0681304919a226b2089a417c2ab7b4320dffafc2a", - "0xa988cfed9f481bc98beb5fc188ed3f6893a3ebba27c3ebace669792f6abf0997727023c3b6930a6421224f5b257b8b49", - "0x812d3ded3a3c9e58eecf13a29bb4cc13b01b2a0af322423a29bb0e4f6d9021d1d87ac4af7a2a6b88d34f44a8bc1b3c55", - "0xb2baa7eba496ac4ef60ad8ef27a9677f9507820d95a1c572d322621c4d0226b36146bfc3a9ca1645d123acbd945de3f4", - "0x89ab1e5c2565f154f92c9b3554160832d176613f1a2f872b6ed62ed925a33fb0b40b71b7443eaaa15099ab24693c8d13", - "0x8982534f2c343dda20cccf5a9c8bf98240bba5f4e8eb2206e63a1847097deadb6bf0d24b358014d564c5ef1d0448c43e", - "0xa1e47798a782a024da340d6d6a1b1e5e15a0f2d8668adf349ca375086964414a563cc1eea3226ae637f87e78c0a630b3", - "0x847b58626f306ef2d785e3fe1b6515f98d9f72037eea0604d92e891a0219142fec485323bec4e93a4ee132af61026b80", - "0x8368a0f17c8427beb71dbf11a09a2fe8495a33f08c29c74a9a996a88aa01c0a09f9555abeb1ef1592cab99a9e05875cf", - "0xb38e558a5e62ad196be361651264f5c28ced6ab7c2229d7e33fb04b7f4e441e9dcb82b463b118e73e05055dcc9ce64b6", - "0x8018499ef720e28759133033833edfe17ed23e42f99058bb79fe844ddee823cfdc43916be2dc9724d18f9726e6f1b409", - "0xaa9b9cc039d147677aedd1e47ad9013fcc0da0164070ff7305b18e5786c7fac0471368637a3adbb78f3af174a5c1592a", - "0xa5c0e42851b769d2d822e39222e708068455aae3bdf782975b59d3201e67a58fd66e16d380558bf2086bcab890a92dd5", - "0xaf3f765fd293c253072b33a780ed68933f78d7e079d9a2079b6232755bedf6ebcbce9ba65c01f695602fa8ee17899867", - "0x8a0192ef0903d7a5ed2e5614a715901f2554b324ee72390974dc90727ff08dafa580041a21a8e6c48a3e08e1b042afab", - "0x907c827a4fb5f698bf0e6f10ca07741c5b8e3ecb26aa53f938ba34ceb50c01be80c4afc5ac4358a5fda88eadea0cbe73", - "0xa35ee5c2d7800489723c78008b495e1742f0542dbb487172ef438f60424c81aa41c2397095821248066140662133f6f4", - "0xb1925ee53c9228cf80e2f5ac0117008a91e98d878f69bf03d00d873ef45f4351cb6988772d89d4ccddb40778d11e0dd6", - "0x95aafa379cc6a2b4bdd0cad30b7f0a47839952af41f584219ec201c6c4d54610eb2c04b67b29080acb8cecc5e7543fbc", - "0x8f44c43b80a3c5f488118859fab054745cfe5b0824821944b82fcf870fda6d93489ea9ca4220c24db2f4ad09c6080cb7", - "0xaf861bb21f84c3e7cab55370839d18ac24c475a9e833607fcd7e65c773ee9d64bea203ee9e8fd9d337f1cd28d5ca0d90", - "0x8f6fde2ebbd7682c69026069cfe93aa5410071f05de9ccd7070c8c3299a6539b39b3798f01a0b4e9b1330510bdb51de7", - "0xa35d9d6d5dd5428cce7616842203b5fa3721cb4b20f50c0113f138604954fe0cf214ca3d065b578f921054b9efe823df", - "0x8d562d6c0e0d8325032e1fbf836022c82a8f600a6fbb56c553ee5d1fac0f052c7ce2504c0fd48c9fa6494a6bff63c9fc", - "0xb02ce594310f1eb8acc92bb80de524a43e663e12fb64fc28291ff207f9d8ae761631416410c3c8f4d6890b8b7e6ed24d", - "0xa258f8c0eff666c2bb70e505544c3d10d6b258310e4fb2206fd0999f69bfb739a1e232d1e810e7206f490f6c44f6934a", - "0xa8a77936ca91df3b2ee7394ea821f2bfe91c6ad8193f44651466c170b6ecca97ab356fa7d947ebb4b767e8967092f143", - "0x88ad79a0320a896415e15b827a89969b4590d4dfa269b662bdc8f4633618f67b249f7e35a35884b131772d08025bfc32", - "0xa3c66439724d737d20a640bceed8671b20cf6795671b6d442ed1ea5eda6723ae559396c24f44e982ba7751dcc6adef5c", - "0x8d0e6475acfa2b904e7d53bc7acd070a2ee4894ff5720a20e560e9ecb7872ea442a51cf2f2eee4bef66604a5c08ad9eb", - "0x804c021152c3304853941847e80480fdaceba3b9676fbe018268cf77d1a1856966c2f9686bb4d4aa0c4118a7e85f83cc", - "0xa6565a060dc98e2bfab26b59aff2e494777654015c3292653ecdcefbeeebd2ce9091a4f3d1da10f0a4061f81d721f6ec", - "0x8d5de60e934ea0471d9e0a46489f21e03abb9722f5b3633631a9a099b9524beac5d67716969c83d824498796d9c106b7", - "0x8c5a9f6eb0a3ea95e75362b06e5cd23968447a212cf22e1419c984d74432c51d290b717f80e8ed3e76b1232216f99758", - "0x918ebb73eef984d0ce28083306626d04817038056aab4a82ff9ac8176ffdfbf3173c0b05e936daf553248b323fe54f56", - "0x8f9aededb605db4e499d3c383b0984b1322007c748dea18dc2f1c73da104a5c0bece6bb41d83abdfac594954801b6b62", - "0xadb198f70a7f1969ed0958be4a9a60dcc1806bced79c63692b9aad6c5648ffea1fed60b24bf4b1862e817cf229e93e83", - "0xb118f77f99ac947df97e7682f0fb446175185b842380af4ee7394531e4f93002c72b41a57a7c1b923a4f24b10924c84f", - "0x944f722d9a4879b5997dc3a3b06299182d8f68d767229220a2c9e369c00539a7a076c95f998bea86595e8ec9f1b957bb", - "0xb7270f33011db1bad18e076a162d6e53d9123808609773eb46e3a4ac69c84c257407907bd5d05b6eb5e926b8d8c6d884", - "0xb09c0a505457c6b473fc7b2d634222905b36a6ffcc015dbdffa3bd62218c94e891615e77f28e6e18dd8474be8c156695", - "0x97d076617cf0a64ab3d1f030cfd72a303b6b252c0a7b96157ff7fc8af5970f00d14492c46e8f6f37caafe837d0dc95c7", - "0xb405520ef829a2a3b8947f1687ab56a7af4026c1a6f99f59aa192bc4f3b12a2de407862ff74ba1b2c51889b8d6b090c7", - "0x8bb045e7482b7abe670d72eb2f7afe4207b5a3d488364ff7bb4266f8784ea41893553a4bf7d01e78c99ed9008e2c13bb", - "0xb2df29442b469c8e9e85a03cb8ea6544598efe3e35109b14c8101a0d2da5837a0427d5559f4e48ae302dec73464fec04", - "0x99daf03fa434a482d9aa4d090884c99b7208c1f5380b9acbf304e1bc33d3d6902afa5d248d20ccf03795e26901356ede", - "0xb60df25a7ac1ad14aef7e8809c4bfc190b715f94f14b0534cc2e4015ff6c322883cbdc5309e05d67dca4bc641c69725a", - "0xb46a818f3e492e231d8fa8de8848c16f0d648a2e0d1c816adf9306a8596fdf45922e59cbf745430570a19e54f45e28f7", - "0xb3ca2ab7d64b71e40693bd3e2288a1f78741a139403c783d259cb9dc9c29f16c00796b6302cdcea4a4314e132b4f9d1c", - "0xaf3d3dffbe55842dfb4417295a6ed1a82d26a579199494b305445215045785759be4cb57dc870c7ddaffbc101a854a92", - "0xb21785008910a949804d1291e7533752641d31beae3cb518806488f81d58c38a5efe5ed9534ac692e68c3121e2f9d97d", - "0xab7eff4ef8696db334bce564bc273af0412bb4de547056326dff2037e1eca7abde039a51953948dd61d3d15925cd92f6", - "0x8bb4d08318386c91a0136d980a42da18c05743a5c52a861ce52a436e66a8ebe472dac7f7461db32ea5da59a23e9bd6c9", - "0xa1c84730a5c41dcab9a5ef9e1508a48213dbc69b00c8f814baf3f5e676355fc0b432d58a23ad542b55b527a3909b3af6", - "0x948f808c6b8e3e109a999657ef966e1e02c96a7aae6eecaf912344e1c7bf7ea51c911cecd3cea2b41ff55acc31df9454", - "0x8d264fbfeeebb6c4df37ff02224e75e245e508f53fb3446192cd786ecf10d0f704c4fc2e53e7f7318ae1407e46fc0fb8", - "0x8d47a7c2c62b459b91e8f67e9841b34a282ceb11e2c4b0549883b627c8526d9e0ebd7333ba70630bc0ec2478114b6ae8", - "0xa4348ad30c12bb7dd03dd014cca599c3499ddf348e7795b0392a18f998289979478374e374a8297b5b6c427441e2b5af", - "0x92ec1aeb2aa24c51cd5f724972c8b6095e77b237d83f93ed34ca0bc91a1dbf1ad95adccc59e0f0abbfef33f331f3298c", - "0x941f73b2138b4347ecafcc7b8c3d03f2a54dc49f580394ed08f22b0878ee7cb63d42978f1d320c09e7dbc67648c06f8c", - "0xa308ed8737b3a9346ff20dc9f112efccc193472e6fde6aa218ceae11e288bbd2c35fa45c1d8bb238696a96767cd68b46", - "0x8eb03001ac9e22c6956a682ed458e650785c36d23ddbcd51ac4d9cc991325c02519ff1958987a08eb29ff56ff6e2c293", - "0x80637db55287f891baa0e865d2423191b9a575620bc4493ea76166d47b99fd89ad8625c21f446b01e3ae17292c78f7ef", - "0xa5b3da08aad945effdb645c797a0a8bfa828c9d658df2783a214597acebda3ffc07ee48d0ce1147d77540b557d9ada91", - "0x8d5e0b8cde1f62cc8f15d9f596e31de09c221da91b10335b92ef1155802e742442def161223333573158723f3408bbd3", - "0x931923f0c1f75a197e6244d67525b524ceb07510a6aae8cb3d56167cc1aacc76d26fadfa1bdfc55d8439c6ee4d4d8174", - "0x963a298fc8876b702424a697929c7a1938d298075e38b616c8711f1c7116f74868113a7617e0b4783fc00f88c614e72d", - "0x91ead7dacf43905eb5d4b179af29f945479ed074126bad3b5a2bbc1663af5f664fe53a36684e9389ab5819e53f1344fc", - "0xb8a6c999068c13fb71a99d75eabadf7edd2d32e28607baf001a0aeec412fdd3575602c68d3feb4d743b90396705e37f3", - "0x938bbaa0ba14597067ff4c0a7cfc1529c44160d6f61cfad12246526d84fb7a1ba964d3bbb065a348cf7a98356ee15234", - "0x80e44d3577f12cabaed7074feeb57162ff80b61f86cce8f41d1d1250bc455070b09f6ea9d0c263b7b4824701480f4c14", - "0x8d74f4c192561ce3acf87ffadc523294197831f2c9ff764734baa61cbad179f8c59ef81c437faaf0480f2b1f0ba1d4c8", - "0xa0133deca5ae8f1100df8db69920b2d0c31aa21bd3849dbaf4c264eaeaec8937ab8f982770ce1ea17e0e258910a56d02", - "0xb6a25d493d708b035b853f1f7a6628d8e0b205d2678293f763d7ea4da11d298539533b22b43ed2e5f708648556f3094e", - "0xa58c3a4ba86d0d6b81c8411bb73a528b4f3bc2debac0e0208f788c080a3a96541d57c927143c165f595070afe14b0517", - "0xa52c15840b89d92897d1e140b2b8468a88886c5e1092861e598b3a433b340ded5b35b3d632a9879820fd56f20ca3a68b", - "0x8c122bea78deee98f00a86184ded61c10c97335bd672dadddc8224a1da21a325e221f8a7cfd4e723608ebcd85a2f19fe", - "0x87a51e0011dd0488009baac9c611fbde01878f9cf1584ea407599742bb32ef10586d9040dae3e9800a125de54f80c047", - "0x98181e9291622f3f3f72937c3828cee9a1661ca522250dfbbe1c39cda23b23be5b6e970faf400c6c7f15c9ca1d563868", - "0xb01a30d439def99e676c097e5f4b2aa249aa4d184eaace81819a698cb37d33f5a24089339916ee0acb539f0e62936d83", - "0x830e70476c6093d8b9c621ddf0468a7890942589cae744300416639a8b3bc59a57a7e1150b8207b6ab83dafcc5b65d3c", - "0x83ca733849830cb8fc2ef469e7e464fd94def561ce49ff0aa352a6ecd0e52c7aefcd69ab59f3d1ed2d5b8536d0a7895d", - "0xb76cb8cb446eb3cb4f682a5cd884f6c93086a8bf626c5b5c557a06499de9c13315618d48a0c5693512a3dc143a799c07", - "0x8b027c14affe47f83ee59b504d83b2fd2d9303de2c03ee59d169bb199d9f4bd6533d7f8c812dd7a6f1e8155e3e185689", - "0x8e6b888197010ebadd216da35b9716daa8675d93b3c33a96a19fd9ca42624f6b430b2ff115cd0f5b717341605dda24bf", - "0xb6652440bd01316523feefceb460158cd9ba268dd8dbe860a0271f0176230f057767597e4197885ba907318ca202ba06", - "0xa0b3dff15982a38a2f56d8c6cfc5c5543c045bf2db24571d23387ccab42abe2756f34d5f0bf6a426bbad3c358b8bdb00", - "0xa8b593de2c6c90392325b2d7a6cb3f54ec441b33ed584076cc9da4ec6012e3aaf02cec64cc1fd222df32bf1c452cc024", - "0x96b478b1e5e49d4ea3fd97c4846ae0f781dcc9f9ff61ee022ca92c3d8dfba89c513c46e8bb38b73e6b678a79b9b12177", - "0x946d585d7aa452d37a8c89d404757c3cce2adf2410e18613483c19199abd88f7a12e206f87a43f6009e42f4e31ed20c0", - "0x8c432e044af778fb5e5e5677dbd29cd52d6574a66b09b0cd6e2a5812e71c91559c3f257587bfc557b4b072a822973a60", - "0xad2cdae4ce412c92c6d0e6d7401639eecb9e31de949b5e6c09941aeafb89753a00ea1eb79fa70b54699acbfa31eda6b7", - "0xb504cb87a024fd71b7ee7bed2833115567461d1ae8902cccd26809005c4a56078617ec5d3fa5b29a1c5954adc3867a26", - "0xb8876bda1e709ab16e1347a1107852a7898a334a84af978de39920790b4d82eb0739cbfc34da1c7154dd6e9f7674759c", - "0x973dcf44ab60f55f5d10a8753ea16db9faedd839466a130729538f3a0724f00f74b3ca1de16987d7c6e24e9467f62bc7", - "0x94df5fe87661101a89b49091a3d4de89331cdbd88531ebb08a95f2629886ee53b3dcbcc26bb6bc68b443303d8d397141", - "0xa92beb343caf6a945990adcf84302c55d1fccdef96c34a21f2c00d3e206a9b2c6c6b412f66e5d4fafe26ef6446cde705", - "0xb298aa927713c86adfe0de1a8d6f4083b718c8be27156da9fd11abd8edb3a54a926ad487801eb39cfc9363a0a3be0d44", - "0xb34d4d2e15079e7e80fdba30cddf4fc0e6c9a61f7ab06a6ea0a4e55fd5bf632c6d72e021d6264d935439d321de883bb6", - "0xb4a86fb5b0049718caead1bc036833a2caeb88e1afadbbbcb0cd021d95e1f33fcc916f0b97fc1b9226c37050e3463796", - "0xb6cec65e5268818c82c0a4a029b02f8d23de98b68730a445119fee670118eb34027c23c987fac950f9b0151631328a4e", - "0x880b4ef2b278e1b2cccf36a3b5b7fbce94f106ed9fa2820cb9099a7a540a57e9fdeef5c0fb0a743049828fc2b8c46163", - "0xab2053c376c6bd113b89fdb2ae3b8401aa891135345885730c61cac7813f69ea7d906c531be752e28657f73af92d1f4e", - "0x8fa2d7b22af8e6b82679ebdfa13efdcb34289a554653ea6c1b16efb9f957f7fe64df787e7b03d8cdc8a732b91c916bd1", - "0x8e825c03c8409a3302266dc5f47fbfc381dfbafbadc37bd8d40f079ca8963d4c5ae6ef0d0ba6aef2d4688736f5f6bb45", - "0xa40ef3d2291d8782540961ce285054678b3d322d3cf7fc154207228c290708b1abfc37a4d7762dab3dfea582a112444a", - "0x8dbe8fcbcc414eb352245c52549973f73d987012de9d5f2b2f55dfdc43cf8cc9ea6b147abf149817f80f9e15aea566c6", - "0xa7e8775e04214e3b9898ffb9625dc8bcd1b683e333acdceddb8ca6db241df08a7b80e9d476a711b8b7d66aefca81e9cd", - "0x8b6ed54668f78a4a7624683b9bf3abf2bb0b6dccffccd8c0967df6297dadaf51732800fb9832b069437a6bf82ed7e6ae", - "0x9437ce85146202d3815df7f341a182678665dfb74b96006dc9d6acc16110d00b4a02717b702a765566457710ff5a7280", - "0x86a790072efa2cafa97be4b6b31f8c533f3b20cf3922fc0285fd403da436e4c49c65c5f08d77bfe823526c67bb58fab6", - "0x8ee8873de7cd28a54ba2c63a80b63399effed76b154e96ed26e7c0668b9f2476e298688b6a00c4b2ab9d020a897695d7", - "0x975c3261f0f32d59473e588f89593be38f5694cfa09394a861e4330b7800fb2528ea832106a928c54c76a303d49140e2", - "0xb5222582ed6604b9856a48039bd643340f4bf1bf0fc805e8453a9eb7630d6cea1452d28536706d6fa3ec16617617991c", - "0xb75c28941ee3f91b3535b4eaa0fb17b59ca65b5256601a1f6d0cf2bb4d66837fd16e51d6942856679012a5730a66e519", - "0x97b510f9f46bdf77a002b2403d8e42b6d6ad5329ea080940844429763ad3efd592652789c8d3d4fac0903c705f533cf7", - "0xa3fd9d8bbdc98394883022299fd9793e0c4f374d8e40d6ce89b2869d3173cb6a5476371d6095dad068ff217729f60af4", - "0xa57d5de556853484b1d88808d2529450238bc467376ded84cfd7b4a1ba258f6d43b5958220f962c57b033abcef1d5158", - "0x8465bd8be9bd9c2c6116d4ae44ec6618c109cb9aaee2d241e7a6ed906d398ef15a6fc18bc8b1d3398184241405954bba", - "0xab1cc44983e46a6ea2430aa6616ab28614f43624665e3e6ae31a9357c0c5434f34e56c720906e184327693cc4ebe1fa2", - "0xaafe14dd3b680f096010788226d8413ca628feedad79a2bc78cb04d47c6ad910f7f46ca87b8f8281744625d8f42d5eea", - "0x86a533b02ae929f67c301649a2d58651b98cdffe731b63fa32aa1013c271634bbb088c0d02865913c11bbb1bf57c0e12", - "0xb28df3e04bde4ec373171401dbd0546f4cb6fa8e9a4a8019aadc653d4e05e0b5b9a64417715dd87f6df9e7b3145f6659", - "0xac63fc758c1a3bc5cbff0f5e0b5a07a5aa801363b129d4e0360165c7dc1057ec37b0d808e9fd6b179e2c1e66bbc6090e", - "0x93f941b4fe6c05621e7a651b87669eefd60b6e8a4a8e630a51fa3fee27417b9eebce39f80a5bade9ca779133ad8388f6", - "0x96d7a69eaf2761bf0e5ebcd607b134d5dedba8e262ca1d6d3e8fbf23e6419a8ce1bbe4cd23b9e4b5f80db54a802a9795", - "0x8b62902fb2855300580e94830a4bc825d997ede33bf356fe3b7c08d6a8bd85a37879433fc6bee58f9b44ca280f4e8dfd", - "0xb043156fcd02b75dbe940c763fa8e8a7c7f6d74c1d5395db5ce544af3b6097eab61686950535a810aa95889ced12f74d", - "0x8614a7599c8d97aa9ca63b876f677977cf0daa969ff2a9a153f297a4a46e08fa5d91492995de94dc32cf009ce6bb5b5f", - "0x81351fd284d6d07092875f366bc5e53bfd7944b81eece85eab71a00443d1d2a9fc0337aaf34c980f6778dd211caa9f64", - "0x8c722aaf5d5dad1845056bf5e56dbff0f8b501f4846610f99da01130a49c96db9962bfd9be20670658cf276cc308be08", - "0x8effe3fb27c9f76bbd78687b743b52e6f3330eddc81bc9006ca81fd640f149d73630af578694f4530833c2151522dcc1", - "0xa3d327f48eb34998a3b19a745bca3fade6a71360022c9180efb60d5a6f4126c3f4dfa498f45b9a626ca567fdd66ffbff", - "0xa59a59db246f981e9c8e54aba52898c714d9787fef8969a6d8677fe6dec82950ff22a1364393b579f3e596cdf5bcd7b1", - "0xa15ebe9ab6de62a4d1ff30b7fc58acfb14ea54d7fa513cbcb045af3070db22bf9c1e987fa26c0c54356b9e38fa412626", - "0xb58396bce7d32ba6c70adbd37156d859e153c1932d2b0c7c874a1182ba831439e80d6fc6d7d88a870e193f515aef2264", - "0xb666dae42ea858c9b7d903ea3ca5279f619c71ac6e3fda7469e2bbba08c7e8e12d6a3c35ff2c6383673b1b7c21db5e0e", - "0x8eaaa21c8955f15bbcfd5756421a045e7b4825576379cc6229fe9751f7a7738b90be19ba52261db01c1e13af955675b0", - "0x8027bc62b59f9f15613e38da74ccc71fc3eaee26f096d187c613068195ce6eb64176013f2d86b00c4b0b6a7c11b9a9e5", - "0x8275eb1a7356f403d4e67a5a70d49e0e1ad13f368ab12527f8a84e71944f71dd0d725352157dbf09732160ec99f7b3b0", - "0xb8c41c09c228da62a548e49cfa107630166ac5c1469abf6d8aab55938ed1d142d5ddbc4f1043eed9496e9002cac99945", - "0x912750d2f1b21756662a400236f797b8ba76c73e5af95941a8c6ef9427838c4826715c80942cf8cb7ed01566bc490754", - "0x862af7dbb38ad7293a4e598cb52a8ac84dacee3d9bf007b5cb6a18a1acead0aa33f6dba796ce630e632c97aeb7100d68", - "0x890def696fc04bbb9e9ed87a2a4965b896a9ae127bc0e1cc515549b88ddbcbc02647e983561cab691f7d25cf7c7eb254", - "0xb835ffaf54c8b878d3c4262ca2bf5e6be2c691adced622b35d998ed72e1467ba907f4fde8d64ce43b43a8196f48e55db", - "0xa6d7e65bf9f889532090ae4f9067bb63f15b21f05f22c2540ff1bb5b0b5d98f205e150b1b1690e9aa13d0dee37222143", - "0x8ebfbcaccddd2489c4a29a374a2babc26987c3312607eadb2c4b0a53a17de97107c54eab34def09144b3098c082c286b", - "0x900b9972180a2c8753f5ff49fdd2cfe18c700d9927b3c3e16deb6376ad6ee665c698be72d4837b94911a0b4c183cb140", - "0xaa9679c01ecf1f1452c54688e01cb25bf157bde6b09b1ed460b8c175d65eba439c7ad4b7c1d72415f5622f3fbc068dc8", - "0x887a4277ee8754733f3692a90416eeac1ebee52ff23173a827f0ba569bd84efd806eb9139049f66cc577e370d3f0962d", - "0x951b27456e2af80436608aadec54ebd03bda37fa58452631da63bc5ff3eecb5ffb73d356b19f6c9c4225fcb0da8fda20", - "0x9104b5af82dbca914370eadb5518b26bee7ed7edeca74b741585ba8b249204e2c998bd47a02cef4335e236f8efafef94", - "0x8757e9a6a2dac742ab66011c53fa76edb5ebc3c2fbd9a7265529a3e5608b5c24b4482fed095725e9b8fed5a8319c17a4", - "0xa7acf82999de75f231fd80770bcb0f4c720d6b1e4a2558fa1ce854382fda92beb89fea5b5d229dad85fafee7a9e98329", - "0x8fb74891a8642f25a55b5eda5818367aac2fdf9663ad1e3dbc0166b484c0cda581b243cc75131167f1afa9caaf6705a0", - "0x897d7a19b70dcef1af006df3365981d73068c81f18017f32fb9966599481496efd5f6caceef943b31c52750c46d9590d", - "0x87ac804ccfe7f1fa156b8666664a397236832569f8945e11d4688a9e43ada4d4104efb3fda750f48ef655a29357c5e7d", - "0xaf18cf1e3d094b4d8423da072f98b3023d296f6a1f2a35d500f02bde522bb81dc65e9741c5bc74f7d5613bd78ce6bc03", - "0x9752561179783f336937757b619b2fdcb9dfce05aa3c4fce6d582dc966182eb85ab4ccb63e7e1736a7c5fad9d33cccd2", - "0x89e19b665ce7f6617884afaf854e88bb7b501ecdd195a5662c79802d721f5340eca8c48341ad1d6c78f519f82e5a9836", - "0x94402d05dbe02a7505da715c5b26438880d086e3130dce7d6c59a9cca1943fe88c44771619303ec71736774b3cc5b1f6", - "0xa76adeddf2454d131c91d5e2e3a464ef5d3c40ee6a2ab95e70ef2e49e0920d24f9b09276250ed7b29851affbdbc7885a", - "0x8934e9a3feababa12ed142daa30e91bd6d28b432d182ac625501fe1dc82f973c67f0fe82d39c9b1da3613bb8bfe2f77b", - "0xa5c11337eb91ce0e9b6d61bbdadea0a063beee1bc471cc02dc1d81c5dd2095315c400cbc6c33d23c77e98bba6bdf5439", - "0x92d00e64ed711951aeb852908aeb6fd379ea516872dd512384b1e773ef078e52e6d618beb202d437d2a46bcb78087f7a", - "0x97f1a7370b4f5acf83b466f519da361c366915f560385dd7eff9d53700ad81b25c9862bc71d35428e82372a5ae555ea0", - "0x95614544f65808f096c8297d7cf45b274fc9b2b1bd63f8c3a95d84393f1d0784d18cacb59a7ddd2caf2764b675fba272", - "0x8d474636a638e7b398566a39b3f939a314f1cf88e64d81db0f556ca60951ec1dca1b93e3906a6654ed9ba06f2c31d4ea", - "0xb87e5f481b938ac8a481b775cc58be2a06604549e3c810fc4734bab76099e5c617f0243c4c140cb7dd6d36a6dc2286bf", - "0x806efb61d1c948efc10dbf9bef30197d1c269e5e7fcf20a84367b26223d33fade413a0bbf4e33f0d1f1a00967289015e", - "0x880b99e77a6efb26c0a69583abb8e1e09a5307ac037962ddf752407cacaf8f46b5a67faf9126bdbcb9b75abf854f1c89", - "0x82ffe4de0e474109c9d99ad861f90afd33c99eae86ea7930551be40f08f0a6b44cad094cdfc9ed7dd165065b390579d0", - "0x941cd102228aa81ef99506313a4492a17c506e7169808c6b14dd330164e9e8b71b757cbe6e1bb02184372a8c26f7ad1f", - "0xae96dc808c316a677977831bad1e529ef965dadb5d6aea25ab008fe7bb1543e596e33052cfbe4279fa060201199d2c34", - "0xa2053719da2b7501dab42011ae144b3c8d72bd17493181bf3ae79a678068dc3ee2f19d29a60b5a323692c3f684f96392", - "0xb17171939519d90e243d41839c3c5ce7ac7e6a978e4a7e56b2c8e6a2b1b587c7eacea47f2e31a55d88555d252c810ebd", - "0xa958987c2b3c84df8176b600f5b75a8badef9653c71eff967e76648937def38826eaab4027a639f4f300b20019166250", - "0x854aafa329e2b2563355641eba95f2aba5b33d443ab16f5e342048f97d97c4e2812ff27c6f4180b8110272f3151be690", - "0x94d4a1e3a3d28a948f14d1507372701ac6fc884a4905405a63663e170831578a2719714ef56f920baa0ca27954823e39", - "0x826be957cf66db958028fa95655b54b2337f78fb6ef26bd29e2e3a64b130b90521333f31d132c04779e4b23a6b6cd951", - "0x8261f7e644b929d18197b3a5dcbba5897e03dea3f6270a7218119bd6ec3955591f369b693daff58133b62a07f4031394", - "0x84926cf2265981e5531d90d8f2da1041cb73bdb1a7e11eb8ab21dbe94fefad5bbd674f6cafbcaa597480567edf0b2029", - "0x8fb51e3ef3c1047ae7c527dc24dc8824b2655faff2c4c78da1fcedde48b531d19abaf517363bf30605a87336b8642073", - "0x8ba45888012549a343983c43cea12a0c268d2f7884fcf563d98e8c0e08686064a9231ae83680f225e46d021a4e7959bb", - "0x973ab82026d360e2cf5676d883906186bc61b43f60767ca58f11d0995e40780b163961e6e096299ccf1c86175203abde", - "0xb77416ea9a6b819e63ae427057d5741788bd6301b02d180083c7aa662200f5ebed14a486efae63c3de81572fe0d92a9c", - "0x820cc2ac3eed5bce7dc72df2aa3214e71690b91445d8bb1634c0488a671e3669028efbe1eae52f7132bde29b16a020b7", - "0xa6b434ac201b511dceeed63b731111d2b985934884f07d65c9d7642075b581604e8a66afc7164fbc0eb556282e8d83d2", - "0xb81821a79c9148b41d24d85dc997336a1e1719da0e31e42af30812b97a5af31708ca3e7bc2e803c3751cff23af5c509d", - "0xa013cc5e3fbb47951637426581c1d72764556798f93e413e1317849efd60f3ecb64c762f92544201eb5d6cfb68233050", - "0xb5f32034d0f66bcbccefe2a177a60f31132d98c0899aa1ffff5ebf807546ff3104103077b1435fa6587bfe3e67ac0266", - "0x86ca8ed7c475d33455fae4242b05b1b3576e6ec05ac512ca7d3f9c8d44376e909c734c25cd0e33f0f6b4857d40452024", - "0xb781956110d24e4510a8b5500b71529f8635aa419a009d314898e8c572a4f923ba643ae94bdfdf9224509177aa8e6b73", - "0xa3f9dcc48290883d233100b69404b0b05cf34df5f6e6f6833a17cc7b23a2612b85c39df03c1e6e3cd380f259402c6120", - "0xa104d4bad69f1720307ed12363d1ec97952acfe09d9e3650034c33f3f20c763271ebe0d5b50b1d3bd15c469f4573b09d", - "0x94bbc6b2742d21eff4fae77c720313015dd4bbcc5add8146bf1c4b89e32f6f5df46ca770e1f385fdd29dc5c7b9653361", - "0x951aa38464912a29df2101c60771d6de7fadb63f2db3f13527f8bdacb66e9e8a97aaac7b81b19e3d1025b54e2c8facff", - "0x919b5187af7dae210f151dc64a9cbd396d1ae04acadebf542a7123004efc7ce00d6e14c170d876fbc64dc1b5d141a5f4", - "0x88e1e459ee5aeb8b36ed004f6d03da296101106fbe1b18f9bbf63e92321db51670c34050fd3b7dc56a4bad76403823ee", - "0x86b3ec14a8ffb811a0ecc3771f600d8b08c098537d100fba66def19e7ee4d1c397a311977bf37e6cd2d47a8a2ee8c223", - "0x898c4873bd356ba8015f6f686d57088fa8f79f38a187a0ef177a6a5f2bc470f263454ee63d0863b62fca37e5a0292987", - "0xb471c72bd2971353f4b44248b8e6cf5316812861a88ccfc20fd0d89a5e010428c387228b2f6f14c12f79e31afc9d0753", - "0x8b7cb5b8de09a6dfceddcbaa498bc65f86297bcf95d107880c08854ed2289441a67721340285cfe1749c62e8ef0f3c58", - "0x983cb6bbfe83bce8326e699e83fca01ea2958c09808c703cac97a0ea777e5a5f3f5bba9169a47732de7459a3c7af47d2", - "0x8235a3f09078dd34ce2fc17cc625e061298713b113dda12d354b3d2ba80e11c443b1dd59c9eb5a29513a909645ae97d4", - "0x8bb51b380a8a52d61a94e7b382ff6ce601260fa9b8c5d616764a3df719b382ec43aec9266444a16951e102d8b1fb2f38", - "0x9579973ee2559da09b327c62b1cc0177f2859872885dca709e24dcfbb9bdf9224a6d26869aafce498f44c0e6bd8a996c", - "0x842ba3c847c99532bf3a9339380e84839326d39d404f9c2994821eaf265185c1ac87d3dc04a7f851df4961e540330323", - "0x99dad12f78e1a554f2163afc50aa26ee2a3067fc30f9c2382975d7da40c738313eaae7adbc2521f34c1c708f3a7475b7", - "0xb96e3ff8bdae47aa13067c29318b1e96a7fe3941869c17ce6662183b7b064bf261e1cea03e2a4643c993728a2606b5b5", - "0x955bc897171aa65d0159aa6e5d51855833f83d8bd5e65f93ad26c27781171783f3988a12bf987472edb39994bd071ea5", - "0xa59249e4dfb674dfdc648ae00b4226f85f8374076ecfccb43dfde2b9b299bb880943181e8b908ddeba2411843e288085", - "0xac2955c1d48354e1f95f1b36e085b9ea9829e8de4f2a3e2418a403cb1286e2599ba00a6b82609dd489eda370218dcf4c", - "0xb2eedff11e346518fa54e161be1d45db77136b724d497e337a55edfc896417de3a180bf90dd5f9d92c19db48e8574760", - "0x976eb5543e043b88d87fda18634470911dfe0e0cabab874ca38c1009e64d43026d9637d39dcd777bc7f809bbfc3e2110", - "0x8ea5f88a79f4eb9e7c0b6b29f8ef2d1cc4c15ed0ed798ab11a13d28b17ab99278d16cd59c3fa8217776c6dfae3aedf88", - "0xb7f146a357e02a63cd79ca47bf93998b193ce1174446953f12fa751f85dc2a54c9ed00c01a9308509152b3bad21d7230", - "0x87fd7e26a0749350ebdcd7c5d30e4b969a76bda530c831262fc98b36be932a4d025310f695d5b210ead89ee70eb7e53b", - "0xb9445bafb56298082c43ccbdabac4b0bf5c2f0a60a3f9e65916af4108d773d62ffc898a35b0b8efb72ea846e214faa02", - "0xb106c6d13ca17a4c8ea599306e84918127cf2de21027ac3fe5a57d35cf6f3b1d7671c70b866f6e02168ae4e7adb56860", - "0x9276e8051bed8f5dbfc6b35765aac577dd9351d9d6ac1bb14496bd98091005b9a4737b213e347336413743f681f5043b", - "0xaefc682f8784b18d36202a069269be7dba8ab67ae3543838e6d473fbc5713d103abcc8da1729a288503b786baac182d3", - "0x97578474be98726192cb0eac3cb9195a54c7315e9c619d5c44c56b3f98671636c383416f73605d4ea7ca9fbeff8dd699", - "0x99c34f9bd0fcb18b3d931e562988cf91886a417f8678f22651bf3cf138df2bbec3f675de90f62dda769e0eda03d72b7e", - "0xa0047e03c89a95248543618e6b7ca2c7aad7acda3c9f85771ec5c93fa898c651e8b2ea3b6b799d8cd592290a986cdd7d", - "0x993726e0b1c2277b97b83c80192e14b67977bf21b6ebcde2bda30261aa1897251cd2e277cfcb6193517f1eb156d2fe86", - "0x974a5180e55eab23d4c973fbee6ad1010335161ecdb849fe6520b34c1f96530a4faff80bd738fe281019b79d968c472c", - "0x8f1d90034f998018c3f4b5947b40b139fcead2e40aa80fdec6a4337c60e9d5ff1923dda7f0b5b1731ff16f55027d41bf", - "0xa7d9ae9621dd1f3da3cd2d435e891cc3579c4c0d60d6a4565cac86c315cea21a9ad883559fe7b897ae6e05f1aa989ad9", - "0x800f6be579b31ea950a50be65f7de8f678b23b7466579c01ac26ebf9c19599fb2b446da40ad4fc92c6109fcd6793303f", - "0x86fa3d4b60e8282827115c50b1b49b29a371b52aa9c9b8f83cd5268b535859f86e1a60aade6bf4f52e234777bea30bda", - "0xa80ac2a197002879ef4db6e2b1e1b9c239e4f6c0f0abf1cc9b9b7bf3da7e078a21893c01eaaab236a7e8618ac146b4a6", - "0xb4bf70468eff528bf8815a8d07080a7e98d1b03da1b499573e0dbbd9846408654535657062e7a87a54773d5493fc5079", - "0xae0e15a09238508b769de83b30582cc224b31cd854d04fdb7b8008d5d8d936dbdd3f4a70fff560a8be634c141772561b", - "0x936f7e20c96b97548fef667aa9fa9e6cfdc578f392774586abe124e7afc36be3a484735e88cc0d6de6d69cf4548b1227", - "0x8163eea18eacc062e71bb9f7406c58ebe1ce42a8b93656077dd781c2772e37775fe20e8d5b980dd52fdad98b72f10b71", - "0x86a6560763e95ba0b4c3aa16efd240b1873813386871681d075266511063b2f5077779a4fe49ffc35e1f320b613b8c94", - "0xb156d9d22722bb6e3b75b3b885b64642fa510ba7e6057657cd61bac43fb9c284d05bb09e2d4b78a2a4ddada85da9c702", - "0x9779ca2759dbed8081f0cbbfffcb3b842ba335e3ae48a60c5e5c77c7a2a0623e4c415ec3a023cc4e216885fcbac3ce52", - "0xb8137fd57ce7d3cfaf8bdbaa28704734d567d0e7a2d87fb84716722c524bb93acb2c1284249027f3c87bccc264c01f4e", - "0x8cf06b34e7021e9401eb705dde411ecf7e7e7185f8c0b0aeed949097df31812a9fdd4db7d18f9383a8a5a8d2d58fa176", - "0x8c65aa29a9ee9066b81cf24cf9e0beca3e8e8926e3df22d5ff1236297e158cc8bc7970a2c7016009cc4efa8f14b14347", - "0xac7e49f2059e99ff65505742978f8d61a03f73f40141a2bd46fde5a2346f36ce5366e01ed7f0b7e807a5ce0730e9eaa9", - "0xa1c25eb9b73723982be78180770aa63c5f7b23c2e54a2ed7e75a860c4512d273008066f1124ac8a43c60fe1e2a8bf03c", - "0x9310722e360a5652737362f6b9cb6e9c3969a0c9bb79b488b3c7d19d9e8c42ebd841df346258ded2e393895c99b413cf", - "0x893272a63650b08e5b8f9b3f17f8547b456192ad649c168bafd7166b4c08c5adf795c508b88fd2425f7be8334592afb2", - "0xb576c49c2a7b7c3445bbf9ba8eac10e685cc3760d6819de43b7d1e20769772bcab9f557df96f28fd24409ac8c84d05c4", - "0xaf17532b35bcb373ce1deebce1c84abe34f88a412082b97795b0c73570cb6b88ea4ba52e7f5eb5ca181277cdba7a2d6d", - "0x8b8813bd2c07001a4d745cd6d9491bc2c4a9177512459a75dc2a0fa989680d173de638f76f887de3303a266b1ede9480", - "0xab73a043ccdfe63437a339e6ee96ef1241264e04dd4d917f6d6bc99396006de54e1e156d38596ba3d15cb1aaa329f8f5", - "0xb67146b202afec0132ac0070c005cf664081e860339f8f4d45ac3e630dda05560936e646673e652d08cecd8d18fc64da", - "0xa750404e9d4b1a48f767d2b6aa699200c92c3b8102597f8c5c1dbaaf08112a0587c05801dfebb3612fb6dfd76ddc9ccb", - "0xb0d4231814e40e53ab4eed8333d418a6e2e4bd3910148b610dec5f91961df1ad63f4661d533137a503d809ea1ad576fa", - "0x81fc724846b5781f3736795c32b217458bb29972af36cc4483dd98ab91680d3d9bc18842db2661487d3a85430dc9e326", - "0xa5cf6f4fd67aecb845eebc8d7304c98c69806d774d4c468350f7f82ff0f5baeecc56837705e39432a8d246aa2a7075ed", - "0xa71d2c8374776f773bad4de6edfc5f3ff1ea41f06eb807787d3fba5b1f0f741aae63503dbca533e7d4d7d46ab8e4988a", - "0x825359cfe68ad6a75578a94be6419179e0aa088170b6c20fc5c249dc3be7a260d687c93d8d8a343c7c72c2ed6a716de3", - "0xb6aeb7a9b934a54e811921494f271d5d717924c561cd7a23ab3ef3dd3e86184d211c53c418f0746cdb3a12a26a334fc8", - "0x8c6fc89428c74f0c025e980c5a1e576deadf8685f57136e50600175fa2d19389c853d532bb45a3e22b4a879fab1fcb0d", - "0xae95ddcf3db88f6b107dcf5d8aa907b2035e0250f7d664027656146395a794349d08a6a306ce7317b728ca83f70f3eaf", - "0x8c03fb67dd8c11034bd03c74a53a3d55a75a5752ea390bd2e7f74090bf30c271541b83c984d495871d32c98018088939", - "0xb8d68610fdee190ec5a1f4be4c4f750b00ad78d3e9c96b576c6913eab9e7a81e1d6d6a675ee3c6efac5d02ed4b3c093a", - "0x87d4b20bbe2dcd4f65f4e1087f58532d5140b39a5288e1a63fc0b7e97a6a56946eafdd90ba09300c3d1fef6356ac6b7c", - "0x83e264b1d3d4622826ab98d06f28bbbd03014cc55a41aaf3f2a30eec50430877d62b28c9d6d4be98cb83e1e20f3b13db", - "0x97ffcbf88b668cde86b2839c7f14d19cb7f634a4cf05d977e65f3cd0e8051b2670e521ae74edc572d88201cff225e38a", - "0x91efdbcaad9931312d7c41d24de977f94d7f3f7b88090a1f72d9a097a1e30cc805c5ea16180f463022d9b26b8863f958", - "0xa4b507a4bc2bc424297bf8968bf385fae3acc686cff4b7933b4f5b6ef3149995393d5331dbac4b629e8adce01a91a4cc", - "0xa76a26c30d8abbbd4bf982bb8bd2066a2ec823a5eb6fbe37c664e67efbe2f72d8ce2d00223b900699149f8441bff5ada", - "0xb3a5497365bd40a81202b8a94a5e28a8a039cc2e639d73de289294cbda2c0e987c1f9468daba09ea4390f8e4e806f3c8", - "0xa09b2a07d861e01645accfb088f7f9ad524186bd439712775459a60f8a1fbbd43ee084e4d6e23ffce06daa189cd1e654", - "0xa41cf5d678a007044005d62f5368b55958b733e3fdde302ba699842b1c4ecc000036eda22174a8e0c6d3e7ef93663659", - "0xa698b04227e8593a6fed6a1f6f6d1eafe186b9e73f87e42e7997f264d97225165c3f76e929a3c562ec93ee2babe953ed", - "0x8bc66e370296649989a27117c17fbc705d5ac2bda37c5dad0e4990d44fcc40d3e1872945f8b11195538af97961b5c496", - "0x8bff10f91b8c0abb6c9542588da17fa0118ffda4c82626a754887e333d7d69661b3ae4e400da15c49565f8d10a77d0d7", - "0xac715c7b3d794860a61d9c7bd224a2b14a6023f696afa30345aad2ce0a6ea6dbc142f34af1ffe7f783542851a28e8ece", - "0x91c5e0b9146fe5403fcc309b8c0eede5933b0ab1de71ab02fac6614753caac5d1097369bdeed3a101f62bbcae258e927", - "0x8553748da4e0b695967e843277d0f6efeb8ba24b44aa9fa3230f4b731caec6ed5e87d3a2fcd31d8ee206e2e4414d6cf4", - "0xac722bd742374f925185ea7d4d62d7510b2d8a6ebf5c750af6ce83e2d8a28c95a3e298870ec8254ab2d1d0aa2a063c60", - "0xb083c4cefb555576bb37b71f30532822cb4b1e1998e35cb00ffb80ca14e2853193c16a6756417853d4a74d625744dd76", - "0x85745bd84c92ddfc55df11fe134cf70e3c340aa1c7cdd6188a03308cf3a840f4f19629f9730b2e6426424989ff03000d", - "0x845b4531dee808b583645f56fa98cbdecce3ea100db60524b64f68e29866173791f01137714f4dc7fb8612f7f7943263", - "0x93f03495d53c781be8b76e37e68b64aa260523004eff6455ddc8a8552af39854e5181f8c5365812b1f65926534fba5dd", - "0x801c126abff96fe9b042be8869d2907d0c6963a79901f9db46577a445418b7465a1f4b346933d433e539536a9a2df01c", - "0x952cf6782b0ad3e85625391cc5f486a16bb5b1f8ea20defcb6857bd7d068dcd2701bc7ed5c3b773a869180d9042f772b", - "0xb3b6eccb2ec8509b4eea8392877887180841ab5794c512b2447be5df7165466d7e293696deaabf063173e5f2238ce763", - "0xb63fd45023f850985813a3f54eceaccb523d98d4c2ba77310a21f396e19a47c4f655f906783b4891de32b61a05dc7933", - "0xa113b889be5dcc859a7f50421614a51516b3aadc60489a8c52f668e035c59d61640da74ba1a608856db4ff1fa1fe2dfd", - "0x87fec026beda4217b0a2014a2e86f5920e6113b54ac79ab727da2666f57ff8a9bc3a21b327ad7e091a07720a30c507c9", - "0xa3ee8fd53158dad3b6d9757033abf2f3d1d78a4da4022643920c233711ff5378ac4a94eadcaf0416fdcca525391d0c64", - "0x8d6bed5f6b3f47b1428f00c306df550784cd24212ebac7e6384a0b1226ab50129c0341d0a10d990bd59b229869e7665a", - "0xb549cef11bf7c8bcf4bb11e5cdf5a289fc4bf145826e96a446fb4c729a2c839a4d8d38629cc599eda7efa05f3cf3425b", - "0x982691766a549df56436acd0fe76da78132e027515f27174c10d117bfcc20ed73fc31f5465bd7a22a101094fe913e221", - "0x985af1d441b93fa2a86c86b6d7b70b16973d3971e4e89e093b65f0ae626d702202336869af8e3af3923e287547d5384b", - "0x994b7baecc8bb68d270a3a88c58e4054afdbd713b4472f9522b27c1762c637ef8f013d745ce9d1dc8fc4d986d4c9338c", - "0x827dabda84c7f7b1adc0f5ca0fccf0729e9d7f78e1ffa7c5e9c4f66610ff0ab776c880b00c77137cf7abe14df977febc", - "0xacd17cba1203748b55bd9d7b940a16bb7c02988c93007a80b87e0bdb049b91f5ecce577e3e4ea68a0abe998a72cd300d", - "0x989fa046d04b41fc95a04dabb7ab8b64e84afaa85c0aa49e1c6878d7b2814094402d62ae42dfbf3ac72e6770ee0926a8", - "0x99dc48a054f448792523dcdeec819e1b928b1bd66f60f457261f0554f8532eedd7152792df70ae5316ab2f9c02a57cdc", - "0xab33c65587ecb3278325948c706aed26547e47ed2b4bc027e9119bb37bec67ddf5489fbc30304ef6c80699c10662d392", - "0xae89e41d8cfbf26057a4078f8a5146978e658801b08814190cbce017d79beaeb71558231a72bde726fa592fb0828c01c", - "0xa9901df92e2d3abbb25f3bf4b913692c4cd57da327b01c8ee2362c02fbefcf66cdb792c17a81dcbde3c9b9dba313e4a1", - "0x8ee41011424da5e2ecea941cbf069ea32420749f2519434d3d8f9725ac789753404687a6745cffe4bd5dfc8fec71a719", - "0x8cfcdfa192b17321be4e447204e1a49ecaadca70a3b5dd96b0c70ab64d1a927d1f8c11a7e596367e5fa34e2307af86fc", - "0xb8a0003e949cf994b1bb25e270cb61358200c93b1c6f611a041cf8536e2e0de59342453c5a8d13c6d4cc95ed8ce058f3", - "0xadc806dfa5fbf8ce659aab56fe6cfe0b9162ddd5874b6dcf6d658bd2a626379baeb7df80d765846fa16ad6aad0320540", - "0xa83b036b01e12cadd7260b00a750093388666aff6d9b639e2ce7dfc771504ef8b2090da28ec4613988f2ec553d1d749e", - "0x825aca3d3dfa1d0b914e59fc3eeab6afcc5dc7e30fccd4879c592da4ea9a4e8a7a1057fc5b3faab12086e587126aa443", - "0x845a4a09941f48677e6c03699770f9a56ba72695089e432a6f232294dd8da6d34e394116a9a87f3b0902c78332af9439", - "0xb2f168afc35ed9b308ab86c8c4aaf1dcd6833ce09153bb5e124dad198b006e86a941832d387b1bd34b63c261c6b88678", - "0xa094cca9d120d92c0e92ce740bc774a89667c6f796b438b0d98df0b7aef0935d8c915d5b0dad4b53e383dc9f095c29fa", - "0x956ecb233b3529b2d9cb80ae49e48667f2a3120e4a0d7131d1e9ec36db3a59dc2ef2a579cbb99d6f14880ca83f02b64c", - "0x906cde18b34f777027d0c64b16c94c9d8f94250449d353e94972d42c94dd4d915aa1b6c73a581da2986e09f336af9673", - "0x824c8a1399ab199498f84e4baa49ff2c905cf94d6ac176e27ec5e2c7985140dbaa9cc6303d906a07ab5d8e19adf25d8a", - "0x889a5cf9315383bf64dfe88e562d772213c256b0eed15ce27c41c3767c048afe06410d7675e5d59a2302993e7dc45d83", - "0x95791fb6b08443445b8757906f3a2b1a8414a9016b5f8059c577752b701d6dc1fe9b784bac1fa57a1446b7adfd11c868", - "0x99049e9a23c59bb5e8df27976b9e09067d66e4a248926d28171d6c3fdd1ab338944a8b428b2eaae5e491932c68711c7c", - "0x95c810431c8d4af4aa2b889f9ab3d87892c65a3df793f2bfd35df5cfdb604ca0129010fa9f8acae594700bece707d67f", - "0x841d77b358c4567396925040dffe17b3b82c6f199285ac621b2a95aa401ddb2bc6f07ebd5fa500af01f64d3bb44de2df", - "0x90c402a39cd1237c1c91ff04548d6af806663cbc57ff338ed309419c44121108d1fbe23f3166f61e4ab7502e728e31fd", - "0x968d44188e2d9d1508b0659e96d6dabd0b46aa22df8d182e977c7f59e13aa05d5da09f293f14f6f2ee1b996071cd2f25", - "0x8ae9585caa3c73e679fe9b00f2c691732f7b7ca096e22d88c475a89d4d55cb9fba3cd0fe0cedd64ce75c591211664955", - "0x94b81d5ad72efb4dd60867e71afcd8e87e1f24bf958d42fc07db66f6185a1e610987ab9ceef63109a36fe5544a0cf826", - "0x8499a8c3d67d1f6eccf1c69274393dc498cff862ea8e6c11ffb8107ae190d258ddc1d294f2a8f050488df0212063ece2", - "0x921109a390e4d7fbc94dff3228db755f71cb00df70a1d48f92d1a6352f5169025bb68bcd04d96ac72f40000cc140f863", - "0xb464d763e5ef724ab7ee13a60015df5c9a7809a79188ff6a7e0d5e5400febd42ad7330406a59704a44a08f2289d659c8", - "0x96f1a36134e0d4137a7fe8bbb354f50aaa67f28f194ae2fdbe8be3eb24596678d8c9287765ee90c1f2778d0d607931e0", - "0xb031d93b8f119211af76cfafee7c157d3759b2167ee1495d79ad5f83647d38248b4345917309ef1a10ecaa579af34760", - "0x88a7dc337d89324f025f686f37d21240c7da9a1cb802259ea8d8a83e246dcc2adceca7ca3534bc7bf8f3ae1cbeafb5c0", - "0xb30e022b8a563655074e08e123b5f96956bbf0fe221cc629c5fedd2764a66b475916ceb98867f935b4a47212e53ae9f3", - "0xab6e3180dae399d41243f23545e5e6d118844f9b8edba502a3503fd1162ed826f9fc610889a1d685d374b6c21e86067d", - "0x96cf5760c79cfc830d1d5bd6df6cfd67596bef24e22eed52cee04c290ad418add74e77965ea5748b7f0fb34ee4f43232", - "0xa5817c74a394b0359a4376ef7e9e8f7dfa6a7829602da225074fb392b715e1fd52c50cae0f128a7006f28b22f233fbf5", - "0xa50ab79cf3f6777a45f28d1b5cdad2c7ea718c60efeeb4c828d6307b29ef319445e6a9f98aa90f351c78b496575150c1", - "0x8b300dea07e73dd2f07b05d477e51f8424589f6b2fa6f461240e1322a3a7ab5bf227b74544bb5d66a297702cdbf6c6bf", - "0xb13b5cb86dc8b8fe87125f1a51fe98db36bdde4f600401408b75059a44e70b1bbfefd874e539691f3f1bf6f54db883c8", - "0x8d06205cd66703ce6776b38b98c32b27f45c7b3f65ea2d05e2b702c24d553f51c69bf0b17e8db7382475e3d370d2e8d6", - "0xa11a7496c712734aec80738e30d2bf245758b34245076149854eb209fa6403be8bb0d4e515becc881b7f3610749260c0", - "0x9615800f8c95f95bf25055ae079b964e0a64fa0176cc98da272662014f57e7cd2745929daf838df0094b9f54be18b415", - "0xb19ca6e55f349bbb2dc3e429520ff5b2e817972470794f35c1aac8c118b37a694cfcc875b6d72225343799825d2f5c39", - "0xa650864b7eb6769aaf0625c254891447351e702e40d2be34dfd25f3b5367370de354318d8935ba18db7929270455ae6a", - "0xa649208372f44f32eb1cd895de458ca1b8be782746356f08ac8ef629429d0780a0799fcff85736e19aead0b79bfff261", - "0x89461cb2dadf51d6f1208b0965c8eabec895d7b19b7d90d3c6e49dbe75a75c30fd26db3dfb169dd46a4342280225032a", - "0xb5d6f664ec92e5343792d5d6b629919c5fd8cfb874677df2264daf02bcd9d12facf9b859d5402839c9022396e20d260b", - "0xa7179d338fe5a0e4669364a364e17f8d00cb6c59a80a069afd5f4f14510df2eee90c07826553e4f7fe46d28f72b2903e", - "0x8ded37d67b5368619a090266e9b5585fbff60319a90a4244a3c3342641f5bfa5130998dd97d7a42505cd896c29255530", - "0xa3fd63e87a00b48ba46a646a26187ae6dcb16779721973ada13a545853e2e51b5e4df04630d670884ad4a2304cc60c67", - "0x92761b7e31f0c758b3b1f5b43a194b25aabec668101946eb6511132863d3afb9d18f833d43a8338d0e7bc78d8689e523", - "0xab8a8769c754008a7976b6799e81d7bfe97413d0a79b90715703c1f8f567675463ec93aabee59277121fc4df88b5c7a9", - "0xb354d0d1bd942f79002a2eaf37eb99dab650170e7040c13c824803ed7c1670dc910ccae13bbe58bde003829b140b45ea", - "0xb9eed89e003894ad2cc9d9b93a45247e1367ac69a00b0ed5e3280c1188b4cb90eb870d449b83a852a798bd02f9d0c813", - "0xb900a55013d0427e5da6b21611d6ae3e648f54f794cb099b2d2beebae0a957477a94dc415e8ec5e68e9029ce50d43843", - "0xafbf44071c2c905f7c8ef396eaed7f13deb7a91719cb5e8b9226aaceb876d81a10076383edc6216bc2f5c38a480b2957", - "0x80bdb82b7d583bf1e41653966b0ba3b4fec0e7df2ff08e3fa06fd9064bca0364263e075e1582741a5243bde786c9c32e", - "0xa841fe9ff26db21ade698f6dbfba025d90ae9f81f02af9e008fa0a429b993fb04d06acb93e40a9f81c78f73334555a17", - "0x8cd49711b42af58a5aae75a38fea9ddc5e4183c467a3159b5b0629f01ba548513c577456d34c861911e85782e52c3b1b", - "0xa322b5d2a6e3cb98b8aaa4c068e097188affef5dec2f08c3e9ce29e73687340d4e5a743a8be5f10e138f9cabbe0c7211", - "0x942772b7c7c47d4e5957ccf1d6f1450070930af3e2b7eaab0dd7699372445df0cc910e6c0efcf501887dd1adabdaee23", - "0x9834f66e5c946c3a8241ca2bbde046a7e88072124911d5d15c037a95b61e82b88b5c2058fa4a3721537dee39dee5da18", - "0xa90cc5b9c4d84f36962d0d55d5bc123dbe5ec5f4fe7b6bf0d009028b3cf14e36c11bc5365391cb4ae548d5eb04fe371b", - "0xa7c2174eea2b66b2a71cc8095fae39c423a353c7d5020ec2d0551317a66202fcf082c6119ba768755523fff49791bb4e", - "0xab92b2a177dfa55d202a653532f0e04d1339ca301aebe6a0e8419bf45be3e573b6b9ae4d3d822cc8279367a3d2c39b06", - "0x8a9ad977988eb8d98d9f549e4fd2305348a34e6874674bcd6e467c793bba6d7a2f3c20fa44aabbf7151ca53ecb1612f6", - "0xa7d1676816e81a752267d309014de1772b571b109c2901dc7c9810f45417faa18c81965c114be489ed178e54ac3687a1", - "0xa575be185551c40eb8edbdb21a0df381c801b6e99467fcf5882dd7cb34916960ce47ac732c1920ad3218f497b690cef4", - "0xb50c306f78143b37986e68efa10dbe1fb047d58562e9b5c5439b341dd8f1896c7ae586afac0a3213759784a905c1caaa", - "0xb31e89b4a034c1b73d43b3d63ea3bddea682a6a5327eff389c70b13e9e72185b0327682a0cb1ff3c4a4f8ba08b13d898" - ], - "aggregate_pubkey": "0x948a4b8d91bd29969cd4470b1bc24d34586d38e73d5be71c98a9894899471a5f708747563276b4b6d2716fdb72860267" - }, - "next_sync_committee_branch": [ - "0xcb3fea582872d90706ddc6d029bac0d791ea75d43c3ab04f056f62a11b89d27b", - "0xf26b4bb68eb7e6906c8ef4a9958398a48e4450bf9c8a462fafa4fde51cd5628f", - "0x690925f92c1d322d2ff2a5636539094825dfd2c9bf7538fe111b2358e03a71de", - "0x51d977e358166401c7cd3f6185468c1a8c69a4c3d8577535dd583bc427692e02", - "0x88d2089aaf2f6fd8f6e4ae499c6fe33cc34289eb9310780861e772204f07b670" - ] - }, - "finalized_header": { - "slot": 4055040, - "proposer_index": 854, - "parent_root": "0x8adf3b288deb17566a553fa7a06a2f63f4ac4cea4868af4d89ddca41f73ae9b9", - "state_root": "0x595e9ebaaa23f027672b4d2a33173a22b2839baac709c7f8e66d3219f492ee9f", - "body_root": "0xacf37b466d4f6b5d1db5b6ffe5d77c13972d116c2b0809de924427fd597d391a" - }, - "finality_branch": [ - "0x00ef010000000000000000000000000000000000000000000000000000000000", - "0x3d4be5d019ba15ea3ef304a83b8a067f2e79f46a3fac8069306a6c814a0a35eb", - "0xa2e2a28c0bb0ad56c25f3c461a4bfe4f3b3b894bc0105a62e85f43a4ae1adc3f", - "0x690925f92c1d322d2ff2a5636539094825dfd2c9bf7538fe111b2358e03a71de", - "0x51d977e358166401c7cd3f6185468c1a8c69a4c3d8577535dd583bc427692e02", - "0x88d2089aaf2f6fd8f6e4ae499c6fe33cc34289eb9310780861e772204f07b670" - ], - "block_roots_root": "0x7054ba439f83e9b2223911e25fad48eb28f5c362d94c0de2455a45436cc93897", - "block_roots_branch": [ - "0xc99a842c81d0b956eef988dbcd90499457d61f942375c6cbf67262909b708db5", - "0x5d32345aeb10aa3ede4be021d2231dac47cc2074f74b72466f0b042e69adf70f", - "0xb69608a2377956c1a39c3423d3399ccfb12307623c9df6358f5fcfca64a80102", - "0xcefd9b668e49ece82bd4b0ee2f1efc88ecaf0d9af464fb622735663aaf106c4c", - "0xc113ad1c971779b15c64772ab69cd775edfb926a60447974913bb6f58fbd12fb" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.minimal.json b/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.minimal.json deleted file mode 100644 index a962a0c87c4c..000000000000 --- a/bridges/snowbridge/parachain/pallets/ethereum-client/tests/fixtures/sync-committee-update.minimal.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "attested_header": { - "slot": 3600, - "proposer_index": 7, - "parent_root": "0xdf60c2d58beccd89678b9267c689e9ba1cf1d58ce5114ad5c16e8341459cfd75", - "state_root": "0x023f14c7a38ef4d6ec19b522edfb427c6b70c6ffbd8610ca802dd1491c92c852", - "body_root": "0x0f78a1c45e42711efc5fb7b7f6238be1bee9273f7c44ff6892d815858bb77e25" - }, - "sync_aggregate": { - "sync_committee_bits": "0xffffffff", - "sync_committee_signature": "0xa4dd8f0991de88ca6f81476f72f48cdb67b9414ad7bf6bba37f627c5ec84dd2c2ebc12cddd5d2e7c927276cee2d3d144158b4c067db3e9911fe52fe1875b14c93f90e4eb57bf5e8f0e6e6effe22f9ba076f30207e0ec683354961ae8e9779556" - }, - "signature_slot": 3601, - "next_sync_committee_update": { - "next_sync_committee": { - "pubkeys": [ - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c", - "0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34", - "0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac", - "0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b", - "0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b", - "0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e", - "0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e", - "0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373", - "0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c" - ], - "aggregate_pubkey": "0x8fe11476a05750c52618deb79918e2e674f56dfbf12dbce55ae4386d108e8a1e83c6326f5957e2ef19137582ce270dc6" - }, - "next_sync_committee_branch": [ - "0x1446606d0129c324a4ea374bd29a625175e0659512cd8650097e0a9c38ce6379", - "0xd92466c7e9a53b7b55f4fdb151746a3058931d7559b7e84e7b15384ddc903ca0", - "0x9fd10c3f68b75cfd3ebd2af0d4e2cbbfbe120e0b5423dde89ff0f743c7a4f937", - "0x1ed6aac0ab29a883de2bb2e3579ad4d6807ddcf3db8afcaf0ae25a076ac9a5f4", - "0xf17a840df410a15f0e4e48abf521c29ad0d296d3fb4e8b847ea37f2cc8236f1f" - ] - }, - "finalized_header": { - "slot": 3584, - "proposer_index": 1, - "parent_root": "0x91c285af2ec25d485310391afe667108b787ec570cdbb0e3fd87b1e0e2c47bd7", - "state_root": "0xccc4baf90024e035f1252520d2f2ef1e50f840ff0ecc8e6e365721e083871a32", - "body_root": "0x91df5e0077434aad609aaa7e030005cee77cca83868ffc2724e5befe9a3f6a02" - }, - "finality_branch": [ - "0xc001000000000000000000000000000000000000000000000000000000000000", - "0x10c726fac935bf9657cc7476d3cfa7bedec5983dcfb59e8a7df6d0a619e108d7", - "0x83c3d5360d254f4a44be712c1f433e88e810b6d1e0e789e90bada9e36126b857", - "0x9fd10c3f68b75cfd3ebd2af0d4e2cbbfbe120e0b5423dde89ff0f743c7a4f937", - "0x1ed6aac0ab29a883de2bb2e3579ad4d6807ddcf3db8afcaf0ae25a076ac9a5f4", - "0xf17a840df410a15f0e4e48abf521c29ad0d296d3fb4e8b847ea37f2cc8236f1f" - ], - "block_roots_root": "0x9eab8a05c396a29c32f4f8ac9654fc0fb7cd97ec659236392ede48951a794505", - "block_roots_branch": [ - "0x5c175efdbafacdfdab21c93a318b0e8e2291a5a86c40b1fc564f91ad33c106d4", - "0x5c1e0b76176ab033858b2835f90d5e25d708b563f77efd7d9938f0faa1c20878", - "0x7aea32464adee801e2a05c3af227f24231d3c088e3b7265a5fada9ac850549fe", - "0x9d9fca29e23c5d4ae433adf17e7fd9a0e4d1b09b68f5c45e7ca1b13ebe4a9e98", - "0x6b35238f188021c859d6b317457ebb6fe4cf362cab35c988010cb1343eabbfc5" - ] -} \ No newline at end of file diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/Cargo.toml b/bridges/snowbridge/parachain/pallets/inbound-queue/Cargo.toml deleted file mode 100644 index 8101ecd5a483..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/Cargo.toml +++ /dev/null @@ -1,100 +0,0 @@ -[package] -name = "snowbridge-pallet-inbound-queue" -description = "Snowbridge Inbound Queue Pallet" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -serde = { version = "1.0.195", optional = true } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -hex-literal = { version = "0.4.1", optional = true } -log = { version = "0.4.20", default-features = false } -alloy-primitives = { version = "0.4.2", default-features = false, features = ["rlp"] } -alloy-sol-types = { version = "0.4.2", default-features = false } -alloy-rlp = { version = "0.3.3", default-features = false, features = ["derive"] } -num-traits = { version = "0.2.16", default-features = false } - -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } - -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } - -snowbridge-core = { path = "../../primitives/core", default-features = false } -snowbridge-ethereum = { path = "../../primitives/ethereum", default-features = false } -snowbridge-router-primitives = { path = "../../primitives/router", default-features = false } -snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-features = false, optional = true } - -[dev-dependencies] -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking" } -sp-keyring = { path = "../../../../../substrate/primitives/keyring" } -snowbridge-beacon-primitives = { path = "../../primitives/beacon" } -snowbridge-pallet-ethereum-client = { path = "../ethereum-client" } -hex-literal = { version = "0.4.1" } - -[features] -default = ["std"] -std = [ - "alloy-primitives/std", - "alloy-rlp/std", - "alloy-sol-types/std", - "codec/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "log/std", - "num-traits/std", - "pallet-balances/std", - "scale-info/std", - "serde", - "snowbridge-core/std", - "snowbridge-ethereum/std", - "snowbridge-router-primitives/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "hex-literal", - "pallet-balances/runtime-benchmarks", - "snowbridge-beacon-primitives", - "snowbridge-core/runtime-benchmarks", - "snowbridge-pallet-ethereum-client/runtime-benchmarks", - "snowbridge-router-primitives/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-balances/try-runtime", - "snowbridge-pallet-ethereum-client/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/README.md b/bridges/snowbridge/parachain/pallets/inbound-queue/README.md deleted file mode 100644 index cc2f7c636e68..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ethereum Inbound Queue - -Reads messages from Ethereum and sends it to intended destination on Polkadot, using XCM. diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs deleted file mode 100644 index 4f2382d072ab..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/fixtures.rs +++ /dev/null @@ -1,40 +0,0 @@ -use hex_literal::hex; -use snowbridge_beacon_primitives::CompactExecutionHeader; -use snowbridge_core::inbound::{Log, Message, Proof}; -use sp_std::vec; - -pub struct InboundQueueTest { - pub execution_header: CompactExecutionHeader, - pub message: Message, -} - -pub fn make_create_message() -> InboundQueueTest { - InboundQueueTest{ - execution_header: CompactExecutionHeader{ - parent_hash: hex!("b5608f0af7c3b6fe5c593772fc25436b8d6549eb236adb0855c6ad33e0004e04").into(), - block_number: 115, - state_root: hex!("47ed174789836c622499d9659a4ac32c3b91a7b15642d39b0a11b82ff23995c1").into(), - receipts_root: hex!("42c08b5303fcdf9e49c833fe5f1182cdbc8206bf8aec581125fc34aba11e1f1a").into(), - }, - message: Message { - event_log: Log { - address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), - topics: vec![ - hex!("7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f").into(), - hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539").into(), - hex!("5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0").into(), - ], - data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000").into(), - }, - proof: Proof { - block_hash: hex!("add15f439c8a57fe375d0a679870b1359921d70cb0e3e44f0dd3e272849f4097").into(), - tx_index: 0, - data: (vec![ - hex!("42c08b5303fcdf9e49c833fe5f1182cdbc8206bf8aec581125fc34aba11e1f1a").to_vec(), - ], vec![ - hex!("f9028e822080b9028802f90284018301ed20b9010000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000080000000000000000000000000000004000000000080000000000000000000000000000000000010100000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000040004000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000200000000000010f90179f85894eda338e4dc46038493b885327842fd3e301cab39e1a0f78bb28d4b1d7da699e5c0bc2be29c2b04b5aab6aacf6298fe5304f9db9c6d7ea000000000000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7df9011c94eda338e4dc46038493b885327842fd3e301cab39f863a07153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84fa0c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539a05f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0b8a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e00a736aa00000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000").to_vec(), - ]), - }, - }, - } -} diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/mod.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/mod.rs deleted file mode 100644 index c10de9dff2ff..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/benchmarking/mod.rs +++ /dev/null @@ -1,55 +0,0 @@ -mod fixtures; - -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use crate::Pallet as InboundQueue; -use frame_benchmarking::v2::*; -use frame_support::assert_ok; -use frame_system::RawOrigin; - -#[benchmarks] -mod benchmarks { - use super::*; - use crate::benchmarking::fixtures::make_create_message; - - #[benchmark] - fn submit() -> Result<(), BenchmarkError> { - let caller: T::AccountId = whitelisted_caller(); - - let create_message = make_create_message(); - - T::Helper::initialize_storage( - create_message.message.proof.block_hash, - create_message.execution_header, - ); - - let sovereign_account = sibling_sovereign_account::(1000u32.into()); - - let minimum_balance = T::Token::minimum_balance(); - - // So that the receiving account exists - assert_ok!(T::Token::mint_into(&caller, minimum_balance)); - // Fund the sovereign account (parachain sovereign account) so it can transfer a reward - // fee to the caller account - assert_ok!(T::Token::mint_into( - &sovereign_account, - 3_000_000_000_000u128 - .try_into() - .unwrap_or_else(|_| panic!("unable to cast sovereign account balance")), - )); - - #[block] - { - assert_ok!(InboundQueue::::submit( - RawOrigin::Signed(caller.clone()).into(), - create_message.message, - )); - } - - Ok(()) - } - - impl_benchmark_test_suite!(InboundQueue, crate::mock::new_tester(), crate::mock::Test); -} diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/envelope.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/envelope.rs deleted file mode 100644 index 826d535c2cb9..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/envelope.rs +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use snowbridge_core::{inbound::Log, ChannelId}; - -use sp_core::{RuntimeDebug, H160, H256}; -use sp_std::{convert::TryFrom, prelude::*}; - -use alloy_primitives::B256; -use alloy_sol_types::{sol, SolEvent}; - -sol! { - event OutboundMessageAccepted(bytes32 indexed channel_id, uint64 nonce, bytes32 indexed message_id, bytes payload); -} - -/// An inbound message that has had its outer envelope decoded. -#[derive(Clone, RuntimeDebug)] -pub struct Envelope { - /// The address of the outbound queue on Ethereum that emitted this message as an event log - pub gateway: H160, - /// The message Channel - pub channel_id: ChannelId, - /// A nonce for enforcing replay protection and ordering. - pub nonce: u64, - /// An id for tracing the message on its route (has no role in bridge consensus) - pub message_id: H256, - /// The inner payload generated from the source application. - pub payload: Vec, -} - -#[derive(Copy, Clone, RuntimeDebug)] -pub struct EnvelopeDecodeError; - -impl TryFrom<&Log> for Envelope { - type Error = EnvelopeDecodeError; - - fn try_from(log: &Log) -> Result { - let topics: Vec = log.topics.iter().map(|x| B256::from_slice(x.as_ref())).collect(); - - let event = OutboundMessageAccepted::decode_log(topics, &log.data, true) - .map_err(|_| EnvelopeDecodeError)?; - - Ok(Self { - gateway: log.address, - channel_id: ChannelId::from(event.channel_id.as_ref()), - nonce: event.nonce, - message_id: H256::from(event.message_id.as_ref()), - payload: event.payload, - }) - } -} diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/lib.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/lib.rs deleted file mode 100644 index bdc21fcf0370..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/lib.rs +++ /dev/null @@ -1,372 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Inbound Queue -//! -//! # Overview -//! -//! Receives messages emitted by the Gateway contract on Ethereum, whereupon they are verified, -//! translated to XCM, and finally sent to their final destination parachain. -//! -//! The message relayers are rewarded using native currency from the sovereign account of the -//! destination parachain. -//! -//! # Extrinsics -//! -//! ## Governance -//! -//! * [`Call::set_operating_mode`]: Set the operating mode of the pallet. Can be used to disable -//! processing of inbound messages. -//! -//! ## Message Submission -//! -//! * [`Call::submit`]: Submit a message for verification and dispatch the final destination -//! parachain. -#![cfg_attr(not(feature = "std"), no_std)] - -mod envelope; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[cfg(feature = "runtime-benchmarks")] -use snowbridge_beacon_primitives::CompactExecutionHeader; - -pub mod weights; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod test; - -use codec::{Decode, DecodeAll, Encode}; -use envelope::Envelope; -use frame_support::{ - traits::{ - fungible::{Inspect, Mutate}, - tokens::Preservation, - }, - weights::WeightToFee, - PalletError, -}; -use frame_system::ensure_signed; -use scale_info::TypeInfo; -use sp_core::{H160, H256}; -use sp_std::{convert::TryFrom, vec}; -use xcm::prelude::{ - send_xcm, Instruction::SetTopic, Junction::*, Location, SendError as XcmpSendError, SendXcm, - Xcm, XcmContext, XcmHash, -}; -use xcm_executor::traits::TransactAsset; - -use snowbridge_core::{ - inbound::{Message, VerificationError, Verifier}, - sibling_sovereign_account, BasicOperatingMode, Channel, ChannelId, ParaId, PricingParameters, - StaticLookup, -}; -use snowbridge_router_primitives::{ - inbound, - inbound::{ConvertMessage, ConvertMessageError}, -}; -use sp_runtime::{traits::Saturating, SaturatedConversion, TokenError}; - -pub use weights::WeightInfo; - -type BalanceOf = - <::Token as Inspect<::AccountId>>::Balance; - -pub use pallet::*; - -pub const LOG_TARGET: &str = "snowbridge-inbound-queue"; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[cfg(feature = "runtime-benchmarks")] - pub trait BenchmarkHelper { - fn initialize_storage(block_hash: H256, header: CompactExecutionHeader); - } - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// The verifier for inbound messages from Ethereum - type Verifier: Verifier; - - /// Message relayers are rewarded with this asset - type Token: Mutate + Inspect; - - /// XCM message sender - type XcmSender: SendXcm; - - // Address of the Gateway contract - #[pallet::constant] - type GatewayAddress: Get; - - /// Convert inbound message to XCM - type MessageConverter: ConvertMessage< - AccountId = Self::AccountId, - Balance = BalanceOf, - >; - - /// Lookup a channel descriptor - type ChannelLookup: StaticLookup; - - /// Lookup pricing parameters - type PricingParameters: Get>>; - - type WeightInfo: WeightInfo; - - #[cfg(feature = "runtime-benchmarks")] - type Helper: BenchmarkHelper; - - /// Convert a weight value into deductible balance type. - type WeightToFee: WeightToFee>; - - /// Convert a length value into deductible balance type - type LengthToFee: WeightToFee>; - - /// The upper limit here only used to estimate delivery cost - type MaxMessageSize: Get; - - /// To withdraw and deposit an asset. - type AssetTransactor: TransactAsset; - } - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// A message was received from Ethereum - MessageReceived { - /// The message channel - channel_id: ChannelId, - /// The message nonce - nonce: u64, - /// ID of the XCM message which was forwarded to the final destination parachain - message_id: [u8; 32], - /// Fee burned for the teleport - fee_burned: BalanceOf, - }, - /// Set OperatingMode - OperatingModeChanged { mode: BasicOperatingMode }, - } - - #[pallet::error] - pub enum Error { - /// Message came from an invalid outbound channel on the Ethereum side. - InvalidGateway, - /// Message has an invalid envelope. - InvalidEnvelope, - /// Message has an unexpected nonce. - InvalidNonce, - /// Message has an invalid payload. - InvalidPayload, - /// Message channel is invalid - InvalidChannel, - /// The max nonce for the type has been reached - MaxNonceReached, - /// Cannot convert location - InvalidAccountConversion, - /// Pallet is halted - Halted, - /// Message verification error, - Verification(VerificationError), - /// XCMP send failure - Send(SendError), - /// Message conversion error - ConvertMessage(ConvertMessageError), - } - - #[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, PalletError)] - pub enum SendError { - NotApplicable, - NotRoutable, - Transport, - DestinationUnsupported, - ExceedsMaxMessageSize, - MissingArgument, - Fees, - } - - impl From for Error { - fn from(e: XcmpSendError) -> Self { - match e { - XcmpSendError::NotApplicable => Error::::Send(SendError::NotApplicable), - XcmpSendError::Unroutable => Error::::Send(SendError::NotRoutable), - XcmpSendError::Transport(_) => Error::::Send(SendError::Transport), - XcmpSendError::DestinationUnsupported => - Error::::Send(SendError::DestinationUnsupported), - XcmpSendError::ExceedsMaxMessageSize => - Error::::Send(SendError::ExceedsMaxMessageSize), - XcmpSendError::MissingArgument => Error::::Send(SendError::MissingArgument), - XcmpSendError::Fees => Error::::Send(SendError::Fees), - } - } - } - - /// The current nonce for each channel - #[pallet::storage] - pub type Nonce = StorageMap<_, Twox64Concat, ChannelId, u64, ValueQuery>; - - /// The current operating mode of the pallet. - #[pallet::storage] - #[pallet::getter(fn operating_mode)] - pub type OperatingMode = StorageValue<_, BasicOperatingMode, ValueQuery>; - - #[pallet::call] - impl Pallet { - /// Submit an inbound message originating from the Gateway contract on Ethereum - #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::submit())] - pub fn submit(origin: OriginFor, message: Message) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(!Self::operating_mode().is_halted(), Error::::Halted); - - // submit message to verifier for verification - T::Verifier::verify(&message.event_log, &message.proof) - .map_err(|e| Error::::Verification(e))?; - - // Decode event log into an Envelope - let envelope = - Envelope::try_from(&message.event_log).map_err(|_| Error::::InvalidEnvelope)?; - - // Verify that the message was submitted from the known Gateway contract - ensure!(T::GatewayAddress::get() == envelope.gateway, Error::::InvalidGateway); - - // Retrieve the registered channel for this message - let channel = - T::ChannelLookup::lookup(envelope.channel_id).ok_or(Error::::InvalidChannel)?; - - // Verify message nonce - >::try_mutate(envelope.channel_id, |nonce| -> DispatchResult { - if *nonce == u64::MAX { - return Err(Error::::MaxNonceReached.into()) - } - if envelope.nonce != nonce.saturating_add(1) { - Err(Error::::InvalidNonce.into()) - } else { - *nonce = nonce.saturating_add(1); - Ok(()) - } - })?; - - // Reward relayer from the sovereign account of the destination parachain - // Expected to fail if sovereign account has no funds - let sovereign_account = sibling_sovereign_account::(channel.para_id); - let delivery_cost = Self::calculate_delivery_cost(message.encode().len() as u32); - T::Token::transfer(&sovereign_account, &who, delivery_cost, Preservation::Preserve)?; - - // Decode message into XCM - let (xcm, fee) = - match inbound::VersionedMessage::decode_all(&mut envelope.payload.as_ref()) { - Ok(message) => Self::do_convert(envelope.message_id, message)?, - Err(_) => return Err(Error::::InvalidPayload.into()), - }; - - log::info!( - target: LOG_TARGET, - "💫 xcm decoded as {:?} with fee {:?}", - xcm, - fee - ); - - // Burning fees for teleport - Self::burn_fees(channel.para_id, fee)?; - - // Attempt to send XCM to a dest parachain - let message_id = Self::send_xcm(xcm, channel.para_id)?; - - Self::deposit_event(Event::MessageReceived { - channel_id: envelope.channel_id, - nonce: envelope.nonce, - message_id, - fee_burned: fee, - }); - - Ok(()) - } - - /// Halt or resume all pallet operations. May only be called by root. - #[pallet::call_index(1)] - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operating_mode( - origin: OriginFor, - mode: BasicOperatingMode, - ) -> DispatchResult { - ensure_root(origin)?; - OperatingMode::::set(mode); - Self::deposit_event(Event::OperatingModeChanged { mode }); - Ok(()) - } - } - - impl Pallet { - pub fn do_convert( - message_id: H256, - message: inbound::VersionedMessage, - ) -> Result<(Xcm<()>, BalanceOf), Error> { - let (mut xcm, fee) = - T::MessageConverter::convert(message).map_err(|e| Error::::ConvertMessage(e))?; - // Append the message id as an XCM topic - xcm.inner_mut().extend(vec![SetTopic(message_id.into())]); - Ok((xcm, fee)) - } - - pub fn send_xcm(xcm: Xcm<()>, dest: ParaId) -> Result> { - let dest = Location::new(1, [Parachain(dest.into())]); - let (xcm_hash, _) = send_xcm::(dest, xcm).map_err(Error::::from)?; - Ok(xcm_hash) - } - - pub fn calculate_delivery_cost(length: u32) -> BalanceOf { - let weight_fee = T::WeightToFee::weight_to_fee(&T::WeightInfo::submit()); - let len_fee = T::LengthToFee::weight_to_fee(&Weight::from_parts(length as u64, 0)); - weight_fee - .saturating_add(len_fee) - .saturating_add(T::PricingParameters::get().rewards.local) - } - - /// Burn the amount of the fee embedded into the XCM for teleports - pub fn burn_fees(para_id: ParaId, fee: BalanceOf) -> DispatchResult { - let dummy_context = - XcmContext { origin: None, message_id: Default::default(), topic: None }; - let dest = Location::new(1, [Parachain(para_id.into())]); - let fees = (Location::parent(), fee.saturated_into::()).into(); - T::AssetTransactor::can_check_out(&dest, &fees, &dummy_context).map_err(|error| { - log::error!( - target: LOG_TARGET, - "XCM asset check out failed with error {:?}", error - ); - TokenError::FundsUnavailable - })?; - T::AssetTransactor::check_out(&dest, &fees, &dummy_context); - T::AssetTransactor::withdraw_asset(&fees, &dest, None).map_err(|error| { - log::error!( - target: LOG_TARGET, - "XCM asset withdraw failed with error {:?}", error - ); - TokenError::FundsUnavailable - })?; - Ok(()) - } - } - - /// API for accessing the delivery cost of a message - impl Get> for Pallet { - fn get() -> BalanceOf { - // Cost here based on MaxMessagePayloadSize(the worst case) - Self::calculate_delivery_cost(T::MaxMessageSize::get()) - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/mock.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/mock.rs deleted file mode 100644 index 39374aa3d71a..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/mock.rs +++ /dev/null @@ -1,344 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use frame_support::{ - parameter_types, - traits::{ConstU128, ConstU32, Everything}, - weights::IdentityFee, -}; -use hex_literal::hex; -use snowbridge_beacon_primitives::{Fork, ForkVersions}; -use snowbridge_core::{ - gwei, - inbound::{Log, Proof, VerificationError}, - meth, Channel, ChannelId, PricingParameters, Rewards, StaticLookup, -}; -use snowbridge_router_primitives::inbound::MessageToXcm; -use sp_core::{H160, H256}; -use sp_runtime::{ - traits::{BlakeTwo256, IdentifyAccount, IdentityLookup, Verify}, - BuildStorage, FixedU128, MultiSignature, -}; -use sp_std::convert::From; -use xcm::v4::{prelude::*, SendXcm}; -use xcm_executor::AssetsInHolding; - -use crate::{self as inbound_queue}; - -type Block = frame_system::mocking::MockBlock; - -frame_support::construct_runtime!( - pub enum Test - { - System: frame_system::{Pallet, Call, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - EthereumBeaconClient: snowbridge_pallet_ethereum_client::{Pallet, Call, Storage, Event}, - InboundQueue: inbound_queue::{Pallet, Call, Storage, Event}, - } -); - -pub type Signature = MultiSignature; -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - -type Balance = u128; - -impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - type Nonce = u64; - type Block = Block; -} - -impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - type MaxHolds = (); -} - -parameter_types! { - pub const ExecutionHeadersPruneThreshold: u32 = 10; - pub const ChainForkVersions: ForkVersions = ForkVersions{ - genesis: Fork { - version: [0, 0, 0, 1], // 0x00000001 - epoch: 0, - }, - altair: Fork { - version: [1, 0, 0, 1], // 0x01000001 - epoch: 0, - }, - bellatrix: Fork { - version: [2, 0, 0, 1], // 0x02000001 - epoch: 0, - }, - capella: Fork { - version: [3, 0, 0, 1], // 0x03000001 - epoch: 0, - }, - }; -} - -impl snowbridge_pallet_ethereum_client::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ForkVersions = ChainForkVersions; - type MaxExecutionHeadersToKeep = ExecutionHeadersPruneThreshold; - type WeightInfo = (); -} - -// Mock verifier -pub struct MockVerifier; - -impl Verifier for MockVerifier { - fn verify(_: &Log, _: &Proof) -> Result<(), VerificationError> { - Ok(()) - } -} - -const GATEWAY_ADDRESS: [u8; 20] = hex!["eda338e4dc46038493b885327842fd3e301cab39"]; - -parameter_types! { - pub const EthereumNetwork: xcm::v3::NetworkId = xcm::v3::NetworkId::Ethereum { chain_id: 11155111 }; - pub const GatewayAddress: H160 = H160(GATEWAY_ADDRESS); - pub const CreateAssetCall: [u8;2] = [53, 0]; - pub const CreateAssetExecutionFee: u128 = 2_000_000_000; - pub const CreateAssetDeposit: u128 = 100_000_000_000; - pub const SendTokenExecutionFee: u128 = 1_000_000_000; - pub const InitialFund: u128 = 1_000_000_000_000; - pub const InboundQueuePalletInstance: u8 = 80; -} - -#[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelper for Test { - // not implemented since the MockVerifier is used for tests - fn initialize_storage(_: H256, _: CompactExecutionHeader) {} -} - -// Mock XCM sender that always succeeds -pub struct MockXcmSender; - -impl SendXcm for MockXcmSender { - type Ticket = Xcm<()>; - - fn validate( - dest: &mut Option, - xcm: &mut Option>, - ) -> SendResult { - if let Some(location) = dest { - match location.unpack() { - (_, [Parachain(1001)]) => return Err(XcmpSendError::NotApplicable), - _ => Ok((xcm.clone().unwrap(), Assets::default())), - } - } else { - Ok((xcm.clone().unwrap(), Assets::default())) - } - } - - fn deliver(xcm: Self::Ticket) -> core::result::Result { - let hash = xcm.using_encoded(sp_io::hashing::blake2_256); - Ok(hash) - } -} - -parameter_types! { - pub const OwnParaId: ParaId = ParaId::new(1013); - pub Parameters: PricingParameters = PricingParameters { - exchange_rate: FixedU128::from_rational(1, 400), - fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } - }; -} - -pub const DOT: u128 = 10_000_000_000; - -pub struct MockChannelLookup; -impl StaticLookup for MockChannelLookup { - type Source = ChannelId; - type Target = Channel; - - fn lookup(channel_id: Self::Source) -> Option { - if channel_id != - hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539").into() - { - return None - } - Some(Channel { agent_id: H256::zero(), para_id: ASSET_HUB_PARAID.into() }) - } -} - -pub struct SuccessfulTransactor; -impl TransactAsset for SuccessfulTransactor { - fn can_check_in(_origin: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult { - Ok(()) - } - - fn can_check_out(_dest: &Location, _what: &Asset, _context: &XcmContext) -> XcmResult { - Ok(()) - } - - fn deposit_asset(_what: &Asset, _who: &Location, _context: Option<&XcmContext>) -> XcmResult { - Ok(()) - } - - fn withdraw_asset( - _what: &Asset, - _who: &Location, - _context: Option<&XcmContext>, - ) -> Result { - Ok(AssetsInHolding::default()) - } - - fn internal_transfer_asset( - _what: &Asset, - _from: &Location, - _to: &Location, - _context: &XcmContext, - ) -> Result { - Ok(AssetsInHolding::default()) - } -} - -impl inbound_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Verifier = MockVerifier; - type Token = Balances; - type XcmSender = MockXcmSender; - type WeightInfo = (); - type GatewayAddress = GatewayAddress; - type MessageConverter = MessageToXcm< - CreateAssetCall, - CreateAssetDeposit, - InboundQueuePalletInstance, - AccountId, - Balance, - >; - type PricingParameters = Parameters; - type ChannelLookup = MockChannelLookup; - #[cfg(feature = "runtime-benchmarks")] - type Helper = Test; - type WeightToFee = IdentityFee; - type LengthToFee = IdentityFee; - type MaxMessageSize = ConstU32<1024>; - type AssetTransactor = SuccessfulTransactor; -} - -pub fn last_events(n: usize) -> Vec { - frame_system::Pallet::::events() - .into_iter() - .rev() - .take(n) - .rev() - .map(|e| e.event) - .collect() -} - -pub fn expect_events(e: Vec) { - assert_eq!(last_events(e.len()), e); -} - -pub fn setup() { - System::set_block_number(1); - Balances::mint_into( - &sibling_sovereign_account::(ASSET_HUB_PARAID.into()), - InitialFund::get(), - ) - .unwrap(); - Balances::mint_into( - &sibling_sovereign_account::(TEMPLATE_PARAID.into()), - InitialFund::get(), - ) - .unwrap(); -} - -pub fn new_tester() -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext: sp_io::TestExternalities = storage.into(); - ext.execute_with(setup); - ext -} - -// Generated from smoketests: -// cd smoketests -// ./make-bindings -// cargo test --test register_token -- --nocapture -pub fn mock_event_log() -> Log { - Log { - // gateway address - address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), - topics: vec![ - hex!("7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f").into(), - // channel id - hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539").into(), - // message id - hex!("5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0").into(), - ], - // Nonce + Payload - data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e000f000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d00e40b54020000000000000000000000000000000000000000000000000000000000").into(), - } -} - -pub fn mock_event_log_invalid_channel() -> Log { - Log { - address: hex!("eda338e4dc46038493b885327842fd3e301cab39").into(), - topics: vec![ - hex!("7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f").into(), - // invalid channel id - hex!("0000000000000000000000000000000000000000000000000000000000000000").into(), - hex!("5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0").into(), - ], - data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e000f000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d0000").into(), - } -} - -pub fn mock_event_log_invalid_gateway() -> Log { - Log { - // gateway address - address: H160::zero(), - topics: vec![ - hex!("7153f9357c8ea496bba60bf82e67143e27b64462b49041f8e689e1b05728f84f").into(), - // channel id - hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539").into(), - // message id - hex!("5f7060e971b0dc81e63f0aa41831091847d97c1a4693ac450cc128c7214e65e0").into(), - ], - // Nonce + Payload - data: hex!("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001e000f000000000000000087d1f7fdfee7f651fabc8bfcb6e086c278b77a7d0000").into(), - } -} - -pub const ASSET_HUB_PARAID: u32 = 1000u32; -pub const TEMPLATE_PARAID: u32 = 1001u32; diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/test.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/test.rs deleted file mode 100644 index 9a47e475b8c9..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/test.rs +++ /dev/null @@ -1,212 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use frame_support::{assert_noop, assert_ok}; -use hex_literal::hex; -use snowbridge_core::{inbound::Proof, ChannelId}; -use sp_keyring::AccountKeyring as Keyring; -use sp_runtime::{DispatchError, TokenError}; -use sp_std::convert::From; - -use crate::{Error, Event as InboundQueueEvent}; - -use crate::mock::*; - -#[test] -fn test_submit_happy_path() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let channel_sovereign = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); - - let origin = RuntimeOrigin::signed(relayer.clone()); - - // Submit message - let message = Message { - event_log: mock_event_log(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - - let initial_fund = InitialFund::get(); - assert_eq!(Balances::balance(&relayer), 0); - assert_eq!(Balances::balance(&channel_sovereign), initial_fund); - - assert_ok!(InboundQueue::submit(origin.clone(), message.clone())); - expect_events(vec![InboundQueueEvent::MessageReceived { - channel_id: hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539") - .into(), - nonce: 1, - message_id: [ - 57, 61, 232, 3, 66, 61, 25, 190, 234, 188, 193, 174, 13, 186, 1, 64, 237, 94, 73, - 83, 14, 18, 209, 213, 78, 121, 43, 108, 251, 245, 107, 67, - ], - fee_burned: 110000000000, - } - .into()]); - - let delivery_cost = InboundQueue::calculate_delivery_cost(message.encode().len() as u32); - assert!( - Parameters::get().rewards.local < delivery_cost, - "delivery cost exceeds pure reward" - ); - - assert_eq!(Balances::balance(&relayer), delivery_cost, "relayer was rewarded"); - assert!( - Balances::balance(&channel_sovereign) <= initial_fund - delivery_cost, - "sovereign account paid reward" - ); - }); -} - -#[test] -fn test_submit_xcm_invalid_channel() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - - // Deposit funds into sovereign account of parachain 1001 - let sovereign_account = sibling_sovereign_account::(TEMPLATE_PARAID.into()); - println!("account: {}", sovereign_account); - let _ = Balances::mint_into(&sovereign_account, 10000); - - // Submit message - let message = Message { - event_log: mock_event_log_invalid_channel(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - assert_noop!( - InboundQueue::submit(origin.clone(), message.clone()), - Error::::InvalidChannel, - ); - }); -} - -#[test] -fn test_submit_with_invalid_gateway() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - - // Deposit funds into sovereign account of Asset Hub (Statemint) - let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); - let _ = Balances::mint_into(&sovereign_account, 10000); - - // Submit message - let message = Message { - event_log: mock_event_log_invalid_gateway(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - assert_noop!( - InboundQueue::submit(origin.clone(), message.clone()), - Error::::InvalidGateway - ); - }); -} - -#[test] -fn test_submit_with_invalid_nonce() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - - // Deposit funds into sovereign account of Asset Hub (Statemint) - let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); - let _ = Balances::mint_into(&sovereign_account, 10000); - - // Submit message - let message = Message { - event_log: mock_event_log(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - assert_ok!(InboundQueue::submit(origin.clone(), message.clone())); - - let nonce: u64 = >::get(ChannelId::from(hex!( - "c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539" - ))); - assert_eq!(nonce, 1); - - // Submit the same again - assert_noop!( - InboundQueue::submit(origin.clone(), message.clone()), - Error::::InvalidNonce - ); - }); -} - -#[test] -fn test_submit_no_funds_to_reward_relayers() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - - // Reset balance of sovereign_account to zero so to trigger the FundsUnavailable error - let sovereign_account = sibling_sovereign_account::(ASSET_HUB_PARAID.into()); - Balances::set_balance(&sovereign_account, 0); - - // Submit message - let message = Message { - event_log: mock_event_log(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - assert_noop!( - InboundQueue::submit(origin.clone(), message.clone()), - TokenError::FundsUnavailable - ); - }); -} - -#[test] -fn test_set_operating_mode() { - new_tester().execute_with(|| { - let relayer: AccountId = Keyring::Bob.into(); - let origin = RuntimeOrigin::signed(relayer); - let message = Message { - event_log: mock_event_log(), - proof: Proof { - block_hash: Default::default(), - tx_index: Default::default(), - data: Default::default(), - }, - }; - - assert_ok!(InboundQueue::set_operating_mode( - RuntimeOrigin::root(), - snowbridge_core::BasicOperatingMode::Halted - )); - - assert_noop!(InboundQueue::submit(origin, message), Error::::Halted); - }); -} - -#[test] -fn test_set_operating_mode_root_only() { - new_tester().execute_with(|| { - assert_noop!( - InboundQueue::set_operating_mode( - RuntimeOrigin::signed(Keyring::Bob.into()), - snowbridge_core::BasicOperatingMode::Halted - ), - DispatchError::BadOrigin - ); - }); -} diff --git a/bridges/snowbridge/parachain/pallets/inbound-queue/src/weights.rs b/bridges/snowbridge/parachain/pallets/inbound-queue/src/weights.rs deleted file mode 100644 index c2c665f40d9e..000000000000 --- a/bridges/snowbridge/parachain/pallets/inbound-queue/src/weights.rs +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Autogenerated weights for `snowbridge_inbound_queue` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `macbook pro 14 m2`, CPU: `m2-arm64` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for ethereum_beacon_client. -pub trait WeightInfo { - fn submit() -> Weight; -} - -// For backwards compatibility and tests -impl WeightInfo for () { - fn submit() -> Weight { - Weight::from_parts(70_000_000, 0) - .saturating_add(Weight::from_parts(0, 3601)) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(2)) - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/Cargo.toml b/bridges/snowbridge/parachain/pallets/outbound-queue/Cargo.toml deleted file mode 100644 index e499ab887294..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/Cargo.toml +++ /dev/null @@ -1,82 +0,0 @@ -[package] -name = "snowbridge-pallet-outbound-queue" -description = "Snowbridge Outbound Queue Pallet" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -serde = { version = "1.0.195", features = ["alloc", "derive"], default-features = false } -codec = { version = "3.6.1", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -hex-literal = { version = "0.4.1", optional = true } - -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-arithmetic = { path = "../../../../../substrate/primitives/arithmetic", default-features = false } - -bridge-hub-common = { path = "../../../../../cumulus/parachains/runtimes/bridge-hubs/common", default-features = false } - -snowbridge-core = { path = "../../primitives/core", default-features = false, features = ["serde"] } -snowbridge-outbound-queue-merkle-tree = { path = "merkle-tree", default-features = false } -ethabi = { git = "https://github.com/snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } - -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } - -[dev-dependencies] -pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -sp-keyring = { path = "../../../../../substrate/primitives/keyring" } -hex-literal = { version = "0.4.1" } - -[features] -default = ["std"] -std = [ - "bridge-hub-common/std", - "codec/std", - "ethabi/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "pallet-message-queue/std", - "scale-info/std", - "serde/std", - "snowbridge-core/std", - "snowbridge-outbound-queue-merkle-tree/std", - "sp-arithmetic/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm/std", -] -runtime-benchmarks = [ - "bridge-hub-common/runtime-benchmarks", - "frame-benchmarking", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "hex-literal", - "pallet-message-queue/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-message-queue/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/README.md b/bridges/snowbridge/parachain/pallets/outbound-queue/README.md deleted file mode 100644 index 19638f90e6a5..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ethereum Outbound Queue - -Sends messages from an origin in the Polkadot ecosystem to Ethereum. diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/Cargo.toml b/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/Cargo.toml deleted file mode 100644 index 27c4ae02e52e..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -name = "snowbridge-outbound-queue-merkle-tree" -description = "Snowbridge Outbound Queue Merkle Tree" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { version = "3.1.5", package = "parity-scale-codec", default-features = false, features = ["derive"] } -scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } - -sp-core = { path = "../../../../../../substrate/primitives/core", default-features = false } -sp-runtime = { path = "../../../../../../substrate/primitives/runtime", default-features = false } - -[dev-dependencies] -hex-literal = { version = "0.4.1" } -env_logger = "0.9" -hex = "0.4" -array-bytes = "4.1" - -[features] -default = ["std"] -std = [ - "codec/std", - "scale-info/std", - "sp-core/std", - "sp-runtime/std", -] diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/README.md b/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/README.md deleted file mode 100644 index a3afef1d6713..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Snowbridge Outbound Queue Merkle Tree - -This crate implements a simple binary Merkle Tree utilities required for inter-op with Ethereum -bridge & Solidity contract. diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/src/lib.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/src/lib.rs deleted file mode 100644 index d03eb578ef4d..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/merkle-tree/src/lib.rs +++ /dev/null @@ -1,464 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -// SPDX-FileCopyrightText: 2021-2022 Parity Technologies (UK) Ltd. -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] - -//! This crate implements a simple binary Merkle Tree utilities required for inter-op with Ethereum -//! bridge & Solidity contract. -//! -//! The implementation is optimised for usage within Substrate Runtime and supports no-std -//! compilation targets. -//! -//! Merkle Tree is constructed from arbitrary-length leaves, that are initially hashed using the -//! same `\[`Hasher`\]` as the inner nodes. -//! Inner nodes are created by concatenating child hashes and hashing again. The implementation -//! does not perform any sorting of the input data (leaves) nor when inner nodes are created. -//! -//! If the number of leaves is not even, last leaf (hash of) is promoted to the upper layer. - -#[cfg(not(feature = "std"))] -extern crate alloc; -#[cfg(not(feature = "std"))] -use alloc::vec; -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; - -use codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_core::{RuntimeDebug, H256}; -use sp_runtime::traits::Hash; - -/// Construct a root hash of a Binary Merkle Tree created from given leaves. -/// -/// See crate-level docs for details about Merkle Tree construction. -/// -/// In case an empty list of leaves is passed the function returns a 0-filled hash. -pub fn merkle_root(leaves: I) -> H256 -where - H: Hash, - I: Iterator, -{ - merkelize::(leaves, &mut ()) -} - -fn merkelize(leaves: I, visitor: &mut V) -> H256 -where - H: Hash, - V: Visitor, - I: Iterator, -{ - let upper = Vec::with_capacity(leaves.size_hint().0); - let mut next = match merkelize_row::(leaves, upper, visitor) { - Ok(root) => return root, - Err(next) if next.is_empty() => return H256::default(), - Err(next) => next, - }; - - let mut upper = Vec::with_capacity((next.len() + 1) / 2); - loop { - visitor.move_up(); - - match merkelize_row::(next.drain(..), upper, visitor) { - Ok(root) => return root, - Err(t) => { - // swap collections to avoid allocations - upper = next; - next = t; - }, - }; - } -} - -/// A generated merkle proof. -/// -/// The structure contains all necessary data to later on verify the proof and the leaf itself. -#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo)] -pub struct MerkleProof { - /// Root hash of generated merkle tree. - pub root: H256, - /// Proof items (does not contain the leaf hash, nor the root obviously). - /// - /// This vec contains all inner node hashes necessary to reconstruct the root hash given the - /// leaf hash. - pub proof: Vec, - /// Number of leaves in the original tree. - /// - /// This is needed to detect a case where we have an odd number of leaves that "get promoted" - /// to upper layers. - pub number_of_leaves: u64, - /// Index of the leaf the proof is for (0-based). - pub leaf_index: u64, - /// Leaf content (hashed). - pub leaf: H256, -} - -/// A trait of object inspecting merkle root creation. -/// -/// It can be passed to [`merkelize_row`] or [`merkelize`] functions and will be notified -/// about tree traversal. -trait Visitor { - /// We are moving one level up in the tree. - fn move_up(&mut self); - - /// We are creating an inner node from given `left` and `right` nodes. - /// - /// Note that in case of last odd node in the row `right` might be empty. - /// The method will also visit the `root` hash (level 0). - /// - /// The `index` is an index of `left` item. - fn visit(&mut self, index: u64, left: &Option, right: &Option); -} - -/// No-op implementation of the visitor. -impl Visitor for () { - fn move_up(&mut self) {} - fn visit(&mut self, _index: u64, _left: &Option, _right: &Option) {} -} - -/// Construct a Merkle Proof for leaves given by indices. -/// -/// The function constructs a (partial) Merkle Tree first and stores all elements required -/// to prove the requested item (leaf) given the root hash. -/// -/// Both the Proof and the Root Hash are returned. -/// -/// # Panic -/// -/// The function will panic if given `leaf_index` is greater than the number of leaves. -pub fn merkle_proof(leaves: I, leaf_index: u64) -> MerkleProof -where - H: Hash, - I: Iterator, -{ - let mut leaf = None; - let mut hashes = vec![]; - let mut number_of_leaves = 0; - for (idx, l) in (0u64..).zip(leaves) { - // count the leaves - number_of_leaves = idx + 1; - hashes.push(l); - // find the leaf for the proof - if idx == leaf_index { - leaf = Some(l); - } - } - - /// The struct collects a proof for single leaf. - struct ProofCollection { - proof: Vec, - position: u64, - } - - impl ProofCollection { - fn new(position: u64) -> Self { - ProofCollection { proof: Default::default(), position } - } - } - - impl Visitor for ProofCollection { - fn move_up(&mut self) { - self.position /= 2; - } - - fn visit(&mut self, index: u64, left: &Option, right: &Option) { - // we are at left branch - right goes to the proof. - if self.position == index { - if let Some(right) = right { - self.proof.push(*right); - } - } - // we are at right branch - left goes to the proof. - if self.position == index + 1 { - if let Some(left) = left { - self.proof.push(*left); - } - } - } - } - - let mut collect_proof = ProofCollection::new(leaf_index); - - let root = merkelize::(hashes.into_iter(), &mut collect_proof); - let leaf = leaf.expect("Requested `leaf_index` is greater than number of leaves."); - - #[cfg(feature = "debug")] - log::debug!( - "[merkle_proof] Proof: {:?}", - collect_proof.proof.iter().map(hex::encode).collect::>() - ); - - MerkleProof { root, proof: collect_proof.proof, number_of_leaves, leaf_index, leaf } -} - -/// Leaf node for proof verification. -/// -/// Can be either a value that needs to be hashed first, -/// or the hash itself. -#[derive(Debug, PartialEq, Eq)] -pub enum Leaf<'a> { - /// Leaf content. - Value(&'a [u8]), - /// Hash of the leaf content. - Hash(H256), -} - -impl<'a, T: AsRef<[u8]>> From<&'a T> for Leaf<'a> { - fn from(v: &'a T) -> Self { - Leaf::Value(v.as_ref()) - } -} - -impl<'a> From for Leaf<'a> { - fn from(v: H256) -> Self { - Leaf::Hash(v) - } -} - -/// Verify Merkle Proof correctness versus given root hash. -/// -/// The proof is NOT expected to contain leaf hash as the first -/// element, but only all adjacent nodes required to eventually by process of -/// concatenating and hashing end up with given root hash. -/// -/// The proof must not contain the root hash. -pub fn verify_proof<'a, H, P, L>( - root: &'a H256, - proof: P, - number_of_leaves: u64, - leaf_index: u64, - leaf: L, -) -> bool -where - H: Hash, - P: IntoIterator, - L: Into>, -{ - if leaf_index >= number_of_leaves { - return false - } - - let leaf_hash = match leaf.into() { - Leaf::Value(content) => ::hash(content), - Leaf::Hash(hash) => hash, - }; - - let hash_len = ::LENGTH; - let mut combined = [0_u8; 64]; - let computed = proof.into_iter().fold(leaf_hash, |a, b| { - if a < b { - combined[..hash_len].copy_from_slice(a.as_ref()); - combined[hash_len..].copy_from_slice(b.as_ref()); - } else { - combined[..hash_len].copy_from_slice(b.as_ref()); - combined[hash_len..].copy_from_slice(a.as_ref()); - } - ::hash(&combined) - }); - - root == &computed -} - -/// Processes a single row (layer) of a tree by taking pairs of elements, -/// concatenating them, hashing and placing into resulting vector. -/// -/// In case only one element is provided it is returned via `Ok` result, in any other case (also an -/// empty iterator) an `Err` with the inner nodes of upper layer is returned. -fn merkelize_row( - mut iter: I, - mut next: Vec, - visitor: &mut V, -) -> Result> -where - H: Hash, - V: Visitor, - I: Iterator, -{ - #[cfg(feature = "debug")] - log::debug!("[merkelize_row]"); - next.clear(); - - let hash_len = ::LENGTH; - let mut index = 0; - let mut combined = vec![0_u8; hash_len * 2]; - loop { - let a = iter.next(); - let b = iter.next(); - visitor.visit(index, &a, &b); - - #[cfg(feature = "debug")] - log::debug!(" {:?}\n {:?}", a.as_ref().map(hex::encode), b.as_ref().map(hex::encode)); - - index += 2; - match (a, b) { - (Some(a), Some(b)) => { - if a < b { - combined[..hash_len].copy_from_slice(a.as_ref()); - combined[hash_len..].copy_from_slice(b.as_ref()); - } else { - combined[..hash_len].copy_from_slice(b.as_ref()); - combined[hash_len..].copy_from_slice(a.as_ref()); - } - - next.push(::hash(&combined)); - }, - // Odd number of items. Promote the item to the upper layer. - (Some(a), None) if !next.is_empty() => { - next.push(a); - }, - // Last item = root. - (Some(a), None) => return Ok(a), - // Finish up, no more items. - _ => { - #[cfg(feature = "debug")] - log::debug!( - "[merkelize_row] Next: {:?}", - next.iter().map(hex::encode).collect::>() - ); - return Err(next) - }, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - use sp_core::keccak_256; - use sp_runtime::traits::Keccak256; - - fn make_leaves(count: u64) -> Vec { - (0..count).map(|i| keccak_256(&i.to_le_bytes()).into()).collect() - } - - #[test] - fn should_generate_empty_root() { - // given - let _ = env_logger::try_init(); - let data = vec![]; - - // when - let out = merkle_root::(data.into_iter()); - - // then - assert_eq!( - hex::encode(out), - "0000000000000000000000000000000000000000000000000000000000000000" - ); - } - - #[test] - fn should_generate_single_root() { - // given - let _ = env_logger::try_init(); - let data = make_leaves(1); - - // when - let out = merkle_root::(data.into_iter()); - - // then - assert_eq!( - hex::encode(out), - "011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce" - ); - } - - #[test] - fn should_generate_root_pow_2() { - // given - let _ = env_logger::try_init(); - let data = make_leaves(2); - - // when - let out = merkle_root::(data.into_iter()); - - // then - assert_eq!( - hex::encode(out), - "e497bd1c13b13a60af56fa0d2703517c232fde213ad20d2c3dd60735c6604512" - ); - } - - #[test] - fn should_generate_root_complex() { - let _ = env_logger::try_init(); - let test = |root, data: Vec| { - assert_eq!( - array_bytes::bytes2hex("", merkle_root::(data.into_iter()).as_ref()), - root - ); - }; - - test("816cc37bd8d39f7b0851838ebc875faf2afe58a03e95aca3b1333b3693f39dd3", make_leaves(3)); - - test("7501ea976cb92f305cca65ab11254589ea28bb8b59d3161506350adaa237d22f", make_leaves(4)); - - test("d26ba4eb398747bdd39255b1fadb99b803ce39696021b3b0bff7301ac146ee4e", make_leaves(10)); - } - - #[test] - #[ignore] - fn should_generate_and_verify_proof() { - // given - let _ = env_logger::try_init(); - let data: Vec = make_leaves(3); - - // when - let proof0 = merkle_proof::(data.clone().into_iter(), 0); - assert!(verify_proof::( - &proof0.root, - proof0.proof.clone(), - data.len() as u64, - proof0.leaf_index, - &data[0], - )); - - let proof1 = merkle_proof::(data.clone().into_iter(), 1); - assert!(verify_proof::( - &proof1.root, - proof1.proof, - data.len() as u64, - proof1.leaf_index, - &proof1.leaf, - )); - - let proof2 = merkle_proof::(data.clone().into_iter(), 2); - assert!(verify_proof::( - &proof2.root, - proof2.proof, - data.len() as u64, - proof2.leaf_index, - &proof2.leaf - )); - - // then - assert_eq!(hex::encode(proof0.root), hex::encode(proof1.root)); - assert_eq!(hex::encode(proof2.root), hex::encode(proof1.root)); - - assert!(!verify_proof::( - &H256::from_slice(&hex!( - "fb3b3be94be9e983ba5e094c9c51a7d96a4fa2e5d8e891df00ca89ba05bb1239" - )), - proof0.proof, - data.len() as u64, - proof0.leaf_index, - &proof0.leaf - )); - - assert!(!verify_proof::( - &proof0.root, - vec![], - data.len() as u64, - proof0.leaf_index, - &proof0.leaf - )); - } - - #[test] - #[should_panic] - fn should_panic_on_invalid_leaf_index() { - let _ = env_logger::try_init(); - merkle_proof::(make_leaves(1).into_iter(), 5); - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/Cargo.toml b/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/Cargo.toml deleted file mode 100644 index 1f2b51a6752f..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "snowbridge-outbound-queue-runtime-api" -description = "Snowbridge Outbound Queue Runtime API" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { version = "3.1.5", package = "parity-scale-codec", features = ["derive"], default-features = false } -sp-core = { path = "../../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../../substrate/primitives/std", default-features = false } -sp-api = { path = "../../../../../../substrate/primitives/api", default-features = false } -frame-support = { path = "../../../../../../substrate/frame/support", default-features = false } -xcm = { package = "staging-xcm", path = "../../../../../../polkadot/xcm", default-features = false } -snowbridge-outbound-queue-merkle-tree = { path = "../merkle-tree", default-features = false } -snowbridge-core = { path = "../../../primitives/core", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-support/std", - "snowbridge-core/std", - "snowbridge-outbound-queue-merkle-tree/std", - "sp-api/std", - "sp-core/std", - "sp-std/std", - "xcm/std", -] diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/README.md b/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/README.md deleted file mode 100644 index 98ae01fb33da..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Ethereum Outbound Queue Runtime API - -Provides an API: - -- to generate merkle proofs for outbound messages -- calculate delivery fee for delivering messages to Ethereum diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/src/lib.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/src/lib.rs deleted file mode 100644 index 51f46a7b49c8..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/runtime-api/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] - -use frame_support::traits::tokens::Balance as BalanceT; -use snowbridge_core::outbound::Message; -use snowbridge_outbound_queue_merkle_tree::MerkleProof; - -sp_api::decl_runtime_apis! { - pub trait OutboundQueueApi where Balance: BalanceT - { - /// Generate a merkle proof for a committed message identified by `leaf_index`. - /// The merkle root is stored in the block header as a - /// `\[`sp_runtime::generic::DigestItem::Other`\]` - fn prove_message(leaf_index: u64) -> Option; - - /// Calculate the delivery fee for `message` - fn calculate_fee(message: Message) -> Option; - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/api.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/api.rs deleted file mode 100644 index 44d63f1e2d23..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/api.rs +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Helpers for implementing runtime api - -use crate::{Config, MessageLeaves}; -use frame_support::storage::StorageStreamIter; -use snowbridge_core::outbound::{Message, SendMessage}; -use snowbridge_outbound_queue_merkle_tree::{merkle_proof, MerkleProof}; - -pub fn prove_message(leaf_index: u64) -> Option -where - T: Config, -{ - if !MessageLeaves::::exists() { - return None - } - let proof = - merkle_proof::<::Hashing, _>(MessageLeaves::::stream_iter(), leaf_index); - Some(proof) -} - -pub fn calculate_fee(message: Message) -> Option -where - T: Config, -{ - match crate::Pallet::::validate(&message) { - Ok((_, fees)) => Some(fees.total()), - _ => None, - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/benchmarking.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/benchmarking.rs deleted file mode 100644 index ee5754e86962..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/benchmarking.rs +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use bridge_hub_common::AggregateMessageOrigin; -use codec::Encode; -use frame_benchmarking::v2::*; -use snowbridge_core::{ - outbound::{Command, Initializer}, - ChannelId, -}; -use sp_core::{H160, H256}; - -#[allow(unused_imports)] -use crate::Pallet as OutboundQueue; - -#[benchmarks( - where - ::MaxMessagePayloadSize: Get, -)] -mod benchmarks { - use super::*; - - /// Benchmark for processing a message. - #[benchmark] - fn do_process_message() -> Result<(), BenchmarkError> { - let enqueued_message = QueuedMessage { - id: H256::zero(), - channel_id: ChannelId::from([1; 32]), - command: Command::Upgrade { - impl_address: H160::zero(), - impl_code_hash: H256::zero(), - initializer: Some(Initializer { - params: [7u8; 256].into_iter().collect(), - maximum_required_gas: 200_000, - }), - }, - }; - let origin = AggregateMessageOrigin::Snowbridge([1; 32].into()); - let encoded_enqueued_message = enqueued_message.encode(); - - #[block] - { - let _ = OutboundQueue::::do_process_message(origin, &encoded_enqueued_message); - } - - assert_eq!(MessageLeaves::::decode_len().unwrap(), 1); - - Ok(()) - } - - /// Benchmark for producing final messages commitment - #[benchmark] - fn commit() -> Result<(), BenchmarkError> { - // Assume worst case, where `MaxMessagesPerBlock` messages need to be committed. - for i in 0..T::MaxMessagesPerBlock::get() { - let leaf_data: [u8; 1] = [i as u8]; - let leaf = ::Hashing::hash(&leaf_data); - MessageLeaves::::append(leaf); - } - - #[block] - { - OutboundQueue::::commit(); - } - - Ok(()) - } - - /// Benchmark for producing commitment for a single message - #[benchmark] - fn commit_single() -> Result<(), BenchmarkError> { - let leaf = ::Hashing::hash(&[100; 1]); - MessageLeaves::::append(leaf); - - #[block] - { - OutboundQueue::::commit(); - } - - Ok(()) - } - - impl_benchmark_test_suite!(OutboundQueue, crate::mock::new_tester(), crate::mock::Test,); -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/lib.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/lib.rs deleted file mode 100644 index 9e949a4791a8..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/lib.rs +++ /dev/null @@ -1,406 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Pallet for committing outbound messages for delivery to Ethereum -//! -//! # Overview -//! -//! Messages come either from sibling parachains via XCM, or BridgeHub itself -//! via the `snowbridge-pallet-system`: -//! -//! 1. `snowbridge_router_primitives::outbound::EthereumBlobExporter::deliver` -//! 2. `snowbridge_pallet_system::Pallet::send` -//! -//! The message submission pipeline works like this: -//! 1. The message is first validated via the implementation for -//! [`snowbridge_core::outbound::SendMessage::validate`] -//! 2. The message is then enqueued for later processing via the implementation for -//! [`snowbridge_core::outbound::SendMessage::deliver`] -//! 3. The underlying message queue is implemented by [`Config::MessageQueue`] -//! 4. The message queue delivers messages back to this pallet via the implementation for -//! [`frame_support::traits::ProcessMessage::process_message`] -//! 5. The message is processed in `Pallet::do_process_message`: a. Assigned a nonce b. ABI-encoded, -//! hashed, and stored in the `MessageLeaves` vector -//! 6. At the end of the block, a merkle root is constructed from all the leaves in `MessageLeaves`. -//! 7. This merkle root is inserted into the parachain header as a digest item -//! 8. Offchain relayers are able to relay the message to Ethereum after: a. Generating a merkle -//! proof for the committed message using the `prove_message` runtime API b. Reading the actual -//! message content from the `Messages` vector in storage -//! -//! On the Ethereum side, the message root is ultimately the thing being -//! verified by the Polkadot light client. -//! -//! # Message Priorities -//! -//! The processing of governance commands can never be halted. This effectively -//! allows us to pause processing of normal user messages while still allowing -//! governance commands to be sent to Ethereum. -//! -//! # Fees -//! -//! An upfront fee must be paid for delivering a message. This fee covers several -//! components: -//! 1. The weight of processing the message locally -//! 2. The gas refund paid out to relayers for message submission -//! 3. An additional reward paid out to relayers for message submission -//! -//! Messages are weighed to determine the maximum amount of gas they could -//! consume on Ethereum. Using this upper bound, a final fee can be calculated. -//! -//! The fee calculation also requires the following parameters: -//! * ETH/DOT exchange rate -//! * Ether fee per unit of gas -//! -//! By design, it is expected that governance should manually update these -//! parameters every few weeks using the `set_pricing_parameters` extrinsic in the -//! system pallet. -//! -//! ## Fee Computation Function -//! -//! ```text -//! LocalFee(Message) = WeightToFee(ProcessMessageWeight(Message)) -//! RemoteFee(Message) = MaxGasRequired(Message) * FeePerGas + Reward -//! Fee(Message) = LocalFee(Message) + (RemoteFee(Message) / Ratio("ETH/DOT")) -//! ``` -//! -//! By design, the computed fee is always going to conservative, to cover worst-case -//! costs of dispatch on Ethereum. In future iterations of the design, we will optimize -//! this, or provide a mechanism to asynchronously refund a portion of collected fees. -//! -//! # Extrinsics -//! -//! * [`Call::set_operating_mode`]: Set the operating mode -//! -//! # Runtime API -//! -//! * `prove_message`: Generate a merkle proof for a committed message -//! * `calculate_fee`: Calculate the delivery fee for a message -#![cfg_attr(not(feature = "std"), no_std)] -pub mod api; -pub mod process_message_impl; -pub mod send_message_impl; -pub mod types; -pub mod weights; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod test; - -use bridge_hub_common::{AggregateMessageOrigin, CustomDigestItem}; -use codec::Decode; -use frame_support::{ - storage::StorageStreamIter, - traits::{tokens::Balance, Contains, Defensive, EnqueueMessage, Get, ProcessMessageError}, - weights::{Weight, WeightToFee}, -}; -use snowbridge_core::{ - outbound::{Fee, GasMeter, QueuedMessage, VersionedQueuedMessage, ETHER_DECIMALS}, - BasicOperatingMode, ChannelId, -}; -use snowbridge_outbound_queue_merkle_tree::merkle_root; -pub use snowbridge_outbound_queue_merkle_tree::MerkleProof; -use sp_core::{H256, U256}; -use sp_runtime::{ - traits::{CheckedDiv, Hash}, - DigestItem, -}; -use sp_std::prelude::*; -pub use types::{CommittedMessage, ProcessMessageOriginOf}; -pub use weights::WeightInfo; - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - use snowbridge_core::PricingParameters; - use sp_arithmetic::FixedU128; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - type Hashing: Hash; - - type MessageQueue: EnqueueMessage; - - /// Measures the maximum gas used to execute a command on Ethereum - type GasMeter: GasMeter; - - type Balance: Balance + From; - - /// Number of decimal places in native currency - #[pallet::constant] - type Decimals: Get; - - /// Max bytes in a message payload - #[pallet::constant] - type MaxMessagePayloadSize: Get; - - /// Max number of messages processed per block - #[pallet::constant] - type MaxMessagesPerBlock: Get; - - /// Check whether a channel exists - type Channels: Contains; - - type PricingParameters: Get>; - - /// Convert a weight value into a deductible fee based. - type WeightToFee: WeightToFee; - - /// Weight information for extrinsics in this pallet - type WeightInfo: WeightInfo; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Message has been queued and will be processed in the future - MessageQueued { - /// ID of the message. Usually the XCM message hash or a SetTopic. - id: H256, - }, - /// Message will be committed at the end of current block. From now on, to track the - /// progress the message, use the `nonce` of `id`. - MessageAccepted { - /// ID of the message - id: H256, - /// The nonce assigned to this message - nonce: u64, - }, - /// Some messages have been committed - MessagesCommitted { - /// Merkle root of the committed messages - root: H256, - /// number of committed messages - count: u64, - }, - /// Set OperatingMode - OperatingModeChanged { mode: BasicOperatingMode }, - } - - #[pallet::error] - pub enum Error { - /// The message is too large - MessageTooLarge, - /// The pallet is halted - Halted, - /// Invalid Channel - InvalidChannel, - } - - /// Messages to be committed in the current block. This storage value is killed in - /// `on_initialize`, so should never go into block PoV. - /// - /// Is never read in the runtime, only by offchain message relayers. - /// - /// Inspired by the `frame_system::Pallet::Events` storage value - #[pallet::storage] - #[pallet::unbounded] - pub(super) type Messages = StorageValue<_, Vec, ValueQuery>; - - /// Hashes of the ABI-encoded messages in the [`Messages`] storage value. Used to generate a - /// merkle root during `on_finalize`. This storage value is killed in - /// `on_initialize`, so should never go into block PoV. - #[pallet::storage] - #[pallet::unbounded] - #[pallet::getter(fn message_leaves)] - pub(super) type MessageLeaves = StorageValue<_, Vec, ValueQuery>; - - /// The current nonce for each message origin - #[pallet::storage] - pub type Nonce = StorageMap<_, Twox64Concat, ChannelId, u64, ValueQuery>; - - /// The current operating mode of the pallet. - #[pallet::storage] - #[pallet::getter(fn operating_mode)] - pub type OperatingMode = StorageValue<_, BasicOperatingMode, ValueQuery>; - - #[pallet::hooks] - impl Hooks> for Pallet - where - T::AccountId: AsRef<[u8]>, - { - fn on_initialize(_: BlockNumberFor) -> Weight { - // Remove storage from previous block - Messages::::kill(); - MessageLeaves::::kill(); - // Reserve some weight for the `on_finalize` handler - T::WeightInfo::commit() - } - - fn on_finalize(_: BlockNumberFor) { - Self::commit(); - } - - fn integrity_test() { - let decimals = T::Decimals::get(); - assert!(decimals == 10 || decimals == 12, "Decimals should be 10 or 12"); - } - } - - #[pallet::call] - impl Pallet { - /// Halt or resume all pallet operations. May only be called by root. - #[pallet::call_index(0)] - #[pallet::weight((T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational))] - pub fn set_operating_mode( - origin: OriginFor, - mode: BasicOperatingMode, - ) -> DispatchResult { - ensure_root(origin)?; - OperatingMode::::put(mode); - Self::deposit_event(Event::OperatingModeChanged { mode }); - Ok(()) - } - } - - impl Pallet { - /// Generate a messages commitment and insert it into the header digest - pub(crate) fn commit() { - let count = MessageLeaves::::decode_len().unwrap_or_default() as u64; - if count == 0 { - return - } - - // Create merkle root of messages - let root = merkle_root::<::Hashing, _>(MessageLeaves::::stream_iter()); - - let digest_item: DigestItem = CustomDigestItem::Snowbridge(root).into(); - - // Insert merkle root into the header digest - >::deposit_log(digest_item); - - Self::deposit_event(Event::MessagesCommitted { root, count }); - } - - /// Process a message delivered by the MessageQueue pallet - pub(crate) fn do_process_message( - _: ProcessMessageOriginOf, - mut message: &[u8], - ) -> Result { - use ProcessMessageError::*; - - // Yield if the maximum number of messages has been processed this block. - // This ensures that the weight of `on_finalize` has a known maximum bound. - ensure!( - MessageLeaves::::decode_len().unwrap_or(0) < - T::MaxMessagesPerBlock::get() as usize, - Yield - ); - - // Decode bytes into versioned message - let versioned_queued_message: VersionedQueuedMessage = - VersionedQueuedMessage::decode(&mut message).map_err(|_| Corrupt)?; - - // Convert versioned message into latest supported message version - let queued_message: QueuedMessage = - versioned_queued_message.try_into().map_err(|_| Unsupported)?; - - // Obtain next nonce - let nonce = >::try_mutate( - queued_message.channel_id, - |nonce| -> Result { - *nonce = nonce.checked_add(1).ok_or(Unsupported)?; - Ok(*nonce) - }, - )?; - - let pricing_params = T::PricingParameters::get(); - let command = queued_message.command.index(); - let params = queued_message.command.abi_encode(); - let max_dispatch_gas = - T::GasMeter::maximum_dispatch_gas_used_at_most(&queued_message.command); - let reward = pricing_params.rewards.remote; - - // Construct the final committed message - let message = CommittedMessage { - channel_id: queued_message.channel_id, - nonce, - command, - params, - max_dispatch_gas, - max_fee_per_gas: pricing_params - .fee_per_gas - .try_into() - .defensive_unwrap_or(u128::MAX), - reward: reward.try_into().defensive_unwrap_or(u128::MAX), - id: queued_message.id, - }; - - // ABI-encode and hash the prepared message - let message_abi_encoded = ethabi::encode(&[message.clone().into()]); - let message_abi_encoded_hash = ::Hashing::hash(&message_abi_encoded); - - Messages::::append(Box::new(message)); - MessageLeaves::::append(message_abi_encoded_hash); - - Self::deposit_event(Event::MessageAccepted { id: queued_message.id, nonce }); - - Ok(true) - } - - /// Calculate total fee in native currency to cover all costs of delivering a message to the - /// remote destination. See module-level documentation for more details. - pub(crate) fn calculate_fee( - gas_used_at_most: u64, - params: PricingParameters, - ) -> Fee { - // Remote fee in ether - let fee = Self::calculate_remote_fee( - gas_used_at_most, - params.fee_per_gas, - params.rewards.remote, - ); - - // downcast to u128 - let fee: u128 = fee.try_into().defensive_unwrap_or(u128::MAX); - - // convert to local currency - let fee = FixedU128::from_inner(fee) - .checked_div(¶ms.exchange_rate) - .expect("exchange rate is not zero; qed") - .into_inner(); - - // adjust fixed point to match local currency - let fee = Self::convert_from_ether_decimals(fee); - - Fee::from((Self::calculate_local_fee(), fee)) - } - - /// Calculate fee in remote currency for dispatching a message on Ethereum - pub(crate) fn calculate_remote_fee( - gas_used_at_most: u64, - fee_per_gas: U256, - reward: U256, - ) -> U256 { - fee_per_gas.saturating_mul(gas_used_at_most.into()).saturating_add(reward) - } - - /// The local component of the message processing fees in native currency - pub(crate) fn calculate_local_fee() -> T::Balance { - T::WeightToFee::weight_to_fee( - &T::WeightInfo::do_process_message().saturating_add(T::WeightInfo::commit_single()), - ) - } - - // 1 DOT has 10 digits of precision - // 1 KSM has 12 digits of precision - // 1 ETH has 18 digits of precision - pub(crate) fn convert_from_ether_decimals(value: u128) -> T::Balance { - let decimals = ETHER_DECIMALS.saturating_sub(T::Decimals::get()) as u32; - let denom = 10u128.saturating_pow(decimals); - value.checked_div(denom).expect("divisor is non-zero; qed").into() - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/mock.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/mock.rs deleted file mode 100644 index dd8fee4e2ed0..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/mock.rs +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use super::*; - -use frame_support::{ - parameter_types, - traits::{Everything, Hooks}, - weights::IdentityFee, -}; - -use snowbridge_core::{ - gwei, meth, - outbound::*, - pricing::{PricingParameters, Rewards}, - ParaId, PRIMARY_GOVERNANCE_CHANNEL, -}; -use sp_core::{ConstU32, ConstU8, H160, H256}; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup, Keccak256}, - AccountId32, BuildStorage, FixedU128, -}; -use sp_std::marker::PhantomData; - -type Block = frame_system::mocking::MockBlock; -type AccountId = AccountId32; - -frame_support::construct_runtime!( - pub enum Test - { - System: frame_system::{Pallet, Call, Storage, Event}, - MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event}, - OutboundQueue: crate::{Pallet, Storage, Event}, - } -); - -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - -impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - type Nonce = u64; - type Block = Block; -} - -parameter_types! { - pub const HeapSize: u32 = 32 * 1024; - pub const MaxStale: u32 = 32; - pub static ServiceWeight: Option = Some(Weight::from_parts(100, 100)); -} - -impl pallet_message_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type MessageProcessor = OutboundQueue; - type Size = u32; - type QueueChangeHandler = (); - type HeapSize = HeapSize; - type MaxStale = MaxStale; - type ServiceWeight = ServiceWeight; - type QueuePausedQuery = (); -} - -parameter_types! { - pub const OwnParaId: ParaId = ParaId::new(1013); - pub Parameters: PricingParameters = PricingParameters { - exchange_rate: FixedU128::from_rational(1, 400), - fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } - }; -} - -pub const DOT: u128 = 10_000_000_000; - -impl crate::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Hashing = Keccak256; - type MessageQueue = MessageQueue; - type Decimals = ConstU8<12>; - type MaxMessagePayloadSize = ConstU32<1024>; - type MaxMessagesPerBlock = ConstU32<20>; - type GasMeter = ConstantGasMeter; - type Balance = u128; - type PricingParameters = Parameters; - type Channels = Everything; - type WeightToFee = IdentityFee; - type WeightInfo = (); -} - -fn setup() { - System::set_block_number(1); -} - -pub fn new_tester() -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - let mut ext: sp_io::TestExternalities = storage.into(); - ext.execute_with(setup); - ext -} - -pub fn run_to_end_of_next_block() { - // finish current block - MessageQueue::on_finalize(System::block_number()); - OutboundQueue::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - // start next block - System::set_block_number(System::block_number() + 1); - System::on_initialize(System::block_number()); - OutboundQueue::on_initialize(System::block_number()); - MessageQueue::on_initialize(System::block_number()); - // finish next block - MessageQueue::on_finalize(System::block_number()); - OutboundQueue::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); -} - -pub fn mock_governance_message() -> Message -where - T: Config, -{ - let _marker = PhantomData::; // for clippy - - Message { - id: None, - channel_id: PRIMARY_GOVERNANCE_CHANNEL, - command: Command::Upgrade { - impl_address: H160::zero(), - impl_code_hash: H256::zero(), - initializer: None, - }, - } -} - -// Message should fail validation as it is too large -pub fn mock_invalid_governance_message() -> Message -where - T: Config, -{ - let _marker = PhantomData::; // for clippy - - Message { - id: None, - channel_id: PRIMARY_GOVERNANCE_CHANNEL, - command: Command::Upgrade { - impl_address: H160::zero(), - impl_code_hash: H256::zero(), - initializer: Some(Initializer { - params: (0..1000).map(|_| 1u8).collect::>(), - maximum_required_gas: 0, - }), - }, - } -} - -pub fn mock_message(sibling_para_id: u32) -> Message { - Message { - id: None, - channel_id: ParaId::from(sibling_para_id).into(), - command: Command::AgentExecute { - agent_id: Default::default(), - command: AgentExecuteCommand::TransferToken { - token: Default::default(), - recipient: Default::default(), - amount: 0, - }, - }, - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/process_message_impl.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/process_message_impl.rs deleted file mode 100644 index 575ed9e0e7c2..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/process_message_impl.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Implementation for [`frame_support::traits::ProcessMessage`] -use super::*; -use crate::weights::WeightInfo; -use frame_support::{ - traits::{ProcessMessage, ProcessMessageError}, - weights::WeightMeter, -}; - -impl ProcessMessage for Pallet { - type Origin = AggregateMessageOrigin; - fn process_message( - message: &[u8], - origin: Self::Origin, - meter: &mut WeightMeter, - _: &mut [u8; 32], - ) -> Result { - let weight = T::WeightInfo::do_process_message(); - if meter.try_consume(weight).is_err() { - return Err(ProcessMessageError::Overweight(weight)) - } - Self::do_process_message(origin, message) - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/send_message_impl.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/send_message_impl.rs deleted file mode 100644 index a84e2c520e59..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/send_message_impl.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! Implementation for [`snowbridge_core::outbound::SendMessage`] -use super::*; -use bridge_hub_common::AggregateMessageOrigin; -use codec::Encode; -use frame_support::{ - ensure, - traits::{EnqueueMessage, Get}, - CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, -}; -use frame_system::unique; -use snowbridge_core::{ - outbound::{ - Fee, Message, QueuedMessage, SendError, SendMessage, SendMessageFeeProvider, - VersionedQueuedMessage, - }, - ChannelId, PRIMARY_GOVERNANCE_CHANNEL, -}; -use sp_core::H256; -use sp_runtime::BoundedVec; - -/// The maximal length of an enqueued message, as determined by the MessageQueue pallet -pub type MaxEnqueuedMessageSizeOf = - <::MessageQueue as EnqueueMessage>::MaxMessageLen; - -#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound)] -pub struct Ticket -where - T: Config, -{ - pub message_id: H256, - pub channel_id: ChannelId, - pub message: BoundedVec>, -} - -impl SendMessage for Pallet -where - T: Config, -{ - type Ticket = Ticket; - - fn validate( - message: &Message, - ) -> Result<(Self::Ticket, Fee<::Balance>), SendError> { - // The inner payload should not be too large - let payload = message.command.abi_encode(); - ensure!( - payload.len() < T::MaxMessagePayloadSize::get() as usize, - SendError::MessageTooLarge - ); - - // Ensure there is a registered channel we can transmit this message on - ensure!(T::Channels::contains(&message.channel_id), SendError::InvalidChannel); - - // Generate a unique message id unless one is provided - let message_id: H256 = message - .id - .unwrap_or_else(|| unique((message.channel_id, &message.command)).into()); - - let gas_used_at_most = T::GasMeter::maximum_gas_used_at_most(&message.command); - let fee = Self::calculate_fee(gas_used_at_most, T::PricingParameters::get()); - - let queued_message: VersionedQueuedMessage = QueuedMessage { - id: message_id, - channel_id: message.channel_id, - command: message.command.clone(), - } - .into(); - // The whole message should not be too large - let encoded = queued_message.encode().try_into().map_err(|_| SendError::MessageTooLarge)?; - - let ticket = Ticket { message_id, channel_id: message.channel_id, message: encoded }; - - Ok((ticket, fee)) - } - - fn deliver(ticket: Self::Ticket) -> Result { - let origin = AggregateMessageOrigin::Snowbridge(ticket.channel_id); - - if ticket.channel_id != PRIMARY_GOVERNANCE_CHANNEL { - ensure!(!Self::operating_mode().is_halted(), SendError::Halted); - } - - let message = ticket.message.as_bounded_slice(); - - T::MessageQueue::enqueue_message(message, origin); - Self::deposit_event(Event::MessageQueued { id: ticket.message_id }); - Ok(ticket.message_id) - } -} - -impl SendMessageFeeProvider for Pallet { - type Balance = T::Balance; - - /// The local component of the message processing fees in native currency - fn local_fee() -> Self::Balance { - Self::calculate_local_fee() - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/test.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/test.rs deleted file mode 100644 index 0028d75e7b79..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/test.rs +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{mock::*, *}; - -use frame_support::{ - assert_err, assert_noop, assert_ok, - traits::{Hooks, ProcessMessage, ProcessMessageError}, - weights::WeightMeter, -}; - -use codec::Encode; -use snowbridge_core::{ - outbound::{Command, SendError, SendMessage}, - ParaId, -}; -use sp_arithmetic::FixedU128; -use sp_core::H256; -use sp_runtime::FixedPointNumber; - -#[test] -fn submit_messages_and_commit() { - new_tester().execute_with(|| { - for para_id in 1000..1004 { - let message = mock_message(para_id); - let (ticket, _) = OutboundQueue::validate(&message).unwrap(); - assert_ok!(OutboundQueue::deliver(ticket)); - } - - ServiceWeight::set(Some(Weight::MAX)); - run_to_end_of_next_block(); - - for para_id in 1000..1004 { - let origin: ParaId = (para_id as u32).into(); - let channel_id: ChannelId = origin.into(); - assert_eq!(Nonce::::get(channel_id), 1); - } - - let digest = System::digest(); - let digest_items = digest.logs(); - assert!(digest_items.len() == 1 && digest_items[0].as_other().is_some()); - assert_eq!(Messages::::decode_len(), Some(4)); - }); -} - -#[test] -fn submit_message_fail_too_large() { - new_tester().execute_with(|| { - let message = mock_invalid_governance_message::(); - assert_err!(OutboundQueue::validate(&message), SendError::MessageTooLarge); - }); -} - -#[test] -fn convert_from_ether_decimals() { - assert_eq!( - OutboundQueue::convert_from_ether_decimals(1_000_000_000_000_000_000), - 1_000_000_000_000 - ); -} - -#[test] -fn commit_exits_early_if_no_processed_messages() { - new_tester().execute_with(|| { - // on_finalize should do nothing, nor should it panic - OutboundQueue::on_finalize(System::block_number()); - - let digest = System::digest(); - let digest_items = digest.logs(); - assert_eq!(digest_items.len(), 0); - }); -} - -#[test] -fn process_message_yields_on_max_messages_per_block() { - new_tester().execute_with(|| { - for _ in 0..::MaxMessagesPerBlock::get() { - MessageLeaves::::append(H256::zero()) - } - - let channel_id: ChannelId = ParaId::from(1000).into(); - let origin = AggregateMessageOrigin::Snowbridge(channel_id); - let message = QueuedMessage { - id: Default::default(), - channel_id, - command: Command::Upgrade { - impl_address: Default::default(), - impl_code_hash: Default::default(), - initializer: None, - }, - } - .encode(); - - let mut meter = WeightMeter::new(); - - assert_noop!( - OutboundQueue::process_message(message.as_slice(), origin, &mut meter, &mut [0u8; 32]), - ProcessMessageError::Yield - ); - }) -} - -#[test] -fn process_message_fails_on_max_nonce_reached() { - new_tester().execute_with(|| { - let sibling_id = 1000; - let channel_id: ChannelId = ParaId::from(sibling_id).into(); - let origin = AggregateMessageOrigin::Snowbridge(channel_id); - let message: QueuedMessage = QueuedMessage { - id: H256::zero(), - channel_id, - command: mock_message(sibling_id).command, - }; - let versioned_queued_message: VersionedQueuedMessage = message.try_into().unwrap(); - let encoded = versioned_queued_message.encode(); - let mut meter = WeightMeter::with_limit(Weight::MAX); - - Nonce::::set(channel_id, u64::MAX); - - assert_noop!( - OutboundQueue::process_message(encoded.as_slice(), origin, &mut meter, &mut [0u8; 32]), - ProcessMessageError::Unsupported - ); - }) -} - -#[test] -fn process_message_fails_on_overweight_message() { - new_tester().execute_with(|| { - let sibling_id = 1000; - let channel_id: ChannelId = ParaId::from(sibling_id).into(); - let origin = AggregateMessageOrigin::Snowbridge(channel_id); - let message: QueuedMessage = QueuedMessage { - id: H256::zero(), - channel_id, - command: mock_message(sibling_id).command, - }; - let versioned_queued_message: VersionedQueuedMessage = message.try_into().unwrap(); - let encoded = versioned_queued_message.encode(); - let mut meter = WeightMeter::with_limit(Weight::from_parts(1, 1)); - assert_noop!( - OutboundQueue::process_message(encoded.as_slice(), origin, &mut meter, &mut [0u8; 32]), - ProcessMessageError::Overweight(::WeightInfo::do_process_message()) - ); - }) -} - -// Governance messages should be able to bypass a halted operating mode -// Other message sends should fail when halted -#[test] -fn submit_upgrade_message_success_when_queue_halted() { - new_tester().execute_with(|| { - // halt the outbound queue - OutboundQueue::set_operating_mode(RuntimeOrigin::root(), BasicOperatingMode::Halted) - .unwrap(); - - // submit a high priority message from bridge_hub should success - let message = mock_governance_message::(); - let (ticket, _) = OutboundQueue::validate(&message).unwrap(); - assert_ok!(OutboundQueue::deliver(ticket)); - - // submit a low priority message from asset_hub will fail as pallet is halted - let message = mock_message(1000); - let (ticket, _) = OutboundQueue::validate(&message).unwrap(); - assert_noop!(OutboundQueue::deliver(ticket), SendError::Halted); - }); -} - -#[test] -fn governance_message_does_not_get_the_chance_to_processed_in_same_block_when_congest_of_low_priority_sibling_messages( -) { - use snowbridge_core::PRIMARY_GOVERNANCE_CHANNEL; - use AggregateMessageOrigin::*; - - let sibling_id: u32 = 1000; - let sibling_channel_id: ChannelId = ParaId::from(sibling_id).into(); - - new_tester().execute_with(|| { - // submit a lot of low priority messages from asset_hub which will need multiple blocks to - // execute(20 messages for each block so 40 required at least 2 blocks) - let max_messages = 40; - for _ in 0..max_messages { - // submit low priority message - let message = mock_message(sibling_id); - let (ticket, _) = OutboundQueue::validate(&message).unwrap(); - OutboundQueue::deliver(ticket).unwrap(); - } - - let footprint = MessageQueue::footprint(Snowbridge(sibling_channel_id)); - assert_eq!(footprint.storage.count, (max_messages) as u64); - - let message = mock_governance_message::(); - let (ticket, _) = OutboundQueue::validate(&message).unwrap(); - OutboundQueue::deliver(ticket).unwrap(); - - // move to next block - ServiceWeight::set(Some(Weight::MAX)); - run_to_end_of_next_block(); - - // first process 20 messages from sibling channel - let footprint = MessageQueue::footprint(Snowbridge(sibling_channel_id)); - assert_eq!(footprint.storage.count, 40 - 20); - - // and governance message does not have the chance to execute in same block - let footprint = MessageQueue::footprint(Snowbridge(PRIMARY_GOVERNANCE_CHANNEL)); - assert_eq!(footprint.storage.count, 1); - - // move to next block - ServiceWeight::set(Some(Weight::MAX)); - run_to_end_of_next_block(); - - // now governance message get executed in this block - let footprint = MessageQueue::footprint(Snowbridge(PRIMARY_GOVERNANCE_CHANNEL)); - assert_eq!(footprint.storage.count, 0); - - // and this time process 19 messages from sibling channel so we have 1 message left - let footprint = MessageQueue::footprint(Snowbridge(sibling_channel_id)); - assert_eq!(footprint.storage.count, 1); - - // move to the next block, the last 1 message from sibling channel get executed - ServiceWeight::set(Some(Weight::MAX)); - run_to_end_of_next_block(); - let footprint = MessageQueue::footprint(Snowbridge(sibling_channel_id)); - assert_eq!(footprint.storage.count, 0); - }); -} - -#[test] -fn convert_local_currency() { - new_tester().execute_with(|| { - let fee: u128 = 1_000_000; - let fee1 = FixedU128::from_inner(fee).into_inner(); - let fee2 = FixedU128::from(fee) - .into_inner() - .checked_div(FixedU128::accuracy()) - .expect("accuracy is not zero; qed"); - assert_eq!(fee, fee1); - assert_eq!(fee, fee2); - }); -} - -#[test] -fn encode_digest_item_with_correct_index() { - new_tester().execute_with(|| { - let digest_item: DigestItem = CustomDigestItem::Snowbridge(H256::default()).into(); - let enum_prefix = match digest_item { - DigestItem::Other(data) => data[0], - _ => u8::MAX, - }; - assert_eq!(enum_prefix, 0); - }); -} - -#[test] -fn encode_digest_item() { - new_tester().execute_with(|| { - let digest_item: DigestItem = CustomDigestItem::Snowbridge([5u8; 32].into()).into(); - let digest_item_raw = digest_item.encode(); - assert_eq!(digest_item_raw[0], 0); // DigestItem::Other - assert_eq!(digest_item_raw[2], 0); // CustomDigestItem::Snowbridge - assert_eq!( - digest_item_raw, - [ - 0, 132, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5 - ] - ); - }); -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/types.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/types.rs deleted file mode 100644 index 28d400bb9d46..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/types.rs +++ /dev/null @@ -1,57 +0,0 @@ -use codec::{Decode, Encode}; -use ethabi::Token; -use frame_support::traits::ProcessMessage; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -use super::Pallet; - -use snowbridge_core::ChannelId; -pub use snowbridge_outbound_queue_merkle_tree::MerkleProof; - -pub type ProcessMessageOriginOf = as ProcessMessage>::Origin; - -pub const LOG_TARGET: &str = "snowbridge-outbound-queue"; - -/// Message which has been assigned a nonce and will be committed at the end of a block -#[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, TypeInfo)] -pub struct CommittedMessage { - /// Message channel - pub channel_id: ChannelId, - /// Unique nonce to prevent replaying messages - #[codec(compact)] - pub nonce: u64, - /// Command to execute in the Gateway contract - pub command: u8, - /// Params for the command - pub params: Vec, - /// Maximum gas allowed for message dispatch - #[codec(compact)] - pub max_dispatch_gas: u64, - /// Maximum fee per gas - #[codec(compact)] - pub max_fee_per_gas: u128, - /// Reward in ether for delivering this message, in addition to the gas refund - #[codec(compact)] - pub reward: u128, - /// Message ID (Used for tracing messages across route, has no role in consensus) - pub id: H256, -} - -/// Convert message into an ABI-encoded form for delivery to the InboundQueue contract on Ethereum -impl From for Token { - fn from(x: CommittedMessage) -> Token { - Token::Tuple(vec![ - Token::FixedBytes(Vec::from(x.channel_id.as_ref())), - Token::Uint(x.nonce.into()), - Token::Uint(x.command.into()), - Token::Bytes(x.params.to_vec()), - Token::Uint(x.max_dispatch_gas.into()), - Token::Uint(x.max_fee_per_gas.into()), - Token::Uint(x.reward.into()), - Token::FixedBytes(Vec::from(x.id.as_ref())), - ]) - } -} diff --git a/bridges/snowbridge/parachain/pallets/outbound-queue/src/weights.rs b/bridges/snowbridge/parachain/pallets/outbound-queue/src/weights.rs deleted file mode 100644 index 87eee1a31e87..000000000000 --- a/bridges/snowbridge/parachain/pallets/outbound-queue/src/weights.rs +++ /dev/null @@ -1,81 +0,0 @@ - -//! Autogenerated weights for `snowbridge-pallet-outbound-queue` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-19, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `192.168.1.7`, CPU: `` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: `1024` - -// Executed Command: -// target/release/polkadot-parachain -// benchmark -// pallet -// --chain=bridge-hub-rococo-dev -// --pallet=snowbridge-pallet-outbound-queue -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --template -// ../parachain/templates/module-weight-template.hbs -// --output -// ../parachain/pallets/outbound-queue/src/weights.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `snowbridge-pallet-outbound-queue`. -pub trait WeightInfo { - fn do_process_message() -> Weight; - fn commit() -> Weight; - fn commit_single() -> Weight; -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:1) - /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: EthereumOutboundQueue PendingHighPriorityMessageCount (r:1 w:1) - /// Proof: EthereumOutboundQueue PendingHighPriorityMessageCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue Nonce (r:1 w:1) - /// Proof: EthereumOutboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue Messages (r:1 w:1) - /// Proof Skipped: EthereumOutboundQueue Messages (max_values: Some(1), max_size: None, mode: Measured) - fn do_process_message() -> Weight { - // Proof Size summary in bytes: - // Measured: `42` - // Estimated: `3485` - // Minimum execution time: 39_000_000 picoseconds. - Weight::from_parts(39_000_000, 3485) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(4_u64)) - } - /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:0) - /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Digest (r:1 w:1) - /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - fn commit() -> Weight { - // Proof Size summary in bytes: - // Measured: `1094` - // Estimated: `2579` - // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(28_000_000, 2579) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - - fn commit_single() -> Weight { - // Proof Size summary in bytes: - // Measured: `1094` - // Estimated: `2579` - // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(9_000_000, 1586) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} diff --git a/bridges/snowbridge/parachain/pallets/system/Cargo.toml b/bridges/snowbridge/parachain/pallets/system/Cargo.toml deleted file mode 100644 index 70155370d196..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/Cargo.toml +++ /dev/null @@ -1,87 +0,0 @@ -[package] -name = "snowbridge-pallet-system" -description = "Snowbridge System Pallet" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -log = { version = "0.4.20", default-features = false } - -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } - -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } - -ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } -snowbridge-core = { path = "../../primitives/core", default-features = false } - -[dev-dependencies] -hex = "0.4.1" -hex-literal = { version = "0.4.1" } -pallet-balances = { path = "../../../../../substrate/frame/balances" } -sp-keyring = { path = "../../../../../substrate/primitives/keyring" } -polkadot-primitives = { path = "../../../../../polkadot/primitives" } -pallet-message-queue = { path = "../../../../../substrate/frame/message-queue" } -snowbridge-pallet-outbound-queue = { path = "../outbound-queue" } - -[features] -default = ["std"] -std = [ - "codec/std", - "ethabi/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "snowbridge-core/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "polkadot-primitives/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "snowbridge-pallet-outbound-queue/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "pallet-balances/try-runtime", - "pallet-message-queue/try-runtime", - "snowbridge-pallet-outbound-queue/try-runtime", - "sp-runtime/try-runtime", -] diff --git a/bridges/snowbridge/parachain/pallets/system/README.md b/bridges/snowbridge/parachain/pallets/system/README.md deleted file mode 100644 index 5ab11d45eae2..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ethereum System - -Contains management functions to manage functions on Ethereum. For example, creating agents and channels. diff --git a/bridges/snowbridge/parachain/pallets/system/runtime-api/Cargo.toml b/bridges/snowbridge/parachain/pallets/system/runtime-api/Cargo.toml deleted file mode 100644 index 96d5aa522c03..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/runtime-api/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "snowbridge-system-runtime-api" -description = "Snowbridge System Runtime API" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = [ - "derive", -] } -sp-core = { path = "../../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../../substrate/primitives/std", default-features = false } -sp-api = { path = "../../../../../../substrate/primitives/api", default-features = false } -xcm = { package = "staging-xcm", path = "../../../../../../polkadot/xcm", default-features = false } -snowbridge-core = { path = "../../../primitives/core", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "snowbridge-core/std", - "sp-api/std", - "sp-core/std", - "sp-std/std", - "xcm/std", -] diff --git a/bridges/snowbridge/parachain/pallets/system/runtime-api/README.md b/bridges/snowbridge/parachain/pallets/system/runtime-api/README.md deleted file mode 100644 index 99827c9c2fc2..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/runtime-api/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Ethereum System Runtime API - -Provides an API for looking up an agent ID on Ethereum. diff --git a/bridges/snowbridge/parachain/pallets/system/runtime-api/src/lib.rs b/bridges/snowbridge/parachain/pallets/system/runtime-api/src/lib.rs deleted file mode 100644 index 7f119809546e..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/runtime-api/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] - -use snowbridge_core::AgentId; -use xcm::VersionedLocation; - -sp_api::decl_runtime_apis! { - pub trait ControlApi - { - fn agent_id(location: VersionedLocation) -> Option; - } -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/api.rs b/bridges/snowbridge/parachain/pallets/system/src/api.rs deleted file mode 100644 index ef12b03e1d75..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/api.rs +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Helpers for implementing runtime api - -use snowbridge_core::AgentId; -use xcm::{prelude::*, VersionedLocation}; - -use crate::{agent_id_of, Config}; - -pub fn agent_id(location: VersionedLocation) -> Option -where - Runtime: Config, -{ - let location: Location = location.try_into().ok()?; - agent_id_of::(&location).ok() -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/benchmarking.rs b/bridges/snowbridge/parachain/pallets/system/src/benchmarking.rs deleted file mode 100644 index ef908ad6a3f9..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/benchmarking.rs +++ /dev/null @@ -1,167 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Benchmarking setup for pallet-template -use super::*; - -#[allow(unused)] -use crate::Pallet as SnowbridgeControl; -use frame_benchmarking::v2::*; -use frame_system::RawOrigin; -use snowbridge_core::{eth, outbound::OperatingMode}; -use sp_runtime::SaturatedConversion; -use xcm::prelude::*; - -#[allow(clippy::result_large_err)] -fn fund_sovereign_account(para_id: ParaId) -> Result<(), BenchmarkError> { - let amount: BalanceOf = (10_000_000_000_000_u64).saturated_into::().saturated_into(); - let sovereign_account = sibling_sovereign_account::(para_id); - T::Token::mint_into(&sovereign_account, amount)?; - Ok(()) -} - -#[benchmarks] -mod benchmarks { - use super::*; - - #[benchmark] - fn upgrade() -> Result<(), BenchmarkError> { - let impl_address = H160::repeat_byte(1); - let impl_code_hash = H256::repeat_byte(1); - - // Assume 256 bytes passed to initializer - let params: Vec = (0..256).map(|_| 1u8).collect(); - - #[extrinsic_call] - _( - RawOrigin::Root, - impl_address, - impl_code_hash, - Some(Initializer { params, maximum_required_gas: 100000 }), - ); - - Ok(()) - } - - #[benchmark] - fn set_operating_mode() -> Result<(), BenchmarkError> { - #[extrinsic_call] - _(RawOrigin::Root, OperatingMode::RejectingOutboundMessages); - - Ok(()) - } - - #[benchmark] - fn set_pricing_parameters() -> Result<(), BenchmarkError> { - let params = T::DefaultPricingParameters::get(); - - #[extrinsic_call] - _(RawOrigin::Root, params); - - Ok(()) - } - - #[benchmark] - fn create_agent() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location); - fund_sovereign_account::(origin_para_id.into())?; - - #[extrinsic_call] - _(origin as T::RuntimeOrigin); - - Ok(()) - } - - #[benchmark] - fn create_channel() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location); - fund_sovereign_account::(origin_para_id.into())?; - - SnowbridgeControl::::create_agent(origin.clone())?; - - #[extrinsic_call] - _(origin as T::RuntimeOrigin, OperatingMode::Normal); - - Ok(()) - } - - #[benchmark] - fn update_channel() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location); - fund_sovereign_account::(origin_para_id.into())?; - SnowbridgeControl::::create_agent(origin.clone())?; - SnowbridgeControl::::create_channel(origin.clone(), OperatingMode::Normal)?; - - #[extrinsic_call] - _(origin as T::RuntimeOrigin, OperatingMode::RejectingOutboundMessages); - - Ok(()) - } - - #[benchmark] - fn force_update_channel() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location); - let channel_id: ChannelId = ParaId::from(origin_para_id).into(); - - fund_sovereign_account::(origin_para_id.into())?; - SnowbridgeControl::::create_agent(origin.clone())?; - SnowbridgeControl::::create_channel(origin.clone(), OperatingMode::Normal)?; - - #[extrinsic_call] - _(RawOrigin::Root, channel_id, OperatingMode::RejectingOutboundMessages); - - Ok(()) - } - - #[benchmark] - fn transfer_native_from_agent() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location); - fund_sovereign_account::(origin_para_id.into())?; - SnowbridgeControl::::create_agent(origin.clone())?; - SnowbridgeControl::::create_channel(origin.clone(), OperatingMode::Normal)?; - - #[extrinsic_call] - _(origin as T::RuntimeOrigin, H160::default(), 1); - - Ok(()) - } - - #[benchmark] - fn force_transfer_native_from_agent() -> Result<(), BenchmarkError> { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let origin = T::Helper::make_xcm_origin(origin_location.clone()); - fund_sovereign_account::(origin_para_id.into())?; - SnowbridgeControl::::create_agent(origin.clone())?; - - let versioned_location: VersionedLocation = origin_location.into(); - - #[extrinsic_call] - _(RawOrigin::Root, Box::new(versioned_location), H160::default(), 1); - - Ok(()) - } - - #[benchmark] - fn set_token_transfer_fees() -> Result<(), BenchmarkError> { - #[extrinsic_call] - _(RawOrigin::Root, 1, 1, eth(1)); - - Ok(()) - } - - impl_benchmark_test_suite!( - SnowbridgeControl, - crate::mock::new_test_ext(true), - crate::mock::Test - ); -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/lib.rs b/bridges/snowbridge/parachain/pallets/system/src/lib.rs deleted file mode 100644 index e742bd8e1102..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/lib.rs +++ /dev/null @@ -1,681 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Governance API for controlling the Ethereum side of the bridge -//! -//! # Extrinsics -//! -//! ## Agents -//! -//! Agents are smart contracts on Ethereum that act as proxies for consensus systems on Polkadot -//! networks. -//! -//! * [`Call::create_agent`]: Create agent for a sibling parachain -//! * [`Call::transfer_native_from_agent`]: Withdraw ether from an agent -//! -//! The `create_agent` extrinsic should be called via an XCM `Transact` instruction from the sibling -//! parachain. -//! -//! ## Channels -//! -//! Each sibling parachain has its own dedicated messaging channel for sending and receiving -//! messages. As a prerequisite to creating a channel, the sibling should have already created -//! an agent using the `create_agent` extrinsic. -//! -//! * [`Call::create_channel`]: Create channel for a sibling -//! * [`Call::update_channel`]: Update a channel for a sibling -//! -//! ## Governance -//! -//! Only Polkadot governance itself can call these extrinsics. Delivery fees are waived. -//! -//! * [`Call::upgrade`]`: Upgrade the gateway contract -//! * [`Call::set_operating_mode`]: Update the operating mode of the gateway contract -//! * [`Call::force_update_channel`]: Allow root to update a channel for a sibling -//! * [`Call::force_transfer_native_from_agent`]: Allow root to withdraw ether from an agent -//! -//! Typically, Polkadot governance will use the `force_transfer_native_from_agent` and -//! `force_update_channel` and extrinsics to manage agents and channels for system parachains. -#![cfg_attr(not(feature = "std"), no_std)] - -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -pub mod migration; - -pub mod api; -pub mod weights; -pub use weights::*; - -use frame_support::{ - pallet_prelude::*, - traits::{ - fungible::{Inspect, Mutate}, - tokens::Preservation, - Contains, EnsureOrigin, - }, -}; -use frame_system::pallet_prelude::*; -use snowbridge_core::{ - meth, - outbound::{Command, Initializer, Message, OperatingMode, SendError, SendMessage}, - sibling_sovereign_account, AgentId, Channel, ChannelId, ParaId, - PricingParameters as PricingParametersRecord, PRIMARY_GOVERNANCE_CHANNEL, - SECONDARY_GOVERNANCE_CHANNEL, -}; -use sp_core::{RuntimeDebug, H160, H256}; -use sp_io::hashing::blake2_256; -use sp_runtime::{traits::BadOrigin, DispatchError, SaturatedConversion}; -use sp_std::prelude::*; -use xcm::prelude::*; -use xcm_executor::traits::ConvertLocation; - -#[cfg(feature = "runtime-benchmarks")] -use frame_support::traits::OriginTrait; - -pub use pallet::*; - -pub type BalanceOf = - <::Token as Inspect<::AccountId>>::Balance; -pub type AccountIdOf = ::AccountId; -pub type PricingParametersOf = PricingParametersRecord>; - -/// Ensure origin location is a sibling -fn ensure_sibling(location: &Location) -> Result<(ParaId, H256), DispatchError> -where - T: Config, -{ - match location.unpack() { - (1, [Parachain(para_id)]) => { - let agent_id = agent_id_of::(location)?; - Ok(((*para_id).into(), agent_id)) - }, - _ => Err(BadOrigin.into()), - } -} - -/// Hash the location to produce an agent id -fn agent_id_of(location: &Location) -> Result { - T::AgentIdOf::convert_location(location).ok_or(Error::::LocationConversionFailed.into()) -} - -#[cfg(feature = "runtime-benchmarks")] -pub trait BenchmarkHelper -where - O: OriginTrait, -{ - fn make_xcm_origin(location: Location) -> O; -} - -/// Whether a fee should be withdrawn to an account for sending an outbound message -#[derive(Clone, PartialEq, RuntimeDebug)] -pub enum PaysFee -where - T: Config, -{ - /// Fully charge includes (local + remote fee) - Yes(AccountIdOf), - /// Partially charge includes local fee only - Partial(AccountIdOf), - /// No charge - No, -} - -#[frame_support::pallet] -pub mod pallet { - use snowbridge_core::StaticLookup; - use sp_core::U256; - - use super::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// Send messages to Ethereum - type OutboundQueue: SendMessage>; - - /// Origin check for XCM locations that can create agents - type SiblingOrigin: EnsureOrigin; - - /// Converts Location to AgentId - type AgentIdOf: ConvertLocation; - - /// Token reserved for control operations - type Token: Mutate; - - /// TreasuryAccount to collect fees - #[pallet::constant] - type TreasuryAccount: Get; - - /// Number of decimal places of local currency - type DefaultPricingParameters: Get>; - - /// Cost of delivering a message from Ethereum - type InboundDeliveryCost: Get>; - - type WeightInfo: WeightInfo; - - #[cfg(feature = "runtime-benchmarks")] - type Helper: BenchmarkHelper; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// An Upgrade message was sent to the Gateway - Upgrade { - impl_address: H160, - impl_code_hash: H256, - initializer_params_hash: Option, - }, - /// An CreateAgent message was sent to the Gateway - CreateAgent { - location: Box, - agent_id: AgentId, - }, - /// An CreateChannel message was sent to the Gateway - CreateChannel { - channel_id: ChannelId, - agent_id: AgentId, - }, - /// An UpdateChannel message was sent to the Gateway - UpdateChannel { - channel_id: ChannelId, - mode: OperatingMode, - }, - /// An SetOperatingMode message was sent to the Gateway - SetOperatingMode { - mode: OperatingMode, - }, - /// An TransferNativeFromAgent message was sent to the Gateway - TransferNativeFromAgent { - agent_id: AgentId, - recipient: H160, - amount: u128, - }, - /// A SetTokenTransferFees message was sent to the Gateway - SetTokenTransferFees { - create_asset_xcm: u128, - transfer_asset_xcm: u128, - register_token: U256, - }, - PricingParametersChanged { - params: PricingParametersOf, - }, - } - - #[pallet::error] - pub enum Error { - LocationConversionFailed, - AgentAlreadyCreated, - NoAgent, - ChannelAlreadyCreated, - NoChannel, - UnsupportedLocationVersion, - InvalidLocation, - Send(SendError), - InvalidTokenTransferFees, - InvalidPricingParameters, - } - - /// The set of registered agents - #[pallet::storage] - #[pallet::getter(fn agents)] - pub type Agents = StorageMap<_, Twox64Concat, AgentId, (), OptionQuery>; - - /// The set of registered channels - #[pallet::storage] - #[pallet::getter(fn channels)] - pub type Channels = StorageMap<_, Twox64Concat, ChannelId, Channel, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn parameters)] - pub type PricingParameters = - StorageValue<_, PricingParametersOf, ValueQuery, T::DefaultPricingParameters>; - - #[pallet::genesis_config] - #[derive(frame_support::DefaultNoBound)] - pub struct GenesisConfig { - // Own parachain id - pub para_id: ParaId, - // AssetHub's parachain id - pub asset_hub_para_id: ParaId, - #[serde(skip)] - pub _config: PhantomData, - } - - #[pallet::genesis_build] - impl BuildGenesisConfig for GenesisConfig { - fn build(&self) { - Pallet::::initialize(self.para_id, self.asset_hub_para_id).expect("infallible; qed"); - } - } - - #[pallet::call] - impl Pallet { - /// Sends command to the Gateway contract to upgrade itself with a new implementation - /// contract - /// - /// Fee required: No - /// - /// - `origin`: Must be `Root`. - /// - `impl_address`: The address of the implementation contract. - /// - `impl_code_hash`: The codehash of the implementation contract. - /// - `initializer`: Optionally call an initializer on the implementation contract. - #[pallet::call_index(0)] - #[pallet::weight((T::WeightInfo::upgrade(), DispatchClass::Operational))] - pub fn upgrade( - origin: OriginFor, - impl_address: H160, - impl_code_hash: H256, - initializer: Option, - ) -> DispatchResult { - ensure_root(origin)?; - - let initializer_params_hash: Option = - initializer.as_ref().map(|i| H256::from(blake2_256(i.params.as_ref()))); - let command = Command::Upgrade { impl_address, impl_code_hash, initializer }; - Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; - - Self::deposit_event(Event::::Upgrade { - impl_address, - impl_code_hash, - initializer_params_hash, - }); - Ok(()) - } - - /// Sends a message to the Gateway contract to change its operating mode - /// - /// Fee required: No - /// - /// - `origin`: Must be `Location` - #[pallet::call_index(1)] - #[pallet::weight((T::WeightInfo::set_operating_mode(), DispatchClass::Operational))] - pub fn set_operating_mode(origin: OriginFor, mode: OperatingMode) -> DispatchResult { - ensure_root(origin)?; - - let command = Command::SetOperatingMode { mode }; - Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; - - Self::deposit_event(Event::::SetOperatingMode { mode }); - Ok(()) - } - - /// Set pricing parameters on both sides of the bridge - /// - /// Fee required: No - /// - /// - `origin`: Must be root - #[pallet::call_index(2)] - #[pallet::weight((T::WeightInfo::set_pricing_parameters(), DispatchClass::Operational))] - pub fn set_pricing_parameters( - origin: OriginFor, - params: PricingParametersOf, - ) -> DispatchResult { - ensure_root(origin)?; - params.validate().map_err(|_| Error::::InvalidPricingParameters)?; - PricingParameters::::put(params.clone()); - - let command = Command::SetPricingParameters { - exchange_rate: params.exchange_rate.into(), - delivery_cost: T::InboundDeliveryCost::get().saturated_into::(), - }; - Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; - - Self::deposit_event(Event::PricingParametersChanged { params }); - Ok(()) - } - - /// Sends a command to the Gateway contract to instantiate a new agent contract representing - /// `origin`. - /// - /// Fee required: Yes - /// - /// - `origin`: Must be `Location` of a sibling parachain - #[pallet::call_index(3)] - #[pallet::weight(T::WeightInfo::create_agent())] - pub fn create_agent(origin: OriginFor) -> DispatchResult { - let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?; - - // Ensure that origin location is some consensus system on a sibling parachain - let (para_id, agent_id) = ensure_sibling::(&origin_location)?; - - // Record the agent id or fail if it has already been created - ensure!(!Agents::::contains_key(agent_id), Error::::AgentAlreadyCreated); - Agents::::insert(agent_id, ()); - - let command = Command::CreateAgent { agent_id }; - let pays_fee = PaysFee::::Yes(sibling_sovereign_account::(para_id)); - Self::send(SECONDARY_GOVERNANCE_CHANNEL, command, pays_fee)?; - - Self::deposit_event(Event::::CreateAgent { - location: Box::new(origin_location), - agent_id, - }); - Ok(()) - } - - /// Sends a message to the Gateway contract to create a new channel representing `origin` - /// - /// Fee required: Yes - /// - /// This extrinsic is permissionless, so a fee is charged to prevent spamming and pay - /// for execution costs on the remote side. - /// - /// The message is sent over the bridge on BridgeHub's own channel to the Gateway. - /// - /// - `origin`: Must be `Location` - /// - `mode`: Initial operating mode of the channel - #[pallet::call_index(4)] - #[pallet::weight(T::WeightInfo::create_channel())] - pub fn create_channel(origin: OriginFor, mode: OperatingMode) -> DispatchResult { - let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?; - - // Ensure that origin location is a sibling parachain - let (para_id, agent_id) = ensure_sibling::(&origin_location)?; - - let channel_id: ChannelId = para_id.into(); - - ensure!(Agents::::contains_key(agent_id), Error::::NoAgent); - ensure!(!Channels::::contains_key(channel_id), Error::::ChannelAlreadyCreated); - - let channel = Channel { agent_id, para_id }; - Channels::::insert(channel_id, channel); - - let command = Command::CreateChannel { channel_id, agent_id, mode }; - let pays_fee = PaysFee::::Yes(sibling_sovereign_account::(para_id)); - Self::send(SECONDARY_GOVERNANCE_CHANNEL, command, pays_fee)?; - - Self::deposit_event(Event::::CreateChannel { channel_id, agent_id }); - Ok(()) - } - - /// Sends a message to the Gateway contract to update a channel configuration - /// - /// The origin must already have a channel initialized, as this message is sent over it. - /// - /// A partial fee will be charged for local processing only. - /// - /// - `origin`: Must be `Location` - /// - `mode`: Initial operating mode of the channel - #[pallet::call_index(5)] - #[pallet::weight(T::WeightInfo::update_channel())] - pub fn update_channel(origin: OriginFor, mode: OperatingMode) -> DispatchResult { - let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?; - - // Ensure that origin location is a sibling parachain - let (para_id, _) = ensure_sibling::(&origin_location)?; - - let channel_id: ChannelId = para_id.into(); - - ensure!(Channels::::contains_key(channel_id), Error::::NoChannel); - - let command = Command::UpdateChannel { channel_id, mode }; - let pays_fee = PaysFee::::Partial(sibling_sovereign_account::(para_id)); - - // Parachains send the update message on their own channel - Self::send(channel_id, command, pays_fee)?; - - Self::deposit_event(Event::::UpdateChannel { channel_id, mode }); - Ok(()) - } - - /// Sends a message to the Gateway contract to update an arbitrary channel - /// - /// Fee required: No - /// - /// - `origin`: Must be root - /// - `channel_id`: ID of channel - /// - `mode`: Initial operating mode of the channel - /// - `outbound_fee`: Fee charged to users for sending outbound messages to Polkadot - #[pallet::call_index(6)] - #[pallet::weight(T::WeightInfo::force_update_channel())] - pub fn force_update_channel( - origin: OriginFor, - channel_id: ChannelId, - mode: OperatingMode, - ) -> DispatchResult { - ensure_root(origin)?; - - ensure!(Channels::::contains_key(channel_id), Error::::NoChannel); - - let command = Command::UpdateChannel { channel_id, mode }; - Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; - - Self::deposit_event(Event::::UpdateChannel { channel_id, mode }); - Ok(()) - } - - /// Sends a message to the Gateway contract to transfer ether from an agent to `recipient`. - /// - /// A partial fee will be charged for local processing only. - /// - /// - `origin`: Must be `Location` - #[pallet::call_index(7)] - #[pallet::weight(T::WeightInfo::transfer_native_from_agent())] - pub fn transfer_native_from_agent( - origin: OriginFor, - recipient: H160, - amount: u128, - ) -> DispatchResult { - let origin_location: Location = T::SiblingOrigin::ensure_origin(origin)?; - - // Ensure that origin location is some consensus system on a sibling parachain - let (para_id, agent_id) = ensure_sibling::(&origin_location)?; - - // Since the origin is also the owner of the channel, they only need to pay - // the local processing fee. - let pays_fee = PaysFee::::Partial(sibling_sovereign_account::(para_id)); - - Self::do_transfer_native_from_agent( - agent_id, - para_id.into(), - recipient, - amount, - pays_fee, - ) - } - - /// Sends a message to the Gateway contract to transfer ether from an agent to `recipient`. - /// - /// Privileged. Can only be called by root. - /// - /// Fee required: No - /// - /// - `origin`: Must be root - /// - `location`: Location used to resolve the agent - /// - `recipient`: Recipient of funds - /// - `amount`: Amount to transfer - #[pallet::call_index(8)] - #[pallet::weight(T::WeightInfo::force_transfer_native_from_agent())] - pub fn force_transfer_native_from_agent( - origin: OriginFor, - location: Box, - recipient: H160, - amount: u128, - ) -> DispatchResult { - ensure_root(origin)?; - - // Ensure that location is some consensus system on a sibling parachain - let location: Location = - (*location).try_into().map_err(|_| Error::::UnsupportedLocationVersion)?; - let (_, agent_id) = - ensure_sibling::(&location).map_err(|_| Error::::InvalidLocation)?; - - let pays_fee = PaysFee::::No; - - Self::do_transfer_native_from_agent( - agent_id, - PRIMARY_GOVERNANCE_CHANNEL, - recipient, - amount, - pays_fee, - ) - } - - /// Sends a message to the Gateway contract to update fee related parameters for - /// token transfers. - /// - /// Privileged. Can only be called by root. - /// - /// Fee required: No - /// - /// - `origin`: Must be root - /// - `create_asset_xcm`: The XCM execution cost for creating a new asset class on AssetHub, - /// in DOT - /// - `transfer_asset_xcm`: The XCM execution cost for performing a reserve transfer on - /// AssetHub, in DOT - /// - `register_token`: The Ether fee for registering a new token, to discourage spamming - #[pallet::call_index(9)] - #[pallet::weight((T::WeightInfo::set_token_transfer_fees(), DispatchClass::Operational))] - pub fn set_token_transfer_fees( - origin: OriginFor, - create_asset_xcm: u128, - transfer_asset_xcm: u128, - register_token: U256, - ) -> DispatchResult { - ensure_root(origin)?; - - // Basic validation of new costs. Particularly for token registration, we want to ensure - // its relatively expensive to discourage spamming. Like at least 100 USD. - ensure!( - create_asset_xcm > 0 && transfer_asset_xcm > 0 && register_token > meth(100), - Error::::InvalidTokenTransferFees - ); - - let command = Command::SetTokenTransferFees { - create_asset_xcm, - transfer_asset_xcm, - register_token, - }; - Self::send(PRIMARY_GOVERNANCE_CHANNEL, command, PaysFee::::No)?; - - Self::deposit_event(Event::::SetTokenTransferFees { - create_asset_xcm, - transfer_asset_xcm, - register_token, - }); - Ok(()) - } - } - - impl Pallet { - /// Send `command` to the Gateway on the Channel identified by `channel_id` - fn send(channel_id: ChannelId, command: Command, pays_fee: PaysFee) -> DispatchResult { - let message = Message { id: None, channel_id, command }; - let (ticket, fee) = - T::OutboundQueue::validate(&message).map_err(|err| Error::::Send(err))?; - - let payment = match pays_fee { - PaysFee::Yes(account) => Some((account, fee.total())), - PaysFee::Partial(account) => Some((account, fee.local)), - PaysFee::No => None, - }; - - if let Some((payer, fee)) = payment { - T::Token::transfer( - &payer, - &T::TreasuryAccount::get(), - fee, - Preservation::Preserve, - )?; - } - - T::OutboundQueue::deliver(ticket).map_err(|err| Error::::Send(err))?; - Ok(()) - } - - /// Issue a `Command::TransferNativeFromAgent` command. The command will be sent on the - /// channel `channel_id` - pub fn do_transfer_native_from_agent( - agent_id: H256, - channel_id: ChannelId, - recipient: H160, - amount: u128, - pays_fee: PaysFee, - ) -> DispatchResult { - ensure!(Agents::::contains_key(agent_id), Error::::NoAgent); - - let command = Command::TransferNativeFromAgent { agent_id, recipient, amount }; - Self::send(channel_id, command, pays_fee)?; - - Self::deposit_event(Event::::TransferNativeFromAgent { - agent_id, - recipient, - amount, - }); - Ok(()) - } - - /// Initializes agents and channels. - pub fn initialize(para_id: ParaId, asset_hub_para_id: ParaId) -> Result<(), DispatchError> { - // Asset Hub - let asset_hub_location: Location = - ParentThen(Parachain(asset_hub_para_id.into()).into()).into(); - let asset_hub_agent_id = agent_id_of::(&asset_hub_location)?; - let asset_hub_channel_id: ChannelId = asset_hub_para_id.into(); - Agents::::insert(asset_hub_agent_id, ()); - Channels::::insert( - asset_hub_channel_id, - Channel { agent_id: asset_hub_agent_id, para_id: asset_hub_para_id }, - ); - - // Governance channels - let bridge_hub_agent_id = agent_id_of::(&Location::here())?; - // Agent for BridgeHub - Agents::::insert(bridge_hub_agent_id, ()); - - // Primary governance channel - Channels::::insert( - PRIMARY_GOVERNANCE_CHANNEL, - Channel { agent_id: bridge_hub_agent_id, para_id }, - ); - - // Secondary governance channel - Channels::::insert( - SECONDARY_GOVERNANCE_CHANNEL, - Channel { agent_id: bridge_hub_agent_id, para_id }, - ); - - Ok(()) - } - - /// Checks if the pallet has been initialized. - pub(crate) fn is_initialized() -> bool { - let primary_exists = Channels::::contains_key(PRIMARY_GOVERNANCE_CHANNEL); - let secondary_exists = Channels::::contains_key(SECONDARY_GOVERNANCE_CHANNEL); - primary_exists && secondary_exists - } - } - - impl StaticLookup for Pallet { - type Source = ChannelId; - type Target = Channel; - fn lookup(channel_id: Self::Source) -> Option { - Channels::::get(channel_id) - } - } - - impl Contains for Pallet { - fn contains(channel_id: &ChannelId) -> bool { - Channels::::get(channel_id).is_some() - } - } - - impl Get> for Pallet { - fn get() -> PricingParametersOf { - PricingParameters::::get() - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/migration.rs b/bridges/snowbridge/parachain/pallets/system/src/migration.rs deleted file mode 100644 index ee94fc091bd1..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/migration.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Governance API for controlling the Ethereum side of the bridge -use super::*; -use frame_support::traits::OnRuntimeUpgrade; -use log; - -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - -pub mod v0 { - use frame_support::{pallet_prelude::*, weights::Weight}; - - use super::*; - - const LOG_TARGET: &str = "ethereum_system::migration"; - - pub struct InitializeOnUpgrade( - sp_std::marker::PhantomData<(T, BridgeHubParaId, AssetHubParaId)>, - ); - impl OnRuntimeUpgrade - for InitializeOnUpgrade - where - T: Config, - BridgeHubParaId: Get, - AssetHubParaId: Get, - { - fn on_runtime_upgrade() -> Weight { - if !Pallet::::is_initialized() { - Pallet::::initialize( - BridgeHubParaId::get().into(), - AssetHubParaId::get().into(), - ) - .expect("infallible; qed"); - log::info!( - target: LOG_TARGET, - "Ethereum system initialized." - ); - T::DbWeight::get().reads_writes(2, 5) - } else { - log::info!( - target: LOG_TARGET, - "Ethereum system already initialized. Skipping." - ); - T::DbWeight::get().reads(2) - } - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - if !Pallet::::is_initialized() { - log::info!( - target: LOG_TARGET, - "Agents and channels not initialized. Initialization will run." - ); - } else { - log::info!( - target: LOG_TARGET, - "Agents and channels are initialized. Initialization will not run." - ); - } - Ok(vec![]) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - frame_support::ensure!( - Pallet::::is_initialized(), - "Agents and channels were not initialized." - ); - Ok(()) - } - } -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/mock.rs b/bridges/snowbridge/parachain/pallets/system/src/mock.rs deleted file mode 100644 index bc2295781327..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/mock.rs +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate as snowbridge_system; -use frame_support::{ - parameter_types, - traits::{tokens::fungible::Mutate, ConstU128, ConstU16, ConstU64, ConstU8}, - weights::IdentityFee, - PalletId, -}; -use sp_core::H256; -use xcm_executor::traits::ConvertLocation; - -use snowbridge_core::{ - gwei, meth, outbound::ConstantGasMeter, sibling_sovereign_account, AgentId, AllowSiblingsOnly, - ParaId, PricingParameters, Rewards, -}; -use sp_runtime::{ - traits::{AccountIdConversion, BlakeTwo256, IdentityLookup, Keccak256}, - AccountId32, BuildStorage, FixedU128, -}; -use xcm::prelude::*; - -#[cfg(feature = "runtime-benchmarks")] -use crate::BenchmarkHelper; - -type Block = frame_system::mocking::MockBlock; -type Balance = u128; - -pub type AccountId = AccountId32; - -// A stripped-down version of pallet-xcm that only inserts an XCM origin into the runtime -#[allow(dead_code)] -#[frame_support::pallet] -mod pallet_xcm_origin { - use frame_support::{ - pallet_prelude::*, - traits::{Contains, OriginTrait}, - }; - use xcm::latest::prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeOrigin: From + From<::RuntimeOrigin>; - } - - // Insert this custom Origin into the aggregate RuntimeOrigin - #[pallet::origin] - #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] - pub struct Origin(pub Location); - - impl From for Origin { - fn from(location: Location) -> Origin { - Origin(location) - } - } - - /// `EnsureOrigin` implementation succeeding with a `Location` value to recognize and - /// filter the contained location - pub struct EnsureXcm(PhantomData); - impl, F: Contains> EnsureOrigin for EnsureXcm - where - O::PalletsOrigin: From + TryInto, - { - type Success = Location; - - fn try_origin(outer: O) -> Result { - outer.try_with_caller(|caller| { - caller.try_into().and_then(|o| match o { - Origin(location) if F::contains(&location) => Ok(location), - o => Err(o.into()), - }) - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn try_successful_origin() -> Result { - Ok(O::from(Origin(Location::new(1, [Parachain(2000)])))) - } - } -} - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test - { - System: frame_system, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - XcmOrigin: pallet_xcm_origin::{Pallet, Origin}, - OutboundQueue: snowbridge_pallet_outbound_queue::{Pallet, Call, Storage, Event}, - EthereumSystem: snowbridge_system, - MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} - } -); - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type RuntimeTask = RuntimeTask; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - type Nonce = u64; - type Block = Block; -} - -impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = (); - type RuntimeHoldReason = (); - type RuntimeFreezeReason = (); - type MaxHolds = (); -} - -impl pallet_xcm_origin::Config for Test { - type RuntimeOrigin = RuntimeOrigin; -} - -parameter_types! { - pub const HeapSize: u32 = 32 * 1024; - pub const MaxStale: u32 = 32; - pub static ServiceWeight: Option = Some(Weight::from_parts(100, 100)); -} - -impl pallet_message_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type MessageProcessor = OutboundQueue; - type Size = u32; - type QueueChangeHandler = (); - type HeapSize = HeapSize; - type MaxStale = MaxStale; - type ServiceWeight = ServiceWeight; - type QueuePausedQuery = (); -} - -parameter_types! { - pub const MaxMessagePayloadSize: u32 = 1024; - pub const MaxMessagesPerBlock: u32 = 20; - pub const OwnParaId: ParaId = ParaId::new(1013); -} - -impl snowbridge_pallet_outbound_queue::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Hashing = Keccak256; - type MessageQueue = MessageQueue; - type Decimals = ConstU8<10>; - type MaxMessagePayloadSize = MaxMessagePayloadSize; - type MaxMessagesPerBlock = MaxMessagesPerBlock; - type GasMeter = ConstantGasMeter; - type Balance = u128; - type PricingParameters = EthereumSystem; - type Channels = EthereumSystem; - type WeightToFee = IdentityFee; - type WeightInfo = (); -} - -parameter_types! { - pub const SS58Prefix: u8 = 42; - pub const AnyNetwork: Option = None; - pub const RelayNetwork: Option = Some(NetworkId::Kusama); - pub const RelayLocation: Location = Location::parent(); - pub UniversalLocation: InteriorLocation = - [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(1013)].into(); -} - -pub const DOT: u128 = 10_000_000_000; - -parameter_types! { - pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating(); - pub Fee: u64 = 1000; - pub const RococoNetwork: NetworkId = NetworkId::Rococo; - pub const InitialFunding: u128 = 1_000_000_000_000; - pub AssetHubParaId: ParaId = ParaId::new(1000); - pub TestParaId: u32 = 2000; - pub Parameters: PricingParameters = PricingParameters { - exchange_rate: FixedU128::from_rational(1, 400), - fee_per_gas: gwei(20), - rewards: Rewards { local: DOT, remote: meth(1) } - }; - pub const InboundDeliveryCost: u128 = 1_000_000_000; - -} - -#[cfg(feature = "runtime-benchmarks")] -impl BenchmarkHelper for () { - fn make_xcm_origin(location: Location) -> RuntimeOrigin { - RuntimeOrigin::from(pallet_xcm_origin::Origin(location)) - } -} - -impl crate::Config for Test { - type RuntimeEvent = RuntimeEvent; - type OutboundQueue = OutboundQueue; - type SiblingOrigin = pallet_xcm_origin::EnsureXcm; - type AgentIdOf = snowbridge_core::AgentIdOf; - type TreasuryAccount = TreasuryAccount; - type Token = Balances; - type DefaultPricingParameters = Parameters; - type WeightInfo = (); - type InboundDeliveryCost = InboundDeliveryCost; - #[cfg(feature = "runtime-benchmarks")] - type Helper = (); -} - -// Build genesis storage according to the mock runtime. -pub fn new_test_ext(genesis_build: bool) -> sp_io::TestExternalities { - let mut storage = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - if genesis_build { - crate::GenesisConfig:: { - para_id: OwnParaId::get(), - asset_hub_para_id: AssetHubParaId::get(), - _config: Default::default(), - } - .assimilate_storage(&mut storage) - .unwrap(); - } - - let mut ext: sp_io::TestExternalities = storage.into(); - let initial_amount = InitialFunding::get(); - let test_para_id = TestParaId::get(); - let sovereign_account = sibling_sovereign_account::(test_para_id.into()); - let treasury_account = TreasuryAccount::get(); - ext.execute_with(|| { - System::set_block_number(1); - Balances::mint_into(&AccountId32::from([0; 32]), initial_amount).unwrap(); - Balances::mint_into(&sovereign_account, initial_amount).unwrap(); - Balances::mint_into(&treasury_account, initial_amount).unwrap(); - }); - ext -} - -// Test helpers - -pub fn make_xcm_origin(location: Location) -> RuntimeOrigin { - pallet_xcm_origin::Origin(location).into() -} - -pub fn make_agent_id(location: Location) -> AgentId { - ::AgentIdOf::convert_location(&location) - .expect("convert location") -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/tests.rs b/bridges/snowbridge/parachain/pallets/system/src/tests.rs deleted file mode 100644 index 8b417c258ea1..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/tests.rs +++ /dev/null @@ -1,649 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{mock::*, *}; -use frame_support::{assert_noop, assert_ok}; -use hex_literal::hex; -use snowbridge_core::{eth, sibling_sovereign_account_raw}; -use sp_core::H256; -use sp_runtime::{AccountId32, DispatchError::BadOrigin, TokenError}; - -#[test] -fn create_agent() { - new_test_ext(true).execute_with(|| { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let agent_id = make_agent_id(origin_location.clone()); - let sovereign_account = sibling_sovereign_account::(origin_para_id.into()); - - // fund sovereign account of origin - let _ = Balances::mint_into(&sovereign_account, 10000); - - assert!(!Agents::::contains_key(agent_id)); - - let origin = make_xcm_origin(origin_location); - assert_ok!(EthereumSystem::create_agent(origin)); - - assert!(Agents::::contains_key(agent_id)); - }); -} - -#[test] -fn test_agent_for_here() { - new_test_ext(true).execute_with(|| { - let origin_location = Location::here(); - let agent_id = make_agent_id(origin_location); - assert_eq!( - agent_id, - hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - ) - }); -} - -#[test] -fn create_agent_fails_on_funds_unavailable() { - new_test_ext(true).execute_with(|| { - let origin_location = Location::new(1, [Parachain(2000)]); - let origin = make_xcm_origin(origin_location); - // Reset balance of sovereign_account to zero so to trigger the FundsUnavailable error - let sovereign_account = sibling_sovereign_account::(2000.into()); - Balances::set_balance(&sovereign_account, 0); - assert_noop!(EthereumSystem::create_agent(origin), TokenError::FundsUnavailable); - }); -} - -#[test] -fn create_agent_bad_origin() { - new_test_ext(true).execute_with(|| { - // relay chain location not allowed - assert_noop!( - EthereumSystem::create_agent(make_xcm_origin(Location::new(1, [],))), - BadOrigin, - ); - - // local account location not allowed - assert_noop!( - EthereumSystem::create_agent(make_xcm_origin(Location::new( - 0, - [Junction::AccountId32 { network: None, id: [67u8; 32] }], - ))), - BadOrigin, - ); - - // Signed origin not allowed - assert_noop!( - EthereumSystem::create_agent(RuntimeOrigin::signed([14; 32].into())), - BadOrigin - ); - - // None origin not allowed - assert_noop!(EthereumSystem::create_agent(RuntimeOrigin::none()), BadOrigin); - }); -} - -#[test] -fn upgrade_as_root() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let address: H160 = Default::default(); - let code_hash: H256 = Default::default(); - - assert_ok!(EthereumSystem::upgrade(origin, address, code_hash, None)); - - System::assert_last_event(RuntimeEvent::EthereumSystem(crate::Event::Upgrade { - impl_address: address, - impl_code_hash: code_hash, - initializer_params_hash: None, - })); - }); -} - -#[test] -fn upgrade_as_signed_fails() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::signed(AccountId32::new([0; 32])); - let address: H160 = Default::default(); - let code_hash: H256 = Default::default(); - - assert_noop!(EthereumSystem::upgrade(origin, address, code_hash, None), BadOrigin); - }); -} - -#[test] -fn upgrade_with_params() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let address: H160 = Default::default(); - let code_hash: H256 = Default::default(); - let initializer: Option = - Some(Initializer { params: [0; 256].into(), maximum_required_gas: 10000 }); - assert_ok!(EthereumSystem::upgrade(origin, address, code_hash, initializer)); - }); -} - -#[test] -fn set_operating_mode() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let mode = OperatingMode::RejectingOutboundMessages; - - assert_ok!(EthereumSystem::set_operating_mode(origin, mode)); - - System::assert_last_event(RuntimeEvent::EthereumSystem(crate::Event::SetOperatingMode { - mode, - })); - }); -} - -#[test] -fn set_operating_mode_as_signed_fails() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::signed([14; 32].into()); - let mode = OperatingMode::RejectingOutboundMessages; - - assert_noop!(EthereumSystem::set_operating_mode(origin, mode), BadOrigin); - }); -} - -#[test] -fn set_pricing_parameters() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let mut params = Parameters::get(); - params.rewards.local = 7; - - assert_ok!(EthereumSystem::set_pricing_parameters(origin, params)); - - assert_eq!(PricingParameters::::get().rewards.local, 7); - }); -} - -#[test] -fn set_pricing_parameters_as_signed_fails() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::signed([14; 32].into()); - let params = Parameters::get(); - - assert_noop!(EthereumSystem::set_pricing_parameters(origin, params), BadOrigin); - }); -} - -#[test] -fn set_pricing_parameters_invalid() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let mut params = Parameters::get(); - params.rewards.local = 0; - - assert_noop!( - EthereumSystem::set_pricing_parameters(origin.clone(), params), - Error::::InvalidPricingParameters - ); - - let mut params = Parameters::get(); - params.exchange_rate = 0u128.into(); - assert_noop!( - EthereumSystem::set_pricing_parameters(origin.clone(), params), - Error::::InvalidPricingParameters - ); - params = Parameters::get(); - params.fee_per_gas = sp_core::U256::zero(); - assert_noop!( - EthereumSystem::set_pricing_parameters(origin.clone(), params), - Error::::InvalidPricingParameters - ); - params = Parameters::get(); - params.rewards.local = 0; - assert_noop!( - EthereumSystem::set_pricing_parameters(origin.clone(), params), - Error::::InvalidPricingParameters - ); - params = Parameters::get(); - params.rewards.remote = sp_core::U256::zero(); - assert_noop!( - EthereumSystem::set_pricing_parameters(origin, params), - Error::::InvalidPricingParameters - ); - }); -} - -#[test] -fn set_token_transfer_fees() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - - assert_ok!(EthereumSystem::set_token_transfer_fees(origin, 1, 1, eth(1))); - }); -} - -#[test] -fn set_token_transfer_fees_root_only() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::signed([14; 32].into()); - - assert_noop!(EthereumSystem::set_token_transfer_fees(origin, 1, 1, 1.into()), BadOrigin); - }); -} - -#[test] -fn set_token_transfer_fees_invalid() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - - assert_noop!( - EthereumSystem::set_token_transfer_fees(origin, 0, 0, 0.into()), - Error::::InvalidTokenTransferFees - ); - }); -} - -#[test] -fn create_channel() { - new_test_ext(true).execute_with(|| { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let sovereign_account = sibling_sovereign_account::(origin_para_id.into()); - let origin = make_xcm_origin(origin_location); - - // fund sovereign account of origin - let _ = Balances::mint_into(&sovereign_account, 10000); - - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal)); - }); -} - -#[test] -fn create_channel_fail_already_exists() { - new_test_ext(true).execute_with(|| { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let sovereign_account = sibling_sovereign_account::(origin_para_id.into()); - let origin = make_xcm_origin(origin_location); - - // fund sovereign account of origin - let _ = Balances::mint_into(&sovereign_account, 10000); - - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin.clone(), OperatingMode::Normal)); - - assert_noop!( - EthereumSystem::create_channel(origin, OperatingMode::Normal), - Error::::ChannelAlreadyCreated - ); - }); -} - -#[test] -fn create_channel_bad_origin() { - new_test_ext(true).execute_with(|| { - // relay chain location not allowed - assert_noop!( - EthereumSystem::create_channel( - make_xcm_origin(Location::new(1, [])), - OperatingMode::Normal, - ), - BadOrigin, - ); - - // child of sibling location not allowed - assert_noop!( - EthereumSystem::create_channel( - make_xcm_origin(Location::new( - 1, - [Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }], - )), - OperatingMode::Normal, - ), - BadOrigin, - ); - - // local account location not allowed - assert_noop!( - EthereumSystem::create_channel( - make_xcm_origin(Location::new( - 0, - [Junction::AccountId32 { network: None, id: [67u8; 32] }], - )), - OperatingMode::Normal, - ), - BadOrigin, - ); - - // Signed origin not allowed - assert_noop!( - EthereumSystem::create_channel( - RuntimeOrigin::signed([14; 32].into()), - OperatingMode::Normal, - ), - BadOrigin - ); - - // None origin not allowed - assert_noop!(EthereumSystem::create_agent(RuntimeOrigin::none()), BadOrigin); - }); -} - -#[test] -fn update_channel() { - new_test_ext(true).execute_with(|| { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let sovereign_account = sibling_sovereign_account::(origin_para_id.into()); - let origin = make_xcm_origin(origin_location); - - // First create the channel - let _ = Balances::mint_into(&sovereign_account, 10000); - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin.clone(), OperatingMode::Normal)); - - // Now try to update it - assert_ok!(EthereumSystem::update_channel(origin, OperatingMode::Normal)); - - System::assert_last_event(RuntimeEvent::EthereumSystem(crate::Event::UpdateChannel { - channel_id: ParaId::from(2000).into(), - mode: OperatingMode::Normal, - })); - }); -} - -#[test] -fn update_channel_bad_origin() { - new_test_ext(true).execute_with(|| { - let mode = OperatingMode::Normal; - - // relay chain location not allowed - assert_noop!( - EthereumSystem::update_channel(make_xcm_origin(Location::new(1, [])), mode,), - BadOrigin, - ); - - // child of sibling location not allowed - assert_noop!( - EthereumSystem::update_channel( - make_xcm_origin(Location::new( - 1, - [Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }], - )), - mode, - ), - BadOrigin, - ); - - // local account location not allowed - assert_noop!( - EthereumSystem::update_channel( - make_xcm_origin(Location::new( - 0, - [Junction::AccountId32 { network: None, id: [67u8; 32] }], - )), - mode, - ), - BadOrigin, - ); - - // Signed origin not allowed - assert_noop!( - EthereumSystem::update_channel(RuntimeOrigin::signed([14; 32].into()), mode), - BadOrigin - ); - - // None origin not allowed - assert_noop!(EthereumSystem::update_channel(RuntimeOrigin::none(), mode), BadOrigin); - }); -} - -#[test] -fn update_channel_fails_not_exist() { - new_test_ext(true).execute_with(|| { - let origin_location = Location::new(1, [Parachain(2000)]); - let origin = make_xcm_origin(origin_location); - - // Now try to update it - assert_noop!( - EthereumSystem::update_channel(origin, OperatingMode::Normal), - Error::::NoChannel - ); - }); -} - -#[test] -fn force_update_channel() { - new_test_ext(true).execute_with(|| { - let origin_para_id = 2000; - let origin_location = Location::new(1, [Parachain(origin_para_id)]); - let sovereign_account = sibling_sovereign_account::(origin_para_id.into()); - let origin = make_xcm_origin(origin_location); - - let channel_id: ChannelId = ParaId::from(origin_para_id).into(); - - // First create the channel - let _ = Balances::mint_into(&sovereign_account, 10000); - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin.clone(), OperatingMode::Normal)); - - // Now try to force update it - let force_origin = RuntimeOrigin::root(); - assert_ok!(EthereumSystem::force_update_channel( - force_origin, - channel_id, - OperatingMode::Normal, - )); - - System::assert_last_event(RuntimeEvent::EthereumSystem(crate::Event::UpdateChannel { - channel_id: ParaId::from(2000).into(), - mode: OperatingMode::Normal, - })); - }); -} - -#[test] -fn force_update_channel_bad_origin() { - new_test_ext(true).execute_with(|| { - let mode = OperatingMode::Normal; - - // signed origin not allowed - assert_noop!( - EthereumSystem::force_update_channel( - RuntimeOrigin::signed([14; 32].into()), - ParaId::from(1000).into(), - mode, - ), - BadOrigin, - ); - }); -} - -#[test] -fn transfer_native_from_agent() { - new_test_ext(true).execute_with(|| { - let origin_location = Location::new(1, [Parachain(2000)]); - let origin = make_xcm_origin(origin_location.clone()); - let recipient: H160 = [27u8; 20].into(); - let amount = 103435; - - // First create the agent and channel - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal)); - - let origin = make_xcm_origin(origin_location.clone()); - assert_ok!(EthereumSystem::transfer_native_from_agent(origin, recipient, amount),); - - System::assert_last_event(RuntimeEvent::EthereumSystem( - crate::Event::TransferNativeFromAgent { - agent_id: make_agent_id(origin_location), - recipient, - amount, - }, - )); - }); -} - -#[test] -fn force_transfer_native_from_agent() { - new_test_ext(true).execute_with(|| { - let origin = RuntimeOrigin::root(); - let location = Location::new(1, [Parachain(2000)]); - let versioned_location: Box = Box::new(location.clone().into()); - let recipient: H160 = [27u8; 20].into(); - let amount = 103435; - - // First create the agent - Agents::::insert(make_agent_id(location.clone()), ()); - - assert_ok!(EthereumSystem::force_transfer_native_from_agent( - origin, - versioned_location, - recipient, - amount - ),); - - System::assert_last_event(RuntimeEvent::EthereumSystem( - crate::Event::TransferNativeFromAgent { - agent_id: make_agent_id(location), - recipient, - amount, - }, - )); - }); -} - -#[test] -fn force_transfer_native_from_agent_bad_origin() { - new_test_ext(true).execute_with(|| { - let recipient: H160 = [27u8; 20].into(); - let amount = 103435; - - // signed origin not allowed - assert_noop!( - EthereumSystem::force_transfer_native_from_agent( - RuntimeOrigin::signed([14; 32].into()), - Box::new( - Location::new( - 1, - [Parachain(2000), Junction::AccountId32 { network: None, id: [67u8; 32] }], - ) - .into() - ), - recipient, - amount, - ), - BadOrigin, - ); - }); -} - -// NOTE: The following tests are not actually tests and are more about obtaining location -// conversions for devops purposes. They need to be removed here and incorporated into a command -// line utility. - -#[ignore] -#[test] -fn check_sibling_sovereign_account() { - new_test_ext(true).execute_with(|| { - let para_id = 1001; - let sovereign_account = sibling_sovereign_account::(para_id.into()); - let sovereign_account_raw = sibling_sovereign_account_raw(para_id.into()); - println!( - "Sovereign account for parachain {}: {:#?}", - para_id, - hex::encode(sovereign_account.clone()) - ); - assert_eq!(sovereign_account, sovereign_account_raw.into()); - }); -} - -#[test] -fn charge_fee_for_create_agent() { - new_test_ext(true).execute_with(|| { - let para_id: u32 = TestParaId::get(); - let origin_location = Location::new(1, [Parachain(para_id)]); - let origin = make_xcm_origin(origin_location.clone()); - let sovereign_account = sibling_sovereign_account::(para_id.into()); - let (_, agent_id) = ensure_sibling::(&origin_location).unwrap(); - - let initial_sovereign_balance = Balances::balance(&sovereign_account); - assert_ok!(EthereumSystem::create_agent(origin.clone())); - let fee_charged = initial_sovereign_balance - Balances::balance(&sovereign_account); - - assert_ok!(EthereumSystem::create_channel(origin, OperatingMode::Normal)); - - // assert sovereign_balance decreased by (fee.base_fee + fee.delivery_fee) - let message = Message { - id: None, - channel_id: ParaId::from(para_id).into(), - command: Command::CreateAgent { agent_id }, - }; - let (_, fee) = OutboundQueue::validate(&message).unwrap(); - assert_eq!(fee.local + fee.remote, fee_charged); - - // and treasury_balance increased - let treasury_balance = Balances::balance(&TreasuryAccount::get()); - assert!(treasury_balance > InitialFunding::get()); - - let final_sovereign_balance = Balances::balance(&sovereign_account); - // (sovereign_balance + treasury_balance) keeps the same - assert_eq!(final_sovereign_balance + treasury_balance, { InitialFunding::get() * 2 }); - }); -} - -#[test] -fn charge_fee_for_transfer_native_from_agent() { - new_test_ext(true).execute_with(|| { - let para_id: u32 = TestParaId::get(); - let origin_location = Location::new(1, [Parachain(para_id)]); - let recipient: H160 = [27u8; 20].into(); - let amount = 103435; - let origin = make_xcm_origin(origin_location.clone()); - let (_, agent_id) = ensure_sibling::(&origin_location).unwrap(); - - let sovereign_account = sibling_sovereign_account::(para_id.into()); - - // create_agent & create_channel first - assert_ok!(EthereumSystem::create_agent(origin.clone())); - assert_ok!(EthereumSystem::create_channel(origin.clone(), OperatingMode::Normal)); - - // assert sovereign_balance decreased by only the base_fee - let sovereign_balance_before = Balances::balance(&sovereign_account); - assert_ok!(EthereumSystem::transfer_native_from_agent(origin.clone(), recipient, amount)); - let message = Message { - id: None, - channel_id: ParaId::from(para_id).into(), - command: Command::TransferNativeFromAgent { agent_id, recipient, amount }, - }; - let (_, fee) = OutboundQueue::validate(&message).unwrap(); - let sovereign_balance_after = Balances::balance(&sovereign_account); - assert_eq!(sovereign_balance_after + fee.local, sovereign_balance_before); - }); -} - -#[test] -fn charge_fee_for_upgrade() { - new_test_ext(true).execute_with(|| { - let para_id: u32 = TestParaId::get(); - let origin = RuntimeOrigin::root(); - let address: H160 = Default::default(); - let code_hash: H256 = Default::default(); - let initializer: Option = - Some(Initializer { params: [0; 256].into(), maximum_required_gas: 10000 }); - assert_ok!(EthereumSystem::upgrade(origin, address, code_hash, initializer.clone())); - - // assert sovereign_balance does not change as we do not charge for sudo operations - let sovereign_account = sibling_sovereign_account::(para_id.into()); - let sovereign_balance = Balances::balance(&sovereign_account); - assert_eq!(sovereign_balance, InitialFunding::get()); - }); -} - -#[test] -fn genesis_build_initializes_correctly() { - new_test_ext(true).execute_with(|| { - assert!(EthereumSystem::is_initialized(), "Ethereum uninitialized."); - }); -} - -#[test] -fn no_genesis_build_is_uninitialized() { - new_test_ext(false).execute_with(|| { - assert!(!EthereumSystem::is_initialized(), "Ethereum initialized."); - }); -} diff --git a/bridges/snowbridge/parachain/pallets/system/src/weights.rs b/bridges/snowbridge/parachain/pallets/system/src/weights.rs deleted file mode 100644 index 6e532a0d8a8c..000000000000 --- a/bridges/snowbridge/parachain/pallets/system/src/weights.rs +++ /dev/null @@ -1,249 +0,0 @@ - -//! Autogenerated weights for `snowbridge_system` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-09, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `crake.local`, CPU: `` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: `1024` - -// Executed Command: -// target/release/polkadot-parachain -// benchmark -// pallet -// --chain -// bridge-hub-rococo-dev -// --pallet=snowbridge_system -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --template -// ../parachain/templates/module-weight-template.hbs -// --output -// ../parachain/pallets/control/src/weights.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -/// Weight functions needed for `snowbridge_system`. -pub trait WeightInfo { - fn upgrade() -> Weight; - fn create_agent() -> Weight; - fn create_channel() -> Weight; - fn update_channel() -> Weight; - fn force_update_channel() -> Weight; - fn set_operating_mode() -> Weight; - fn transfer_native_from_agent() -> Weight; - fn force_transfer_native_from_agent() -> Weight; - fn set_token_transfer_fees() -> Weight; - fn set_pricing_parameters() -> Weight; -} - -// For backwards compatibility and tests. -impl WeightInfo for () { - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn upgrade() -> Weight { - // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 44_000_000 picoseconds. - Weight::from_parts(44_000_000, 3517) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: EthereumSystem Agents (r:1 w:1) - /// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn create_agent() -> Weight { - // Proof Size summary in bytes: - // Measured: `187` - // Estimated: `6196` - // Minimum execution time: 85_000_000 picoseconds. - Weight::from_parts(85_000_000, 6196) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: EthereumSystem Agents (r:1 w:0) - /// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: EthereumSystem Channels (r:1 w:1) - /// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:1 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn create_channel() -> Weight { - // Proof Size summary in bytes: - // Measured: `602` - // Estimated: `69050` - // Minimum execution time: 83_000_000 picoseconds. - Weight::from_parts(83_000_000, 69050) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - /// Storage: EthereumSystem Channels (r:1 w:0) - /// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn update_channel() -> Weight { - // Proof Size summary in bytes: - // Measured: `256` - // Estimated: `6044` - // Minimum execution time: 40_000_000 picoseconds. - Weight::from_parts(40_000_000, 6044) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: EthereumSystem Channels (r:1 w:0) - /// Proof: EthereumSystem Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn force_update_channel() -> Weight { - // Proof Size summary in bytes: - // Measured: `256` - // Estimated: `6044` - // Minimum execution time: 41_000_000 picoseconds. - Weight::from_parts(41_000_000, 6044) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn set_operating_mode() -> Weight { - // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 31_000_000 picoseconds. - Weight::from_parts(31_000_000, 3517) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: EthereumSystem Agents (r:1 w:0) - /// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn transfer_native_from_agent() -> Weight { - // Proof Size summary in bytes: - // Measured: `252` - // Estimated: `6044` - // Minimum execution time: 45_000_000 picoseconds. - Weight::from_parts(45_000_000, 6044) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: EthereumSystem Agents (r:1 w:0) - /// Proof: EthereumSystem Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:2 w:2) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:0) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn force_transfer_native_from_agent() -> Weight { - // Proof Size summary in bytes: - // Measured: `252` - // Estimated: `6044` - // Minimum execution time: 42_000_000 picoseconds. - Weight::from_parts(42_000_000, 6044) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn set_token_transfer_fees() -> Weight { - // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 31_000_000 picoseconds. - Weight::from_parts(42_000_000, 3517) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - - /// Storage: ParachainInfo ParachainId (r:1 w:0) - /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) - /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) - /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) - /// Storage: MessageQueue BookStateFor (r:1 w:1) - /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) - /// Storage: MessageQueue ServiceHead (r:1 w:1) - /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) - /// Storage: MessageQueue Pages (r:0 w:1) - /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) - fn set_pricing_parameters() -> Weight { - // Proof Size summary in bytes: - // Measured: `80` - // Estimated: `3517` - // Minimum execution time: 31_000_000 picoseconds. - Weight::from_parts(42_000_000, 3517) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/Cargo.toml b/bridges/snowbridge/parachain/primitives/beacon/Cargo.toml deleted file mode 100644 index 87f13ad5f6ea..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/Cargo.toml +++ /dev/null @@ -1,57 +0,0 @@ -[package] -name = "snowbridge-beacon-primitives" -description = "Snowbridge Beacon Primitives" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -serde = { version = "1.0.195", optional = true, features = ["derive"] } -hex = { version = "0.4", default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -rlp = { version = "0.5", default-features = false } - -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } - -ssz_rs = { version = "0.9.0", default-features = false } -ssz_rs_derive = { version = "0.9.0", default-features = false } -byte-slice-cast = { version = "1.2.1", default-features = false } - -snowbridge-ethereum = { path = "../ethereum", default-features = false } -static_assertions = { version = "1.1.0" } -milagro_bls = { git = "https://github.com/snowfork/milagro_bls", default-features = false, rev = "a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" } - -[dev-dependencies] -hex-literal = { version = "0.4.1" } - -[features] -default = ["std"] -std = [ - "byte-slice-cast/std", - "codec/std", - "frame-support/std", - "frame-system/std", - "hex/std", - "milagro_bls/std", - "rlp/std", - "scale-info/std", - "serde", - "snowbridge-ethereum/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "ssz_rs/std", -] diff --git a/bridges/snowbridge/parachain/primitives/beacon/README.md b/bridges/snowbridge/parachain/primitives/beacon/README.md deleted file mode 100644 index 658d7c5be7df..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Beacon Primitives - -Crate with low-level supporting functions for the beacon client, including: - -- bls12-381 signature handling to verify signatures on the beacon chain -- merkle proofs -- receipt verification -- ssz types - -The code in this crate relates to the Ethereum consensus chain, commonly referred to as the beacon chain. diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/bits.rs b/bridges/snowbridge/parachain/primitives/beacon/src/bits.rs deleted file mode 100644 index 72b7135ee293..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/bits.rs +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use sp_std::{convert::TryInto, prelude::*}; -use ssz_rs::{Bitvector, Deserialize}; - -pub fn decompress_sync_committee_bits< - const SYNC_COMMITTEE_SIZE: usize, - const SYNC_COMMITTEE_BITS_SIZE: usize, ->( - input: [u8; SYNC_COMMITTEE_BITS_SIZE], -) -> [u8; SYNC_COMMITTEE_SIZE] { - Bitvector::<{ SYNC_COMMITTEE_SIZE }>::deserialize(&input) - .expect("checked statically; qed") - .iter() - .map(|bit| u8::from(bit == true)) - .collect::>() - .try_into() - .expect("checked statically; qed") -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/bls.rs b/bridges/snowbridge/parachain/primitives/beacon/src/bls.rs deleted file mode 100644 index 589b72e67348..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/bls.rs +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{PublicKey, Signature}; -use codec::{Decode, Encode}; -use frame_support::{ensure, PalletError}; -pub use milagro_bls::{ - AggregatePublicKey, AggregateSignature, PublicKey as PublicKeyPrepared, - Signature as SignaturePrepared, -}; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, TypeInfo, RuntimeDebug, PalletError)] -pub enum BlsError { - InvalidSignature, - InvalidPublicKey, - InvalidAggregatePublicKeys, - SignatureVerificationFailed, -} - -/// fast_aggregate_verify optimized with aggregate key subtracting absent ones. -pub fn fast_aggregate_verify( - aggregate_pubkey: &PublicKeyPrepared, - absent_pubkeys: &Vec, - message: H256, - signature: &Signature, -) -> Result<(), BlsError> { - let agg_sig = prepare_aggregate_signature(signature)?; - let agg_key = prepare_aggregate_pubkey_from_absent(aggregate_pubkey, absent_pubkeys)?; - fast_aggregate_verify_pre_aggregated(agg_sig, agg_key, message) -} - -/// Decompress one public key into a point in G1. -pub fn prepare_milagro_pubkey(pubkey: &PublicKey) -> Result { - PublicKeyPrepared::from_bytes_unchecked(&pubkey.0).map_err(|_| BlsError::InvalidPublicKey) -} - -/// Prepare for G1 public keys. -pub fn prepare_g1_pubkeys(pubkeys: &[PublicKey]) -> Result, BlsError> { - pubkeys - .iter() - // Deserialize one public key from compressed bytes - .map(prepare_milagro_pubkey) - .collect::, BlsError>>() -} - -/// Prepare for G1 AggregatePublicKey. -pub fn prepare_aggregate_pubkey( - pubkeys: &[PublicKeyPrepared], -) -> Result { - AggregatePublicKey::into_aggregate(pubkeys).map_err(|_| BlsError::InvalidPublicKey) -} - -/// Prepare for G1 AggregatePublicKey. -pub fn prepare_aggregate_pubkey_from_absent( - aggregate_key: &PublicKeyPrepared, - absent_pubkeys: &Vec, -) -> Result { - let mut aggregate_pubkey = AggregatePublicKey::from_public_key(aggregate_key); - if !absent_pubkeys.is_empty() { - let absent_aggregate_key = prepare_aggregate_pubkey(absent_pubkeys)?; - aggregate_pubkey.point.sub(&absent_aggregate_key.point); - } - Ok(AggregatePublicKey { point: aggregate_pubkey.point }) -} - -/// Prepare for G2 AggregateSignature, normally more expensive than G1 operation. -pub fn prepare_aggregate_signature(signature: &Signature) -> Result { - Ok(AggregateSignature::from_signature( - &SignaturePrepared::from_bytes(&signature.0).map_err(|_| BlsError::InvalidSignature)?, - )) -} - -/// fast_aggregate_verify_pre_aggregated which is the most expensive call in beacon light client. -pub fn fast_aggregate_verify_pre_aggregated( - agg_sig: AggregateSignature, - aggregate_key: AggregatePublicKey, - message: H256, -) -> Result<(), BlsError> { - ensure!( - agg_sig.fast_aggregate_verify_pre_aggregated(&message[..], &aggregate_key), - BlsError::SignatureVerificationFailed - ); - Ok(()) -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/config.rs b/bridges/snowbridge/parachain/primitives/beacon/src/config.rs deleted file mode 100644 index aa5fda706f99..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/config.rs +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pub const MAX_PROOF_SIZE: u32 = 20; - -pub const FEE_RECIPIENT_SIZE: usize = 20; -pub const EXTRA_DATA_SIZE: usize = 32; -pub const LOGS_BLOOM_SIZE: usize = 256; - -pub const PUBKEY_SIZE: usize = 48; -pub const SIGNATURE_SIZE: usize = 96; diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/lib.rs b/bridges/snowbridge/parachain/primitives/beacon/src/lib.rs deleted file mode 100644 index 3527e1ff0d19..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/lib.rs +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod bits; -pub mod bls; -pub mod config; -pub mod merkle_proof; -pub mod receipt; -pub mod ssz; -pub mod types; -pub mod updates; - -#[cfg(feature = "std")] -mod serde_utils; - -pub use types::{ - BeaconHeader, CompactBeaconState, CompactExecutionHeader, ExecutionHeaderState, - ExecutionPayloadHeader, FinalizedHeaderState, Fork, ForkData, ForkVersion, ForkVersions, Mode, - PublicKey, Signature, SigningData, SyncAggregate, SyncCommittee, SyncCommitteePrepared, -}; -pub use updates::{CheckpointUpdate, ExecutionHeaderUpdate, NextSyncCommitteeUpdate, Update}; - -pub use bits::decompress_sync_committee_bits; -pub use bls::{ - fast_aggregate_verify, prepare_aggregate_pubkey, prepare_aggregate_pubkey_from_absent, - prepare_aggregate_signature, prepare_g1_pubkeys, AggregatePublicKey, AggregateSignature, - BlsError, PublicKeyPrepared, SignaturePrepared, -}; -pub use merkle_proof::verify_merkle_branch; -pub use receipt::verify_receipt_proof; diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/merkle_proof.rs b/bridges/snowbridge/parachain/primitives/beacon/src/merkle_proof.rs deleted file mode 100644 index a6ee6e9452c3..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/merkle_proof.rs +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use sp_core::H256; -use sp_io::hashing::sha2_256; - -/// Specified by -/// with improvements from -pub fn verify_merkle_branch( - leaf: H256, - branch: &[H256], - index: usize, - depth: usize, - root: H256, -) -> bool { - // verify the proof length - if branch.len() != depth { - return false - } - // verify the computed merkle root - root == compute_merkle_root(leaf, branch, index) -} - -fn compute_merkle_root(leaf: H256, proof: &[H256], index: usize) -> H256 { - let mut value: [u8; 32] = leaf.into(); - for (i, node) in proof.iter().enumerate() { - let mut data = [0u8; 64]; - if generalized_index_bit(index, i) { - // right node - data[0..32].copy_from_slice(node.as_bytes()); - data[32..64].copy_from_slice(&value); - value = sha2_256(&data); - } else { - // left node - data[0..32].copy_from_slice(&value); - data[32..64].copy_from_slice(node.as_bytes()); - value = sha2_256(&data); - } - } - value.into() -} - -/// Spec: -fn generalized_index_bit(index: usize, position: usize) -> bool { - index & (1 << position) > 0 -} - -/// Spec: -pub const fn subtree_index(generalized_index: usize) -> usize { - generalized_index % (1 << generalized_index_length(generalized_index)) -} - -/// Spec: -pub const fn generalized_index_length(generalized_index: usize) -> usize { - match generalized_index.checked_ilog2() { - Some(v) => v as usize, - None => panic!("checked statically; qed"), - } -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/receipt.rs b/bridges/snowbridge/parachain/primitives/beacon/src/receipt.rs deleted file mode 100644 index 0588f3f73f71..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/receipt.rs +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use sp_core::H256; -use sp_io::hashing::keccak_256; -use sp_std::prelude::*; - -use snowbridge_ethereum::{mpt, Receipt}; - -pub fn verify_receipt_proof( - receipts_root: H256, - proof: &[Vec], -) -> Option> { - match apply_merkle_proof(proof) { - Some((root, data)) if root == receipts_root => Some(rlp::decode(&data)), - Some((_, _)) => None, - None => None, - } -} - -fn apply_merkle_proof(proof: &[Vec]) -> Option<(H256, Vec)> { - let mut iter = proof.iter().rev(); - let first_bytes = match iter.next() { - Some(b) => b, - None => return None, - }; - let item_to_prove: mpt::ShortNode = rlp::decode(first_bytes).ok()?; - - let final_hash: Option<[u8; 32]> = iter.try_fold(keccak_256(first_bytes), |acc, x| { - let node: Box = x.as_slice().try_into().ok()?; - if (*node).contains_hash(acc.into()) { - return Some(keccak_256(x)) - } - None - }); - - final_hash.map(|hash| (hash.into(), item_to_prove.value)) -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - - #[test] - fn test_verify_receipt_proof() { - let root: H256 = - hex!("fd5e397a84884641f53c496804f24b5276cbb8c5c9cfc2342246be8e3ce5ad02").into(); - - // Valid proof - let proof_receipt5 = vec!( - hex!("f90131a0b5ba404eb5a6a88e56579f4d37ef9813b5ad7f86f0823ff3b407ac5a6bb465eca0398ead2655e78e03c127ce22c5830e90f18b1601ec055f938336c084feb915a9a026d322c26e46c50942c1aabde50e36df5cde572aed650ce73ea3182c6e90a02ca00600a356135f4db1db0d9842264cdff2652676f881669e91e316c0b6dd783011a0837f1deb4075336da320388c1edfffc56c448a43f4a5ba031300d32a7b509fc5a01c3ac82fd65b4aba7f9afaf604d9c82ec7e2deb573a091ae235751bc5c0c288da05d454159d9071b0f68b6e0503d290f23ac7602c1db0c569dee4605d8f5298f09a00bbed10350ec954448df795f6fd46e3faefc800ede061b3840eedc6e2b07a74da0acb02d26a3650f2064c14a435fdf1f668d8655daf455ebdf671713a7c089b3898080808080808080").to_vec(), - hex!("f901f180a00046a08d4f0bdbdc6b31903086ce323182bce6725e7d9415f7ff91ee8f4820bda0e7cd26ad5f3d2771e4b5ab788e268a14a10209f94ee918eb6c829d21d3d11c1da00d4a56d9e9a6751874fd86c7e3cb1c6ad5a848da62751325f478978a00ea966ea064b81920c8f04a8a1e21f53a8280e739fbb7b00b2ab92493ca3f610b70e8ac85a0b1040ed4c55a73178b76abb16f946ce5bebd6b93ab873c83327df54047d12c27a0de6485e9ac58dc6e2b04b4bb38f562684f0b1a2ee586cc11079e7d9a9dc40b32a0d394f4d3532c3124a65fa36e69147e04fd20453a72ee9c50660f17e13ce9df48a066501003fc3e3478efd2803cd0eded6bbe9243ca01ba754d6327071ddbcbc649a0b2684e518f325fee39fc8ea81b68f3f5c785be00d087f3bed8857ae2ee8da26ea071060a5c52042e8d7ce21092f8ecf06053beb9a0b773a6f91a30c4220aa276b2a0fc22436632574ccf6043d0986dede27ea94c9ca9a3bb5ec03ce776a4ddef24a9a05a8a1d6698c4e7d8cc3a2506cb9b12ea9a079c9c7099bc919dc804033cc556e4a0170c468b0716fd36d161f0bf05875f15756a2976de92f9efe7716320509d79c9a0182f909a90cab169f3efb62387f9cccdd61440acc4deec42f68a4f7ca58075c7a055cf0e9202ac75689b76318f1171f3a44465eddc06aae0713bfb6b34fdd27b7980").to_vec(), - hex!("f904de20b904daf904d701830652f0b9010004200000000000000000000080020000000000010000000000010000000000000000000000000000000000000000000002000000080000000000000000200000000000000000000000000008000000220000000000400010000000000000000000000000000000000000000000000000000000000000040000000010000100000000000800000000004000000000000000000000000000080000004000000000020000000000020000000000000000000000000000000000000000000004000000000002000000000100000000000000000000000000001000000002000020000010200000000000010000000000000000000000000000000000000010000000f903ccf89b9421130f34829b4c343142047a28ce96ec07814b15f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a000000000000000000000000000000000000000000000000000000005d09b7380f89b9421130f34829b4c343142047a28ce96ec07814b15f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da0ffffffffffffffffffffffffffffffffffffffffffffffffffffffcc840c6920f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078ef87994e9c1281aae66801fa35ec404d5f2aea393ff6988e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000000000000001f1420ad1d40000000000000000000000000000000000000000000000014ad400879d159a38f8fc94e9c1281aae66801fa35ec404d5f2aea393ff6988f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488db88000000000000000000000000000000000000000000000000000000005d415f3320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e973b5a5d1078ef87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078e").to_vec(), - ); - assert!(verify_receipt_proof(root, &proof_receipt5).is_some()); - - // Various invalid proofs - let proof_empty: Vec> = vec![]; - let proof_missing_full_node = vec![proof_receipt5[0].clone(), proof_receipt5[2].clone()]; - let proof_missing_short_node1 = vec![proof_receipt5[0].clone(), proof_receipt5[1].clone()]; - let proof_missing_short_node2 = vec![proof_receipt5[0].clone()]; - let proof_invalid_encoding = vec![proof_receipt5[2][2..].to_vec()]; - let proof_no_full_node = vec![proof_receipt5[2].clone(), proof_receipt5[2].clone()]; - assert!(verify_receipt_proof(root, &proof_empty).is_none()); - assert!(verify_receipt_proof(root, &proof_missing_full_node).is_none()); - - assert_eq!( - verify_receipt_proof(root, &proof_missing_short_node1), - Some(Err(rlp::DecoderError::Custom("Unsupported receipt type"))) - ); - - assert_eq!( - verify_receipt_proof(root, &proof_missing_short_node2), - Some(Err(rlp::DecoderError::Custom("Unsupported receipt type"))) - ); - - assert!(verify_receipt_proof(root, &proof_invalid_encoding).is_none()); - assert!(verify_receipt_proof(root, &proof_no_full_node).is_none()); - } - - #[test] - fn test_verify_receipt_proof_with_intermediate_short_node() { - let root: H256 = - hex!("d128e3a57142d2bf15bc0cbcac7ad54f40750d571b5c3097e425882c10c9ba66").into(); - - let proof_receipt263 = vec![ - hex!("f90131a00d3cb8d3f57ac1c0e12918a2ebe0cafed8c273577b9dd73e7ed1079b403ef494a0678b9835b834f8a287c0dd33a8fca9146e456ca688555ed4ec1361a2180b778da0fe42da181a46677a043b3d9d4b8bb05a6a17b7b5c010c17e7c1d31cfb7c4f911a0c89f0e2c53241cdb578e1f2b4caf6ba36e00500bdc57fecd66b84a6a58394c19a086c3c1fae5a0575940b5d38e111c469d07883106c26856f3ef608469a2081f13a06c5992ff00aab6226a70a032fd2f571ba22f797321f45e2daa73020d638d21b0a050861e9503ef68728f6c90a44f7fe1bceb2a9bdab6957bbe7136166bd849561ea006aa6eaca8a07e57176e9aa41e6a09edfb7678d1a112404e0ec779d7e567e82ea0bb0b430d303ba21b0af11c487b8a218bd75db54c98940b3f11bad8ff47cad3ef8080808080808080").to_vec(), - hex!("f871a0246de222036ee6a03329b0105da0a6b3f916fc95a9ed5a403a581a0c4d74242ca0ac108a49a88b57a05ac34a108b39f1e45f6f167f2b9fbc8d52fb58e2e5a6af1ea0fcfe07ac2ccd3c28b6eab68d1bce112f6f6dbd9023e4ec3c05b96615aa803d798080808080808080808080808080").to_vec(), - hex!("e4820001a04fff54398cad4d05ea6abfd8b0f3b4fe14c04d7ff5f5211c5b927d9cf72ac1d8").to_vec(), - hex!("f851a096d010643ca2d47412ca66898286b5f2412963b9ec051b33e570d575914c9c5ca028cd24c652989542fe89479ec6388eac4592432242af5ba97563b3ac7c71c019808080808080808080808080808080").to_vec(), - hex!("f90211a0bb35a84c5b1dcb78ec9d32614912c696e62df77bebf9ab326ee55b5d3acdde46a01084b30dac8df0accfcd0fd6330b7f6fc72a4651246d0694be9162151686a620a03eed50afdce7909d784c6157c445a444c806b5f23d31f3b63786f600c84a95b2a0af5232f1df6c6d41879804d081abe867002abe26ba3e5f8e0254a83a54769831a0607915fb13dd5da594256389a45007a67a7f7a86e95d38d8462792b6c98a722ea00e1260fda1730f2738c650ce2bfba83857bc10f8fb119ebc4fb39acba24e6fbaa0d11de17e417327457812675ca3b84ae8e1b64827abfe01420953697c8313d5b1a05fcaf2f7a88f76336a0c32ffc78acb87ae2005454bd25d658035331be3173b46a03f94f4952ab9e650f83cfd0e7f367b1bcc493aacf39a06f16c4a2e1b5605da48a0bdb4ec79785ca8ae22d60f1bbd42d707b4d7ec4aff231a3ebab755e315b35053a043a67c3f2bcef37c8f47a673adcb7061007a553696d1092408601c11b2e6846aa0c519d5af48cae87c7f4538845417c9735813bee892a6fe2dda79f5c414e8576aa0f7058256e09589501d7c231d739e61c84a850e139690989d24fda6058b432e98a081a52faab520978cb19ce14400dba0cd5bcdc4e5a3c0740678aa8f97ee0e5c56a0bcecc61cadeae52518e3b68a48af4b11603dfd9d99d99d7985efa6d2de44f904a02cba4accfc6f39bc5adb6d4440eb6358b4a5103ef93298e4e694f1f940f8b48280").to_vec(), - hex!("f901ae20b901aaf901a70183bb444eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000100000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000000000000002000000000000000000081000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000f89df89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000002e514404ff6823f1b46a8318a709251db414e5e1a000000000000000000000000055021c55847c00d764357a352e5803237d328954a0000000000000000000000000000000000000000000000000000000000201c370").to_vec(), - ]; - assert!(verify_receipt_proof(root, &proof_receipt263).is_some()); - } -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/serde_utils.rs b/bridges/snowbridge/parachain/primitives/beacon/src/serde_utils.rs deleted file mode 100644 index 07f5cbe724ed..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/serde_utils.rs +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use sp_core::U256; - -use core::fmt::Formatter; -use serde::{Deserialize, Deserializer}; - -// helper to deserialize arbitrary arrays like [T; N] -pub mod arrays { - use std::{convert::TryInto, marker::PhantomData}; - - use serde::{ - de::{SeqAccess, Visitor}, - ser::SerializeTuple, - Deserialize, Deserializer, Serialize, Serializer, - }; - - pub fn serialize( - data: &[T; N], - ser: S, - ) -> Result { - let mut s = ser.serialize_tuple(N)?; - for item in data { - s.serialize_element(item)?; - } - s.end() - } - - struct ArrayVisitor(PhantomData); - - impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor - where - T: Deserialize<'de>, - { - type Value = [T; N]; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str(&format!("an array of length {}", N)) - } - - #[inline] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - // can be optimized using MaybeUninit - let mut data = Vec::with_capacity(N); - for _ in 0..N { - match (seq.next_element())? { - Some(val) => data.push(val), - None => return Err(serde::de::Error::invalid_length(N, &self)), - } - } - match data.try_into() { - Ok(arr) => Ok(arr), - Err(_) => unreachable!(), - } - } - } - - pub fn deserialize<'de, D, T, const N: usize>(deserializer: D) -> Result<[T; N], D::Error> - where - D: Deserializer<'de>, - T: Deserialize<'de>, - { - deserializer.deserialize_tuple(N, ArrayVisitor::(PhantomData)) - } -} - -pub(crate) fn from_hex_to_bytes<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - - let str_without_0x = match s.strip_prefix("0x") { - Some(val) => val, - None => &s, - }; - - let hex_bytes = match hex::decode(str_without_0x) { - Ok(bytes) => bytes, - Err(e) => return Err(serde::de::Error::custom(e.to_string())), - }; - - Ok(hex_bytes) -} - -pub(crate) fn from_int_to_u256<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let number = u128::deserialize(deserializer)?; - - Ok(U256::from(number)) -} - -pub struct HexVisitor(); - -impl<'de, const LENGTH: usize> serde::de::Visitor<'de> for HexVisitor { - type Value = [u8; LENGTH]; - - fn expecting(&self, formatter: &mut Formatter) -> sp_std::fmt::Result { - formatter.write_str("a hex string with an '0x' prefix") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - let stripped = match v.strip_prefix("0x") { - Some(stripped) => stripped, - None => v, - }; - - let decoded = match hex::decode(stripped) { - Ok(decoded) => decoded, - Err(e) => return Err(serde::de::Error::custom(e.to_string())), - }; - if decoded.len() != LENGTH { - return Err(serde::de::Error::custom("publickey expected to be 48 characters")) - } - - let data: Self::Value = decoded - .try_into() - .map_err(|_e| serde::de::Error::custom("hex data has unexpected length"))?; - - Ok(data) - } -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/ssz.rs b/bridges/snowbridge/parachain/primitives/beacon/src/ssz.rs deleted file mode 100644 index 4f8b19ca8892..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/ssz.rs +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{ - config::{EXTRA_DATA_SIZE, FEE_RECIPIENT_SIZE, LOGS_BLOOM_SIZE, PUBKEY_SIZE, SIGNATURE_SIZE}, - types::{ - BeaconHeader, ExecutionPayloadHeader, ForkData, SigningData, SyncAggregate, SyncCommittee, - }, -}; -use byte_slice_cast::AsByteSlice; -use sp_core::H256; -use sp_std::{vec, vec::Vec}; -use ssz_rs::{ - prelude::{List, Vector}, - Bitvector, Deserialize, DeserializeError, SimpleSerialize, SimpleSerializeError, Sized, U256, -}; -use ssz_rs_derive::SimpleSerialize as SimpleSerializeDerive; - -#[derive(Default, SimpleSerializeDerive, Clone, Debug)] -pub struct SSZBeaconBlockHeader { - pub slot: u64, - pub proposer_index: u64, - pub parent_root: [u8; 32], - pub state_root: [u8; 32], - pub body_root: [u8; 32], -} - -impl From for SSZBeaconBlockHeader { - fn from(beacon_header: BeaconHeader) -> Self { - SSZBeaconBlockHeader { - slot: beacon_header.slot, - proposer_index: beacon_header.proposer_index, - parent_root: beacon_header.parent_root.to_fixed_bytes(), - state_root: beacon_header.state_root.to_fixed_bytes(), - body_root: beacon_header.body_root.to_fixed_bytes(), - } - } -} - -#[derive(Default, SimpleSerializeDerive, Clone)] -pub struct SSZSyncCommittee { - pub pubkeys: Vector, COMMITTEE_SIZE>, - pub aggregate_pubkey: Vector, -} - -impl From> - for SSZSyncCommittee -{ - fn from(sync_committee: SyncCommittee) -> Self { - let mut pubkeys_vec = Vec::new(); - - for pubkey in sync_committee.pubkeys.iter() { - // The only thing that can go wrong in the conversion from vec to Vector (ssz type) is - // that the Vector size is 0, or that the given data to create the Vector from does not - // match the expected size N. Because these sizes are statically checked (i.e. - // PublicKey's size is 48, and const PUBKEY_SIZE is 48, it is impossible for "try_from" - // to return an error condition. - let conv_pubkey = Vector::::try_from(pubkey.0.to_vec()) - .expect("checked statically; qed"); - - pubkeys_vec.push(conv_pubkey); - } - - let pubkeys = Vector::, { COMMITTEE_SIZE }>::try_from(pubkeys_vec) - .expect("checked statically; qed"); - - let aggregate_pubkey = - Vector::::try_from(sync_committee.aggregate_pubkey.0.to_vec()) - .expect("checked statically; qed"); - - SSZSyncCommittee { pubkeys, aggregate_pubkey } - } -} - -#[derive(Default, Debug, SimpleSerializeDerive, Clone)] -pub struct SSZSyncAggregate { - pub sync_committee_bits: Bitvector, - pub sync_committee_signature: Vector, -} - -impl - From> for SSZSyncAggregate -{ - fn from(sync_aggregate: SyncAggregate) -> Self { - SSZSyncAggregate { - sync_committee_bits: Bitvector::::deserialize( - &sync_aggregate.sync_committee_bits, - ) - .expect("checked statically; qed"), - sync_committee_signature: Vector::::try_from( - sync_aggregate.sync_committee_signature.0.to_vec(), - ) - .expect("checked statically; qed"), - } - } -} - -#[derive(Default, SimpleSerializeDerive, Clone)] -pub struct SSZForkData { - pub current_version: [u8; 4], - pub genesis_validators_root: [u8; 32], -} - -impl From for SSZForkData { - fn from(fork_data: ForkData) -> Self { - SSZForkData { - current_version: fork_data.current_version, - genesis_validators_root: fork_data.genesis_validators_root, - } - } -} - -#[derive(Default, SimpleSerializeDerive, Clone)] -pub struct SSZSigningData { - pub object_root: [u8; 32], - pub domain: [u8; 32], -} - -impl From for SSZSigningData { - fn from(signing_data: SigningData) -> Self { - SSZSigningData { - object_root: signing_data.object_root.into(), - domain: signing_data.domain.into(), - } - } -} - -#[derive(Default, SimpleSerializeDerive, Clone, Debug)] -pub struct SSZExecutionPayloadHeader { - pub parent_hash: [u8; 32], - pub fee_recipient: Vector, - pub state_root: [u8; 32], - pub receipts_root: [u8; 32], - pub logs_bloom: Vector, - pub prev_randao: [u8; 32], - pub block_number: u64, - pub gas_limit: u64, - pub gas_used: u64, - pub timestamp: u64, - pub extra_data: List, - pub base_fee_per_gas: U256, - pub block_hash: [u8; 32], - pub transactions_root: [u8; 32], - pub withdrawals_root: [u8; 32], -} - -impl TryFrom for SSZExecutionPayloadHeader { - type Error = SimpleSerializeError; - - fn try_from(payload: ExecutionPayloadHeader) -> Result { - Ok(SSZExecutionPayloadHeader { - parent_hash: payload.parent_hash.to_fixed_bytes(), - fee_recipient: Vector::::try_from( - payload.fee_recipient.to_fixed_bytes().to_vec(), - ) - .expect("checked statically; qed"), - state_root: payload.state_root.to_fixed_bytes(), - receipts_root: payload.receipts_root.to_fixed_bytes(), - // Logs bloom bytes size is not constrained, so here we do need to check the try_from - // error - logs_bloom: Vector::::try_from(payload.logs_bloom) - .map_err(|(_, err)| err)?, - prev_randao: payload.prev_randao.to_fixed_bytes(), - block_number: payload.block_number, - gas_limit: payload.gas_limit, - gas_used: payload.gas_used, - timestamp: payload.timestamp, - // Extra data bytes size is not constrained, so here we do need to check the try_from - // error - extra_data: List::::try_from(payload.extra_data) - .map_err(|(_, err)| err)?, - base_fee_per_gas: U256::from_bytes_le( - payload - .base_fee_per_gas - .as_byte_slice() - .try_into() - .expect("checked in prep; qed"), - ), - block_hash: payload.block_hash.to_fixed_bytes(), - transactions_root: payload.transactions_root.to_fixed_bytes(), - withdrawals_root: payload.withdrawals_root.to_fixed_bytes(), - }) - } -} - -pub fn hash_tree_root(mut object: T) -> Result { - match object.hash_tree_root() { - Ok(node) => { - let fixed_bytes: [u8; 32] = - node.as_ref().try_into().expect("Node is a newtype over [u8; 32]; qed"); - Ok(fixed_bytes.into()) - }, - Err(err) => Err(err.into()), - } -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/types.rs b/bridges/snowbridge/parachain/primitives/beacon/src/types.rs deleted file mode 100644 index f893551d9d17..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/types.rs +++ /dev/null @@ -1,512 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; -use scale_info::TypeInfo; -use sp_core::{H160, H256, U256}; -use sp_runtime::RuntimeDebug; -use sp_std::{boxed::Box, prelude::*}; - -use crate::config::{PUBKEY_SIZE, SIGNATURE_SIZE}; - -#[cfg(feature = "std")] -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -#[cfg(feature = "std")] -use crate::serde_utils::HexVisitor; - -use crate::ssz::{ - hash_tree_root, SSZBeaconBlockHeader, SSZExecutionPayloadHeader, SSZForkData, SSZSigningData, - SSZSyncAggregate, SSZSyncCommittee, -}; -use ssz_rs::SimpleSerializeError; - -pub use crate::bits::decompress_sync_committee_bits; - -use crate::bls::{prepare_g1_pubkeys, prepare_milagro_pubkey, BlsError}; -use milagro_bls::PublicKey as PublicKeyPrepared; - -pub type ValidatorIndex = u64; -pub type ForkVersion = [u8; 4]; - -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct ForkVersions { - pub genesis: Fork, - pub altair: Fork, - pub bellatrix: Fork, - pub capella: Fork, -} - -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Fork { - pub version: [u8; 4], - pub epoch: u64, -} - -#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct PublicKey(pub [u8; PUBKEY_SIZE]); - -impl Default for PublicKey { - fn default() -> Self { - PublicKey([0u8; PUBKEY_SIZE]) - } -} - -impl From<[u8; PUBKEY_SIZE]> for PublicKey { - fn from(v: [u8; PUBKEY_SIZE]) -> Self { - Self(v) - } -} - -impl MaxEncodedLen for PublicKey { - fn max_encoded_len() -> usize { - PUBKEY_SIZE - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for PublicKey { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(HexVisitor::()).map(|v| v.into()) - } -} - -#[cfg(feature = "std")] -impl Serialize for PublicKey { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_bytes(&self.0) - } -} - -#[derive(Copy, Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Signature(pub [u8; SIGNATURE_SIZE]); - -impl Default for Signature { - fn default() -> Self { - Signature([0u8; SIGNATURE_SIZE]) - } -} - -impl From<[u8; SIGNATURE_SIZE]> for Signature { - fn from(v: [u8; SIGNATURE_SIZE]) -> Self { - Self(v) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for Signature { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(HexVisitor::()).map(|v| v.into()) - } -} - -#[derive(Copy, Clone, Default, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct ExecutionHeaderState { - pub beacon_block_root: H256, - pub beacon_slot: u64, - pub block_hash: H256, - pub block_number: u64, -} - -#[derive(Copy, Clone, Default, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct FinalizedHeaderState { - pub beacon_block_root: H256, - pub beacon_slot: u64, -} - -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] -pub struct ForkData { - // 1 or 0 bit, indicates whether a sync committee participated in a vote - pub current_version: [u8; 4], - pub genesis_validators_root: [u8; 32], -} - -impl ForkData { - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::(self.clone().into()) - } -} - -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] -pub struct SigningData { - pub object_root: H256, - pub domain: H256, -} - -impl SigningData { - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::(self.clone().into()) - } -} - -/// Sync committee as it is stored in the runtime storage. -#[derive( - Encode, Decode, PartialEqNoBound, CloneNoBound, RuntimeDebugNoBound, TypeInfo, MaxEncodedLen, -)] -#[cfg_attr( - feature = "std", - derive(Serialize, Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -#[codec(mel_bound())] -pub struct SyncCommittee { - #[cfg_attr(feature = "std", serde(with = "crate::serde_utils::arrays"))] - pub pubkeys: [PublicKey; COMMITTEE_SIZE], - pub aggregate_pubkey: PublicKey, -} - -impl Default for SyncCommittee { - fn default() -> Self { - SyncCommittee { - pubkeys: [Default::default(); COMMITTEE_SIZE], - aggregate_pubkey: Default::default(), - } - } -} - -impl SyncCommittee { - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::>(self.clone().into()) - } -} - -/// Prepared G1 public key of sync committee as it is stored in the runtime storage. -#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct SyncCommitteePrepared { - pub root: H256, - pub pubkeys: Box<[PublicKeyPrepared; COMMITTEE_SIZE]>, - pub aggregate_pubkey: PublicKeyPrepared, -} - -impl Default for SyncCommitteePrepared { - fn default() -> Self { - SyncCommitteePrepared { - root: H256::default(), - pubkeys: Box::new([PublicKeyPrepared::default(); COMMITTEE_SIZE]), - aggregate_pubkey: PublicKeyPrepared::default(), - } - } -} - -impl TryFrom<&SyncCommittee> - for SyncCommitteePrepared -{ - type Error = BlsError; - - fn try_from(sync_committee: &SyncCommittee) -> Result { - let g1_pubkeys = prepare_g1_pubkeys(&sync_committee.pubkeys)?; - let sync_committee_root = sync_committee.hash_tree_root().expect("checked statically; qed"); - - Ok(SyncCommitteePrepared:: { - pubkeys: g1_pubkeys.try_into().expect("checked statically; qed"), - aggregate_pubkey: prepare_milagro_pubkey(&sync_committee.aggregate_pubkey)?, - root: sync_committee_root, - }) - } -} - -/// Beacon block header as it is stored in the runtime storage. The block root is the -/// Merkleization of a BeaconHeader. -#[derive( - Copy, Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, -)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct BeaconHeader { - // The slot for which this block is created. Must be greater than the slot of the block defined - // by parent root. - pub slot: u64, - // The index of the validator that proposed the block. - pub proposer_index: ValidatorIndex, - // The block root of the parent block, forming a block chain. - pub parent_root: H256, - // The hash root of the post state of running the state transition through this block. - pub state_root: H256, - // The hash root of the beacon block body - pub body_root: H256, -} - -impl BeaconHeader { - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::((*self).into()) - } -} - -#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)] -#[cfg_attr( - feature = "std", - derive(Deserialize), - serde( - try_from = "IntermediateSyncAggregate", - deny_unknown_fields, - bound(serialize = ""), - bound(deserialize = "") - ) -)] -#[codec(mel_bound())] -pub struct SyncAggregate { - pub sync_committee_bits: [u8; COMMITTEE_BITS_SIZE], - pub sync_committee_signature: Signature, -} - -impl Default - for SyncAggregate -{ - fn default() -> Self { - SyncAggregate { - sync_committee_bits: [0; COMMITTEE_BITS_SIZE], - sync_committee_signature: Default::default(), - } - } -} - -impl - SyncAggregate -{ - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::>(self.clone().into()) - } -} - -/// Serde deserialization helper for SyncAggregate -#[cfg(feature = "std")] -#[derive(Deserialize)] -struct IntermediateSyncAggregate { - #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))] - pub sync_committee_bits: Vec, - pub sync_committee_signature: Signature, -} - -#[cfg(feature = "std")] -impl - TryFrom for SyncAggregate -{ - type Error = String; - - fn try_from(other: IntermediateSyncAggregate) -> Result { - Ok(Self { - sync_committee_bits: other - .sync_committee_bits - .try_into() - .map_err(|_| "unexpected length".to_owned())?, - sync_committee_signature: other.sync_committee_signature, - }) - } -} - -/// ExecutionPayloadHeader -/// -#[derive( - Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, -)] -#[cfg_attr( - feature = "std", - derive(Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -#[codec(mel_bound())] -pub struct ExecutionPayloadHeader { - pub parent_hash: H256, - pub fee_recipient: H160, - pub state_root: H256, - pub receipts_root: H256, - #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))] - pub logs_bloom: Vec, - pub prev_randao: H256, - pub block_number: u64, - pub gas_limit: u64, - pub gas_used: u64, - pub timestamp: u64, - #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_hex_to_bytes"))] - pub extra_data: Vec, - #[cfg_attr(feature = "std", serde(deserialize_with = "crate::serde_utils::from_int_to_u256"))] - pub base_fee_per_gas: U256, - pub block_hash: H256, - pub transactions_root: H256, - pub withdrawals_root: H256, -} - -impl ExecutionPayloadHeader { - pub fn hash_tree_root(&self) -> Result { - hash_tree_root::(self.clone().try_into()?) - } -} - -#[derive( - Default, - Encode, - Decode, - CloneNoBound, - PartialEqNoBound, - RuntimeDebugNoBound, - TypeInfo, - MaxEncodedLen, -)] -pub struct CompactExecutionHeader { - pub parent_hash: H256, - #[codec(compact)] - pub block_number: u64, - pub state_root: H256, - pub receipts_root: H256, -} - -impl From for CompactExecutionHeader { - fn from(execution_payload: ExecutionPayloadHeader) -> Self { - Self { - parent_hash: execution_payload.parent_hash, - block_number: execution_payload.block_number, - state_root: execution_payload.state_root, - receipts_root: execution_payload.receipts_root, - } - } -} - -#[derive( - Default, - Encode, - Decode, - Copy, - Clone, - PartialEqNoBound, - RuntimeDebugNoBound, - TypeInfo, - MaxEncodedLen, -)] -pub struct CompactBeaconState { - #[codec(compact)] - pub slot: u64, - pub block_roots_root: H256, -} - -#[cfg(test)] -mod tests { - use super::*; - use hex_literal::hex; - - #[test] - pub fn test_hash_beacon_header1() { - let hash_root = BeaconHeader { - slot: 3, - proposer_index: 2, - parent_root: hex!("796ea53efb534eab7777809cc5ee2d84e7f25024b9d0c4d7e5bcaab657e4bdbd") - .into(), - state_root: hex!("ba3ff080912be5c9c158b2e962c1b39a91bc0615762ba6fa2ecacafa94e9ae0a") - .into(), - body_root: hex!("a18d7fcefbb74a177c959160e0ee89c23546482154e6831237710414465dcae5") - .into(), - } - .hash_tree_root(); - - assert!(hash_root.is_ok()); - assert_eq!( - hash_root.unwrap(), - hex!("7d42595818709e805dd2fa710a2d2c1f62576ef1ab7273941ac9130fb94b91f7").into() - ); - } - - #[test] - pub fn test_hash_beacon_header2() { - let hash_root = BeaconHeader { - slot: 3476424, - proposer_index: 314905, - parent_root: hex!("c069d7b49cffd2b815b0fb8007eb9ca91202ea548df6f3db60000f29b2489f28") - .into(), - state_root: hex!("444d293e4533501ee508ad608783a7d677c3c566f001313e8a02ce08adf590a3") - .into(), - body_root: hex!("6508a0241047f21ba88f05d05b15534156ab6a6f8e029a9a5423da429834e04a") - .into(), - } - .hash_tree_root(); - - assert!(hash_root.is_ok()); - assert_eq!( - hash_root.unwrap(), - hex!("0aa41166ff01e58e111ac8c42309a738ab453cf8d7285ed8477b1c484acb123e").into() - ); - } - - #[test] - pub fn test_hash_fork_data() { - let hash_root = ForkData { - current_version: hex!("83f38a34"), - genesis_validators_root: hex!( - "22370bbbb358800f5711a10ea9845284272d8493bed0348cab87b8ab1e127930" - ), - } - .hash_tree_root(); - - assert!(hash_root.is_ok()); - assert_eq!( - hash_root.unwrap(), - hex!("57c12c4246bc7152b174b51920506bf943eff9c7ffa50b9533708e9cc1f680fc").into() - ); - } - - #[test] - pub fn test_hash_signing_data() { - let hash_root = SigningData { - object_root: hex!("63654cbe64fc07853f1198c165dd3d49c54fc53bc417989bbcc66da15f850c54") - .into(), - domain: hex!("037da907d1c3a03c0091b2254e1480d9b1783476e228ab29adaaa8f133e08f7a").into(), - } - .hash_tree_root(); - - assert!(hash_root.is_ok()); - assert_eq!( - hash_root.unwrap(), - hex!("b9eb2caf2d691b183c2d57f322afe505c078cd08101324f61c3641714789a54e").into() - ); - } - - #[test] - pub fn test_hash_sync_aggregate() { - let hash_root = SyncAggregate::<512, 64>{ - sync_committee_bits: hex!("cefffffefffffff767fffbedffffeffffeeffdffffdebffffff7f7dbdf7fffdffffbffcfffdff79dfffbbfefff2ffffff7ddeff7ffffc98ff7fbfffffffffff7"), - sync_committee_signature: hex!("8af1a8577bba419fe054ee49b16ed28e081dda6d3ba41651634685e890992a0b675e20f8d9f2ec137fe9eb50e838aa6117f9f5410e2e1024c4b4f0e098e55144843ce90b7acde52fe7b94f2a1037342c951dc59f501c92acf7ed944cb6d2b5f7").into(), - }.hash_tree_root(); - - assert!(hash_root.is_ok()); - assert_eq!( - hash_root.unwrap(), - hex!("e6dcad4f60ce9ff8a587b110facbaf94721f06cd810b6d8bf6cffa641272808d").into() - ); - } - - #[test] - pub fn test_hash_execution_payload() { - let hash_root = - ExecutionPayloadHeader{ - parent_hash: hex!("eadee5ab098dde64e9fd02ae5858064bad67064070679625b09f8d82dec183f7").into(), - fee_recipient: hex!("f97e180c050e5ab072211ad2c213eb5aee4df134").into(), - state_root: hex!("564fa064c2a324c2b5978d7fdfc5d4224d4f421a45388af1ed405a399c845dff").into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), - logs_bloom: hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").to_vec(), - prev_randao: hex!("6bf538bdfbdf1c96ff528726a40658a91d0bda0f1351448c4c4f3604db2a0ccf").into(), - block_number: 477434, - gas_limit: 8154925, - gas_used: 0, - timestamp: 1652816940, - extra_data: vec![], - base_fee_per_gas: U256::from(7_i16), - block_hash: hex!("cd8df91b4503adb8f2f1c7a4f60e07a1f1a2cbdfa2a95bceba581f3ff65c1968").into(), - transactions_root: hex!("7ffe241ea60187fdb0187bfa22de35d1f9bed7ab061d9401fd47e34a54fbede1").into(), - withdrawals_root: hex!("28ba1834a3a7b657460ce79fa3a1d909ab8828fd557659d4d0554a9bdbc0ec30").into(), - }.hash_tree_root(); - assert!(hash_root.is_ok()); - } -} - -/// Operating modes for beacon client -#[derive(Encode, Decode, Copy, Clone, PartialEq, RuntimeDebug, TypeInfo)] -pub enum Mode { - Active, - Blocked, -} diff --git a/bridges/snowbridge/parachain/primitives/beacon/src/updates.rs b/bridges/snowbridge/parachain/primitives/beacon/src/updates.rs deleted file mode 100644 index 9a78b4f1e2d3..000000000000 --- a/bridges/snowbridge/parachain/primitives/beacon/src/updates.rs +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use codec::{Decode, Encode}; -use frame_support::{CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound}; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_std::prelude::*; - -use crate::types::{BeaconHeader, ExecutionPayloadHeader, SyncAggregate, SyncCommittee}; - -#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)] -#[cfg_attr( - feature = "std", - derive(serde::Serialize, serde::Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -pub struct CheckpointUpdate { - pub header: BeaconHeader, - pub current_sync_committee: SyncCommittee, - pub current_sync_committee_branch: Vec, - pub validators_root: H256, - pub block_roots_root: H256, - pub block_roots_branch: Vec, -} - -impl Default for CheckpointUpdate { - fn default() -> Self { - CheckpointUpdate { - header: Default::default(), - current_sync_committee: Default::default(), - current_sync_committee_branch: Default::default(), - validators_root: Default::default(), - block_roots_root: Default::default(), - block_roots_branch: Default::default(), - } - } -} - -#[derive( - Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, -)] -#[cfg_attr( - feature = "std", - derive(serde::Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -pub struct Update { - /// A recent header attesting to the finalized header, using its `state_root`. - pub attested_header: BeaconHeader, - /// The signing data that the sync committee produced for this attested header, including - /// who participated in the vote and the resulting signature. - pub sync_aggregate: SyncAggregate, - /// The slot at which the sync aggregate can be found, typically attested_header.slot + 1, if - /// the next slot block was not missed. - pub signature_slot: u64, - /// The next sync committee for the next sync committee period, if present. - pub next_sync_committee_update: Option>, - /// The latest finalized header. - pub finalized_header: BeaconHeader, - /// The merkle proof testifying to the finalized header, using the `attested_header.state_root` - /// as tree root. - pub finality_branch: Vec, - /// The finalized_header's `block_roots` root in the beacon state, used for ancestry proofs. - pub block_roots_root: H256, - /// The merkle path to prove the `block_roots_root` value. - pub block_roots_branch: Vec, -} - -#[derive( - Default, Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, -)] -#[cfg_attr( - feature = "std", - derive(serde::Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -pub struct NextSyncCommitteeUpdate { - pub next_sync_committee: SyncCommittee, - pub next_sync_committee_branch: Vec, -} - -#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)] -#[cfg_attr( - feature = "std", - derive(serde::Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -pub struct ExecutionHeaderUpdate { - /// Header for the beacon block containing the execution payload - pub header: BeaconHeader, - /// Proof that `header` is an ancestor of a finalized header - pub ancestry_proof: Option, - /// Execution header to be imported - pub execution_header: ExecutionPayloadHeader, - /// Merkle proof that execution payload is contained within `header` - pub execution_branch: Vec, -} - -#[derive(Encode, Decode, CloneNoBound, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo)] -#[cfg_attr( - feature = "std", - derive(serde::Deserialize), - serde(deny_unknown_fields, bound(serialize = ""), bound(deserialize = "")) -)] -pub struct AncestryProof { - /// Merkle proof that `header` is an ancestor of `finalized_header` - pub header_branch: Vec, - /// Root of a finalized block that has already been imported into the light client - pub finalized_block_root: H256, -} diff --git a/bridges/snowbridge/parachain/primitives/core/Cargo.toml b/bridges/snowbridge/parachain/primitives/core/Cargo.toml deleted file mode 100644 index a4092b4ee6f0..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -[package] -name = "snowbridge-core" -description = "Snowbridge Core" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -serde = { version = "1.0.195", optional = true, features = ["alloc", "derive"], default-features = false } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -hex-literal = { version = "0.4.1" } - -polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false } -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } - -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-arithmetic = { path = "../../../../../substrate/primitives/arithmetic", default-features = false } - -snowbridge-beacon-primitives = { path = "../beacon", default-features = false } - -ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } - -[dev-dependencies] -hex = { version = "0.4.3" } - -[features] -default = ["std"] -std = [ - "codec/std", - "ethabi/std", - "frame-support/std", - "frame-system/std", - "polkadot-parachain-primitives/std", - "scale-info/std", - "serde/std", - "snowbridge-beacon-primitives/std", - "sp-arithmetic/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm-builder/std", - "xcm/std", -] -serde = ["dep:serde", "scale-info/serde"] -runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "polkadot-parachain-primitives/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", -] diff --git a/bridges/snowbridge/parachain/primitives/core/README.md b/bridges/snowbridge/parachain/primitives/core/README.md deleted file mode 100644 index 0126be63aeba..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Core Primitives - -Contains common code core to Snowbridge, such as inbound and outbound queue types, pricing structs, ringbuffer data -types (used in the beacon client). diff --git a/bridges/snowbridge/parachain/primitives/core/src/inbound.rs b/bridges/snowbridge/parachain/primitives/core/src/inbound.rs deleted file mode 100644 index 4b04470ad026..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/inbound.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Types for representing inbound messages - -use codec::{Decode, Encode}; -use frame_support::PalletError; -use scale_info::TypeInfo; -use sp_core::{H160, H256}; -use sp_runtime::RuntimeDebug; -use sp_std::vec::Vec; - -/// A trait for verifying inbound messages from Ethereum. -pub trait Verifier { - fn verify(event: &Log, proof: &Proof) -> Result<(), VerificationError>; -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, PalletError, TypeInfo)] -#[cfg_attr(feature = "std", derive(PartialEq))] -pub enum VerificationError { - /// Execution header is missing - HeaderNotFound, - /// Event log was not found in the verified transaction receipt - LogNotFound, - /// Event log has an invalid format - InvalidLog, - /// Unable to verify the transaction receipt with the provided proof - InvalidProof, -} - -pub type MessageNonce = u64; - -/// A bridge message from the Gateway contract on Ethereum -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Message { - /// Event log emitted by Gateway contract - pub event_log: Log, - /// Inclusion proof for a transaction receipt containing the event log - pub proof: Proof, -} - -const MAX_TOPICS: usize = 4; - -#[derive(Clone, RuntimeDebug)] -pub enum LogValidationError { - TooManyTopics, -} - -/// Event log -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Log { - pub address: H160, - pub topics: Vec, - pub data: Vec, -} - -impl Log { - pub fn validate(&self) -> Result<(), LogValidationError> { - if self.topics.len() > MAX_TOPICS { - return Err(LogValidationError::TooManyTopics) - } - Ok(()) - } -} - -/// Inclusion proof for a transaction receipt -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct Proof { - // The block hash of the block in which the receipt was included. - pub block_hash: H256, - // The index of the transaction (and receipt) within the block. - pub tx_index: u32, - // Proof keys and values (receipts tree) - pub data: (Vec>, Vec>), -} diff --git a/bridges/snowbridge/parachain/primitives/core/src/lib.rs b/bridges/snowbridge/parachain/primitives/core/src/lib.rs deleted file mode 100644 index a464557a72b4..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/lib.rs +++ /dev/null @@ -1,170 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! # Core -//! -//! Common traits and types -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(test)] -mod tests; - -pub mod inbound; -pub mod operating_mode; -pub mod outbound; -pub mod pricing; -pub mod ringbuffer; - -pub use polkadot_parachain_primitives::primitives::{ - Id as ParaId, IsSystem, Sibling as SiblingParaId, -}; -pub use ringbuffer::{RingBufferMap, RingBufferMapImpl}; -pub use sp_core::U256; - -use codec::{Decode, Encode, MaxEncodedLen}; -use frame_support::traits::Contains; -use hex_literal::hex; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_io::hashing::keccak_256; -use sp_runtime::{traits::AccountIdConversion, RuntimeDebug}; -use sp_std::prelude::*; -use xcm::prelude::{Junction::Parachain, Location}; -use xcm_builder::{DescribeAllTerminal, DescribeFamily, DescribeLocation, HashedDescription}; - -/// The ID of an agent contract -pub type AgentId = H256; -pub use operating_mode::BasicOperatingMode; - -pub use pricing::{PricingParameters, Rewards}; - -pub fn sibling_sovereign_account(para_id: ParaId) -> T::AccountId -where - T: frame_system::Config, -{ - SiblingParaId::from(para_id).into_account_truncating() -} - -pub fn sibling_sovereign_account_raw(para_id: ParaId) -> [u8; 32] { - SiblingParaId::from(para_id).into_account_truncating() -} - -pub struct AllowSiblingsOnly; -impl Contains for AllowSiblingsOnly { - fn contains(location: &Location) -> bool { - matches!(location.unpack(), (1, [Parachain(_)])) - } -} - -pub fn gwei(x: u128) -> U256 { - U256::from(1_000_000_000u128).saturating_mul(x.into()) -} - -pub fn meth(x: u128) -> U256 { - U256::from(1_000_000_000_000_000u128).saturating_mul(x.into()) -} - -pub fn eth(x: u128) -> U256 { - U256::from(1_000_000_000_000_000_000u128).saturating_mul(x.into()) -} - -pub const ROC: u128 = 1_000_000_000_000; - -/// Identifier for a message channel -#[derive( - Clone, Copy, Encode, Decode, PartialEq, Eq, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, -)] -pub struct ChannelId([u8; 32]); - -/// Deterministically derive a ChannelId for a sibling parachain -/// Generator: keccak256("para" + big_endian_bytes(para_id)) -/// -/// The equivalent generator on the Solidity side is in -/// contracts/src/Types.sol:into(). -fn derive_channel_id_for_sibling(para_id: ParaId) -> ChannelId { - let para_id: u32 = para_id.into(); - let para_id_bytes: [u8; 4] = para_id.to_be_bytes(); - let prefix: [u8; 4] = *b"para"; - let preimage: Vec = prefix.into_iter().chain(para_id_bytes).collect(); - keccak_256(&preimage).into() -} - -impl ChannelId { - pub const fn new(id: [u8; 32]) -> Self { - ChannelId(id) - } -} - -impl From for ChannelId { - fn from(value: ParaId) -> Self { - derive_channel_id_for_sibling(value) - } -} - -impl From<[u8; 32]> for ChannelId { - fn from(value: [u8; 32]) -> Self { - ChannelId(value) - } -} - -impl From for [u8; 32] { - fn from(value: ChannelId) -> Self { - value.0 - } -} - -impl<'a> From<&'a [u8; 32]> for ChannelId { - fn from(value: &'a [u8; 32]) -> Self { - ChannelId(*value) - } -} - -impl From for ChannelId { - fn from(value: H256) -> Self { - ChannelId(value.into()) - } -} - -impl AsRef<[u8]> for ChannelId { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct Channel { - /// ID of the agent contract deployed on Ethereum - pub agent_id: AgentId, - /// ID of the parachain who will receive or send messages using this channel - pub para_id: ParaId, -} - -pub trait StaticLookup { - /// Type to lookup from. - type Source; - /// Type to lookup into. - type Target; - /// Attempt a lookup. - fn lookup(s: Self::Source) -> Option; -} - -/// Channel for high-priority governance commands -pub const PRIMARY_GOVERNANCE_CHANNEL: ChannelId = - ChannelId::new(hex!("0000000000000000000000000000000000000000000000000000000000000001")); - -/// Channel for lower-priority governance commands -pub const SECONDARY_GOVERNANCE_CHANNEL: ChannelId = - ChannelId::new(hex!("0000000000000000000000000000000000000000000000000000000000000002")); - -pub struct DescribeHere; -impl DescribeLocation for DescribeHere { - fn describe_location(l: &Location) -> Option> { - match l.unpack() { - (0, []) => Some(Vec::::new().encode()), - _ => None, - } - } -} - -/// Creates an AgentId from a Location. An AgentId is a unique mapping to a Agent contract on -/// Ethereum which acts as the sovereign account for the Location. -pub type AgentIdOf = HashedDescription)>; diff --git a/bridges/snowbridge/parachain/primitives/core/src/operating_mode.rs b/bridges/snowbridge/parachain/primitives/core/src/operating_mode.rs deleted file mode 100644 index 9894e587ef5e..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/operating_mode.rs +++ /dev/null @@ -1,25 +0,0 @@ -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::RuntimeDebug; - -/// Basic operating modes for a bridges module (Normal/Halted). -#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum BasicOperatingMode { - /// Normal mode, when all operations are allowed. - Normal, - /// The pallet is halted. All non-governance operations are disabled. - Halted, -} - -impl Default for BasicOperatingMode { - fn default() -> Self { - Self::Normal - } -} - -impl BasicOperatingMode { - pub fn is_halted(&self) -> bool { - *self == BasicOperatingMode::Halted - } -} diff --git a/bridges/snowbridge/parachain/primitives/core/src/outbound.rs b/bridges/snowbridge/parachain/primitives/core/src/outbound.rs deleted file mode 100644 index bce123878d3a..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/outbound.rs +++ /dev/null @@ -1,413 +0,0 @@ -use codec::{Decode, Encode}; -use frame_support::PalletError; -use scale_info::TypeInfo; -use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; -use sp_core::{RuntimeDebug, H256}; -pub use v1::{AgentExecuteCommand, Command, Initializer, Message, OperatingMode, QueuedMessage}; - -/// Enqueued outbound messages need to be versioned to prevent data corruption -/// or loss after forkless runtime upgrades -#[derive(Encode, Decode, TypeInfo, Clone, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(PartialEq))] -pub enum VersionedQueuedMessage { - V1(QueuedMessage), -} - -impl TryFrom for QueuedMessage { - type Error = (); - fn try_from(x: VersionedQueuedMessage) -> Result { - use VersionedQueuedMessage::*; - match x { - V1(x) => Ok(x), - } - } -} - -impl> From for VersionedQueuedMessage { - fn from(x: T) -> Self { - VersionedQueuedMessage::V1(x.into()) - } -} - -mod v1 { - use crate::{pricing::UD60x18, ChannelId}; - use codec::{Decode, Encode}; - use ethabi::Token; - use scale_info::TypeInfo; - use sp_core::{RuntimeDebug, H160, H256, U256}; - use sp_std::{borrow::ToOwned, vec, vec::Vec}; - - /// A message which can be accepted by implementations of `/[`SendMessage`\]` - #[derive(Encode, Decode, TypeInfo, Clone, RuntimeDebug)] - #[cfg_attr(feature = "std", derive(PartialEq))] - pub struct Message { - /// ID for this message. One will be automatically generated if not provided. - /// - /// When this message is created from an XCM message, the ID should be extracted - /// from the `SetTopic` instruction. - /// - /// The ID plays no role in bridge consensus, and is purely meant for message tracing. - pub id: Option, - /// The message channel ID - pub channel_id: ChannelId, - /// The stable ID for a receiving gateway contract - pub command: Command, - } - - /// The operating mode of Channels and Gateway contract on Ethereum. - #[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)] - pub enum OperatingMode { - /// Normal operations. Allow sending and receiving messages. - Normal, - /// Reject outbound messages. This allows receiving governance messages but does now allow - /// enqueuing of new messages from the Ethereum side. This can be used to close off an - /// deprecated channel or pause the bridge for upgrade operations. - RejectingOutboundMessages, - } - - /// A command which is executable by the Gateway contract on Ethereum - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - #[cfg_attr(feature = "std", derive(PartialEq))] - pub enum Command { - /// Execute a sub-command within an agent for a consensus system in Polkadot - AgentExecute { - /// The ID of the agent - agent_id: H256, - /// The sub-command to be executed - command: AgentExecuteCommand, - }, - /// Upgrade the Gateway contract - Upgrade { - /// Address of the new implementation contract - impl_address: H160, - /// Codehash of the implementation contract - impl_code_hash: H256, - /// Optionally invoke an initializer in the implementation contract - initializer: Option, - }, - /// Create an agent representing a consensus system on Polkadot - CreateAgent { - /// The ID of the agent, derived from the `MultiLocation` of the consensus system on - /// Polkadot - agent_id: H256, - }, - /// Create bidirectional messaging channel to a parachain - CreateChannel { - /// The ID of the channel - channel_id: ChannelId, - /// The agent ID of the parachain - agent_id: H256, - /// Initial operating mode - mode: OperatingMode, - }, - /// Update the configuration of a channel - UpdateChannel { - /// The ID of the channel - channel_id: ChannelId, - /// The new operating mode - mode: OperatingMode, - }, - /// Set the global operating mode of the Gateway contract - SetOperatingMode { - /// The new operating mode - mode: OperatingMode, - }, - /// Transfer ether from an agent contract to a recipient account - TransferNativeFromAgent { - /// The agent ID - agent_id: H256, - /// The recipient of the ether - recipient: H160, - /// The amount to transfer - amount: u128, - }, - /// Set token fees of the Gateway contract - SetTokenTransferFees { - /// The fee(DOT) for the cost of creating asset on AssetHub - create_asset_xcm: u128, - /// The fee(DOT) for the cost of sending asset on AssetHub - transfer_asset_xcm: u128, - /// The fee(Ether) for register token to discourage spamming - register_token: U256, - }, - /// Set pricing parameters - SetPricingParameters { - // ETH/DOT exchange rate - exchange_rate: UD60x18, - // Cost of delivering a message from Ethereum to BridgeHub, in ROC/KSM/DOT - delivery_cost: u128, - }, - } - - impl Command { - /// Compute the enum variant index - pub fn index(&self) -> u8 { - match self { - Command::AgentExecute { .. } => 0, - Command::Upgrade { .. } => 1, - Command::CreateAgent { .. } => 2, - Command::CreateChannel { .. } => 3, - Command::UpdateChannel { .. } => 4, - Command::SetOperatingMode { .. } => 5, - Command::TransferNativeFromAgent { .. } => 6, - Command::SetTokenTransferFees { .. } => 7, - Command::SetPricingParameters { .. } => 8, - } - } - - /// ABI-encode the Command. - pub fn abi_encode(&self) -> Vec { - match self { - Command::AgentExecute { agent_id, command } => - ethabi::encode(&[Token::Tuple(vec![ - Token::FixedBytes(agent_id.as_bytes().to_owned()), - Token::Bytes(command.abi_encode()), - ])]), - Command::Upgrade { impl_address, impl_code_hash, initializer, .. } => - ethabi::encode(&[Token::Tuple(vec![ - Token::Address(*impl_address), - Token::FixedBytes(impl_code_hash.as_bytes().to_owned()), - initializer - .clone() - .map_or(Token::Bytes(vec![]), |i| Token::Bytes(i.params)), - ])]), - Command::CreateAgent { agent_id } => - ethabi::encode(&[Token::Tuple(vec![Token::FixedBytes( - agent_id.as_bytes().to_owned(), - )])]), - Command::CreateChannel { channel_id, agent_id, mode } => - ethabi::encode(&[Token::Tuple(vec![ - Token::FixedBytes(channel_id.as_ref().to_owned()), - Token::FixedBytes(agent_id.as_bytes().to_owned()), - Token::Uint(U256::from((*mode) as u64)), - ])]), - Command::UpdateChannel { channel_id, mode } => - ethabi::encode(&[Token::Tuple(vec![ - Token::FixedBytes(channel_id.as_ref().to_owned()), - Token::Uint(U256::from((*mode) as u64)), - ])]), - Command::SetOperatingMode { mode } => - ethabi::encode(&[Token::Tuple(vec![Token::Uint(U256::from((*mode) as u64))])]), - Command::TransferNativeFromAgent { agent_id, recipient, amount } => - ethabi::encode(&[Token::Tuple(vec![ - Token::FixedBytes(agent_id.as_bytes().to_owned()), - Token::Address(*recipient), - Token::Uint(U256::from(*amount)), - ])]), - Command::SetTokenTransferFees { - create_asset_xcm, - transfer_asset_xcm, - register_token, - } => ethabi::encode(&[Token::Tuple(vec![ - Token::Uint(U256::from(*create_asset_xcm)), - Token::Uint(U256::from(*transfer_asset_xcm)), - Token::Uint(*register_token), - ])]), - Command::SetPricingParameters { exchange_rate, delivery_cost } => - ethabi::encode(&[Token::Tuple(vec![ - Token::Uint(exchange_rate.clone().into_inner()), - Token::Uint(U256::from(*delivery_cost)), - ])]), - } - } - } - - /// Representation of a call to the initializer of an implementation contract. - /// The initializer has the following ABI signature: `initialize(bytes)`. - #[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] - pub struct Initializer { - /// ABI-encoded params of type `bytes` to pass to the initializer - pub params: Vec, - /// The initializer is allowed to consume this much gas at most. - pub maximum_required_gas: u64, - } - - /// A Sub-command executable within an agent - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - #[cfg_attr(feature = "std", derive(PartialEq))] - pub enum AgentExecuteCommand { - /// Transfer ERC20 tokens - TransferToken { - /// Address of the ERC20 token - token: H160, - /// The recipient of the tokens - recipient: H160, - /// The amount of tokens to transfer - amount: u128, - }, - } - - impl AgentExecuteCommand { - fn index(&self) -> u8 { - match self { - AgentExecuteCommand::TransferToken { .. } => 0, - } - } - - /// ABI-encode the sub-command - pub fn abi_encode(&self) -> Vec { - match self { - AgentExecuteCommand::TransferToken { token, recipient, amount } => - ethabi::encode(&[ - Token::Uint(self.index().into()), - Token::Bytes(ethabi::encode(&[ - Token::Address(*token), - Token::Address(*recipient), - Token::Uint(U256::from(*amount)), - ])), - ]), - } - } - } - - /// Message which is awaiting processing in the MessageQueue pallet - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - #[cfg_attr(feature = "std", derive(PartialEq))] - pub struct QueuedMessage { - /// Message ID - pub id: H256, - /// Channel ID - pub channel_id: ChannelId, - /// Command to execute in the Gateway contract - pub command: Command, - } -} - -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -/// Fee for delivering message -pub struct Fee -where - Balance: BaseArithmetic + Unsigned + Copy, -{ - /// Fee to cover cost of processing the message locally - pub local: Balance, - /// Fee to cover cost processing the message remotely - pub remote: Balance, -} - -impl Fee -where - Balance: BaseArithmetic + Unsigned + Copy, -{ - pub fn total(&self) -> Balance { - self.local.saturating_add(self.remote) - } -} - -impl From<(Balance, Balance)> for Fee -where - Balance: BaseArithmetic + Unsigned + Copy, -{ - fn from((local, remote): (Balance, Balance)) -> Self { - Self { local, remote } - } -} - -/// A trait for sending messages to Ethereum -pub trait SendMessage: SendMessageFeeProvider { - type Ticket: Clone + Encode + Decode; - - /// Validate an outbound message and return a tuple: - /// 1. Ticket for submitting the message - /// 2. Delivery fee - fn validate( - message: &Message, - ) -> Result<(Self::Ticket, Fee<::Balance>), SendError>; - - /// Submit the message ticket for eventual delivery to Ethereum - fn deliver(ticket: Self::Ticket) -> Result; -} - -pub trait Ticket: Encode + Decode + Clone { - fn message_id(&self) -> H256; -} - -/// A trait for getting the local costs associated with sending a message. -pub trait SendMessageFeeProvider { - type Balance: BaseArithmetic + Unsigned + Copy; - - /// The local component of the message processing fees in native currency - fn local_fee() -> Self::Balance; -} - -/// Reasons why sending to Ethereum could not be initiated -#[derive(Copy, Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, PalletError, TypeInfo)] -pub enum SendError { - /// Message is too large to be safely executed on Ethereum - MessageTooLarge, - /// The bridge has been halted for maintenance - Halted, - /// Invalid Channel - InvalidChannel, -} - -pub trait GasMeter { - /// All the gas used for submitting a message to Ethereum, minus the cost of dispatching - /// the command within the message - const MAXIMUM_BASE_GAS: u64; - - fn maximum_gas_used_at_most(command: &Command) -> u64 { - Self::MAXIMUM_BASE_GAS + Self::maximum_dispatch_gas_used_at_most(command) - } - - /// Measures the maximum amount of gas a command payload will require to dispatch, AFTER - /// validation & verification. - fn maximum_dispatch_gas_used_at_most(command: &Command) -> u64; -} - -/// A meter that assigns a constant amount of gas for the execution of a command -/// -/// The gas figures are extracted from this report: -/// > forge test --match-path test/Gateway.t.sol --gas-report -/// -/// A healthy buffer is added on top of these figures to account for: -/// * The EIP-150 63/64 rule -/// * Future EVM upgrades that may increase gas cost -pub struct ConstantGasMeter; - -impl GasMeter for ConstantGasMeter { - // The base transaction cost, which includes: - // 21_000 transaction cost, roughly worst case 64_000 for calldata, and 100_000 - // for message verification - const MAXIMUM_BASE_GAS: u64 = 185_000; - - fn maximum_dispatch_gas_used_at_most(command: &Command) -> u64 { - match command { - Command::CreateAgent { .. } => 275_000, - Command::CreateChannel { .. } => 100_000, - Command::UpdateChannel { .. } => 50_000, - Command::TransferNativeFromAgent { .. } => 60_000, - Command::SetOperatingMode { .. } => 40_000, - Command::AgentExecute { command, .. } => match command { - // Execute IERC20.transferFrom - // - // Worst-case assumptions are important: - // * No gas refund for clearing storage slot of source account in ERC20 contract - // * Assume dest account in ERC20 contract does not yet have a storage slot - // * ERC20.transferFrom possibly does other business logic besides updating balances - AgentExecuteCommand::TransferToken { .. } => 100_000, - }, - Command::Upgrade { initializer, .. } => { - let initializer_max_gas = match *initializer { - Some(Initializer { maximum_required_gas, .. }) => maximum_required_gas, - None => 0, - }; - // total maximum gas must also include the gas used for updating the proxy before - // the the initializer is called. - 50_000 + initializer_max_gas - }, - Command::SetTokenTransferFees { .. } => 60_000, - Command::SetPricingParameters { .. } => 60_000, - } - } -} - -impl GasMeter for () { - const MAXIMUM_BASE_GAS: u64 = 1; - - fn maximum_dispatch_gas_used_at_most(_: &Command) -> u64 { - 1 - } -} - -pub const ETHER_DECIMALS: u8 = 18; diff --git a/bridges/snowbridge/parachain/primitives/core/src/pricing.rs b/bridges/snowbridge/parachain/primitives/core/src/pricing.rs deleted file mode 100644 index 33aeda6d15c4..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/pricing.rs +++ /dev/null @@ -1,67 +0,0 @@ -use codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_arithmetic::traits::{BaseArithmetic, Unsigned, Zero}; -use sp_core::U256; -use sp_runtime::{FixedU128, RuntimeDebug}; -use sp_std::prelude::*; - -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct PricingParameters { - /// ETH/DOT exchange rate - pub exchange_rate: FixedU128, - /// Relayer rewards - pub rewards: Rewards, - /// Ether (wei) fee per gas unit - pub fee_per_gas: U256, -} - -#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct Rewards { - /// Local reward in DOT - pub local: Balance, - /// Remote reward in ETH (wei) - pub remote: U256, -} - -#[derive(RuntimeDebug)] -pub struct InvalidPricingParameters; - -impl PricingParameters -where - Balance: BaseArithmetic + Unsigned + Copy, -{ - pub fn validate(&self) -> Result<(), InvalidPricingParameters> { - if self.exchange_rate == FixedU128::zero() { - return Err(InvalidPricingParameters) - } - if self.fee_per_gas == U256::zero() { - return Err(InvalidPricingParameters) - } - if self.rewards.local.is_zero() { - return Err(InvalidPricingParameters) - } - if self.rewards.remote.is_zero() { - return Err(InvalidPricingParameters) - } - Ok(()) - } -} - -/// Holder for fixed point number implemented in -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(PartialEq))] -pub struct UD60x18(U256); - -impl From for UD60x18 { - fn from(value: FixedU128) -> Self { - // Both FixedU128 and UD60x18 have 18 decimal places - let inner: u128 = value.into_inner(); - UD60x18(inner.into()) - } -} - -impl UD60x18 { - pub fn into_inner(self) -> U256 { - self.0 - } -} diff --git a/bridges/snowbridge/parachain/primitives/core/src/ringbuffer.rs b/bridges/snowbridge/parachain/primitives/core/src/ringbuffer.rs deleted file mode 100644 index dcee20359a78..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/ringbuffer.rs +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use codec::FullCodec; -use core::{cmp::Ord, marker::PhantomData, ops::Add}; -use frame_support::storage::{types::QueryKindTrait, StorageMap, StorageValue}; -use sp_core::{Get, GetDefault}; -use sp_runtime::traits::{One, Zero}; - -/// Trait object presenting the ringbuffer interface. -pub trait RingBufferMap -where - Key: FullCodec, - Value: FullCodec, - QueryKind: QueryKindTrait, -{ - /// Insert a map entry. - fn insert(k: Key, v: Value); - - /// Check if map contains a key - fn contains_key(k: Key) -> bool; - - /// Get the value of the key - fn get(k: Key) -> QueryKind::Query; -} - -pub struct RingBufferMapImpl( - PhantomData<(Index, B, CurrentIndex, Intermediate, M, QueryKind)>, -); - -/// Ringbuffer implementation based on `RingBufferTransient` -impl - RingBufferMap - for RingBufferMapImpl -where - Key: FullCodec + Clone, - Value: FullCodec, - Index: Ord + One + Zero + Add + Copy + FullCodec + Eq, - B: Get, - CurrentIndex: StorageValue, - Intermediate: StorageMap, - M: StorageMap, - QueryKind: QueryKindTrait, -{ - /// Insert a map entry. - fn insert(k: Key, v: Value) { - let bound = B::get(); - let mut current_index = CurrentIndex::get(); - - // Adding one here as bound denotes number of items but our index starts with zero. - if (current_index + Index::one()) >= bound { - current_index = Index::zero(); - } else { - current_index = current_index + Index::one(); - } - - // Deleting earlier entry if it exists - if Intermediate::contains_key(current_index) { - let older_key = Intermediate::get(current_index); - M::remove(older_key); - } - - Intermediate::insert(current_index, k.clone()); - CurrentIndex::set(current_index); - M::insert(k, v); - } - - /// Check if map contains a key - fn contains_key(k: Key) -> bool { - M::contains_key(k) - } - - /// Get the value associated with key - fn get(k: Key) -> M::Query { - M::get(k) - } -} diff --git a/bridges/snowbridge/parachain/primitives/core/src/tests.rs b/bridges/snowbridge/parachain/primitives/core/src/tests.rs deleted file mode 100644 index 725fff1a9c94..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/src/tests.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::{ChannelId, ParaId}; -use hex_literal::hex; - -const EXPECT_CHANNEL_ID: [u8; 32] = - hex!("c173fac324158e77fb5840738a1a541f633cbec8884c6a601c567d2b376a0539"); - -// The Solidity equivalent code is tested in Gateway.t.sol:testDeriveChannelID -#[test] -fn generate_channel_id() { - let para_id: ParaId = 1000.into(); - let channel_id: ChannelId = para_id.into(); - assert_eq!(channel_id, EXPECT_CHANNEL_ID.into()); -} diff --git a/bridges/snowbridge/parachain/primitives/core/tests/fixtures/packet.scale b/bridges/snowbridge/parachain/primitives/core/tests/fixtures/packet.scale deleted file mode 100644 index d5f6696ea69f..000000000000 Binary files a/bridges/snowbridge/parachain/primitives/core/tests/fixtures/packet.scale and /dev/null differ diff --git a/bridges/snowbridge/parachain/primitives/core/tests/mod.rs b/bridges/snowbridge/parachain/primitives/core/tests/mod.rs deleted file mode 100644 index c91063a81480..000000000000 --- a/bridges/snowbridge/parachain/primitives/core/tests/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -#[cfg(test)] -mod tests { - use frame_support::traits::Contains; - use snowbridge_core::AllowSiblingsOnly; - use xcm::prelude::{Junction::Parachain, Location}; - - #[test] - fn allow_siblings_predicate_only_allows_siblings() { - let sibling = Location::new(1, [Parachain(1000)]); - let child = Location::new(0, [Parachain(1000)]); - assert!(AllowSiblingsOnly::contains(&sibling), "Sibling returns true."); - assert!(!AllowSiblingsOnly::contains(&child), "Child returns false."); - } -} diff --git a/bridges/snowbridge/parachain/primitives/ethereum/.cargo/config.toml b/bridges/snowbridge/parachain/primitives/ethereum/.cargo/config.toml deleted file mode 100644 index 4ec2f3b86203..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[target.wasm32-unknown-unknown] -runner = 'wasm-bindgen-test-runner' diff --git a/bridges/snowbridge/parachain/primitives/ethereum/Cargo.toml b/bridges/snowbridge/parachain/primitives/ethereum/Cargo.toml deleted file mode 100644 index 016f16ce0e6a..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/Cargo.toml +++ /dev/null @@ -1,56 +0,0 @@ -[package] -name = "snowbridge-ethereum" -description = "Snowbridge Ethereum" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -serde = { version = "1.0.195", optional = true, features = ["derive"] } -serde-big-array = { version = "0.3.2", optional = true, features = ["const-generics"] } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -ethbloom = { version = "0.13.0", default-features = false } -ethereum-types = { version = "0.14.1", default-features = false, features = ["codec", "rlp", "serialize"] } -hex = { package = "rustc-hex", version = "2.1.0", default-features = false } -hex-literal = { version = "0.4.1", default-features = false } -parity-bytes = { version = "0.1.2", default-features = false } -rlp = { version = "0.5.2", default-features = false } - -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } - -ethabi = { git = "https://github.com/snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } - -[dev-dependencies] -wasm-bindgen-test = "0.3.19" -rand = "0.8.5" -serde_json = "1.0.111" - -[features] -default = ["std"] -expensive_tests = [] -std = [ - "codec/std", - "ethabi/std", - "ethbloom/std", - "ethereum-types/std", - "hex/std", - "parity-bytes/std", - "rlp/std", - "scale-info/std", - "serde", - "serde-big-array", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/bridges/snowbridge/parachain/primitives/ethereum/README.md b/bridges/snowbridge/parachain/primitives/ethereum/README.md deleted file mode 100644 index c295aad9040f..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Ethereum Primitives - -Contains code necessary to decode RLP encoded data (like the Ethereum log), structs for Ethereum execution headers. The -code in this crate relates to the Ethereum execution chain. diff --git a/bridges/snowbridge/parachain/primitives/ethereum/src/header.rs b/bridges/snowbridge/parachain/primitives/ethereum/src/header.rs deleted file mode 100644 index f0b51f8c79de..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/src/header.rs +++ /dev/null @@ -1,414 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use codec::{Decode, Encode}; -use ethbloom::Bloom as EthBloom; -use hex_literal::hex; -use parity_bytes::Bytes; -use rlp::RlpStream; -use scale_info::TypeInfo; -use sp_io::hashing::keccak_256; -use sp_runtime::RuntimeDebug; -use sp_std::{convert::TryInto, prelude::*}; - -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -#[cfg(feature = "std")] -use serde_big_array::BigArray; - -use ethereum_types::{Address, H256, H64, U256}; - -use crate::{mpt, receipt}; - -/// Complete block header id. -#[derive(Clone, Copy, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -pub struct HeaderId { - /// Header number. - pub number: u64, - /// Header hash. - pub hash: H256, -} - -const EMPTY_OMMERS_HASH: [u8; 32] = - hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); - -/// An Ethereum block header. -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Header { - /// Parent block hash. - pub parent_hash: H256, - /// Block timestamp. - pub timestamp: u64, - /// Block number. - pub number: u64, - /// Block author. - pub author: Address, - - /// Transactions root. - pub transactions_root: H256, - /// Block ommers hash. - pub ommers_hash: H256, - /// Block extra data. - pub extra_data: Bytes, - - /// State root. - pub state_root: H256, - /// Block receipts root. - pub receipts_root: H256, - /// Block bloom. - pub logs_bloom: Bloom, - /// Gas used for contracts execution. - pub gas_used: U256, - /// Block gas limit. - pub gas_limit: U256, - - /// Block difficulty. - pub difficulty: U256, - /// Vector of post-RLP-encoded fields. - pub seal: Vec, - - // Base fee per gas (EIP-1559), only in headers from the London hardfork onwards. - pub base_fee: Option, -} - -impl Header { - /// Compute hash of this header (keccak of the RLP with seal). - pub fn compute_hash(&self) -> H256 { - keccak_256(&self.rlp(true)).into() - } - - /// Compute hash of the truncated header i.e. excluding seal. - pub fn compute_partial_hash(&self) -> H256 { - keccak_256(&self.rlp(false)).into() - } - - pub fn check_receipt_proof( - &self, - proof: &[Vec], - ) -> Option> { - match self.apply_merkle_proof(proof) { - Some((root, data)) if root == self.receipts_root => Some(rlp::decode(&data)), - Some((_, _)) => None, - None => None, - } - } - - pub fn apply_merkle_proof(&self, proof: &[Vec]) -> Option<(H256, Vec)> { - let mut iter = proof.iter().rev(); - let first_bytes = match iter.next() { - Some(b) => b, - None => return None, - }; - let item_to_prove: mpt::ShortNode = rlp::decode(first_bytes).ok()?; - - let final_hash: Option<[u8; 32]> = iter.try_fold(keccak_256(first_bytes), |acc, x| { - let node: Box = x.as_slice().try_into().ok()?; - if (*node).contains_hash(acc.into()) { - return Some(keccak_256(x)) - } - None - }); - - final_hash.map(|hash| (hash.into(), item_to_prove.value)) - } - - pub fn mix_hash(&self) -> Option { - let bytes: Bytes = self.decoded_seal_field(0, 32)?; - let size = bytes.len(); - let mut mix_hash = [0u8; 32]; - for i in 0..size { - mix_hash[31 - i] = bytes[size - 1 - i]; - } - Some(mix_hash.into()) - } - - pub fn nonce(&self) -> Option { - let bytes: Bytes = self.decoded_seal_field(1, 8)?; - let size = bytes.len(); - let mut nonce = [0u8; 8]; - for i in 0..size { - nonce[7 - i] = bytes[size - 1 - i]; - } - Some(nonce.into()) - } - - pub fn has_ommers(&self) -> bool { - self.ommers_hash != EMPTY_OMMERS_HASH.into() - } - - fn decoded_seal_field(&self, index: usize, max_len: usize) -> Option { - let bytes: Bytes = rlp::decode(self.seal.get(index)?).ok()?; - if bytes.len() > max_len { - return None - } - Some(bytes) - } - - /// Returns header RLP with or without seals. - /// For EIP-1559 baseFee addition refer to: - /// - fn rlp(&self, with_seal: bool) -> Bytes { - let mut s = RlpStream::new(); - - let stream_length_without_seal = if self.base_fee.is_some() { 14 } else { 13 }; - - if with_seal { - s.begin_list(stream_length_without_seal + self.seal.len()); - } else { - s.begin_list(stream_length_without_seal); - } - - s.append(&self.parent_hash); - s.append(&self.ommers_hash); - s.append(&self.author); - s.append(&self.state_root); - s.append(&self.transactions_root); - s.append(&self.receipts_root); - s.append(&EthBloom::from(self.logs_bloom.0)); - s.append(&self.difficulty); - s.append(&self.number); - s.append(&self.gas_limit); - s.append(&self.gas_used); - s.append(&self.timestamp); - s.append(&self.extra_data); - - if with_seal { - for b in &self.seal { - s.append_raw(b, 1); - } - } - - if let Some(base_fee) = self.base_fee { - s.append(&base_fee); - } - - s.out().to_vec() - } -} - -/// Logs bloom. -#[derive(Clone, Debug, Encode, Decode, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Bloom(#[cfg_attr(feature = "std", serde(with = "BigArray"))] [u8; 256]); - -impl<'a> From<&'a [u8; 256]> for Bloom { - fn from(buffer: &'a [u8; 256]) -> Bloom { - Bloom(*buffer) - } -} - -impl PartialEq for Bloom { - fn eq(&self, other: &Bloom) -> bool { - self.0.iter().zip(other.0.iter()).all(|(l, r)| l == r) - } -} - -impl Default for Bloom { - fn default() -> Self { - Bloom([0; 256]) - } -} - -impl rlp::Decodable for Bloom { - fn decode(rlp: &rlp::Rlp) -> Result { - let v: Vec = rlp.as_val()?; - match v.len() { - 256 => { - let mut bytes = [0u8; 256]; - bytes.copy_from_slice(&v); - Ok(Self(bytes)) - }, - _ => Err(rlp::DecoderError::Custom("Expected 256 bytes")), - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn bloom_decode_rlp() { - let raw_bloom = hex!( - " - b901000420000000000000000000008002000000000001000000000001000000000000000000 - 0000000000000000000000000002000000080000000000000000200000000000000000000000 - 0000080000002200000000004000100000000000000000000000000000000000000000000000 - 0000000000000004000000001000010000000000080000000000400000000000000000000000 - 0000080000004000000000020000000000020000000000000000000000000000000000000000 - 0000040000000000020000000001000000000000000000000000000010000000020000200000 - 10200000000000010000000000000000000000000000000000000010000000 - " - ); - let expected_bytes = &raw_bloom[3..]; - let bloom: Bloom = rlp::decode(&raw_bloom).unwrap(); - assert_eq!(bloom.0, expected_bytes); - } - - #[test] - fn header_compute_hash_poa() { - // PoA header - let header = Header { - parent_hash: Default::default(), - timestamp: 0, - number: 0, - author: Default::default(), - transactions_root: hex!( - "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - ) - .into(), - ommers_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - .into(), - extra_data: vec![], - state_root: hex!("eccf6b74c2bcbe115c71116a23fe963c54406010c244d9650526028ad3e32cce") - .into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - logs_bloom: Default::default(), - gas_used: Default::default(), - gas_limit: 0x222222.into(), - difficulty: 0x20000.into(), - seal: vec![vec![0x80], { - let mut vec = vec![0xb8, 0x41]; - vec.resize(67, 0); - vec - }], - base_fee: None, - }; - assert_eq!( - header.compute_hash().as_bytes(), - hex!("9ff57c7fa155853586382022f0982b71c51fa313a0942f8c456300896643e890"), - ); - } - - #[test] - fn header_compute_hash_pow() { - // - let nonce = hex!("6935bbe7b63c4f8e").to_vec(); - let mix_hash = - hex!("be3adfb0087be62b28b716e2cdf3c79329df5caa04c9eee035d35b5d52102815").to_vec(); - let header = Header { - parent_hash: hex!("bede0bddd6f32c895fc505ffe0c39d9bde58e9a5272f31a3dee448b796edcbe3") - .into(), - timestamp: 1603160977, - number: 11090290, - author: hex!("ea674fdde714fd979de3edf0f56aa9716b898ec8").into(), - transactions_root: hex!( - "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - ) - .into(), - ommers_hash: hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") - .into(), - extra_data: hex!("65746865726d696e652d61736961312d33").to_vec(), - state_root: hex!("7dcb8aca872b712bad81df34a89d4efedc293566ffc3eeeb5cbcafcc703e42c9") - .into(), - receipts_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - .into(), - logs_bloom: Default::default(), - gas_used: 0.into(), - gas_limit: 0xbe8c19.into(), - difficulty: 0xbc140caa61087i64.into(), - seal: vec![rlp::encode(&mix_hash).to_vec(), rlp::encode(&nonce).to_vec()], - base_fee: None, - }; - assert_eq!( - header.compute_hash().as_bytes(), - hex!("0f9bdc91c2e0140acb873330742bda8c8181fa3add91fe7ae046251679cedef7"), - ); - } - - #[test] - fn header_pow_seal_fields_extracted_correctly() { - let nonce: H64 = hex!("6935bbe7b63c4f8e").into(); - let mix_hash: H256 = - hex!("be3adfb0087be62b28b716e2cdf3c79329df5caa04c9eee035d35b5d52102815").into(); - let header = Header { - seal: vec![ - rlp::encode(&mix_hash.0.to_vec()).to_vec(), - rlp::encode(&nonce.0.to_vec()).to_vec(), - ], - ..Default::default() - }; - - assert_eq!(header.nonce().unwrap(), nonce); - assert_eq!(header.mix_hash().unwrap(), mix_hash); - } - - #[test] - fn header_pow_seal_fields_return_none_for_invalid_values() { - let nonce = hex!("696935bbe7b63c4f8e").to_vec(); - let mix_hash = - hex!("bebe3adfb0087be62b28b716e2cdf3c79329df5caa04c9eee035d35b5d52102815").to_vec(); - let mut header = Header { - seal: vec![rlp::encode(&mix_hash).to_vec(), rlp::encode(&nonce).to_vec()], - ..Default::default() - }; - assert_eq!(header.nonce(), None); - assert_eq!(header.mix_hash(), None); - - header.seal = Vec::new(); - assert_eq!(header.nonce(), None); - assert_eq!(header.mix_hash(), None); - } - - #[test] - fn header_check_receipt_proof() { - let header = Header { - receipts_root: hex!("fd5e397a84884641f53c496804f24b5276cbb8c5c9cfc2342246be8e3ce5ad02") - .into(), - ..Default::default() - }; - - // Valid proof - let proof_receipt5 = vec!( - hex!("f90131a0b5ba404eb5a6a88e56579f4d37ef9813b5ad7f86f0823ff3b407ac5a6bb465eca0398ead2655e78e03c127ce22c5830e90f18b1601ec055f938336c084feb915a9a026d322c26e46c50942c1aabde50e36df5cde572aed650ce73ea3182c6e90a02ca00600a356135f4db1db0d9842264cdff2652676f881669e91e316c0b6dd783011a0837f1deb4075336da320388c1edfffc56c448a43f4a5ba031300d32a7b509fc5a01c3ac82fd65b4aba7f9afaf604d9c82ec7e2deb573a091ae235751bc5c0c288da05d454159d9071b0f68b6e0503d290f23ac7602c1db0c569dee4605d8f5298f09a00bbed10350ec954448df795f6fd46e3faefc800ede061b3840eedc6e2b07a74da0acb02d26a3650f2064c14a435fdf1f668d8655daf455ebdf671713a7c089b3898080808080808080").to_vec(), - hex!("f901f180a00046a08d4f0bdbdc6b31903086ce323182bce6725e7d9415f7ff91ee8f4820bda0e7cd26ad5f3d2771e4b5ab788e268a14a10209f94ee918eb6c829d21d3d11c1da00d4a56d9e9a6751874fd86c7e3cb1c6ad5a848da62751325f478978a00ea966ea064b81920c8f04a8a1e21f53a8280e739fbb7b00b2ab92493ca3f610b70e8ac85a0b1040ed4c55a73178b76abb16f946ce5bebd6b93ab873c83327df54047d12c27a0de6485e9ac58dc6e2b04b4bb38f562684f0b1a2ee586cc11079e7d9a9dc40b32a0d394f4d3532c3124a65fa36e69147e04fd20453a72ee9c50660f17e13ce9df48a066501003fc3e3478efd2803cd0eded6bbe9243ca01ba754d6327071ddbcbc649a0b2684e518f325fee39fc8ea81b68f3f5c785be00d087f3bed8857ae2ee8da26ea071060a5c52042e8d7ce21092f8ecf06053beb9a0b773a6f91a30c4220aa276b2a0fc22436632574ccf6043d0986dede27ea94c9ca9a3bb5ec03ce776a4ddef24a9a05a8a1d6698c4e7d8cc3a2506cb9b12ea9a079c9c7099bc919dc804033cc556e4a0170c468b0716fd36d161f0bf05875f15756a2976de92f9efe7716320509d79c9a0182f909a90cab169f3efb62387f9cccdd61440acc4deec42f68a4f7ca58075c7a055cf0e9202ac75689b76318f1171f3a44465eddc06aae0713bfb6b34fdd27b7980").to_vec(), - hex!("f904de20b904daf904d701830652f0b9010004200000000000000000000080020000000000010000000000010000000000000000000000000000000000000000000002000000080000000000000000200000000000000000000000000008000000220000000000400010000000000000000000000000000000000000000000000000000000000000040000000010000100000000000800000000004000000000000000000000000000080000004000000000020000000000020000000000000000000000000000000000000000000004000000000002000000000100000000000000000000000000001000000002000020000010200000000000010000000000000000000000000000000000000010000000f903ccf89b9421130f34829b4c343142047a28ce96ec07814b15f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a000000000000000000000000000000000000000000000000000000005d09b7380f89b9421130f34829b4c343142047a28ce96ec07814b15f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da0ffffffffffffffffffffffffffffffffffffffffffffffffffffffcc840c6920f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078ef87994e9c1281aae66801fa35ec404d5f2aea393ff6988e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000000000000001f1420ad1d40000000000000000000000000000000000000000000000014ad400879d159a38f8fc94e9c1281aae66801fa35ec404d5f2aea393ff6988f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488db88000000000000000000000000000000000000000000000000000000005d415f3320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e973b5a5d1078ef87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078e").to_vec(), - ); - assert!(header.check_receipt_proof(&proof_receipt5).is_some()); - - // Various invalid proofs - let proof_empty: Vec> = vec![]; - let proof_missing_full_node = vec![proof_receipt5[0].clone(), proof_receipt5[2].clone()]; - let proof_missing_short_node1 = vec![proof_receipt5[0].clone(), proof_receipt5[1].clone()]; - let proof_missing_short_node2 = vec![proof_receipt5[0].clone()]; - let proof_invalid_encoding = vec![proof_receipt5[2][2..].to_vec()]; - let proof_no_full_node = vec![proof_receipt5[2].clone(), proof_receipt5[2].clone()]; - assert!(header.check_receipt_proof(&proof_empty).is_none()); - assert!(header.check_receipt_proof(&proof_missing_full_node).is_none()); - - assert_eq!( - header.check_receipt_proof(&proof_missing_short_node1), - Some(Err(rlp::DecoderError::Custom("Unsupported receipt type"))) - ); - - assert_eq!( - header.check_receipt_proof(&proof_missing_short_node2), - Some(Err(rlp::DecoderError::Custom("Unsupported receipt type"))) - ); - - assert!(header.check_receipt_proof(&proof_invalid_encoding).is_none()); - assert!(header.check_receipt_proof(&proof_no_full_node).is_none()); - } - - #[test] - fn header_check_receipt_proof_with_intermediate_short_node() { - let header = Header { - receipts_root: hex!("d128e3a57142d2bf15bc0cbcac7ad54f40750d571b5c3097e425882c10c9ba66") - .into(), - ..Default::default() - }; - - let proof_receipt263 = vec![ - hex!("f90131a00d3cb8d3f57ac1c0e12918a2ebe0cafed8c273577b9dd73e7ed1079b403ef494a0678b9835b834f8a287c0dd33a8fca9146e456ca688555ed4ec1361a2180b778da0fe42da181a46677a043b3d9d4b8bb05a6a17b7b5c010c17e7c1d31cfb7c4f911a0c89f0e2c53241cdb578e1f2b4caf6ba36e00500bdc57fecd66b84a6a58394c19a086c3c1fae5a0575940b5d38e111c469d07883106c26856f3ef608469a2081f13a06c5992ff00aab6226a70a032fd2f571ba22f797321f45e2daa73020d638d21b0a050861e9503ef68728f6c90a44f7fe1bceb2a9bdab6957bbe7136166bd849561ea006aa6eaca8a07e57176e9aa41e6a09edfb7678d1a112404e0ec779d7e567e82ea0bb0b430d303ba21b0af11c487b8a218bd75db54c98940b3f11bad8ff47cad3ef8080808080808080").to_vec(), - hex!("f871a0246de222036ee6a03329b0105da0a6b3f916fc95a9ed5a403a581a0c4d74242ca0ac108a49a88b57a05ac34a108b39f1e45f6f167f2b9fbc8d52fb58e2e5a6af1ea0fcfe07ac2ccd3c28b6eab68d1bce112f6f6dbd9023e4ec3c05b96615aa803d798080808080808080808080808080").to_vec(), - hex!("e4820001a04fff54398cad4d05ea6abfd8b0f3b4fe14c04d7ff5f5211c5b927d9cf72ac1d8").to_vec(), - hex!("f851a096d010643ca2d47412ca66898286b5f2412963b9ec051b33e570d575914c9c5ca028cd24c652989542fe89479ec6388eac4592432242af5ba97563b3ac7c71c019808080808080808080808080808080").to_vec(), - hex!("f90211a0bb35a84c5b1dcb78ec9d32614912c696e62df77bebf9ab326ee55b5d3acdde46a01084b30dac8df0accfcd0fd6330b7f6fc72a4651246d0694be9162151686a620a03eed50afdce7909d784c6157c445a444c806b5f23d31f3b63786f600c84a95b2a0af5232f1df6c6d41879804d081abe867002abe26ba3e5f8e0254a83a54769831a0607915fb13dd5da594256389a45007a67a7f7a86e95d38d8462792b6c98a722ea00e1260fda1730f2738c650ce2bfba83857bc10f8fb119ebc4fb39acba24e6fbaa0d11de17e417327457812675ca3b84ae8e1b64827abfe01420953697c8313d5b1a05fcaf2f7a88f76336a0c32ffc78acb87ae2005454bd25d658035331be3173b46a03f94f4952ab9e650f83cfd0e7f367b1bcc493aacf39a06f16c4a2e1b5605da48a0bdb4ec79785ca8ae22d60f1bbd42d707b4d7ec4aff231a3ebab755e315b35053a043a67c3f2bcef37c8f47a673adcb7061007a553696d1092408601c11b2e6846aa0c519d5af48cae87c7f4538845417c9735813bee892a6fe2dda79f5c414e8576aa0f7058256e09589501d7c231d739e61c84a850e139690989d24fda6058b432e98a081a52faab520978cb19ce14400dba0cd5bcdc4e5a3c0740678aa8f97ee0e5c56a0bcecc61cadeae52518e3b68a48af4b11603dfd9d99d99d7985efa6d2de44f904a02cba4accfc6f39bc5adb6d4440eb6358b4a5103ef93298e4e694f1f940f8b48280").to_vec(), - hex!("f901ae20b901aaf901a70183bb444eb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000100000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000080000000000000000000000000000000000000000000000002000000000000000000081000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000f89df89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000002e514404ff6823f1b46a8318a709251db414e5e1a000000000000000000000000055021c55847c00d764357a352e5803237d328954a0000000000000000000000000000000000000000000000000000000000201c370").to_vec(), - ]; - assert!(header.check_receipt_proof(&proof_receipt263).is_some()); - } -} diff --git a/bridges/snowbridge/parachain/primitives/ethereum/src/lib.rs b/bridges/snowbridge/parachain/primitives/ethereum/src/lib.rs deleted file mode 100644 index 1a10ea9abb77..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod header; -pub mod log; -pub mod mpt; -pub mod receipt; - -pub use ethereum_types::{Address, H160, H256, H64, U256}; - -pub use header::{Bloom, Header, HeaderId}; -pub use log::Log; -pub use receipt::Receipt; - -#[derive(Debug)] -pub enum DecodeError { - // Unexpected RLP data - InvalidRLP(rlp::DecoderError), - // Data does not match expected ABI - InvalidABI(ethabi::Error), - // Invalid message payload - InvalidPayload, -} - -impl From for DecodeError { - fn from(err: rlp::DecoderError) -> Self { - DecodeError::InvalidRLP(err) - } -} - -impl From for DecodeError { - fn from(err: ethabi::Error) -> Self { - DecodeError::InvalidABI(err) - } -} diff --git a/bridges/snowbridge/parachain/primitives/ethereum/src/log.rs b/bridges/snowbridge/parachain/primitives/ethereum/src/log.rs deleted file mode 100644 index 7b8e35bb1133..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/src/log.rs +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use codec::{Decode, Encode}; -use ethereum_types::{H160, H256}; -use sp_std::prelude::*; - -#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)] -pub struct Log { - pub address: H160, - pub topics: Vec, - pub data: Vec, -} - -impl rlp::Decodable for Log { - /// We need to implement rlp::Decodable manually as the derive macro RlpDecodable - /// didn't seem to generate the correct code for parsing our logs. - fn decode(rlp: &rlp::Rlp) -> Result { - let mut iter = rlp.iter(); - - let address: H160 = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected log address")), - }; - - let topics: Vec = match iter.next() { - Some(data) => data.as_list()?, - None => return Err(rlp::DecoderError::Custom("Expected log topics")), - }; - - let data: Vec = match iter.next() { - Some(data) => data.data()?.to_vec(), - None => return Err(rlp::DecoderError::Custom("Expected log data")), - }; - - Ok(Self { address, topics, data }) - } -} - -#[cfg(test)] -mod tests { - - use super::Log; - use hex_literal::hex; - - const RAW_LOG: [u8; 605] = hex!( - " - f9025a941cfd66659d44cfe2e627c5742ba7477a3284cffae1a0266413be5700ce8dd5ac6b9a7dfb - abe99b3e45cae9a68ac2757858710b401a38b9022000000000000000000000000000000000000000 - 00000000000000000000000060000000000000000000000000000000000000000000000000000000 - 00000000c00000000000000000000000000000000000000000000000000000000000000100000000 - 00000000000000000000000000000000000000000000000000000000283163466436363635394434 - 34636665324536323763353734324261373437376133323834634666410000000000000000000000 - 00000000000000000000000000000000000000000000000000000000000000000000000000000000 - 000000000773656e6445544800000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000001000000000000000000000000 - 00cffeaaf7681c89285d65cfbe808b80e50269657300000000000000000000000000000000000000 - 000000000000000000000000a0000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000000000000a000000 - 00000000000000000000000000000000000000000000000000000000020000000000000000000000 - 00000000000000000000000000000000000000002f3146524d4d3850456957585961783772705336 - 5834585a5831614141785357783143724b5479725659685632346667000000000000000000000000 - 0000000000 - " - ); - - #[test] - fn decode_log() { - let log: Log = rlp::decode(&RAW_LOG).unwrap(); - assert_eq!(log.address.as_bytes(), hex!["1cfd66659d44cfe2e627c5742ba7477a3284cffa"]); - assert_eq!( - log.topics[0].as_bytes(), - hex!["266413be5700ce8dd5ac6b9a7dfbabe99b3e45cae9a68ac2757858710b401a38"] - ); - } -} diff --git a/bridges/snowbridge/parachain/primitives/ethereum/src/mpt.rs b/bridges/snowbridge/parachain/primitives/ethereum/src/mpt.rs deleted file mode 100644 index 9a2dae486dcc..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/src/mpt.rs +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Helper types to work with Ethereum's Merkle Patricia Trie nodes - -use ethereum_types::H256; -use sp_std::{convert::TryFrom, prelude::*}; - -pub trait Node { - fn contains_hash(&self, hash: H256) -> bool; -} - -impl TryFrom<&[u8]> for Box { - type Error = rlp::DecoderError; - - fn try_from(bytes: &[u8]) -> Result, Self::Error> { - let rlp = rlp::Rlp::new(bytes); - match rlp.item_count()? { - 2 => { - let node: ShortNode = rlp.as_val()?; - Ok(Box::new(node)) - }, - 17 => { - let node: FullNode = rlp.as_val()?; - Ok(Box::new(node)) - }, - _ => Err(rlp::DecoderError::Custom("Invalid number of list elements")), - } - } -} - -/// Intermediate trie node with children (refers to node with same name in Geth). -/// This struct only handles the proof representation, i.e. a child is either empty -/// or a 32-byte hash of its subtree. -pub struct FullNode { - pub children: Vec>, -} - -impl rlp::Decodable for FullNode { - fn decode(rlp: &rlp::Rlp) -> Result { - let children: Vec> = rlp - .iter() - .map(|item| { - let v: Vec = item.as_val()?; - match v.len() { - 0 => Ok(None), - 32 => { - let mut bytes = [0u8; 32]; - bytes.copy_from_slice(&v); - Ok(Some(bytes.into())) - }, - _ => Err(rlp::DecoderError::Custom("Expected 32-byte hash or empty child")), - } - }) - .collect::>()?; - - Ok(Self { children }) - } -} - -impl Node for FullNode { - fn contains_hash(&self, hash: H256) -> bool { - self.children.iter().any(|h| Some(hash) == *h) - } -} - -/// Trie node where `value` is either the RLP-encoded item we're -/// proving or an intermediate hash (refers to node with same name in Geth) -/// Proof verification should return `value`. `key` is an implementation -/// detail of the trie. -pub struct ShortNode { - pub key: Vec, - pub value: Vec, -} - -impl rlp::Decodable for ShortNode { - fn decode(rlp: &rlp::Rlp) -> Result { - let mut iter = rlp.iter(); - - let key: Vec = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected key bytes")), - }; - - let value: Vec = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected value bytes")), - }; - - Ok(Self { key, value }) - } -} - -impl Node for ShortNode { - fn contains_hash(&self, hash: H256) -> bool { - self.value == hash.0 - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use hex_literal::hex; - - const RAW_PROOF: [&[u8]; 3] = [ - &hex!("f90131a0b5ba404eb5a6a88e56579f4d37ef9813b5ad7f86f0823ff3b407ac5a6bb465eca0398ead2655e78e03c127ce22c5830e90f18b1601ec055f938336c084feb915a9a026d322c26e46c50942c1aabde50e36df5cde572aed650ce73ea3182c6e90a02ca00600a356135f4db1db0d9842264cdff2652676f881669e91e316c0b6dd783011a0837f1deb4075336da320388c1edfffc56c448a43f4a5ba031300d32a7b509fc5a01c3ac82fd65b4aba7f9afaf604d9c82ec7e2deb573a091ae235751bc5c0c288da05d454159d9071b0f68b6e0503d290f23ac7602c1db0c569dee4605d8f5298f09a00bbed10350ec954448df795f6fd46e3faefc800ede061b3840eedc6e2b07a74da0acb02d26a3650f2064c14a435fdf1f668d8655daf455ebdf671713a7c089b3898080808080808080"), - &hex!("f901f180a00046a08d4f0bdbdc6b31903086ce323182bce6725e7d9415f7ff91ee8f4820bda0e7cd26ad5f3d2771e4b5ab788e268a14a10209f94ee918eb6c829d21d3d11c1da00d4a56d9e9a6751874fd86c7e3cb1c6ad5a848da62751325f478978a00ea966ea064b81920c8f04a8a1e21f53a8280e739fbb7b00b2ab92493ca3f610b70e8ac85a0b1040ed4c55a73178b76abb16f946ce5bebd6b93ab873c83327df54047d12c27a0de6485e9ac58dc6e2b04b4bb38f562684f0b1a2ee586cc11079e7d9a9dc40b32a0d394f4d3532c3124a65fa36e69147e04fd20453a72ee9c50660f17e13ce9df48a066501003fc3e3478efd2803cd0eded6bbe9243ca01ba754d6327071ddbcbc649a0b2684e518f325fee39fc8ea81b68f3f5c785be00d087f3bed8857ae2ee8da26ea071060a5c52042e8d7ce21092f8ecf06053beb9a0b773a6f91a30c4220aa276b2a0fc22436632574ccf6043d0986dede27ea94c9ca9a3bb5ec03ce776a4ddef24a9a05a8a1d6698c4e7d8cc3a2506cb9b12ea9a079c9c7099bc919dc804033cc556e4a0170c468b0716fd36d161f0bf05875f15756a2976de92f9efe7716320509d79c9a0182f909a90cab169f3efb62387f9cccdd61440acc4deec42f68a4f7ca58075c7a055cf0e9202ac75689b76318f1171f3a44465eddc06aae0713bfb6b34fdd27b7980"), - &hex!("f904de20b904daf904d701830652f0b9010004200000000000000000000080020000000000010000000000010000000000000000000000000000000000000000000002000000080000000000000000200000000000000000000000000008000000220000000000400010000000000000000000000000000000000000000000000000000000000000040000000010000100000000000800000000004000000000000000000000000000080000004000000000020000000000020000000000000000000000000000000000000000000004000000000002000000000100000000000000000000000000001000000002000020000010200000000000010000000000000000000000000000000000000010000000f903ccf89b9421130f34829b4c343142047a28ce96ec07814b15f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a000000000000000000000000000000000000000000000000000000005d09b7380f89b9421130f34829b4c343142047a28ce96ec07814b15f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da0ffffffffffffffffffffffffffffffffffffffffffffffffffffffcc840c6920f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078ef87994e9c1281aae66801fa35ec404d5f2aea393ff6988e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000000000000001f1420ad1d40000000000000000000000000000000000000000000000014ad400879d159a38f8fc94e9c1281aae66801fa35ec404d5f2aea393ff6988f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488db88000000000000000000000000000000000000000000000000000000005d415f3320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e973b5a5d1078ef87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1078e"), - ]; - - #[test] - fn decode_full_node() { - let node1: FullNode = rlp::decode(RAW_PROOF[0]).unwrap(); - let node2: FullNode = rlp::decode(RAW_PROOF[1]).unwrap(); - assert_eq!(node1.children.len(), 17); - assert_eq!(node2.children.len(), 17); - assert_eq!(node1.children.iter().filter(|c| c.is_none()).count(), 8); - assert_eq!(node2.children.iter().filter(|c| c.is_none()).count(), 2); - - let result: Result = rlp::decode(RAW_PROOF[2]); - assert!(result.is_err()); - } - - #[test] - fn decode_short_node() { - // key + item value - let node: ShortNode = rlp::decode(RAW_PROOF[2]).unwrap(); - assert_eq!(node.key, vec![32]); - assert!(!node.value.is_empty()); - - // key + item hash - let node: ShortNode = rlp::decode(&hex!( - "e4820001a04fff54398cad4d05ea6abfd8b0f3b4fe14c04d7ff5f5211c5b927d9cf72ac1d8" - )) - .unwrap(); - assert_eq!(node.key, vec![0, 1]); - assert_eq!( - node.value, - hex!("4fff54398cad4d05ea6abfd8b0f3b4fe14c04d7ff5f5211c5b927d9cf72ac1d8").to_vec() - ); - } -} diff --git a/bridges/snowbridge/parachain/primitives/ethereum/src/receipt.rs b/bridges/snowbridge/parachain/primitives/ethereum/src/receipt.rs deleted file mode 100644 index 665a93dbb1e2..000000000000 --- a/bridges/snowbridge/parachain/primitives/ethereum/src/receipt.rs +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -use crate::{Bloom, Log}; -use codec::{Decode, Encode}; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -#[derive(Clone, Default, Encode, Decode, PartialEq, RuntimeDebug)] -pub struct Receipt { - pub post_state_or_status: Vec, - pub cumulative_gas_used: u64, - pub bloom: Bloom, - pub logs: Vec, -} - -impl Receipt { - pub fn contains_log(&self, log: &Log) -> bool { - self.logs.iter().any(|l| l == log) - } - - fn decode_list(rlp: &rlp::Rlp) -> Result { - let mut iter = rlp.iter(); - - let post_state_or_status: Vec = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected receipt post state or status")), - }; - - let cumulative_gas_used: u64 = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected receipt cumulative gas used")), - }; - - let bloom: Bloom = match iter.next() { - Some(data) => data.as_val()?, - None => return Err(rlp::DecoderError::Custom("Expected receipt bloom")), - }; - - let logs: Vec = match iter.next() { - Some(data) => data.as_list()?, - None => return Err(rlp::DecoderError::Custom("Expected receipt logs")), - }; - - Ok(Self { post_state_or_status, cumulative_gas_used, bloom, logs }) - } -} - -impl rlp::Decodable for Receipt { - fn decode(rlp: &rlp::Rlp) -> Result { - if rlp.is_data() { - // Typed receipt - let data = rlp.as_raw(); - match data[0] { - // 1 = EIP-2930, 2 = EIP-1559 - 1 | 2 => { - let receipt_rlp = &rlp::Rlp::new(&data[1..]); - if !receipt_rlp.is_list() { - return Err(rlp::DecoderError::RlpExpectedToBeList) - } - Self::decode_list(&rlp::Rlp::new(&data[1..])) - }, - _ => Err(rlp::DecoderError::Custom("Unsupported receipt type")), - } - } else if rlp.is_list() { - // Legacy receipt - Self::decode_list(rlp) - } else { - Err(rlp::DecoderError::RlpExpectedToBeList) - } - } -} - -#[cfg(test)] -mod tests { - - use super::Receipt; - use hex_literal::hex; - - const RAW_RECEIPT: [u8; 1242] = hex!( - " - f904d701830652f0b901000420000000000000000000008002000000000001000000000001000000 - 00000000000000000000000000000000000000020000000800000000000000002000000000000000 - 00000000000008000000220000000000400010000000000000000000000000000000000000000000 - 00000000000000000004000000001000010000000000080000000000400000000000000000000000 - 00000800000040000000000200000000000200000000000000000000000000000000000000000000 - 04000000000002000000000100000000000000000000000000001000000002000020000010200000 - 000000010000000000000000000000000000000000000010000000f903ccf89b9421130f34829b4c - 343142047a28ce96ec07814b15f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a116 - 28f55a4df523b3efa00000000000000000000000007d843005c7433c16b27ff939cb37471541561e - bda0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a00000000000 - 0000000000000000000000000000000000000000000005d09b7380f89b9421130f34829b4c343142 - 047a28ce96ec07814b15f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200a - c8c7c3b925a00000000000000000000000007d843005c7433c16b27ff939cb37471541561ebda000 - 00000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da0ffffffffffffffff - ffffffffffffffffffffffffffffffffffffffcc840c6920f89b94c02aaa39b223fe8d0a0e5c4f27 - ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523 - b3efa0000000000000000000000000e9c1281aae66801fa35ec404d5f2aea393ff6988a000000000 - 00000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da00000000000000000000000 - 0000000000000000000000000003e973b5a5d1078ef87994e9c1281aae66801fa35ec404d5f2aea3 - 93ff6988e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840 - 000000000000000000000000000000000000000000000000000001f1420ad1d40000000000000000 - 000000000000000000000000000000014ad400879d159a38f8fc94e9c1281aae66801fa35ec404d5 - f2aea393ff6988f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159 - d822a00000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488da000000000 - 00000000000000007a250d5630b4cf539739df2c5dacb4c659f2488db88000000000000000000000 - 000000000000000000000000000000000005d415f332000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000000003e973b5a5d1078ef87a - 94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d - 30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000007a250d5630b4cf539739df - 2c5dacb4c659f2488da000000000000000000000000000000000000000000000000003e973b5a5d1 - 078e - " - ); - - #[test] - fn decode_legacy_receipt() { - let receipt: Receipt = rlp::decode(&RAW_RECEIPT).unwrap(); - assert_eq!(receipt.post_state_or_status, vec!(1)); - assert_eq!(receipt.cumulative_gas_used, 414448); - assert_eq!( - receipt.bloom, - (&hex!( - " - 042000000000000000000000800200000000000100000000000100000000000000000000 - 000000000000000000000000020000000800000000000000002000000000000000000000 - 000000080000002200000000004000100000000000000000000000000000000000000000 - 000000000000000000000400000000100001000000000008000000000040000000000000 - 000000000000000800000040000000000200000000000200000000000000000000000000 - 000000000000000000040000000000020000000001000000000000000000000000000010 - 000000020000200000102000000000000100000000000000000000000000000000000000 - 10000000 - " - )) - .into(), - ); - assert_eq!(receipt.logs.len(), 6); - } -} diff --git a/bridges/snowbridge/parachain/primitives/router/Cargo.toml b/bridges/snowbridge/parachain/primitives/router/Cargo.toml deleted file mode 100644 index ed8f68d7bc07..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/Cargo.toml +++ /dev/null @@ -1,66 +0,0 @@ -[package] -name = "snowbridge-router-primitives" -description = "Snowbridge Router Primitives" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -serde = { version = "1.0.195", optional = true, features = ["derive"] } -codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } -scale-info = { version = "2.9.0", default-features = false, features = ["derive"] } -log = { version = "0.4.20", default-features = false } - -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } - -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } - -snowbridge-core = { path = "../core", default-features = false } - -ethabi = { git = "https://github.com/Snowfork/ethabi-decode.git", package = "ethabi-decode", branch = "master", default-features = false } - -hex-literal = { version = "0.4.1" } - -[dev-dependencies] -hex = { package = "rustc-hex", version = "2.1.0" } - -[features] -default = ["std"] -std = [ - "codec/std", - "ethabi/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "serde", - "snowbridge-core/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] diff --git a/bridges/snowbridge/parachain/primitives/router/README.md b/bridges/snowbridge/parachain/primitives/router/README.md deleted file mode 100644 index 45967cbf76ca..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Router Primitives - -Inbound and outbound router logic. Does XCM conversion to a lowered, simpler format the Ethereum contracts can -understand. diff --git a/bridges/snowbridge/parachain/primitives/router/src/inbound/mod.rs b/bridges/snowbridge/parachain/primitives/router/src/inbound/mod.rs deleted file mode 100644 index c20554c6d184..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/src/inbound/mod.rs +++ /dev/null @@ -1,312 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Converts messages from Ethereum to XCM messages - -#[cfg(test)] -mod tests; - -use codec::{Decode, Encode}; -use core::marker::PhantomData; -use frame_support::{traits::tokens::Balance as BalanceT, weights::Weight, PalletError}; -use scale_info::TypeInfo; -use sp_core::{Get, RuntimeDebug, H160}; -use sp_io::hashing::blake2_256; -use sp_runtime::MultiAddress; -use sp_std::prelude::*; -use xcm::prelude::{Junction::AccountKey20, *}; -use xcm_executor::traits::ConvertLocation; - -const MINIMUM_DEPOSIT: u128 = 1; - -/// Messages from Ethereum are versioned. This is because in future, -/// we may want to evolve the protocol so that the ethereum side sends XCM messages directly. -/// Instead having BridgeHub transcode the messages into XCM. -#[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum VersionedMessage { - V1(MessageV1), -} - -/// For V1, the ethereum side sends messages which are transcoded into XCM. These messages are -/// self-contained, in that they can be transcoded using only information in the message. -#[derive(Clone, Encode, Decode, RuntimeDebug)] -pub struct MessageV1 { - /// EIP-155 chain id of the origin Ethereum network - pub chain_id: u64, - /// The command originating from the Gateway contract - pub command: Command, -} - -#[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum Command { - /// Register a wrapped token on the AssetHub `ForeignAssets` pallet - RegisterToken { - /// The address of the ERC20 token to be bridged over to AssetHub - token: H160, - /// XCM execution fee on AssetHub - fee: u128, - }, - /// Send a token to AssetHub or another parachain - SendToken { - /// The address of the ERC20 token to be bridged over to AssetHub - token: H160, - /// The destination for the transfer - destination: Destination, - /// Amount to transfer - amount: u128, - /// XCM execution fee on AssetHub - fee: u128, - }, -} - -/// Destination for bridged tokens -#[derive(Clone, Encode, Decode, RuntimeDebug)] -pub enum Destination { - /// The funds will be deposited into account `id` on AssetHub - AccountId32 { id: [u8; 32] }, - /// The funds will deposited into the sovereign account of destination parachain `para_id` on - /// AssetHub, Account `id` on the destination parachain will receive the funds via a - /// reserve-backed transfer. See - ForeignAccountId32 { - para_id: u32, - id: [u8; 32], - /// XCM execution fee on final destination - fee: u128, - }, - /// The funds will deposited into the sovereign account of destination parachain `para_id` on - /// AssetHub, Account `id` on the destination parachain will receive the funds via a - /// reserve-backed transfer. See - ForeignAccountId20 { - para_id: u32, - id: [u8; 20], - /// XCM execution fee on final destination - fee: u128, - }, -} - -pub struct MessageToXcm< - CreateAssetCall, - CreateAssetDeposit, - InboundQueuePalletInstance, - AccountId, - Balance, -> where - CreateAssetCall: Get, - CreateAssetDeposit: Get, - Balance: BalanceT, -{ - _phantom: PhantomData<( - CreateAssetCall, - CreateAssetDeposit, - InboundQueuePalletInstance, - AccountId, - Balance, - )>, -} - -/// Reason why a message conversion failed. -#[derive(Copy, Clone, TypeInfo, PalletError, Encode, Decode, RuntimeDebug)] -pub enum ConvertMessageError { - /// The message version is not supported for conversion. - UnsupportedVersion, -} - -/// convert the inbound message to xcm which will be forwarded to the destination chain -pub trait ConvertMessage { - type Balance: BalanceT + From; - type AccountId; - /// Converts a versioned message into an XCM message and an optional topicID - fn convert(message: VersionedMessage) -> Result<(Xcm<()>, Self::Balance), ConvertMessageError>; -} - -pub type CallIndex = [u8; 2]; - -impl - ConvertMessage - for MessageToXcm< - CreateAssetCall, - CreateAssetDeposit, - InboundQueuePalletInstance, - AccountId, - Balance, - > where - CreateAssetCall: Get, - CreateAssetDeposit: Get, - InboundQueuePalletInstance: Get, - Balance: BalanceT + From, - AccountId: Into<[u8; 32]>, -{ - type Balance = Balance; - type AccountId = AccountId; - - fn convert(message: VersionedMessage) -> Result<(Xcm<()>, Self::Balance), ConvertMessageError> { - use Command::*; - use VersionedMessage::*; - match message { - V1(MessageV1 { chain_id, command: RegisterToken { token, fee } }) => - Ok(Self::convert_register_token(chain_id, token, fee)), - V1(MessageV1 { chain_id, command: SendToken { token, destination, amount, fee } }) => - Ok(Self::convert_send_token(chain_id, token, destination, amount, fee)), - } - } -} - -impl - MessageToXcm -where - CreateAssetCall: Get, - CreateAssetDeposit: Get, - InboundQueuePalletInstance: Get, - Balance: BalanceT + From, - AccountId: Into<[u8; 32]>, -{ - fn convert_register_token(chain_id: u64, token: H160, fee: u128) -> (Xcm<()>, Balance) { - let network = Ethereum { chain_id }; - let xcm_fee: Asset = (Location::parent(), fee).into(); - let deposit: Asset = (Location::parent(), CreateAssetDeposit::get()).into(); - - let total_amount = fee + CreateAssetDeposit::get(); - let total: Asset = (Location::parent(), total_amount).into(); - - let bridge_location: Location = (Parent, Parent, GlobalConsensus(network)).into(); - - let owner = GlobalConsensusEthereumConvertsFor::<[u8; 32]>::from_chain_id(&chain_id); - let asset_id = Self::convert_token_address(network, token); - let create_call_index: [u8; 2] = CreateAssetCall::get(); - let inbound_queue_pallet_index = InboundQueuePalletInstance::get(); - - let xcm: Xcm<()> = vec![ - // Teleport required fees. - ReceiveTeleportedAsset(total.into()), - // Pay for execution. - BuyExecution { fees: xcm_fee, weight_limit: Unlimited }, - // Fund the snowbridge sovereign with the required deposit for creation. - DepositAsset { assets: Definite(deposit.into()), beneficiary: bridge_location }, - // Only our inbound-queue pallet is allowed to invoke `UniversalOrigin` - DescendOrigin(PalletInstance(inbound_queue_pallet_index).into()), - // Change origin to the bridge. - UniversalOrigin(GlobalConsensus(network)), - // Call create_asset on foreign assets pallet. - Transact { - origin_kind: OriginKind::Xcm, - require_weight_at_most: Weight::from_parts(400_000_000, 8_000), - call: ( - create_call_index, - asset_id, - MultiAddress::<[u8; 32], ()>::Id(owner), - MINIMUM_DEPOSIT, - ) - .encode() - .into(), - }, - RefundSurplus, - // Clear the origin so that remaining assets in holding - // are claimable by the physical origin (BridgeHub) - ClearOrigin, - ] - .into(); - - (xcm, total_amount.into()) - } - - fn convert_send_token( - chain_id: u64, - token: H160, - destination: Destination, - amount: u128, - asset_hub_fee: u128, - ) -> (Xcm<()>, Balance) { - let network = Ethereum { chain_id }; - let asset_hub_fee_asset: Asset = (Location::parent(), asset_hub_fee).into(); - let asset: Asset = (Self::convert_token_address(network, token), amount).into(); - - let (dest_para_id, beneficiary, dest_para_fee) = match destination { - // Final destination is a 32-byte account on AssetHub - Destination::AccountId32 { id } => - (None, Location::new(0, [AccountId32 { network: None, id }]), 0), - // Final destination is a 32-byte account on a sibling of AssetHub - Destination::ForeignAccountId32 { para_id, id, fee } => ( - Some(para_id), - Location::new(0, [AccountId32 { network: None, id }]), - // Total fee needs to cover execution on AssetHub and Sibling - fee, - ), - // Final destination is a 20-byte account on a sibling of AssetHub - Destination::ForeignAccountId20 { para_id, id, fee } => ( - Some(para_id), - Location::new(0, [AccountKey20 { network: None, key: id }]), - // Total fee needs to cover execution on AssetHub and Sibling - fee, - ), - }; - - let total_fees = asset_hub_fee.saturating_add(dest_para_fee); - let total_fee_asset: Asset = (Location::parent(), total_fees).into(); - let inbound_queue_pallet_index = InboundQueuePalletInstance::get(); - - let mut instructions = vec![ - ReceiveTeleportedAsset(total_fee_asset.into()), - BuyExecution { fees: asset_hub_fee_asset, weight_limit: Unlimited }, - DescendOrigin(PalletInstance(inbound_queue_pallet_index).into()), - UniversalOrigin(GlobalConsensus(network)), - ReserveAssetDeposited(asset.clone().into()), - ClearOrigin, - ]; - - match dest_para_id { - Some(dest_para_id) => { - let dest_para_fee_asset: Asset = (Location::parent(), dest_para_fee).into(); - - instructions.extend(vec![ - // Perform a deposit reserve to send to destination chain. - DepositReserveAsset { - assets: Definite(vec![dest_para_fee_asset.clone(), asset.clone()].into()), - dest: Location::new(1, [Parachain(dest_para_id)]), - xcm: vec![ - // Buy execution on target. - BuyExecution { fees: dest_para_fee_asset, weight_limit: Unlimited }, - // Deposit asset to beneficiary. - DepositAsset { assets: Definite(asset.into()), beneficiary }, - ] - .into(), - }, - ]); - }, - None => { - instructions.extend(vec![ - // Deposit asset to beneficiary. - DepositAsset { assets: Definite(asset.into()), beneficiary }, - ]); - }, - } - - (instructions.into(), total_fees.into()) - } - - // Convert ERC20 token address to a location that can be understood by Assets Hub. - fn convert_token_address(network: NetworkId, token: H160) -> Location { - Location::new( - 2, - [GlobalConsensus(network), AccountKey20 { network: None, key: token.into() }], - ) - } -} - -pub struct GlobalConsensusEthereumConvertsFor(PhantomData); -impl ConvertLocation for GlobalConsensusEthereumConvertsFor -where - AccountId: From<[u8; 32]> + Clone, -{ - fn convert_location(location: &Location) -> Option { - match location.unpack() { - (_, [GlobalConsensus(Ethereum { chain_id })]) => - Some(Self::from_chain_id(chain_id).into()), - _ => None, - } - } -} - -impl GlobalConsensusEthereumConvertsFor { - pub fn from_chain_id(chain_id: &u64) -> [u8; 32] { - (b"ethereum-chain", chain_id).using_encoded(blake2_256) - } -} diff --git a/bridges/snowbridge/parachain/primitives/router/src/inbound/tests.rs b/bridges/snowbridge/parachain/primitives/router/src/inbound/tests.rs deleted file mode 100644 index c46b88a84a4b..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/src/inbound/tests.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::GlobalConsensusEthereumConvertsFor; -use crate::inbound::CallIndex; -use frame_support::parameter_types; -use hex_literal::hex; -use xcm::v4::prelude::*; -use xcm_executor::traits::ConvertLocation; - -const NETWORK: NetworkId = Ethereum { chain_id: 11155111 }; - -parameter_types! { - pub EthereumNetwork: NetworkId = NETWORK; - - pub const CreateAssetCall: CallIndex = [1, 1]; - pub const CreateAssetExecutionFee: u128 = 123; - pub const CreateAssetDeposit: u128 = 891; - pub const SendTokenExecutionFee: u128 = 592; -} - -#[test] -fn test_contract_location_with_network_converts_successfully() { - let expected_account: [u8; 32] = - hex!("ce796ae65569a670d0c1cc1ac12515a3ce21b5fbf729d63d7b289baad070139d"); - let contract_location = Location::new(2, [GlobalConsensus(NETWORK)]); - - let account = - GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&contract_location) - .unwrap(); - - assert_eq!(account, expected_account); -} - -#[test] -fn test_contract_location_with_incorrect_location_fails_convert() { - let contract_location = Location::new(2, [GlobalConsensus(Polkadot), Parachain(1000)]); - - assert_eq!( - GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&contract_location), - None, - ); -} diff --git a/bridges/snowbridge/parachain/primitives/router/src/lib.rs b/bridges/snowbridge/parachain/primitives/router/src/lib.rs deleted file mode 100644 index d9031c69b22b..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod inbound; -pub mod outbound; diff --git a/bridges/snowbridge/parachain/primitives/router/src/outbound/mod.rs b/bridges/snowbridge/parachain/primitives/router/src/outbound/mod.rs deleted file mode 100644 index 21823992db7c..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/src/outbound/mod.rs +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! Converts XCM messages into simpler commands that can be processed by the Gateway contract - -#[cfg(test)] -mod tests; - -use core::slice::Iter; - -use codec::{Decode, Encode}; - -use frame_support::{ensure, traits::Get}; -use snowbridge_core::{ - outbound::{AgentExecuteCommand, Command, Message, SendMessage}, - ChannelId, ParaId, -}; -use sp_core::{H160, H256}; -use sp_std::{iter::Peekable, marker::PhantomData, prelude::*}; -use xcm::v4::prelude::*; -use xcm_executor::traits::{ConvertLocation, ExportXcm}; - -pub struct EthereumBlobExporter< - UniversalLocation, - EthereumNetwork, - OutboundQueue, - AgentHashedDescription, ->(PhantomData<(UniversalLocation, EthereumNetwork, OutboundQueue, AgentHashedDescription)>); - -impl ExportXcm - for EthereumBlobExporter -where - UniversalLocation: Get, - EthereumNetwork: Get, - OutboundQueue: SendMessage, - AgentHashedDescription: ConvertLocation, -{ - type Ticket = (Vec, XcmHash); - - fn validate( - network: NetworkId, - _channel: u32, - universal_source: &mut Option, - destination: &mut Option, - message: &mut Option>, - ) -> SendResult { - let expected_network = EthereumNetwork::get(); - let universal_location = UniversalLocation::get(); - - if network != expected_network { - log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched bridge network {network:?}."); - return Err(SendError::NotApplicable) - } - - let dest = destination.take().ok_or(SendError::MissingArgument)?; - if dest != Here { - log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched remote destination {dest:?}."); - return Err(SendError::NotApplicable) - } - - let (local_net, local_sub) = universal_source - .take() - .ok_or_else(|| { - log::error!(target: "xcm::ethereum_blob_exporter", "universal source not provided."); - SendError::MissingArgument - })? - .split_global() - .map_err(|()| { - log::error!(target: "xcm::ethereum_blob_exporter", "could not get global consensus from universal source '{universal_source:?}'."); - SendError::Unroutable - })?; - - if Ok(local_net) != universal_location.global_consensus() { - log::trace!(target: "xcm::ethereum_blob_exporter", "skipped due to unmatched relay network {local_net:?}."); - return Err(SendError::NotApplicable) - } - - let para_id = match local_sub.as_slice() { - [Parachain(para_id)] => *para_id, - _ => { - log::error!(target: "xcm::ethereum_blob_exporter", "could not get parachain id from universal source '{local_sub:?}'."); - return Err(SendError::MissingArgument) - }, - }; - - let message = message.take().ok_or_else(|| { - log::error!(target: "xcm::ethereum_blob_exporter", "xcm message not provided."); - SendError::MissingArgument - })?; - - let mut converter = XcmConverter::new(&message, &expected_network); - let (agent_execute_command, message_id) = converter.convert().map_err(|err|{ - log::error!(target: "xcm::ethereum_blob_exporter", "unroutable due to pattern matching error '{err:?}'."); - SendError::Unroutable - })?; - - let source_location = Location::new(1, local_sub.clone()); - let agent_id = match AgentHashedDescription::convert_location(&source_location) { - Some(id) => id, - None => { - log::error!(target: "xcm::ethereum_blob_exporter", "unroutable due to not being able to create agent id. '{source_location:?}'"); - return Err(SendError::Unroutable) - }, - }; - - let channel_id: ChannelId = ParaId::from(para_id).into(); - - let outbound_message = Message { - id: Some(message_id.into()), - channel_id, - command: Command::AgentExecute { agent_id, command: agent_execute_command }, - }; - - // validate the message - let (ticket, fee) = OutboundQueue::validate(&outbound_message).map_err(|err| { - log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue validation of message failed. {err:?}"); - SendError::Unroutable - })?; - - // convert fee to Asset - let fee = Asset::from((Location::parent(), fee.total())).into(); - - Ok(((ticket.encode(), message_id), fee)) - } - - fn deliver(blob: (Vec, XcmHash)) -> Result { - let ticket: OutboundQueue::Ticket = OutboundQueue::Ticket::decode(&mut blob.0.as_ref()) - .map_err(|_| { - log::trace!(target: "xcm::ethereum_blob_exporter", "undeliverable due to decoding error"); - SendError::NotApplicable - })?; - - let message_id = OutboundQueue::deliver(ticket).map_err(|_| { - log::error!(target: "xcm::ethereum_blob_exporter", "OutboundQueue submit of message failed"); - SendError::Transport("other transport error") - })?; - - log::info!(target: "xcm::ethereum_blob_exporter", "message delivered {message_id:#?}."); - Ok(message_id.into()) - } -} - -/// Errors that can be thrown to the pattern matching step. -#[derive(PartialEq, Debug)] -enum XcmConverterError { - UnexpectedEndOfXcm, - EndOfXcmMessageExpected, - WithdrawAssetExpected, - DepositAssetExpected, - NoReserveAssets, - FilterDoesNotConsumeAllAssets, - TooManyAssets, - ZeroAssetTransfer, - BeneficiaryResolutionFailed, - AssetResolutionFailed, - InvalidFeeAsset, - SetTopicExpected, -} - -macro_rules! match_expression { - ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?, $value:expr $(,)?) => { - match $expression { - $( $pattern )|+ $( if $guard )? => Some($value), - _ => None, - } - }; -} - -struct XcmConverter<'a, Call> { - iter: Peekable>>, - ethereum_network: &'a NetworkId, -} -impl<'a, Call> XcmConverter<'a, Call> { - fn new(message: &'a Xcm, ethereum_network: &'a NetworkId) -> Self { - Self { iter: message.inner().iter().peekable(), ethereum_network } - } - - fn convert(&mut self) -> Result<(AgentExecuteCommand, [u8; 32]), XcmConverterError> { - // Get withdraw/deposit and make native tokens create message. - let result = self.native_tokens_unlock_message()?; - - // All xcm instructions must be consumed before exit. - if self.next().is_ok() { - return Err(XcmConverterError::EndOfXcmMessageExpected) - } - - Ok(result) - } - - fn native_tokens_unlock_message( - &mut self, - ) -> Result<(AgentExecuteCommand, [u8; 32]), XcmConverterError> { - use XcmConverterError::*; - - // Get the reserve assets from WithdrawAsset. - let reserve_assets = - match_expression!(self.next()?, WithdrawAsset(reserve_assets), reserve_assets) - .ok_or(WithdrawAssetExpected)?; - - // Check if clear origin exists and skip over it. - if match_expression!(self.peek(), Ok(ClearOrigin), ()).is_some() { - let _ = self.next(); - } - - // Get the fee asset item from BuyExecution or continue parsing. - let fee_asset = match_expression!(self.peek(), Ok(BuyExecution { fees, .. }), fees); - if fee_asset.is_some() { - let _ = self.next(); - } - - let (deposit_assets, beneficiary) = match_expression!( - self.next()?, - DepositAsset { assets, beneficiary }, - (assets, beneficiary) - ) - .ok_or(DepositAssetExpected)?; - - // assert that the beneficiary is AccountKey20. - let recipient = match_expression!( - beneficiary.unpack(), - (0, [AccountKey20 { network, key }]) - if self.network_matches(network), - H160(*key) - ) - .ok_or(BeneficiaryResolutionFailed)?; - - // Make sure there are reserved assets. - if reserve_assets.len() == 0 { - return Err(NoReserveAssets) - } - - // Check the the deposit asset filter matches what was reserved. - if reserve_assets.inner().iter().any(|asset| !deposit_assets.matches(asset)) { - return Err(FilterDoesNotConsumeAllAssets) - } - - // We only support a single asset at a time. - ensure!(reserve_assets.len() == 1, TooManyAssets); - let reserve_asset = reserve_assets.get(0).ok_or(AssetResolutionFailed)?; - - // If there was a fee specified verify it. - if let Some(fee_asset) = fee_asset { - // The fee asset must be the same as the reserve asset. - if fee_asset.id != reserve_asset.id || fee_asset.fun > reserve_asset.fun { - return Err(InvalidFeeAsset) - } - } - - let (token, amount) = match reserve_asset { - Asset { id: AssetId(inner_location), fun: Fungible(amount) } => - match inner_location.unpack() { - (0, [AccountKey20 { network, key }]) if self.network_matches(network) => - Some((H160(*key), *amount)), - _ => None, - }, - _ => None, - } - .ok_or(AssetResolutionFailed)?; - - // transfer amount must be greater than 0. - ensure!(amount > 0, ZeroAssetTransfer); - - // Check if there is a SetTopic and skip over it if found. - let topic_id = match_expression!(self.next()?, SetTopic(id), id).ok_or(SetTopicExpected)?; - - Ok((AgentExecuteCommand::TransferToken { token, recipient, amount }, *topic_id)) - } - - fn next(&mut self) -> Result<&'a Instruction, XcmConverterError> { - self.iter.next().ok_or(XcmConverterError::UnexpectedEndOfXcm) - } - - fn peek(&mut self) -> Result<&&'a Instruction, XcmConverterError> { - self.iter.peek().ok_or(XcmConverterError::UnexpectedEndOfXcm) - } - - fn network_matches(&self, network: &Option) -> bool { - if let Some(network) = network { - network == self.ethereum_network - } else { - true - } - } -} diff --git a/bridges/snowbridge/parachain/primitives/router/src/outbound/tests.rs b/bridges/snowbridge/parachain/primitives/router/src/outbound/tests.rs deleted file mode 100644 index 111243bb45a7..000000000000 --- a/bridges/snowbridge/parachain/primitives/router/src/outbound/tests.rs +++ /dev/null @@ -1,1058 +0,0 @@ -use frame_support::parameter_types; -use hex_literal::hex; -use snowbridge_core::{ - outbound::{Fee, SendError, SendMessageFeeProvider}, - AgentIdOf, -}; -use xcm::v3::prelude::SendError as XcmSendError; - -use super::*; - -parameter_types! { - const MaxMessageSize: u32 = u32::MAX; - const RelayNetwork: NetworkId = Polkadot; - UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(1013)].into(); - const BridgedNetwork: NetworkId = Ethereum{ chain_id: 1 }; - const NonBridgedNetwork: NetworkId = Ethereum{ chain_id: 2 }; -} - -struct MockOkOutboundQueue; -impl SendMessage for MockOkOutboundQueue { - type Ticket = (); - - fn validate(_: &Message) -> Result<(Self::Ticket, Fee), SendError> { - Ok(((), Fee { local: 1, remote: 1 })) - } - - fn deliver(_: Self::Ticket) -> Result { - Ok(H256::zero()) - } -} - -impl SendMessageFeeProvider for MockOkOutboundQueue { - type Balance = u128; - - fn local_fee() -> Self::Balance { - 1 - } -} -struct MockErrOutboundQueue; -impl SendMessage for MockErrOutboundQueue { - type Ticket = (); - - fn validate(_: &Message) -> Result<(Self::Ticket, Fee), SendError> { - Err(SendError::MessageTooLarge) - } - - fn deliver(_: Self::Ticket) -> Result { - Err(SendError::MessageTooLarge) - } -} - -impl SendMessageFeeProvider for MockErrOutboundQueue { - type Balance = u128; - - fn local_fee() -> Self::Balance { - 1 - } -} - -#[test] -fn exporter_validate_with_unknown_network_yields_not_applicable() { - let network = Ethereum { chain_id: 1337 }; - let channel: u32 = 0; - let mut universal_source: Option = None; - let mut destination: Option = None; - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::NotApplicable)); -} - -#[test] -fn exporter_validate_with_invalid_destination_yields_missing_argument() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = None; - let mut destination: Option = None; - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::MissingArgument)); -} - -#[test] -fn exporter_validate_with_x8_destination_yields_not_applicable() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = None; - let mut destination: Option = Some( - [OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild, OnlyChild] - .into(), - ); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::NotApplicable)); -} - -#[test] -fn exporter_validate_without_universal_source_yields_missing_argument() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = None; - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::MissingArgument)); -} - -#[test] -fn exporter_validate_without_global_universal_location_yields_unroutable() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = Here.into(); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::Unroutable)); -} - -#[test] -fn exporter_validate_without_global_bridge_location_yields_not_applicable() { - let network = NonBridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = Here.into(); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::NotApplicable)); -} - -#[test] -fn exporter_validate_with_remote_universal_source_yields_not_applicable() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = - Some([GlobalConsensus(Kusama), Parachain(1000)].into()); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::NotApplicable)); -} - -#[test] -fn exporter_validate_without_para_id_in_source_yields_missing_argument() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = Some(GlobalConsensus(Polkadot).into()); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::MissingArgument)); -} - -#[test] -fn exporter_validate_complex_para_id_in_source_yields_missing_argument() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = - Some([GlobalConsensus(Polkadot), Parachain(1000), PalletInstance(12)].into()); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::MissingArgument)); -} - -#[test] -fn exporter_validate_without_xcm_message_yields_missing_argument() { - let network = BridgedNetwork::get(); - let channel: u32 = 0; - let mut universal_source: Option = - Some([GlobalConsensus(Polkadot), Parachain(1000)].into()); - let mut destination: Option = Here.into(); - let mut message: Option> = None; - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - assert_eq!(result, Err(XcmSendError::MissingArgument)); -} - -#[test] -fn exporter_validate_with_max_target_fee_yields_unroutable() { - let network = BridgedNetwork::get(); - let mut destination: Option = Here.into(); - - let mut universal_source: Option = - Some([GlobalConsensus(Polkadot), Parachain(1000)].into()); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let channel: u32 = 0; - let fee = Asset { id: AssetId(Here.into()), fun: Fungible(1000) }; - let fees: Assets = vec![fee.clone()].into(); - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let mut message: Option> = Some( - vec![ - WithdrawAsset(fees), - BuyExecution { fees: fee, weight_limit: Unlimited }, - WithdrawAsset(assets), - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: Some(network), key: beneficiary_address } - .into(), - }, - SetTopic([0; 32]), - ] - .into(), - ); - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - - assert_eq!(result, Err(XcmSendError::Unroutable)); -} - -#[test] -fn exporter_validate_with_unparsable_xcm_yields_unroutable() { - let network = BridgedNetwork::get(); - let mut destination: Option = Here.into(); - - let mut universal_source: Option = - Some([GlobalConsensus(Polkadot), Parachain(1000)].into()); - - let channel: u32 = 0; - let fee = Asset { id: AssetId(Here.into()), fun: Fungible(1000) }; - let fees: Assets = vec![fee.clone()].into(); - - let mut message: Option> = - Some(vec![WithdrawAsset(fees), BuyExecution { fees: fee, weight_limit: Unlimited }].into()); - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - - assert_eq!(result, Err(XcmSendError::Unroutable)); -} - -#[test] -fn exporter_validate_xcm_success_case_1() { - let network = BridgedNetwork::get(); - let mut destination: Option = Here.into(); - - let mut universal_source: Option = - Some([GlobalConsensus(Polkadot), Parachain(1000)].into()); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let channel: u32 = 0; - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let fee = assets.clone().get(0).unwrap().clone(); - let filter: AssetFilter = assets.clone().into(); - - let mut message: Option> = Some( - vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: fee, weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(), - ); - - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockOkOutboundQueue, - AgentIdOf, - >::validate( - network, channel, &mut universal_source, &mut destination, &mut message - ); - - assert!(result.is_ok()); -} - -#[test] -fn exporter_deliver_with_submit_failure_yields_unroutable() { - let result = EthereumBlobExporter::< - UniversalLocation, - BridgedNetwork, - MockErrOutboundQueue, - AgentIdOf, - >::deliver((hex!("deadbeef").to_vec(), XcmHash::default())); - assert_eq!(result, Err(XcmSendError::Transport("other transport error"))) -} - -#[test] -fn xcm_converter_convert_success() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let expected_payload = AgentExecuteCommand::TransferToken { - token: token_address.into(), - recipient: beneficiary_address.into(), - amount: 1000, - }; - let result = converter.convert(); - assert_eq!(result, Ok((expected_payload, [0; 32]))); -} - -#[test] -fn xcm_converter_convert_without_buy_execution_yields_success() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let expected_payload = AgentExecuteCommand::TransferToken { - token: token_address.into(), - recipient: beneficiary_address.into(), - amount: 1000, - }; - let result = converter.convert(); - assert_eq!(result, Ok((expected_payload, [0; 32]))); -} - -#[test] -fn xcm_converter_convert_with_wildcard_all_asset_filter_succeeds() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(All); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let expected_payload = AgentExecuteCommand::TransferToken { - token: token_address.into(), - recipient: beneficiary_address.into(), - amount: 1000, - }; - let result = converter.convert(); - assert_eq!(result, Ok((expected_payload, [0; 32]))); -} - -#[test] -fn xcm_converter_convert_with_fees_less_than_reserve_yields_success() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let asset_location: Location = [AccountKey20 { network: None, key: token_address }].into(); - let fee_asset = Asset { id: AssetId(asset_location.clone()), fun: Fungible(500) }; - - let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into(); - - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: fee_asset, weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let expected_payload = AgentExecuteCommand::TransferToken { - token: token_address.into(), - recipient: beneficiary_address.into(), - amount: 1000, - }; - let result = converter.convert(); - assert_eq!(result, Ok((expected_payload, [0; 32]))); -} - -#[test] -fn xcm_converter_convert_without_set_topic_yields_set_topic_expected() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - ClearTopic, - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::SetTopicExpected)); -} - -#[test] -fn xcm_converter_convert_with_partial_message_yields_unexpected_end_of_xcm() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let message: Xcm<()> = vec![WithdrawAsset(assets)].into(); - - let mut converter = XcmConverter::new(&message, &network); - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::UnexpectedEndOfXcm)); -} - -#[test] -fn xcm_converter_with_different_fee_asset_fails() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let asset_location = [AccountKey20 { network: None, key: token_address }].into(); - let fee_asset = - Asset { id: AssetId(Location { parents: 0, interior: Here }), fun: Fungible(1000) }; - - let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into(); - - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: fee_asset, weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::InvalidFeeAsset)); -} - -#[test] -fn xcm_converter_with_fees_greater_than_reserve_fails() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let asset_location: Location = [AccountKey20 { network: None, key: token_address }].into(); - let fee_asset = Asset { id: AssetId(asset_location.clone()), fun: Fungible(1001) }; - - let assets: Assets = vec![Asset { id: AssetId(asset_location), fun: Fungible(1000) }].into(); - - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: fee_asset, weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::InvalidFeeAsset)); -} - -#[test] -fn xcm_converter_convert_with_empty_xcm_yields_unexpected_end_of_xcm() { - let network = BridgedNetwork::get(); - - let message: Xcm<()> = vec![].into(); - - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::UnexpectedEndOfXcm)); -} - -#[test] -fn xcm_converter_convert_with_extra_instructions_yields_end_of_xcm_message_expected() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ClearError, - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::EndOfXcmMessageExpected)); -} - -#[test] -fn xcm_converter_convert_without_withdraw_asset_yields_withdraw_expected() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([AccountKey20 { network: None, key: token_address }].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::WithdrawAssetExpected)); -} - -#[test] -fn xcm_converter_convert_without_withdraw_asset_yields_deposit_expected() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }] - .into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::DepositAssetExpected)); -} - -#[test] -fn xcm_converter_convert_without_assets_yields_no_reserve_assets() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![].into(); - let filter: AssetFilter = assets.clone().into(); - - let fee = Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }; - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: fee, weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::NoReserveAssets)); -} - -#[test] -fn xcm_converter_convert_with_two_assets_yields_too_many_assets() { - let network = BridgedNetwork::get(); - - let token_address_1: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let token_address_2: [u8; 20] = hex!("1100000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![ - Asset { - id: AssetId(AccountKey20 { network: None, key: token_address_1 }.into()), - fun: Fungible(1000), - }, - Asset { - id: AssetId(AccountKey20 { network: None, key: token_address_2 }.into()), - fun: Fungible(500), - }, - ] - .into(); - let filter: AssetFilter = assets.clone().into(); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::TooManyAssets)); -} - -#[test] -fn xcm_converter_convert_without_consuming_filter_yields_filter_does_not_consume_all_assets() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(0)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::FilterDoesNotConsumeAllAssets)); -} - -#[test] -fn xcm_converter_convert_with_zero_amount_asset_yields_zero_asset_transfer() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(0), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::ZeroAssetTransfer)); -} - -#[test] -fn xcm_converter_convert_non_ethereum_asset_yields_asset_resolution_failed() { - let network = BridgedNetwork::get(); - - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId([GlobalConsensus(Polkadot), Parachain(1000), GeneralIndex(0)].into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); -} - -#[test] -fn xcm_converter_convert_non_ethereum_chain_asset_yields_asset_resolution_failed() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId( - AccountKey20 { network: Some(Ethereum { chain_id: 2 }), key: token_address }.into(), - ), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); -} - -#[test] -fn xcm_converter_convert_non_ethereum_chain_yields_asset_resolution_failed() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId( - [AccountKey20 { network: Some(NonBridgedNetwork::get()), key: token_address }].into(), - ), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { network: None, key: beneficiary_address }.into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::AssetResolutionFailed)); -} - -#[test] -fn xcm_converter_convert_with_non_ethereum_beneficiary_yields_beneficiary_resolution_failed() { - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - - let beneficiary_address: [u8; 32] = - hex!("2000000000000000000000000000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: [ - GlobalConsensus(Polkadot), - Parachain(1000), - AccountId32 { network: Some(Polkadot), id: beneficiary_address }, - ] - .into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::BeneficiaryResolutionFailed)); -} - -#[test] -fn xcm_converter_convert_with_non_ethereum_chain_beneficiary_yields_beneficiary_resolution_failed() -{ - let network = BridgedNetwork::get(); - - let token_address: [u8; 20] = hex!("1000000000000000000000000000000000000000"); - let beneficiary_address: [u8; 20] = hex!("2000000000000000000000000000000000000000"); - - let assets: Assets = vec![Asset { - id: AssetId(AccountKey20 { network: None, key: token_address }.into()), - fun: Fungible(1000), - }] - .into(); - let filter: AssetFilter = Wild(WildAsset::AllCounted(1)); - - let message: Xcm<()> = vec![ - WithdrawAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(0).unwrap().clone(), weight_limit: Unlimited }, - DepositAsset { - assets: filter, - beneficiary: AccountKey20 { - network: Some(Ethereum { chain_id: 2 }), - key: beneficiary_address, - } - .into(), - }, - SetTopic([0; 32]), - ] - .into(); - let mut converter = XcmConverter::new(&message, &network); - - let result = converter.convert(); - assert_eq!(result.err(), Some(XcmConverterError::BeneficiaryResolutionFailed)); -} - -#[test] -fn test_describe_asset_hub() { - let legacy_location: Location = Location::new(0, [Parachain(1000)]); - let legacy_agent_id = AgentIdOf::convert_location(&legacy_location).unwrap(); - assert_eq!( - legacy_agent_id, - hex!("72456f48efed08af20e5b317abf8648ac66e86bb90a411d9b0b713f7364b75b4").into() - ); - let location: Location = Location::new(1, [Parachain(1000)]); - let agent_id = AgentIdOf::convert_location(&location).unwrap(); - assert_eq!( - agent_id, - hex!("81c5ab2571199e3188135178f3c2c8e2d268be1313d029b30f534fa579b69b79").into() - ) -} - -#[test] -fn test_describe_here() { - let location: Location = Location::new(0, []); - let agent_id = AgentIdOf::convert_location(&location).unwrap(); - assert_eq!( - agent_id, - hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into() - ) -} diff --git a/bridges/snowbridge/parachain/runtime/runtime-common/Cargo.toml b/bridges/snowbridge/parachain/runtime/runtime-common/Cargo.toml deleted file mode 100644 index b81c5d496e83..000000000000 --- a/bridges/snowbridge/parachain/runtime/runtime-common/Cargo.toml +++ /dev/null @@ -1,46 +0,0 @@ -[package] -name = "snowbridge-runtime-common" -description = "Snowbridge Runtime Common" -version = "0.9.0" -authors = ["Snowfork "] -edition.workspace = true -repository.workspace = true -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -log = { version = "0.4.20", default-features = false } - -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -sp-arithmetic = { path = "../../../../../substrate/primitives/arithmetic", default-features = false } -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } - -snowbridge-core = { path = "../../primitives/core", default-features = false } - -[dev-dependencies] - -[features] -default = ["std"] -std = [ - "frame-support/std", - "frame-system/std", - "log/std", - "snowbridge-core/std", - "sp-arithmetic/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] -runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] diff --git a/bridges/snowbridge/parachain/runtime/runtime-common/README.md b/bridges/snowbridge/parachain/runtime/runtime-common/README.md deleted file mode 100644 index 57d178ea2d2b..000000000000 --- a/bridges/snowbridge/parachain/runtime/runtime-common/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Snowbridge Runtime Common - -Common crate to contain runtime related structs and implementations for Snowbridge. diff --git a/bridges/snowbridge/parachain/runtime/runtime-common/src/lib.rs b/bridges/snowbridge/parachain/runtime/runtime-common/src/lib.rs deleted file mode 100644 index 1a9b704f356c..000000000000 --- a/bridges/snowbridge/parachain/runtime/runtime-common/src/lib.rs +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -//! # Runtime Common -//! -//! Common traits and types shared by runtimes. -#![cfg_attr(not(feature = "std"), no_std)] - -use core::marker::PhantomData; -use frame_support::traits::Get; -use snowbridge_core::{outbound::SendMessageFeeProvider, sibling_sovereign_account_raw}; -use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; -use xcm::prelude::*; -use xcm_builder::{deposit_or_burn_fee, HandleFee}; -use xcm_executor::traits::{FeeReason, TransactAsset}; - -/// A `HandleFee` implementation that takes fees from `ExportMessage` XCM instructions -/// to Snowbridge and splits off the remote fee and deposits it to the origin -/// parachain sovereign account. The local fee is then returned back to be handled by -/// the next fee handler in the chain. Most likely the treasury account. -pub struct XcmExportFeeToSibling< - Balance, - AccountId, - FeeAssetLocation, - EthereumNetwork, - AssetTransactor, - FeeProvider, ->( - PhantomData<( - Balance, - AccountId, - FeeAssetLocation, - EthereumNetwork, - AssetTransactor, - FeeProvider, - )>, -); - -impl HandleFee - for XcmExportFeeToSibling< - Balance, - AccountId, - FeeAssetLocation, - EthereumNetwork, - AssetTransactor, - FeeProvider, - > where - Balance: BaseArithmetic + Unsigned + Copy + From + Into, - AccountId: Clone + Into<[u8; 32]> + From<[u8; 32]>, - FeeAssetLocation: Get, - EthereumNetwork: Get, - AssetTransactor: TransactAsset, - FeeProvider: SendMessageFeeProvider, -{ - fn handle_fee(fees: Assets, context: Option<&XcmContext>, reason: FeeReason) -> Assets { - let token_location = FeeAssetLocation::get(); - - // Check the reason to see if this export is for snowbridge. - if !matches!( - reason, - FeeReason::Export { network: bridged_network, ref destination } - if bridged_network == EthereumNetwork::get() && destination == &Here - ) { - return fees - } - - // Get the parachain sovereign from the `context`. - let para_sovereign = - if let Some(XcmContext { origin: Some(Location { parents: 1, interior }), .. }) = - context - { - if let Some(Parachain(sibling_para_id)) = interior.first() { - let account: AccountId = - sibling_sovereign_account_raw((*sibling_para_id).into()).into(); - account - } else { - return fees - } - } else { - return fees - }; - - // Get the total fee offered by export message. - let maybe_total_supplied_fee: Option<(usize, Balance)> = fees - .inner() - .iter() - .enumerate() - .filter_map(|(index, asset)| { - if let Asset { id: location, fun: Fungible(amount) } = asset { - if location.0 == token_location { - return Some((index, (*amount).into())) - } - } - None - }) - .next(); - - if let Some((fee_index, total_fee)) = maybe_total_supplied_fee { - let remote_fee = total_fee.saturating_sub(FeeProvider::local_fee()); - if remote_fee > (0u128).into() { - // Refund remote component of fee to physical origin - deposit_or_burn_fee::( - Asset { id: AssetId(token_location.clone()), fun: Fungible(remote_fee.into()) } - .into(), - context, - para_sovereign, - ); - // Return remaining fee to the next fee handler in the chain. - let mut modified_fees = fees.inner().clone(); - modified_fees.remove(fee_index); - modified_fees.push(Asset { - id: AssetId(token_location), - fun: Fungible((total_fee - remote_fee).into()), - }); - return modified_fees.into() - } - } - - log::info!( - target: "xcm::fees", - "XcmExportFeeToSibling skipped: {fees:?}, context: {context:?}, reason: {reason:?}", - ); - fees - } -} diff --git a/bridges/snowbridge/parachain/runtime/test-common/Cargo.toml b/bridges/snowbridge/parachain/runtime/test-common/Cargo.toml deleted file mode 100644 index bf7791bbabea..000000000000 --- a/bridges/snowbridge/parachain/runtime/test-common/Cargo.toml +++ /dev/null @@ -1,199 +0,0 @@ -[package] -name = "snowbridge-runtime-test-common" -description = "Snowbridge Runtime Tests" -version = "0.9.0" -authors = ["Snowfork "] -edition = "2021" -license = "Apache-2.0" -categories = ["cryptography::cryptocurrencies"] - -[lints] -workspace = true - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -hex-literal = { version = "0.4.1" } -log = { version = "0.4.20", default-features = false } -scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.195", optional = true, features = ["derive"] } -smallvec = "1.11.0" - -# Substrate -frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } -frame-executive = { path = "../../../../../substrate/frame/executive", default-features = false } -frame-support = { path = "../../../../../substrate/frame/support", default-features = false } -frame-system = { path = "../../../../../substrate/frame/system", default-features = false } -frame-system-benchmarking = { path = "../../../../../substrate/frame/system/benchmarking", default-features = false, optional = true } -frame-system-rpc-runtime-api = { path = "../../../../../substrate/frame/system/rpc/runtime-api", default-features = false } -frame-try-runtime = { path = "../../../../../substrate/frame/try-runtime", default-features = false, optional = true } -pallet-aura = { path = "../../../../../substrate/frame/aura", default-features = false } -pallet-authorship = { path = "../../../../../substrate/frame/authorship", default-features = false } -pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false } -pallet-session = { path = "../../../../../substrate/frame/session", default-features = false } -pallet-multisig = { path = "../../../../../substrate/frame/multisig", default-features = false } -pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } -pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false } -pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false } -pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false } -pallet-utility = { path = "../../../../../substrate/frame/utility", default-features = false } -sp-api = { path = "../../../../../substrate/primitives/api", default-features = false } -sp-block-builder = { path = "../../../../../substrate/primitives/block-builder", default-features = false } -sp-consensus-aura = { path = "../../../../../substrate/primitives/consensus/aura", default-features = false } -sp-core = { path = "../../../../../substrate/primitives/core", default-features = false } -sp-genesis-builder = { path = "../../../../../substrate/primitives/genesis-builder", default-features = false } -sp-inherents = { path = "../../../../../substrate/primitives/inherents", default-features = false } -sp-io = { path = "../../../../../substrate/primitives/io", default-features = false } -sp-offchain = { path = "../../../../../substrate/primitives/offchain", default-features = false } -sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false } -sp-session = { path = "../../../../../substrate/primitives/session", default-features = false } -sp-std = { path = "../../../../../substrate/primitives/std", default-features = false } -sp-storage = { path = "../../../../../substrate/primitives/storage", default-features = false } -sp-transaction-pool = { path = "../../../../../substrate/primitives/transaction-pool", default-features = false } -sp-version = { path = "../../../../../substrate/primitives/version", default-features = false } - -# Polkadot -pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm", default-features = false } -pallet-xcm-benchmarks = { path = "../../../../../polkadot/xcm/pallet-xcm-benchmarks", default-features = false, optional = true } -polkadot-core-primitives = { path = "../../../../../polkadot/core-primitives", default-features = false } -polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false } -polkadot-runtime-common = { path = "../../../../../polkadot/runtime/common", default-features = false } -xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false } -xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false } -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false } - -# Cumulus -cumulus-pallet-aura-ext = { path = "../../../../../cumulus/pallets/aura-ext", default-features = false } -cumulus-pallet-dmp-queue = { path = "../../../../../cumulus/pallets/dmp-queue", default-features = false } -cumulus-pallet-parachain-system = { path = "../../../../../cumulus/pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook"] } -cumulus-pallet-session-benchmarking = { path = "../../../../../cumulus/pallets/session-benchmarking", default-features = false } -cumulus-pallet-xcm = { path = "../../../../../cumulus/pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../../cumulus/pallets/xcmp-queue", default-features = false, features = ["bridging"] } -cumulus-primitives-core = { path = "../../../../../cumulus/primitives/core", default-features = false } -cumulus-primitives-utility = { path = "../../../../../cumulus/primitives/utility", default-features = false } -pallet-collator-selection = { path = "../../../../../cumulus/pallets/collator-selection", default-features = false } -parachain-info = { package = "staging-parachain-info", path = "../../../../../cumulus/parachains/pallets/parachain-info", default-features = false } -parachains-common = { path = "../../../../../cumulus/parachains/common", default-features = false } -parachains-runtimes-test-utils = { path = "../../../../../cumulus/parachains/runtimes/test-utils", default-features = false } -assets-common = { path = "../../../../../cumulus/parachains/runtimes/assets/common", default-features = false } - -# Ethereum Bridge (Snowbridge) -snowbridge-core = { path = "../../primitives/core", default-features = false } -snowbridge-beacon-primitives = { path = "../../primitives/beacon", default-features = false } -snowbridge-router-primitives = { path = "../../primitives/router", default-features = false } -snowbridge-pallet-ethereum-client = { path = "../../pallets/ethereum-client", default-features = false } -snowbridge-pallet-inbound-queue = { path = "../../pallets/inbound-queue", default-features = false } -snowbridge-pallet-outbound-queue = { path = "../../pallets/outbound-queue", default-features = false } -snowbridge-outbound-queue-runtime-api = { path = "../../pallets/outbound-queue/runtime-api", default-features = false } -snowbridge-pallet-system = { path = "../../pallets/system", default-features = false } -snowbridge-system-runtime-api = { path = "../../pallets/system/runtime-api", default-features = false } - -[dev-dependencies] -static_assertions = "1.1" -bridge-hub-test-utils = { path = "../../../../../cumulus/parachains/runtimes/bridge-hubs/test-utils" } -bridge-runtime-common = { path = "../../../../bin/runtime-common", features = ["integrity-test"] } -sp-keyring = { path = "../../../../../substrate/primitives/keyring" } - -[features] -default = ["std"] -std = [ - "assets-common/std", - "codec/std", - "cumulus-pallet-aura-ext/std", - "cumulus-pallet-dmp-queue/std", - "cumulus-pallet-parachain-system/std", - "cumulus-pallet-session-benchmarking/std", - "cumulus-pallet-xcm/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-core/std", - "cumulus-primitives-utility/std", - "frame-benchmarking/std", - "frame-executive/std", - "frame-support/std", - "frame-system-benchmarking?/std", - "frame-system-rpc-runtime-api/std", - "frame-system/std", - "frame-try-runtime?/std", - "log/std", - "pallet-aura/std", - "pallet-authorship/std", - "pallet-balances/std", - "pallet-collator-selection/std", - "pallet-message-queue/std", - "pallet-multisig/std", - "pallet-session/std", - "pallet-timestamp/std", - "pallet-transaction-payment-rpc-runtime-api/std", - "pallet-transaction-payment/std", - "pallet-utility/std", - "pallet-xcm-benchmarks?/std", - "pallet-xcm/std", - "parachain-info/std", - "parachains-common/std", - "parachains-runtimes-test-utils/std", - "polkadot-core-primitives/std", - "polkadot-parachain-primitives/std", - "polkadot-runtime-common/std", - "scale-info/std", - "serde", - "snowbridge-beacon-primitives/std", - "snowbridge-core/std", - "snowbridge-outbound-queue-runtime-api/std", - "snowbridge-pallet-ethereum-client/std", - "snowbridge-pallet-inbound-queue/std", - "snowbridge-pallet-outbound-queue/std", - "snowbridge-pallet-system/std", - "snowbridge-router-primitives/std", - "snowbridge-system-runtime-api/std", - "sp-api/std", - "sp-block-builder/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-genesis-builder/std", - "sp-inherents/std", - "sp-io/std", - "sp-offchain/std", - "sp-runtime/std", - "sp-session/std", - "sp-std/std", - "sp-storage/std", - "sp-transaction-pool/std", - "sp-version/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", -] - -runtime-benchmarks = [ - "assets-common/runtime-benchmarks", - "bridge-runtime-common/runtime-benchmarks", - "cumulus-pallet-dmp-queue/runtime-benchmarks", - "cumulus-pallet-parachain-system/runtime-benchmarks", - "cumulus-pallet-session-benchmarking/runtime-benchmarks", - "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "cumulus-primitives-core/runtime-benchmarks", - "cumulus-primitives-utility/runtime-benchmarks", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-collator-selection/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", - "pallet-multisig/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", - "pallet-xcm-benchmarks/runtime-benchmarks", - "pallet-xcm/runtime-benchmarks", - "parachains-common/runtime-benchmarks", - "polkadot-parachain-primitives/runtime-benchmarks", - "polkadot-runtime-common/runtime-benchmarks", - "snowbridge-core/runtime-benchmarks", - "snowbridge-pallet-ethereum-client/runtime-benchmarks", - "snowbridge-pallet-inbound-queue/runtime-benchmarks", - "snowbridge-pallet-outbound-queue/runtime-benchmarks", - "snowbridge-pallet-system/runtime-benchmarks", - "snowbridge-router-primitives/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", - "xcm-executor/runtime-benchmarks", -] diff --git a/bridges/snowbridge/parachain/runtime/test-common/README.md b/bridges/snowbridge/parachain/runtime/test-common/README.md deleted file mode 100644 index d582f87142b3..000000000000 --- a/bridges/snowbridge/parachain/runtime/test-common/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Runtime Tests - -Tests runtime config and bridge functionality in the boundaries of a runtime. diff --git a/bridges/snowbridge/parachain/runtime/test-common/src/lib.rs b/bridges/snowbridge/parachain/runtime/test-common/src/lib.rs deleted file mode 100644 index 7935a7795238..000000000000 --- a/bridges/snowbridge/parachain/runtime/test-common/src/lib.rs +++ /dev/null @@ -1,291 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork - -use codec::Encode; -use frame_support::{assert_err, assert_ok, traits::fungible::Mutate}; -pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works; -use parachains_runtimes_test_utils::{ - AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf, XcmReceivedFrom, -}; -use sp_core::H160; -use sp_runtime::SaturatedConversion; -use xcm::{ - latest::prelude::*, - v3::Error::{self, Barrier}, -}; -use xcm_executor::XcmExecutor; - -type RuntimeHelper = - parachains_runtimes_test_utils::RuntimeHelper; - -pub fn initial_fund(assethub_parachain_id: u32, initial_amount: u128) -where - Runtime: frame_system::Config + pallet_balances::Config, -{ - // fund asset hub sovereign account enough so it can pay fees - let asset_hub_sovereign_account = - snowbridge_core::sibling_sovereign_account::(assethub_parachain_id.into()); - >::mint_into( - &asset_hub_sovereign_account, - initial_amount.saturated_into::>(), - ) - .unwrap(); -} - -pub fn send_transfer_token_message( - assethub_parachain_id: u32, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, -) -> Outcome -where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config, - XcmConfig: xcm_executor::Config, -{ - let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id)); - let asset = Asset { - id: AssetId(Location::new( - 0, - [AccountKey20 { network: None, key: weth_contract_address.into() }], - )), - fun: Fungible(1000000000), - }; - let assets = vec![asset.clone()]; - - let inner_xcm = Xcm(vec![ - WithdrawAsset(Assets::from(assets.clone())), - ClearOrigin, - BuyExecution { fees: asset, weight_limit: Unlimited }, - DepositAsset { - assets: Wild(All), - beneficiary: Location::new( - 0, - [AccountKey20 { network: None, key: destination_address.into() }], - ), - }, - SetTopic([0; 32]), - ]); - - let fee = - Asset { id: AssetId(Location { parents: 1, interior: Here }), fun: Fungible(fee_amount) }; - - // prepare transfer token message - let xcm = Xcm(vec![ - WithdrawAsset(Assets::from(vec![fee.clone()])), - BuyExecution { fees: fee, weight_limit: Unlimited }, - ExportMessage { - network: Ethereum { chain_id: 11155111 }, - destination: Here, - xcm: inner_xcm, - }, - ]); - - // execute XCM - let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); - XcmExecutor::::prepare_and_execute( - assethub_parachain_location, - xcm, - &mut hash, - RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), - Weight::zero(), - ) -} - -pub fn send_transfer_token_message_success( - collator_session_key: CollatorSessionKeys, - runtime_para_id: u32, - assethub_parachain_id: u32, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, - snowbridge_pallet_outbound_queue: Box< - dyn Fn(Vec) -> Option>, - >, -) where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, - XcmConfig: xcm_executor::Config, - ValidatorIdOf: From>, -{ - ExtBuilder::::default() - .with_collators(collator_session_key.collators()) - .with_session_keys(collator_session_key.session_keys()) - .with_para_id(runtime_para_id.into()) - .with_tracing() - .build() - .execute_with(|| { - >::initialize( - runtime_para_id.into(), - assethub_parachain_id.into(), - ) - .unwrap(); - - // fund asset hub sovereign account enough so it can pay fees - initial_fund::(assethub_parachain_id, 5_000_000_000_000); - - let outcome = send_transfer_token_message::( - assethub_parachain_id, - weth_contract_address, - destination_address, - fee_amount, - ); - - assert_ok!(outcome.ensure_complete()); - - // check events - let mut events = >::events() - .into_iter() - .filter_map(|e| snowbridge_pallet_outbound_queue(e.event.encode())); - assert!(events.any(|e| matches!( - e, - snowbridge_pallet_outbound_queue::Event::MessageQueued { .. } - ))); - }); -} - -pub fn send_unpaid_transfer_token_message( - collator_session_key: CollatorSessionKeys, - runtime_para_id: u32, - assethub_parachain_id: u32, - weth_contract_address: H160, - destination_contract: H160, -) where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config, - XcmConfig: xcm_executor::Config, - ValidatorIdOf: From>, -{ - let assethub_parachain_location = Location::new(1, Parachain(assethub_parachain_id)); - - ExtBuilder::::default() - .with_collators(collator_session_key.collators()) - .with_session_keys(collator_session_key.session_keys()) - .with_para_id(runtime_para_id.into()) - .with_tracing() - .build() - .execute_with(|| { - let asset_hub_sovereign_account = - snowbridge_core::sibling_sovereign_account::(assethub_parachain_id.into()); - - >::mint_into( - &asset_hub_sovereign_account, - 4000000000u32.into(), - ) - .unwrap(); - - let asset = Asset { - id: AssetId(Location::new( - 0, - [AccountKey20 { network: None, key: weth_contract_address.into() }], - )), - fun: Fungible(1000000000), - }; - let assets = vec![asset.clone()]; - - let inner_xcm = Xcm(vec![ - WithdrawAsset(Assets::from(assets.clone())), - ClearOrigin, - BuyExecution { fees: asset, weight_limit: Unlimited }, - DepositAsset { - assets: Wild(AllCounted(1)), - beneficiary: Location::new( - 0, - [AccountKey20 { network: None, key: destination_contract.into() }], - ), - }, - SetTopic([0; 32]), - ]); - - // prepare transfer token message - let xcm = Xcm(vec![ - UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - ExportMessage { - network: Ethereum { chain_id: 11155111 }, - destination: Here, - xcm: inner_xcm, - }, - ]); - - // execute XCM - let mut hash = xcm.using_encoded(sp_io::hashing::blake2_256); - let outcome = XcmExecutor::::prepare_and_execute( - assethub_parachain_location, - xcm, - &mut hash, - RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), - Weight::zero(), - ); - // check error is barrier - assert_err!(outcome.ensure_complete(), Barrier); - }); -} - -#[allow(clippy::too_many_arguments)] -pub fn send_transfer_token_message_failure( - collator_session_key: CollatorSessionKeys, - runtime_para_id: u32, - assethub_parachain_id: u32, - initial_amount: u128, - weth_contract_address: H160, - destination_address: H160, - fee_amount: u128, - expected_error: Error, -) where - Runtime: frame_system::Config - + pallet_balances::Config - + pallet_session::Config - + pallet_xcm::Config - + parachain_info::Config - + pallet_collator_selection::Config - + cumulus_pallet_parachain_system::Config - + snowbridge_pallet_outbound_queue::Config - + snowbridge_pallet_system::Config, - XcmConfig: xcm_executor::Config, - ValidatorIdOf: From>, -{ - ExtBuilder::::default() - .with_collators(collator_session_key.collators()) - .with_session_keys(collator_session_key.session_keys()) - .with_para_id(runtime_para_id.into()) - .with_tracing() - .build() - .execute_with(|| { - >::initialize( - runtime_para_id.into(), - assethub_parachain_id.into(), - ) - .unwrap(); - - // fund asset hub sovereign account enough so it can pay fees - initial_fund::(assethub_parachain_id, initial_amount); - - let outcome = send_transfer_token_message::( - assethub_parachain_id, - weth_contract_address, - destination_address, - fee_amount, - ); - // check err is NotHoldingFees - assert_err!(outcome.ensure_complete(), expected_error); - }); -} diff --git a/bridges/snowbridge/parachain/scripts/benchmark.sh b/bridges/snowbridge/parachain/scripts/benchmark.sh deleted file mode 100755 index c9a561b33c48..000000000000 --- a/bridges/snowbridge/parachain/scripts/benchmark.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -# Example command for updating pallet benchmarking -pushd ../cumulus -cargo run --release --bin polkadot-parachain \ ---features runtime-benchmarks \ --- \ -benchmark pallet \ ---chain=bridge-hub-rococo-dev \ ---pallet=snowbridge_pallet_ethereum_client \ ---extrinsic="*" \ ---execution=wasm --wasm-execution=compiled \ ---steps 50 --repeat 20 \ ---output ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_pallet_ethereum_client.rs -popd diff --git a/bridges/snowbridge/parachain/scripts/hexliteral.sh b/bridges/snowbridge/parachain/scripts/hexliteral.sh deleted file mode 100755 index e34a2b9b5151..000000000000 --- a/bridges/snowbridge/parachain/scripts/hexliteral.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# Creates a string constant from STDIN -echo "const DATA: &'static str = concat!(" -cat - | fold | sed 's/^.*/\t"&",/' -echo ");" \ No newline at end of file diff --git a/bridges/snowbridge/parachain/scripts/init.sh b/bridges/snowbridge/parachain/scripts/init.sh deleted file mode 100755 index 1405a41ef333..000000000000 --- a/bridges/snowbridge/parachain/scripts/init.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo "*** Initializing WASM build environment" - -if [ -z $CI_PROJECT_NAME ] ; then - rustup update nightly - rustup update stable -fi - -rustup target add wasm32-unknown-unknown --toolchain nightly diff --git a/bridges/snowbridge/parachain/scripts/make-build-config.sh b/bridges/snowbridge/parachain/scripts/make-build-config.sh deleted file mode 100755 index a1b116a5dd0c..000000000000 --- a/bridges/snowbridge/parachain/scripts/make-build-config.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -cd ../ethereum - -truffle exec scripts/dumpParachainConfig.js | sed '/^Using/d;/^$/d' diff --git a/bridges/snowbridge/parachain/scripts/verify-pallets-build.sh b/bridges/snowbridge/parachain/scripts/verify-pallets-build.sh deleted file mode 100755 index a62f48c84d4f..000000000000 --- a/bridges/snowbridge/parachain/scripts/verify-pallets-build.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# A script to remove everything from snowbridge repository/subtree, except: -# -# - parachain -# - readme -# - license - -set -eu - -# show CLI help -function show_help() { - set +x - echo " " - echo Error: $1 - echo "Usage:" - echo " ./scripts/verify-pallets-build.sh Exit with code 0 if pallets code is well decoupled from the other code in the repo" - echo "Options:" - echo " --no-revert Leaves only runtime code on exit" - echo " --ignore-git-state Ignores git actual state" - exit 1 -} - -# parse CLI args -NO_REVERT= -IGNORE_GIT_STATE= -for i in "$@" -do - case $i in - --no-revert) - NO_REVERT=true - shift - ;; - --ignore-git-state) - IGNORE_GIT_STATE=true - shift - ;; - *) - show_help "Unknown option: $i" - ;; - esac -done - -# the script is able to work only on clean git copy, unless we want to ignore this check -[[ ! -z "${IGNORE_GIT_STATE}" ]] || [[ -z "$(git status --porcelain)" ]] || { echo >&2 "The git copy must be clean"; exit 1; } - -# let's avoid any restrictions on where this script can be called for - snowbridge repo may be -# plugged into any other repo folder. So the script (and other stuff that needs to be removed) -# may be located either in call dir, or one of it subdirs. -SNOWBRIDGE_FOLDER="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )/../.." - -# remove everything we think is not required for our needs -rm -rf $SNOWBRIDGE_FOLDER/.cargo -rm -rf $SNOWBRIDGE_FOLDER/.github -rm -rf $SNOWBRIDGE_FOLDER/contracts -rm -rf $SNOWBRIDGE_FOLDER/codecov.yml -rm -rf $SNOWBRIDGE_FOLDER/docs -rm -rf $SNOWBRIDGE_FOLDER/hooks -rm -rf $SNOWBRIDGE_FOLDER/relayer -rm -rf $SNOWBRIDGE_FOLDER/scripts -rm -rf $SNOWBRIDGE_FOLDER/SECURITY.md -rm -rf $SNOWBRIDGE_FOLDER/smoketest -rm -rf $SNOWBRIDGE_FOLDER/web -rm -rf $SNOWBRIDGE_FOLDER/.envrc-example -rm -rf $SNOWBRIDGE_FOLDER/.gitbook.yaml -rm -rf $SNOWBRIDGE_FOLDER/.gitignore -rm -rf $SNOWBRIDGE_FOLDER/.gitmodules -rm -rf $SNOWBRIDGE_FOLDER/_typos.toml -rm -rf $SNOWBRIDGE_FOLDER/_codecov.yml -rm -rf $SNOWBRIDGE_FOLDER/flake.lock -rm -rf $SNOWBRIDGE_FOLDER/flake.nix -rm -rf $SNOWBRIDGE_FOLDER/go.work -rm -rf $SNOWBRIDGE_FOLDER/go.work.sum -rm -rf $SNOWBRIDGE_FOLDER/polkadot-sdk -rm -rf $SNOWBRIDGE_FOLDER/rust-toolchain.toml -rm -rf $SNOWBRIDGE_FOLDER/parachain/rustfmt.toml -rm -rf $SNOWBRIDGE_FOLDER/parachain/.gitignore -rm -rf $SNOWBRIDGE_FOLDER/parachain/templates -rm -rf $SNOWBRIDGE_FOLDER/parachain/.cargo -rm -rf $SNOWBRIDGE_FOLDER/parachain/.config -rm -rf $SNOWBRIDGE_FOLDER/parachain/pallets/ethereum-client/fuzz - -cd bridges/snowbridge/parachain - -# fix polkadot-sdk paths in Cargo.toml files -find "." -name 'Cargo.toml' | while read -r file; do - replace=$(printf '../../' ) - if [[ "$(uname)" = "Darwin" ]] || [[ "$(uname)" = *BSD ]]; then - sed -i '' "s|polkadot-sdk/|$replace|g" "$file" - else - sed -i "s|polkadot-sdk/|$replace|g" "$file" - fi -done - -# let's test if everything we need compiles -cargo check -p snowbridge-pallet-ethereum-client -cargo check -p snowbridge-pallet-ethereum-client --features runtime-benchmarks -cargo check -p snowbridge-pallet-ethereum-client --features try-runtime -cargo check -p snowbridge-pallet-inbound-queue -cargo check -p snowbridge-pallet-inbound-queue --features runtime-benchmarks -cargo check -p snowbridge-pallet-inbound-queue --features try-runtime -cargo check -p snowbridge-pallet-outbound-queue -cargo check -p snowbridge-pallet-outbound-queue --features runtime-benchmarks -cargo check -p snowbridge-pallet-outbound-queue --features try-runtime -cargo check -p snowbridge-pallet-system -cargo check -p snowbridge-pallet-system --features runtime-benchmarks -cargo check -p snowbridge-pallet-system --features try-runtime - -cd - - -# we're removing lock file after all checks are done. Otherwise we may use different -# Substrate/Polkadot/Cumulus commits and our checks will fail -rm -f $SNOWBRIDGE_FOLDER/parachain/Cargo.toml -rm -f $SNOWBRIDGE_FOLDER/parachain/Cargo.lock - -echo "OK"