From 24cff45334f26dc4c48d58198869f2ae1721055d Mon Sep 17 00:00:00 2001 From: Giacomo Date: Mon, 28 Sep 2020 17:07:36 +0200 Subject: [PATCH 001/107] Set AWS_REGION as a global env variable (#67) --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 610cfe488a..a5e4a97888 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,10 @@ on: tags: - v* +# Global vars +env: + AWS_REGION: "us-east-1" + jobs: build: name: Build Release @@ -14,7 +18,6 @@ jobs: SCCACHE_CACHE_SIZE: "1G" SCCACHE_IDLE_TIMEOUT: 0 AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" - AWS_REGION: "us-east-1" strategy: matrix: platform: @@ -237,7 +240,7 @@ jobs: run: | # Deploy zip artifacts to S3 bucket to a directory whose name is the tagged release version. # Deploy macos binary artifact (if required, add more `aws s3 cp` commands to deploy specific OS versions) - aws s3 cp macos-artifacts/openethereum s3://${{ env.AWS_S3_ARTIFACTS_BUCKET }}/${{ env.RELEASE_VERSION }}/macos/ + aws s3 cp macos-artifacts/openethereum s3://${{ env.AWS_S3_ARTIFACTS_BUCKET }}/${{ env.RELEASE_VERSION }}/macos/ --region ${{ env.AWS_REGION }} outputs: linux-artifact: ${{ steps.create_zip_linux.outputs.LINUX_ARTIFACT }} From 16542bd3554334250bda244197ded2b19585709d Mon Sep 17 00:00:00 2001 From: Denis Granha Date: Tue, 29 Sep 2020 13:04:59 +0200 Subject: [PATCH 002/107] fix CD env param --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a5e4a97888..5c2fa64329 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ on: # Global vars env: AWS_REGION: "us-east-1" + AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" jobs: build: @@ -17,7 +18,6 @@ jobs: env: SCCACHE_CACHE_SIZE: "1G" SCCACHE_IDLE_TIMEOUT: 0 - AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" strategy: matrix: platform: From 03bfb012a15ab1fb3130bd8e6723f57de4119cea Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 30 Sep 2020 13:10:18 +0200 Subject: [PATCH 003/107] Change wiki links (#68) --- .github/CONTRIBUTING.md | 4 ++-- README.md | 6 +++--- ethcore/src/snapshot/mod.rs | 2 +- rpc/src/tests/rpc.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6aa2d8f698..eb48b425fc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,7 +2,7 @@ ## Do you have a question? -Check out our [Basic Usage](https://openethereum.github.io/wiki/Basic-Usage), [Configuration](https://openethereum.github.io/wiki/Configuring-OpenEthereum), and [FAQ](https://openethereum.github.io/wiki/FAQ) articles on our [wiki](https://openethereum.github.io/wiki)! +Check out our [Beginner Introduction](https://openethereum.github.io/Beginner-Introduction), [Configuration](https://openethereum.github.io//Configuring-OpenEthereum), and [FAQ](https://openethereum.github.io/FAQ) articles on our [wiki](https://openethereum.github.io/)! See also frequently asked questions [tagged with `parity`](https://ethereum.stackexchange.com/questions/tagged/parity?sort=votes&pageSize=50) on Stack Exchange. @@ -35,7 +35,7 @@ There are a few basic ground-rules for contributors (including the maintainer(s) * **No pushing directly to the master branch**. * **All modifications** must be made in a **pull-request** to solicit feedback from other contributors. * Pull-requests cannot be merged before CI runs green and two reviewers have given their approval. -* Contributors should adhere to the [Parity Ethereum Style Guide](https://openethereum.github.io/wiki/Parity-Ethereum-Style-Guide). +* All code changed should be formated by running `cargo fmt -- --config=merge_imports=true` ### Recommendations diff --git a/README.md b/README.md index d8e03fa8e9..86ccc0e16d 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ OpenEthereum's goal is to be the fastest, lightest, and most secure Ethereum cli By default, OpenEthereum runs a JSON-RPC HTTP server on port `:8545` and a Web-Sockets server on port `:8546`. This is fully configurable and supports a number of APIs. -If you run into problems while using OpenEthereum, check out the [old wiki for documentation](https://openethereum.github.io/wiki/), feel free to [file an issue in this repository](https://github.com/openethereum/openethereum/issues/new), or hop on our [Discord](https://discord.io/openethereum) chat room to ask a question. We are glad to help! +If you run into problems while using OpenEthereum, check out the [old wiki for documentation](https://openethereum.github.io/), feel free to [file an issue in this repository](https://github.com/openethereum/openethereum/issues/new), or hop on our [Discord](https://discord.io/openethereum) chat room to ask a question. We are glad to help! You can download OpenEthereum's latest release at [the releases page](https://github.com/openethereum/openethereum/releases) or follow the instructions below to build from source. Read the [CHANGELOG.md](CHANGELOG.md) for a list of all changes between different versions. @@ -135,7 +135,7 @@ To start OpenEthereum as a regular user using `systemd` init: 1. Copy `./scripts/openethereum.service` to your `systemd` user directory (usually `~/.config/systemd/user`). 2. Copy release to bin folder, write `sudo install ./target/release/openethereum /usr/bin/openethereum` -3. To configure OpenEthereum, see [our old wiki](https://openethereum.github.io/wiki/Configuring-OpenEthereum) for details. +3. To configure OpenEthereum, see [our wiki](https://openethereum.github.io/Configuring-OpenEthereum) for details. ## 4. Testing @@ -157,7 +157,7 @@ You can show your logs in the test output by passing `--nocapture` (i.e. `cargo ## 5. Documentation -Be sure to [check out our old wiki](https://openethereum.github.io/wiki/) for more information. +Be sure to [check out our wiki](https://openethereum.github.io/) for more information. ### Viewing documentation for OpenEthereum packages diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 76d2e2e56b..5ffd3cff2d 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -17,7 +17,7 @@ //! Snapshot creation, restoration, and network service. //! //! Documentation of the format can be found at -//! https://openethereum.github.io/wiki/Warp-Sync-Snapshot-Format +//! https://openethereum.github.io/Warp-Sync-Snapshot-Format use hash::{keccak, KECCAK_EMPTY, KECCAK_NULL_RLP}; use std::{ diff --git a/rpc/src/tests/rpc.rs b/rpc/src/tests/rpc.rs index a105dd8834..1eb41550a5 100644 --- a/rpc/src/tests/rpc.rs +++ b/rpc/src/tests/rpc.rs @@ -143,7 +143,7 @@ mod tests { "\ OPTIONS / HTTP/1.1\r\n\ Host: {}\r\n\ - Origin: http://openethereum.github.io/wiki/\r\n\ + Origin: http://openethereum.github.io\r\n\ Content-Length: 0\r\n\ Content-Type: application/json\r\n\ Connection: close\r\n\ From 84f675021cc096003d99fa10db2e078e59e73bb0 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Wed, 30 Sep 2020 13:10:54 +0200 Subject: [PATCH 004/107] Fix warnings (#64) --- ethcore/src/json_tests/executive.rs | 1 + ethcore/src/json_tests/mod.rs | 4 +++- ethcore/src/json_tests/runner.rs | 1 + ethcore/src/json_tests/test_common.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 25535adab3..11288ae2dc 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -240,6 +240,7 @@ where } } +/// run an json executive test pub fn json_executive_test( path: &Path, json_data: &[u8], diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 5f1cad9ad8..004d86d69b 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -19,12 +19,14 @@ mod chain; mod difficulty; mod executive; -pub mod runner; mod state; mod test_common; mod transaction; mod trie; +/// executor of ethereum/json tests +pub mod runner; + pub use self::{ executive::json_executive_test, test_common::{debug_include_test, find_json_files_recursive, HookType}, diff --git a/ethcore/src/json_tests/runner.rs b/ethcore/src/json_tests/runner.rs index 18bad4a7f8..4b22146faa 100644 --- a/ethcore/src/json_tests/runner.rs +++ b/ethcore/src/json_tests/runner.rs @@ -59,6 +59,7 @@ impl std::ops::AddAssign for TestResult { } } +/// An executor of ethereum/json tests pub struct TestRunner(EthereumTestSuite); impl TestRunner { diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index 2af7616fb8..73a6a500c9 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -27,6 +27,7 @@ pub enum HookType { OnStop, } +/// find all json files recursively from a path pub fn find_json_files_recursive(path: &PathBuf) -> Vec { WalkDir::new(path) .into_iter() @@ -36,6 +37,7 @@ pub fn find_json_files_recursive(path: &PathBuf) -> Vec { .collect::>() } +/// check if the test is selected to execute via TEST_DEBUG environment variable pub fn debug_include_test(name: &str) -> bool { match std::env::var_os("TEST_DEBUG") { Some(s) => s.to_string_lossy().split_terminator(",").any(|expr| { From cb0513a8b1df42bef218e05a880ecd3fbc8ec413 Mon Sep 17 00:00:00 2001 From: varasev <33550681+varasev@users.noreply.github.com> Date: Thu, 8 Oct 2020 23:37:48 +0300 Subject: [PATCH 005/107] Add `wasmDisableTransition` spec option (#60) * Add wasmDisableTransition spec option --- ethcore/res/ethereum/kovan_wasm_test.json | 3 ++- ethcore/src/executive.rs | 32 ++++++++++++++++++++--- ethcore/src/spec/spec.rs | 10 ++++++- json/src/spec/params.rs | 9 ++++++- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/ethcore/res/ethereum/kovan_wasm_test.json b/ethcore/res/ethereum/kovan_wasm_test.json index 70143d8a8d..a393cfb5ea 100644 --- a/ethcore/res/ethereum/kovan_wasm_test.json +++ b/ethcore/res/ethereum/kovan_wasm_test.json @@ -42,7 +42,8 @@ "eip211Transition": 5067000, "eip214Transition": 5067000, "eip658Transition": 5067000, - "wasmActivationTransition": 10 + "wasmActivationTransition": 10, + "wasmDisableTransition": 200 }, "genesis": { "seal": { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index d39303b872..ec0b7a8960 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -2919,7 +2919,7 @@ mod tests { let mut info = EnvInfo::default(); - // 100 > 10 + // 200 (wasmDisableTransition) > 100 > 10 (wasmActivationTransition) info.number = 100; // Network with wasm activated at block 10 @@ -2947,7 +2947,7 @@ mod tests { // Transaction successfully returned sender assert_eq!(output[..], sender[..]); - // 1 < 10 + // 1 < 10 (wasmActivationTransition) info.number = 1; let mut output = [0u8; 20]; @@ -2959,7 +2959,7 @@ mod tests { let schedule = machine.schedule(info.number); let mut ex = Executive::new(&mut state, &info, &machine, &schedule); ex.call( - params, + params.clone(), &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer, @@ -2972,5 +2972,31 @@ mod tests { assert_eq!(result, U256::from(20025)); // Since transaction errored due to wasm was not activated, result is just empty assert_eq!(output[..], [0u8; 20][..]); + + // 200 == wasmDisableTransition + info.number = 200; + + let mut output = [0u8; 20]; + let FinalizationResult { + gas_left: result, + return_data, + .. + } = { + let schedule = machine.schedule(info.number); + let mut ex = Executive::new(&mut state, &info, &machine, &schedule); + ex.call( + params, + &mut Substate::new(), + &mut NoopTracer, + &mut NoopVMTracer, + ) + .unwrap() + }; + (&mut output[..(cmp::min(20, return_data.len()))]) + .copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]); + + assert_eq!(result, U256::from(20025)); + // Since transaction errored due to wasm was deactivated, result is just empty + assert_eq!(output[..], [0u8; 20][..]); } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index e8f968a710..c38e19adfa 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -143,6 +143,8 @@ pub struct CommonParams { pub remove_dust_contracts: bool, /// Wasm activation blocknumber, if any disabled initially. pub wasm_activation_transition: BlockNumber, + /// Wasm deactivation blocknumber, if enabled. + pub wasm_disable_transition: BlockNumber, /// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated. pub kip4_transition: BlockNumber, /// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated. @@ -226,7 +228,9 @@ impl CommonParams { false => ::vm::CleanDustMode::BasicOnly, }; } - if block_number >= self.wasm_activation_transition { + if block_number >= self.wasm_activation_transition + && block_number < self.wasm_disable_transition + { let mut wasm = ::vm::WasmCosts::default(); if block_number >= self.kip4_transition { wasm.have_create2 = true; @@ -362,6 +366,9 @@ impl From for CommonParams { wasm_activation_transition: p .wasm_activation_transition .map_or_else(BlockNumber::max_value, Into::into), + wasm_disable_transition: p + .wasm_disable_transition + .map_or_else(BlockNumber::max_value, Into::into), kip4_transition: p .kip4_transition .map_or_else(BlockNumber::max_value, Into::into), @@ -628,6 +635,7 @@ impl Spec { params.eip2315_transition, params.dust_protection_transition, params.wasm_activation_transition, + params.wasm_disable_transition, params.kip4_transition, params.kip6_transition, params.max_code_size_transition, diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index dbaa1f907c..150e9ce1a8 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -132,6 +132,8 @@ pub struct Params { pub transaction_permission_contract_transition: Option, /// Wasm activation block height, if not activated from start pub wasm_activation_transition: Option, + /// Wasm deactivation block height, if activated. + pub wasm_disable_transition: Option, /// KIP4 activiation block height. pub kip4_transition: Option, /// KIP6 activiation block height. @@ -156,7 +158,8 @@ mod tests { "accountStartNonce": "0x01", "gasLimitBoundDivisor": "0x20", "maxCodeSize": "0x1000", - "wasmActivationTransition": "0x1010" + "wasmActivationTransition": "0x1010", + "wasmDisableTransition": "0x2010" }"#; let deserialized: Params = serde_json::from_str(s).unwrap(); @@ -175,6 +178,10 @@ mod tests { deserialized.wasm_activation_transition, Some(Uint(U256::from(0x1010))) ); + assert_eq!( + deserialized.wasm_disable_transition, + Some(Uint(U256::from(0x2010))) + ); } #[test] From 9110b1d9e4cb41ccfcfe5cfe7621e942b0a13001 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Mon, 12 Oct 2020 10:55:21 +0200 Subject: [PATCH 006/107] Update gitactions master->main (#72) --- .github/workflows/build-test.yml | 4 ++-- .github/workflows/build.yml | 2 +- .github/workflows/check.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index a8357e5e96..8e6426e04b 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -4,7 +4,7 @@ on: pull_request: push: branches: - - master + - main - stable jobs: build-tests: @@ -23,7 +23,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - name: Checkout sources - uses: actions/checkout@master + uses: actions/checkout@main with: submodules: true - name: Install toolchain diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5c2fa64329..c0f653c81c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - name: Checkout sources - uses: actions/checkout@master + uses: actions/checkout@main - name: Install toolchain uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 03edc614fd..de58f8a506 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -4,7 +4,7 @@ on: pull_request: push: branches: - - master + - main - stable jobs: check: @@ -15,7 +15,7 @@ jobs: SCCACHE_IDLE_TIMEOUT: 0 steps: - name: Checkout sources - uses: actions/checkout@master + uses: actions/checkout@main with: submodules: true - name: Install stable toolchain From d811f6e3ce894578cdd1028cb4fbb915ea6a3d04 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 23 Oct 2020 10:43:18 +0200 Subject: [PATCH 007/107] Use ubuntu-16.04 for glibc compatibility (#11888) (#73) --- .github/workflows/build-test.yml | 4 ++-- .github/workflows/build.yml | 12 ++++++------ .github/workflows/check.yml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 8e6426e04b..96a9afb06c 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: platform: - - ubuntu-20.04 + - ubuntu-16.04 - macos-latest - windows-latest toolchain: @@ -48,7 +48,7 @@ jobs: path: target key: ${{ runner.os }}-cargo-build-target-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache linux - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-16.04' uses: actions/cache@v2 with: path: "/home/runner/.cache/sccache" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0f653c81c..ef9ef5ba21 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ on: env: AWS_REGION: "us-east-1" AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" - + jobs: build: name: Build Release @@ -21,7 +21,7 @@ jobs: strategy: matrix: platform: - - ubuntu-20.04 + - ubuntu-16.04 - macos-latest - windows-latest toolchain: @@ -52,7 +52,7 @@ jobs: path: target key: ${{ runner.os }}-cargo-build-target-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache linux - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-16.04' uses: actions/cache@v2 with: path: "/home/runner/.cache/sccache" @@ -105,7 +105,7 @@ jobs: - name: Upload Linux build uses: actions/upload-artifact@v2 - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-16.04' with: name: linux-artifacts path: artifacts @@ -132,7 +132,7 @@ jobs: zip-artifacts-creator: name: Create zip artifacts needs: build - runs-on: ubuntu-20.04 + runs-on: ubuntu-16.04 steps: - name: Set env run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/} @@ -253,7 +253,7 @@ jobs: draft-release: name: Draft Release needs: zip-artifacts-creator - runs-on: ubuntu-20.04 + runs-on: ubuntu-16.04 steps: - name: Set env run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index de58f8a506..937d68628f 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -9,7 +9,7 @@ on: jobs: check: name: Check - runs-on: ubuntu-20.04 + runs-on: ubuntu-16.04 env: SCCACHE_CACHE_SIZE: "1G" SCCACHE_IDLE_TIMEOUT: 0 From bf5830f766bf89861b92824de08f92a00de79d44 Mon Sep 17 00:00:00 2001 From: Denis Granha Date: Fri, 23 Oct 2020 22:59:18 +0200 Subject: [PATCH 008/107] revert actions/cache to version 1.1.2 (#80) --- .github/workflows/build-test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 96a9afb06c..3659d46376 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -33,35 +33,35 @@ jobs: profile: minimal override: true - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/registry key: ${{ runner.os }}-cargo-registry-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/git key: ${{ runner.os }}-cargo-git-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo build - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: target key: ${{ runner.os }}-cargo-build-target-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache linux if: matrix.platform == 'ubuntu-16.04' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "/home/runner/.cache/sccache" key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache MacOS if: matrix.platform == 'macos-latest' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "/Users/runner/Library/Caches/Mozilla.sccache" key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache Windows if: matrix.platform == 'windows-latest' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache" key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} From 410853e280fdb238d3d3f151089e29dbc207d1e1 Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Mon, 26 Oct 2020 09:27:44 +0000 Subject: [PATCH 009/107] Update gitactions for dev branch, deprecate stable branch --- .github/workflows/build-test.yml | 2 +- .github/workflows/build.yml | 2 -- .github/workflows/check.yml | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3659d46376..edd0cdabd0 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -5,7 +5,7 @@ on: push: branches: - main - - stable + - dev jobs: build-tests: name: Test and Build diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef9ef5ba21..c44e0fc739 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,8 +2,6 @@ name: Build Release Suite on: push: - branches: - - stable tags: - v* diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 937d68628f..0f46773dab 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -5,7 +5,7 @@ on: push: branches: - main - - stable + - dev jobs: check: name: Check From 50a4d5fa5701357ddd0e8b494a55efd813779714 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 27 Oct 2020 10:45:48 +0100 Subject: [PATCH 010/107] Sync block verification (#74) * Synchronize block verification * max_round_blocks_to_import set to 1 * Fixed test that rely on 12block batches Co-authored-by: adria0.eth <5526331+adria0@users.noreply.github.com> --- ethcore/src/client/client.rs | 2 ++ ethcore/src/client/config.rs | 2 +- ethcore/src/tests/client.rs | 2 +- ethcore/src/verification/queue/mod.rs | 8 +++++++- parity/cli/mod.rs | 4 ++-- parity/configuration.rs | 10 +++++----- 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index f075d6b963..6164f2799c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -389,6 +389,8 @@ impl Importer { let db = client.db.read(); db.key_value().flush().expect("DB flush failed."); + + self.block_queue.resignal_verification(); imported } diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index d53b825486..d23f5028b2 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -151,7 +151,7 @@ impl Default for ClientConfig { history_mem: 32 * mb, check_seal: true, transaction_verification_queue_size: 8192, - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, snapshot: Default::default(), } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 954d2a044d..58ae5eeac4 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -278,7 +278,7 @@ fn can_handle_long_fork() { push_blocks_to_client(&client, 49, 1201, 800); push_blocks_to_client(&client, 53, 1201, 600); - for _ in 0..400 { + for _ in 0..2300 { client.import_verified_blocks(); } assert_eq!(2000, client.chain_info().best_block_number); diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index 1d39db9c27..fff62d4292 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -665,11 +665,17 @@ impl VerificationQueue { .verified .fetch_sub(drained_size, AtomicOrdering::SeqCst); + result + } + + /// release taken signal and call async ClientIoMessage::BlockVerified call to client so that it can continue verification. + /// difference between sync and async is whose thread pool is used. + pub fn resignal_verification(&self) { + let verified = self.verification.verified.lock(); self.ready_signal.reset(); if !verified.is_empty() { self.ready_signal.set_async(); } - result } /// Returns true if there is nothing currently in the queue. diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 207e7db3b0..2508398e05 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -706,7 +706,7 @@ usage! { "--stratum-secret=[STRING]", "Secret for authorizing Stratum server for peers.", - ARG arg_max_round_blocks_to_import: (usize) = 12usize, or |c: &Config| c.mining.as_ref()?.max_round_blocks_to_import.clone(), + ARG arg_max_round_blocks_to_import: (usize) = 1usize, or |c: &Config| c.mining.as_ref()?.max_round_blocks_to_import.clone(), "--max-round-blocks-to-import=[S]", "Maximal number of blocks to import for each import round.", @@ -1386,7 +1386,7 @@ mod tests { arg_notify_work: Some("http://localhost:3001".into()), flag_refuse_service_transactions: false, flag_infinite_pending_block: false, - arg_max_round_blocks_to_import: 12usize, + arg_max_round_blocks_to_import: 1usize, flag_stratum: false, arg_stratum_interface: "local".to_owned(), diff --git a/parity/configuration.rs b/parity/configuration.rs index 7416bfa8c8..c2f3d3c107 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -1369,7 +1369,7 @@ mod tests { check_seal: true, with_color: !cfg!(windows), verifier_settings: Default::default(), - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, })) ); } @@ -1395,7 +1395,7 @@ mod tests { from_block: BlockId::Number(1), to_block: BlockId::Latest, check_seal: true, - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, })) ); } @@ -1423,7 +1423,7 @@ mod tests { code: true, min_balance: None, max_balance: None, - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, })) ); } @@ -1456,7 +1456,7 @@ mod tests { from_block: BlockId::Number(1), to_block: BlockId::Latest, check_seal: true, - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, })) ); } @@ -1550,7 +1550,7 @@ mod tests { download_old_blocks: true, verifier_settings: Default::default(), no_persistent_txqueue: false, - max_round_blocks_to_import: 12, + max_round_blocks_to_import: 1, metrics_conf: MetricsConfiguration::default(), }; expected.secretstore_conf.enabled = cfg!(feature = "secretstore"); From 6078eeaed78ffc30614e6b73efe70ab1439d82fe Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Wed, 4 Nov 2020 19:11:05 +0100 Subject: [PATCH 011/107] EIP2929 with journaling + Yolov3 (#79) --- Cargo.lock | 1 + ethcore/evm/Cargo.toml | 1 + ethcore/evm/benches/basic.rs | 2 +- ethcore/evm/src/interpreter/gasometer.rs | 138 ++++++++---- ethcore/evm/src/interpreter/mod.rs | 43 +++- ethcore/evm/src/lib.rs | 1 + ethcore/evm/src/tests.rs | 107 ++++++++++ ethcore/res/ethereum/berlin_test.json | 3 +- ethcore/res/ethereum/yolo3_test.json | 123 +++++++++++ ethcore/src/client/evm_test_client.rs | 1 + ethcore/src/ethereum/mod.rs | 5 + ethcore/src/executive.rs | 141 +++--------- ethcore/src/externalities.rs | 42 +++- ethcore/src/json_tests/executive.rs | 24 +++ ethcore/src/json_tests/state.rs | 12 +- ethcore/src/machine/impls.rs | 4 +- ethcore/src/spec/spec.rs | 27 ++- ethcore/src/state/substate.rs | 15 ++ ethcore/src/tests/evm.rs | 4 +- ethcore/vm/src/access_list.rs | 260 +++++++++++++++++++++++ ethcore/vm/src/action_params.rs | 8 +- ethcore/vm/src/ext.rs | 18 ++ ethcore/vm/src/lib.rs | 10 +- ethcore/vm/src/schedule.rs | 52 ++++- ethcore/vm/src/tests.rs | 41 +++- evmbin/src/main.rs | 26 ++- json/src/spec/params.rs | 2 + json/src/spec/spec.rs | 1 + rpc/src/v1/tests/mocked/personal.rs | 4 +- 29 files changed, 919 insertions(+), 197 deletions(-) create mode 100644 ethcore/res/ethereum/yolo3_test.json create mode 100644 ethcore/vm/src/access_list.rs diff --git a/Cargo.lock b/Cargo.lock index e9fe52db71..ccb225e0ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1505,6 +1505,7 @@ version = "0.1.0" dependencies = [ "bit-set", "criterion 0.2.11", + "ethcore-builtin", "ethereum-types 0.4.2", "heapsize", "hex-literal", diff --git a/ethcore/evm/Cargo.toml b/ethcore/evm/Cargo.toml index b5f4d0685f..e59bf7e6d9 100644 --- a/ethcore/evm/Cargo.toml +++ b/ethcore/evm/Cargo.toml @@ -15,6 +15,7 @@ vm = { path = "../vm" } keccak-hash = "0.1" parking_lot = "0.7" memory-cache = { path = "../../util/memory-cache" } +ethcore-builtin = { path = "../builtin" } num-bigint = "0.2" [dev-dependencies] diff --git a/ethcore/evm/benches/basic.rs b/ethcore/evm/benches/basic.rs index 9d0b1575b3..f6b7fa4727 100644 --- a/ethcore/evm/benches/basic.rs +++ b/ethcore/evm/benches/basic.rs @@ -33,7 +33,7 @@ use criterion::{black_box, Bencher, Criterion}; use ethereum_types::{Address, U256}; use evm::Factory; use rustc_hex::FromHex; -use std::{str::FromStr, sync::Arc}; +use std::{collections::BTreeMap, str::FromStr, sync::Arc}; use vm::{tests::FakeExt, ActionParams, Ext, GasLeft, Result}; criterion_group!( diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 8bb514aac5..8a710069e5 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -15,9 +15,10 @@ // along with OpenEthereum. If not, see . use super::u256_to_address; -use ethereum_types::{H256, U256}; +use ethereum_types::{Address, H256, U256}; use std::cmp; +use super::stack::VecStack; use evm; use instructions::{self, Instruction, InstructionInfo}; use interpreter::stack::Stack; @@ -115,26 +116,38 @@ impl Gasometer { ext: &dyn vm::Ext, instruction: Instruction, info: &InstructionInfo, - stack: &dyn Stack, + stack: &VecStack, + current_address: &Address, current_mem_size: usize, ) -> vm::Result> { let schedule = ext.schedule(); + let tier = info.tier.idx(); let default_gas = Gas::from(schedule.tier_step_gas[tier]); + let accessed_addresses_gas = |addr: &Address, cold_cost: usize| -> Gas { + if ext.al_contains_address(addr) { + schedule.warm_storage_read_cost.into() + } else { + cold_cost.into() + } + }; + let cost = match instruction { instructions::JUMPDEST => Request::Gas(Gas::from(1)), instructions::SSTORE => { if schedule.eip1706 && self.current_gas <= Gas::from(schedule.call_stipend) { return Err(vm::Error::OutOfGas); } - let address = H256::from(stack.peek(0)); + let key = H256::from(stack.peek(0)); let newval = stack.peek(1); - let val = U256::from(&*ext.storage_at(&address)?); + let val = U256::from(&*ext.storage_at(&key)?); + + let is_cold = !ext.al_contains_storage_key(current_address, &key); let gas = if schedule.eip1283 { - let orig = U256::from(&*ext.initial_storage_at(&address)?); - calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval) + let orig = U256::from(&*ext.initial_storage_at(&key)?); + calculate_eip1283_eip2929_sstore_gas(schedule, is_cold, &orig, &val, &newval) } else { if val.is_zero() && !newval.is_zero() { schedule.sstore_set_gas @@ -144,17 +157,40 @@ impl Gasometer { schedule.sstore_reset_gas } }; - Request::Gas(Gas::from(gas)) + + Request::Gas(gas.into()) + } + instructions::SLOAD => { + let key = H256::from(stack.peek(0)); + let gas = if ext.al_is_enabled() { + if ext.al_contains_storage_key(current_address, &key) { + schedule.warm_storage_read_cost + } else { + schedule.cold_sload_cost + } + } else { + schedule.sload_gas + }; + Request::Gas(gas.into()) + } + instructions::BALANCE => { + let address = u256_to_address(stack.peek(0)); + Request::Gas(accessed_addresses_gas(&address, schedule.balance_gas)) + } + instructions::EXTCODESIZE => { + let address = u256_to_address(stack.peek(0)); + Request::Gas(accessed_addresses_gas(&address, schedule.extcodesize_gas)) + } + instructions::EXTCODEHASH => { + let address = u256_to_address(stack.peek(0)); + Request::Gas(accessed_addresses_gas(&address, schedule.extcodehash_gas)) } - instructions::SLOAD => Request::Gas(Gas::from(schedule.sload_gas)), - instructions::BALANCE => Request::Gas(Gas::from(schedule.balance_gas)), - instructions::EXTCODESIZE => Request::Gas(Gas::from(schedule.extcodesize_gas)), - instructions::EXTCODEHASH => Request::Gas(Gas::from(schedule.extcodehash_gas)), instructions::SUICIDE => { let mut gas = Gas::from(schedule.suicide_gas); let is_value_transfer = !ext.origin_balance()?.is_zero(); let address = u256_to_address(stack.peek(0)); + if (!schedule.no_empty && !ext.exists(&address)?) || (schedule.no_empty && is_value_transfer @@ -164,6 +200,13 @@ impl Gasometer { overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into())); } + if !ext.al_contains_address(&address) { + // EIP2929 If the ETH recipient of a SELFDESTRUCT is not in accessed_addresses + // (regardless of whether or not the amount sent is nonzero), + // charge an additional COLD_ACCOUNT_ACCESS_COST on top of the existing gas costs, + gas = Gas::from(gas.as_usize() + schedule.cold_account_access_cost); + } + Request::Gas(gas) } instructions::MSTORE | instructions::MLOAD => { @@ -189,11 +232,15 @@ impl Gasometer { Gas::from_u256(*stack.peek(2))?, ) } - instructions::EXTCODECOPY => Request::GasMemCopy( - schedule.extcodecopy_base_gas.into(), - mem_needed(stack.peek(1), stack.peek(3))?, - Gas::from_u256(*stack.peek(3))?, - ), + instructions::EXTCODECOPY => { + let address = u256_to_address(stack.peek(0)); + let gas = accessed_addresses_gas(&address, schedule.extcodecopy_base_gas); + Request::GasMemCopy( + gas, + mem_needed(stack.peek(1), stack.peek(3))?, + Gas::from_u256(*stack.peek(3))?, + ) + } instructions::LOG0 | instructions::LOG1 | instructions::LOG2 @@ -218,6 +265,8 @@ impl Gasometer { ); let address = u256_to_address(stack.peek(1)); + gas = accessed_addresses_gas(&address, gas.as_usize()); + let is_value_transfer = !stack.peek(2).is_zero(); if instruction == instructions::CALL @@ -238,7 +287,10 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) } instructions::DELEGATECALL | instructions::STATICCALL => { - let gas = Gas::from(schedule.call_gas); + let mut gas = Gas::from(schedule.call_gas); + let address = u256_to_address(stack.peek(1)); + gas = accessed_addresses_gas(&address, gas.as_usize()); + let mem = cmp::max( mem_needed(stack.peek(4), stack.peek(5))?, mem_needed(stack.peek(2), stack.peek(3))?, @@ -389,41 +441,39 @@ fn to_word_size(value: Gas) -> (Gas, bool) { } #[inline] -fn calculate_eip1283_sstore_gas( +fn calculate_eip1283_eip2929_sstore_gas( schedule: &Schedule, + is_cold: bool, original: &U256, current: &U256, new: &U256, ) -> Gas { - Gas::from(if current == new { - // 1. If current value equals new value (this is a no-op), 200 gas is deducted. - schedule.sload_gas - } else { - // 2. If current value does not equal new value - if original == current { - // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) - if original.is_zero() { - // 2.1.1. If original value is 0, 20000 gas is deducted. - schedule.sstore_set_gas + Gas::from( + if current == new { + // 1. If current value equals new value (this is a no-op). + schedule.sload_gas + } else { + // 2. If current value does not equal new value + if original == current { + // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + if original.is_zero() { + // 2.1.1. If original value is 0. + schedule.sstore_set_gas + } else { + // 2.1.2. Otherwise. + schedule.sstore_reset_gas + } } else { - // 2.1.2. Otherwise, 5000 gas is deducted. - schedule.sstore_reset_gas - - // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + // 2.2. If original value does not equal current value (this storage slot is dirty). + schedule.sload_gas } + } + if is_cold { + // EIP2929 SSTORE changes section + schedule.cold_sload_cost } else { - // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. - schedule.sload_gas - - // 2.2.1. If original value is not 0 - // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. - // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. - - // 2.2.2. If original value equals new value (this storage slot is reset) - // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. - // 2.2.2.2. Otherwise, add 4800 gas to refund counter. - } - }) + 0 + }, + ) } pub fn handle_eip1283_sstore_clears_refund( diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 332b268fb3..418c3572a5 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -398,8 +398,14 @@ impl Interpreter { .gasometer .as_mut() .expect(GASOMETER_PROOF) - .requirements(ext, instruction, info, &self.stack, self.mem.size()) - { + .requirements( + ext, + instruction, + info, + &self.stack, + &self.params.address, + self.mem.size(), + ) { Ok(t) => t, Err(e) => return InterpreterResult::Done(Err(e)), }; @@ -709,6 +715,15 @@ impl Interpreter { return Ok(InstructionResult::UnusedGas(create_gas)); } + let contract_address = { + let contract_code = self.mem.read_slice(init_off, init_size); + ext.calc_address(contract_code, address_scheme) + }; + + if let Some(contract_address) = contract_address { + ext.al_insert_address(contract_address); + } + let contract_code = self.mem.read_slice(init_off, init_size); let create_result = ext.create( @@ -777,6 +792,8 @@ impl Interpreter { )) .0; + ext.al_insert_address(code_address); + // Get sender & receive addresses, check if we have balance let (sender_address, receive_address, has_balance, call_type) = match instruction { instructions::CALL => { @@ -903,8 +920,9 @@ impl Interpreter { return Ok(InstructionResult::StopExecution); } instructions::SUICIDE => { - let address = self.stack.pop_back(); - ext.suicide(&u256_to_address(&address))?; + let address = u256_to_address(&self.stack.pop_back()); + ext.al_insert_address(address.clone()); + ext.suicide(&address)?; return Ok(InstructionResult::StopExecution); } instructions::LOG0 @@ -991,15 +1009,17 @@ impl Interpreter { let key = H256::from(&self.stack.pop_back()); let word = U256::from(&*ext.storage_at(&key)?); self.stack.push(word); + + ext.al_insert_storage_key(self.params.address, key); } instructions::SSTORE => { - let address = H256::from(&self.stack.pop_back()); + let key = H256::from(&self.stack.pop_back()); let val = self.stack.pop_back(); - let current_val = U256::from(&*ext.storage_at(&address)?); + let current_val = U256::from(&*ext.storage_at(&key)?); // Increase refund for clear if ext.schedule().eip1283 { - let original_val = U256::from(&*ext.initial_storage_at(&address)?); + let original_val = U256::from(&*ext.initial_storage_at(&key)?); gasometer::handle_eip1283_sstore_clears_refund( ext, &original_val, @@ -1012,7 +1032,8 @@ impl Interpreter { ext.add_sstore_refund(sstore_clears_schedule); } } - ext.set_storage(address, H256::from(&val))?; + ext.set_storage(key, H256::from(&val))?; + ext.al_insert_storage_key(self.params.address, key); } instructions::PC => { self.stack.push(U256::from(self.reader.position - 1)); @@ -1031,6 +1052,7 @@ impl Interpreter { let address = u256_to_address(&self.stack.pop_back()); let balance = ext.balance(&address)?; self.stack.push(balance); + ext.al_insert_address(address); } instructions::CALLER => { self.stack.push(address_to_u256(self.params.sender.clone())); @@ -1068,11 +1090,15 @@ impl Interpreter { instructions::EXTCODESIZE => { let address = u256_to_address(&self.stack.pop_back()); let len = ext.extcodesize(&address)?.unwrap_or(0); + + ext.al_insert_address(address); self.stack.push(U256::from(len)); } instructions::EXTCODEHASH => { let address = u256_to_address(&self.stack.pop_back()); let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero); + + ext.al_insert_address(address); self.stack.push(U256::from(hash)); } instructions::CALLDATACOPY => { @@ -1108,6 +1134,7 @@ impl Interpreter { &mut self.stack, code.as_ref().map(|c| &(*c)[..]).unwrap_or(&[]), ); + ext.al_insert_address(address); } instructions::GASPRICE => { self.stack.push(self.params.gas_price.clone()); diff --git a/ethcore/evm/src/lib.rs b/ethcore/evm/src/lib.rs index 486e0d8b0f..144cbf8950 100644 --- a/ethcore/evm/src/lib.rs +++ b/ethcore/evm/src/lib.rs @@ -17,6 +17,7 @@ //! Ethereum virtual machine. extern crate bit_set; +extern crate ethcore_builtin as builtin; extern crate ethereum_types; extern crate heapsize; extern crate keccak_hash as hash; diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index 93fe5bd700..a6d359d5ad 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -1554,6 +1554,113 @@ fn test_sar(factory: super::Factory) { ); } +// from https://gist.github.com/holiman/174548cad102096858583c6fbbb0649a +evm_test! {test_access_list_ext_at_precompiles: test_access_list_ext_at_precompiles_int} +fn test_access_list_ext_at_precompiles(factory: super::Factory) { + // 6001 3f 50 + // 6002 3b 50 + // 6003 31 50 + // 60f1 3f 50 + // 60f2 3b 50 + // 60f3 31 50 + // 60f2 3f 50 + // 60f3 3b 50 + // 60f1 31 50 + // 32 31 50 + // 30 31 50 + // 00 + + let code = hex!( + "60013f5060023b506003315060f13f5060f23b5060f3315060f23f5060f33b5060f1315032315030315000" + ) + .to_vec(); + + let mut params = ActionParams::default(); + params.gas = U256::from(8653); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_yolo3( + Address::from("0x0000000000000000000000000000000000000000"), + Address::from("0x000000000000000000000000636F6E7472616374"), + &[ + Address::from("0x0000000000000000000000000000000000000001"), + Address::from("0x0000000000000000000000000000000000000002"), + Address::from("0x0000000000000000000000000000000000000003"), + ], + ); + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + + assert_eq!(gas_left, U256::from(0)); +} + +evm_test! {test_access_list_extcodecopy_twice: test_access_list_extcodecopy_twice_int} +fn test_access_list_extcodecopy_twice(factory: super::Factory) { + let code = hex!("60006000600060ff3c60006000600060ff3c600060006000303c").to_vec(); + + let mut params = ActionParams::default(); + params.gas = U256::from(2835); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_yolo3( + Address::from("0x0000000000000000000000000000000000000000"), + Address::from("0x000000000000000000000000636F6E7472616374"), + &[], + ); + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + + assert_eq!(gas_left, U256::from(0)); +} + +evm_test! {test_access_list_sload_sstore: test_access_list_sload_sstore_int} +fn test_access_list_sload_sstore(factory: super::Factory) { + // 6001 54 50 sload( 0x1) pop + // 6011 6001 55 sstore(loc: 0x01, val:0x11) 20000 + // 6011 6002 55 sstore(loc: 0x02, val:0x11) 20000 + 2100 + // 6011 6002 55 sstore(loc: 0x02, val:0x11) 100 + // 6002 54 sload(0x2) + // 6001 54 sload(0x1) + let code = hex!("60015450 6011600155 6011600255 6011600255 600254 600154").to_vec(); + + let mut params = ActionParams::default(); + params.gas = U256::from(44529); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_yolo3( + Address::from("0x0000000000000000000000000000000000000000"), + Address::from("0x000000000000000000000000636F6E7472616374"), + &[], + ); + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + + assert_eq!(gas_left, U256::from(0)); +} + +evm_test! {test_access_list_cheap_expensive_cheap: test_access_list_cheap_expensive_cheap_int} +fn test_access_list_cheap_expensive_cheap(factory: super::Factory) { + let code = + hex!("60008080808060046000f15060008080808060ff6000f15060008080808060ff6000fa50").to_vec(); + let mut params = ActionParams::default(); + params.gas = U256::from(2869); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_yolo3( + Address::from("0x0000000000000000000000000000000000000000"), + Address::from("0x000000000000000000000000636F6E7472616374"), + &[Address::from("0x0000000000000000000000000000000000000004")], + ); + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + + assert_eq!(gas_left, U256::from(0)); +} + fn push_two_pop_one_constantinople_test( factory: &super::Factory, opcode: u8, diff --git a/ethcore/res/ethereum/berlin_test.json b/ethcore/res/ethereum/berlin_test.json index fc34586490..6e161c8b21 100644 --- a/ethcore/res/ethereum/berlin_test.json +++ b/ethcore/res/ethereum/berlin_test.json @@ -1,5 +1,5 @@ { - "name": "Istanbul (test)", + "name": "Berlin (test)", "engine": { "Ethash": { "params": { @@ -44,7 +44,6 @@ "eip1884Transition": "0x0", "eip2028Transition": "0x0", "eip2315Transition": "0x0" - }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/yolo3_test.json b/ethcore/res/ethereum/yolo3_test.json new file mode 100644 index 0000000000..d8767f6a34 --- /dev/null +++ b/ethcore/res/ethereum/yolo3_test.json @@ -0,0 +1,123 @@ +{ + "name": "Yolo (test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x1BC16D674EC80000", + "homesteadTransition": "0x0", + "eip100bTransition": "0x0", + "difficultyBombDelays": { + "0": 5000000 + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x0", + "eip1344Transition": "0x0", + "eip1706Transition": "0x0", + "eip1884Transition": "0x0", + "eip2028Transition": "0x0", + "eip2315Transition": "0x0", + "eip2929Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "pricing": { + "0": { + "price": { "alt_bn128_const_operations": { "price": 500 }} + }, + "0": { + "info": "EIP 1108 transition", + "price": { "alt_bn128_const_operations": { "price": 150 }} + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "pricing": { + "0": { + "price": { "alt_bn128_const_operations": { "price": 40000 }} + }, + "0": { + "info": "EIP 1108 transition", + "price": { "alt_bn128_const_operations": { "price": 6000 }} + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "pricing": { + "0": { + "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + }, + "0": { + "info": "EIP 1108 transition", + "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + } + } + } + }, + "0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0x00", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + } + } +} diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 94e21bcd97..8a9327f752 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -108,6 +108,7 @@ impl<'a> EvmTestClient<'a> { Some(ethereum::new_byzantium_to_constantinoplefixat5_test()) } ForkSpec::Berlin => Some(ethereum::new_berlin_test()), + ForkSpec::Yolo3 => Some(ethereum::new_yolo3_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 7a38fecd9f..736d0d5ae5 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -252,6 +252,11 @@ pub fn new_berlin_test() -> Spec { load(None, include_bytes!("../../res/ethereum/berlin_test.json")) } +/// Create a new YOLO spec +pub fn new_yolo3_test() -> Spec { + load(None, include_bytes!("../../res/ethereum/yolo3_test.json")) +} + /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index ec0b7a8960..85394fa3d2 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -16,7 +16,6 @@ //! Transaction Execution environment. use bytes::{Bytes, BytesRef}; -use crossbeam_utils::thread; use ethereum_types::{Address, H256, U256, U512}; use evm::{CallType, FinalizationResult, Finalize}; use executed::ExecutionError; @@ -31,26 +30,10 @@ use trace::{self, Tracer, VMTracer}; use transaction_ext::Transaction; use types::transaction::{Action, SignedTransaction}; use vm::{ - self, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo, ResumeCall, - ResumeCreate, ReturnData, Schedule, TrapError, + self, AccessList, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo, + ResumeCall, ResumeCreate, ReturnData, Schedule, TrapError, }; -#[cfg(debug_assertions)] -/// Roughly estimate what stack size each level of evm depth will use. (Debug build) -const STACK_SIZE_PER_DEPTH: usize = 128 * 1024; - -#[cfg(not(debug_assertions))] -/// Roughly estimate what stack size each level of evm depth will use. -const STACK_SIZE_PER_DEPTH: usize = 24 * 1024; - -#[cfg(debug_assertions)] -/// Entry stack overhead prior to execution. (Debug build) -const STACK_SIZE_ENTRY_OVERHEAD: usize = 100 * 1024; - -#[cfg(not(debug_assertions))] -/// Entry stack overhead prior to execution. -const STACK_SIZE_ENTRY_OVERHEAD: usize = 20 * 1024; - #[cfg(any(test, feature = "test-helpers"))] /// Precompile that can never be prunned from state trie (0x3, only in tests) const UNPRUNABLE_PRECOMPILE_ADDRESS: Option
= Some(ethereum_types::H160([ @@ -252,6 +235,18 @@ pub struct CallCreateExecutive<'a> { } impl<'a> CallCreateExecutive<'a> { + /// Create new state with access list. + pub fn new_substate(params: &ActionParams, schedule: &'a Schedule) -> Substate { + if schedule.eip2929 { + let mut substate = Substate::from_access_list(¶ms.access_list); + substate.access_list.insert_address(params.address); + substate.access_list.insert_address(params.sender); + substate + } else { + Substate::default() + } + } + /// Create a new call executive using raw data. pub fn new_call_raw( params: ActionParams, @@ -287,7 +282,8 @@ impl<'a> CallCreateExecutive<'a> { CallCreateExecutiveKind::CallBuiltin(params) } else { if params.code.is_some() { - CallCreateExecutiveKind::ExecCall(params, Substate::new()) + let substate = Self::new_substate(¶ms, schedule); + CallCreateExecutiveKind::ExecCall(params, substate) } else { CallCreateExecutiveKind::Transfer(params) } @@ -327,7 +323,8 @@ impl<'a> CallCreateExecutive<'a> { let gas = params.gas; - let kind = CallCreateExecutiveKind::ExecCreate(params, Substate::new()); + let substate = Self::new_substate(¶ms, schedule); + let kind = CallCreateExecutiveKind::ExecCreate(params, substate); Self { info, @@ -457,6 +454,7 @@ impl<'a> CallCreateExecutive<'a> { } } state.revert_to_checkpoint(); + un_substate.access_list.rollback(); } Ok(_) | Err(vm::Error::Internal(_)) => { state.discard_checkpoint(); @@ -1188,7 +1186,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { }); } - let mut substate = Substate::new(); + let mut access_list = AccessList::new(schedule.eip2929); + if schedule.eip2929 { + for (address, _) in self.machine.builtins() { + access_list.insert_address(*address); + } + } + + let mut substate = Substate::from_access_list(&access_list); // NOTE: there can be no invalid transactions from this point. if !schedule.keep_unsigned_nonce || !t.is_unsigned() { @@ -1221,6 +1226,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { data: None, call_type: CallType::None, params_type: vm::ParamsType::Embedded, + access_list: access_list, }; let res = self.create(params, &mut substate, &mut tracer, &mut vm_tracer); let out = match &res { @@ -1243,6 +1249,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { data: Some(t.data.clone()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, + access_list: access_list, }; let res = self.call(params, &mut substate, &mut tracer, &mut vm_tracer); let out = match &res { @@ -1325,48 +1332,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { result } - /// Calls contract function with given contract params, if the stack depth is above a threshold, create a new thread - /// to execute it. - pub fn call_with_crossbeam( - &mut self, - params: ActionParams, - substate: &mut Substate, - stack_depth: usize, - tracer: &mut T, - vm_tracer: &mut V, - ) -> vm::Result - where - T: Tracer, - V: VMTracer, - { - let local_stack_size = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get()); - let depth_threshold = - local_stack_size.saturating_sub(STACK_SIZE_ENTRY_OVERHEAD) / STACK_SIZE_PER_DEPTH; - - if stack_depth != depth_threshold { - self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) - } else { - thread::scope(|scope| { - let stack_size = cmp::max( - self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, - local_stack_size, - ); - scope - .builder() - .stack_size(stack_size) - .spawn(|_| { - self.call_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) - }) - .expect( - "Sub-thread creation cannot fail; the host might run out of resources; qed", - ) - .join() - }) - .expect("Sub-thread never panics; qed") - .expect("Sub-thread never panics; qed") - } - } - /// Calls contract function with given contract params. pub fn call( &mut self, @@ -1437,54 +1402,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { result } - /// Creates contract with given contract params, if the stack depth is above a threshold, create a new thread to - /// execute it. - pub fn create_with_crossbeam( - &mut self, - params: ActionParams, - substate: &mut Substate, - stack_depth: usize, - tracer: &mut T, - vm_tracer: &mut V, - ) -> vm::Result - where - T: Tracer, - V: VMTracer, - { - let local_stack_size = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get()); - let depth_threshold = - local_stack_size.saturating_sub(STACK_SIZE_ENTRY_OVERHEAD) / STACK_SIZE_PER_DEPTH; - - if stack_depth != depth_threshold { - self.create_with_stack_depth(params, substate, stack_depth, tracer, vm_tracer) - } else { - thread::scope(|scope| { - let stack_size = cmp::max( - self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, - local_stack_size, - ); - scope - .builder() - .stack_size(stack_size) - .spawn(|_| { - self.create_with_stack_depth( - params, - substate, - stack_depth, - tracer, - vm_tracer, - ) - }) - .expect( - "Sub-thread creation cannot fail; the host might run out of resources; qed", - ) - .join() - }) - .expect("Sub-thread never panics; qed") - .expect("Sub-thread never panics; qed") - } - } - /// Creates contract with given contract params. pub fn create( &mut self, diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 46e77c83bf..d1910dd273 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -24,8 +24,8 @@ use std::{cmp, sync::Arc}; use trace::{Tracer, VMTracer}; use types::transaction::UNSIGNED_SENDER; use vm::{ - self, ActionParams, ActionValue, CallType, ContractCreateResult, CreateContractAddress, - EnvInfo, Ext, MessageCallResult, ReturnData, Schedule, TrapKind, + self, AccessList, ActionParams, ActionValue, CallType, ContractCreateResult, + CreateContractAddress, EnvInfo, Ext, MessageCallResult, ReturnData, Schedule, TrapKind, }; /// Policy for handling output data on `RETURN` opcode. @@ -200,10 +200,11 @@ where data: Some(H256::from(number).to_vec()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, + access_list: AccessList::default(), }; let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule); - let r = ex.call_with_crossbeam( + let r = ex.call_with_stack_depth( params, self.substate, self.stack_depth + 1, @@ -288,6 +289,7 @@ where data: None, call_type: CallType::None, params_type: vm::ParamsType::Embedded, + access_list: self.substate.access_list.clone(), }; if !self.static_flag { @@ -312,7 +314,7 @@ where self.depth, self.static_flag, ); - let out = ex.create_with_crossbeam( + let out = ex.create_with_stack_depth( params, self.substate, self.stack_depth + 1, @@ -322,6 +324,15 @@ where Ok(into_contract_create_result(out, &address, self.substate)) } + fn calc_address(&self, code: &[u8], address_scheme: CreateContractAddress) -> Option
{ + match self.state.nonce(&self.origin_info.address) { + Ok(nonce) => { + Some(contract_address(address_scheme, &self.origin_info.address, &nonce, &code).0) + } + Err(_) => None, + } + } + fn call( &mut self, gas: &U256, @@ -358,6 +369,7 @@ where data: Some(data.to_vec()), call_type: call_type, params_type: vm::ParamsType::Separate, + access_list: self.substate.access_list.clone(), }; if let Some(value) = value { @@ -376,7 +388,7 @@ where self.depth, self.static_flag, ); - let out = ex.call_with_crossbeam( + let out = ex.call_with_stack_depth( params, self.substate, self.stack_depth + 1, @@ -518,6 +530,26 @@ where fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) { self.vm_tracer.trace_executed(gas_used, stack_push, mem) } + + fn al_is_enabled(&self) -> bool { + self.substate.access_list.is_enabled() + } + + fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool { + self.substate.access_list.contains_storage_key(address, key) + } + + fn al_insert_storage_key(&mut self, address: Address, key: H256) { + self.substate.access_list.insert_storage_key(address, key) + } + + fn al_contains_address(&self, address: &Address) -> bool { + self.substate.access_list.contains_address(address) + } + + fn al_insert_address(&mut self, address: Address) { + self.substate.access_list.insert_address(address) + } } #[cfg(test)] diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 11288ae2dc..515b730456 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -167,6 +167,10 @@ where Ok(ContractCreateResult::Created(contract_address, *gas)) } + fn calc_address(&self, code: &[u8], address: CreateContractAddress) -> Option
{ + Some(contract_address(address, &self.sender, &self.nonce, &code).0) + } + fn call( &mut self, gas: &U256, @@ -238,6 +242,26 @@ where fn sub_sstore_refund(&mut self, value: usize) { self.ext.sub_sstore_refund(value) } + + fn al_is_enabled(&self) -> bool { + self.ext.al_is_enabled() + } + + fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool { + self.ext.al_contains_storage_key(address, key) + } + + fn al_insert_storage_key(&mut self, address: Address, key: H256) { + self.ext.al_insert_storage_key(address, key) + } + + fn al_contains_address(&self, address: &Address) -> bool { + self.ext.al_contains_address(address) + } + + fn al_insert_address(&mut self, address: Address) { + self.ext.al_insert_address(address) + } } /// run an json executive test diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 000088ee72..2b1c89ebc5 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -68,7 +68,6 @@ pub fn json_chain_test( let pre: PodState = test.pre_state.into(); for (spec_name, states) in test.post_states { - let total = states.len(); let spec = match EvmTestClient::spec_from_json(&spec_name) { Some(spec) => spec, None => { @@ -81,11 +80,10 @@ pub fn json_chain_test( for (i, state) in states.into_iter().enumerate() { let info = format!( - " - state: {} | {:?} ({}/{}) ...", - name, + "TestState/{}/{:?}/{}/trie", + path.to_string_lossy(), spec_name, - i + 1, - total + i ); if skip_test(&state_test, &name, &spec.name, i + 1) { println!("{}: SKIPPED", info); @@ -112,7 +110,7 @@ pub fn json_chain_test( } Ok(Ok(TransactSuccess { state_root, .. })) if state_root != post_root => { println!( - "{} !!! State mismatch (got: {}, expect: {}", + "{}: post state root mismatch: got {:?}, want {:?}", info, state_root, post_root ); flushln!("{} fail", info); @@ -124,7 +122,7 @@ pub fn json_chain_test( .. })) if state_root != post_root => { println!( - "{} !!! State mismatch (got: {}, expect: {}", + "{}: post state root mismatch: got {:?}, want {:?}", info, state_root, post_root ); println!("{} !!! Execution error: {:?}", info, error); diff --git a/ethcore/src/machine/impls.rs b/ethcore/src/machine/impls.rs index f848a320d4..8b98cf08d6 100644 --- a/ethcore/src/machine/impls.rs +++ b/ethcore/src/machine/impls.rs @@ -32,7 +32,8 @@ use types::{ BlockNumber, }; use vm::{ - ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo, ParamsType, Schedule, + AccessList, ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo, ParamsType, + Schedule, }; use block::ExecutedBlock; @@ -201,6 +202,7 @@ impl EthereumMachine { data, call_type: call_type.unwrap_or(CallType::Call), params_type: ParamsType::Separate, + access_list: AccessList::default(), }; let schedule = self.schedule(env_info.number); let mut ex = Executive::new(&mut state, &env_info, self, &schedule); diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index c38e19adfa..85a7589e4c 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -32,7 +32,7 @@ use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; use rustc_hex::FromHex; use types::{header::Header, BlockNumber}; -use vm::{ActionParams, ActionValue, CallType, EnvInfo, ParamsType}; +use vm::{AccessList, ActionParams, ActionValue, CallType, EnvInfo, ParamsType}; use builtin::Builtin; use engines::{ @@ -135,6 +135,8 @@ pub struct CommonParams { pub eip2028_transition: BlockNumber, /// Number of first block where EIP-2315 rules begin. pub eip2315_transition: BlockNumber, + /// Number of first block where EIP-2929 rules begin. + pub eip2929_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -209,6 +211,7 @@ impl CommonParams { || block_number >= self.eip1283_reenable_transition; schedule.eip1706 = block_number >= self.eip1706_transition; schedule.have_subs = block_number >= self.eip2315_transition; + schedule.eip2929 = block_number >= self.eip2929_transition; if block_number >= self.eip1884_transition { schedule.have_selfbalance = true; @@ -222,6 +225,24 @@ impl CommonParams { if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } + if block_number >= self.eip2929_transition { + schedule.eip2929 = true; + schedule.eip1283 = true; + + schedule.call_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.balance_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodecopy_base_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodehash_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodesize_gas = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + + schedule.cold_sload_cost = ::vm::schedule::EIP2929_COLD_SLOAD_COST; + schedule.cold_account_access_cost = ::vm::schedule::EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.warm_storage_read_cost = ::vm::schedule::EIP2929_WARM_STORAGE_READ_COST; + + schedule.sload_gas = ::vm::schedule::EIP2929_WARM_STORAGE_READ_COST; + schedule.sstore_reset_gas = ::vm::schedule::EIP2929_SSTORE_RESET_GAS; + } + if block_number >= self.dust_protection_transition { schedule.kill_dust = match self.remove_dust_contracts { true => ::vm::CleanDustMode::WithCodeAndStorage, @@ -346,6 +367,9 @@ impl From for CommonParams { eip2315_transition: p .eip2315_transition .map_or_else(BlockNumber::max_value, Into::into), + eip2929_transition: p + .eip2929_transition + .map_or_else(BlockNumber::max_value, Into::into), dust_protection_transition: p .dust_protection_transition .map_or_else(BlockNumber::max_value, Into::into), @@ -757,6 +781,7 @@ impl Spec { data: None, call_type: CallType::None, params_type: ParamsType::Embedded, + access_list: AccessList::default(), }; let mut substate = Substate::new(); diff --git a/ethcore/src/state/substate.rs b/ethcore/src/state/substate.rs index ec23e85e6c..e2fe024839 100644 --- a/ethcore/src/state/substate.rs +++ b/ethcore/src/state/substate.rs @@ -20,6 +20,7 @@ use ethereum_types::Address; use evm::{CleanDustMode, Schedule}; use std::collections::HashSet; use types::log_entry::LogEntry; +use vm::access_list::AccessList; /// State changes which should be applied in finalize, /// after transaction is fully executed. @@ -39,6 +40,9 @@ pub struct Substate { /// Created contracts. pub contracts_created: Vec
, + + /// List of accesses addresses and slots + pub access_list: AccessList, } impl Substate { @@ -46,6 +50,17 @@ impl Substate { pub fn new() -> Self { Substate::default() } + /// Creates a new substate from an access list + pub fn from_access_list(access_list: &AccessList) -> Self { + Self { + suicides: HashSet::default(), + touched: HashSet::default(), + logs: Vec::default(), + sstore_clears_refund: 0, + contracts_created: Vec::default(), + access_list: access_list.clone(), + } + } /// Merge secondary substate `s` into self, accruing each element correspondingly. pub fn accrue(&mut self, s: Substate) { diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 555207d0a3..c3ba39d784 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -24,7 +24,7 @@ use std::sync::Arc; use test_helpers::get_temp_state_with_factory; use trace::{NoopTracer, NoopVMTracer}; use types::transaction::SYSTEM_ADDRESS; -use vm::{ActionParams, ActionValue, CallType, EnvInfo, ParamsType}; +use vm::{AccessList, ActionParams, ActionValue, CallType, EnvInfo, ParamsType}; use rustc_hex::FromHex; @@ -62,6 +62,7 @@ fn test_blockhash_eip210(factory: Factory) { data: Some(H256::from(i - 1).to_vec()), call_type: CallType::Call, params_type: ParamsType::Separate, + access_list: AccessList::default(), }; let schedule = machine.schedule(env_info.number); let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule); @@ -85,6 +86,7 @@ fn test_blockhash_eip210(factory: Factory) { data: None, call_type: CallType::Call, params_type: ParamsType::Separate, + access_list: AccessList::default(), }; let schedule = machine.schedule(env_info.number); let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule); diff --git a/ethcore/vm/src/access_list.rs b/ethcore/vm/src/access_list.rs new file mode 100644 index 0000000000..a4a4343687 --- /dev/null +++ b/ethcore/vm/src/access_list.rs @@ -0,0 +1,260 @@ +use ethereum_types::{Address, H256}; +use std::{ + borrow::Borrow, + collections::HashMap, + hash::{Hash, Hasher}, +}; + +use std::{cell::RefCell, rc::Rc}; + +// Implementation of a hasheable borrowed pair +trait KeyPair { + fn a(&self) -> &A; + fn b(&self) -> &B; +} +impl<'a, A, B> Borrow + 'a> for (A, B) +where + A: Eq + Hash + 'a, + B: Eq + Hash + 'a, +{ + fn borrow(&self) -> &(dyn KeyPair + 'a) { + self + } +} +impl Hash for (dyn KeyPair + '_) { + fn hash(&self, state: &mut H) { + self.a().hash(state); + self.b().hash(state); + } +} +impl PartialEq for (dyn KeyPair + '_) { + fn eq(&self, other: &Self) -> bool { + self.a() == other.a() && self.b() == other.b() + } +} +impl Eq for (dyn KeyPair + '_) {} +impl KeyPair for (A, B) { + fn a(&self) -> &A { + &self.0 + } + fn b(&self) -> &B { + &self.1 + } +} +impl KeyPair for (&A, &B) { + fn a(&self) -> &A { + self.0 + } + fn b(&self) -> &B { + self.1 + } +} + +#[derive(Debug)] +struct Journal { + enabled: bool, + last_id: usize, + addresses: HashMap, + storage_keys: HashMap<(Address, H256), usize>, +} +#[derive(Debug)] +pub struct AccessList { + id: usize, + journal: Rc>, +} + +impl Clone for AccessList { + fn clone(&self) -> Self { + let mut journal = self.journal.as_ref().borrow_mut(); + let id = journal.last_id + 1; + journal.last_id = id; + Self { + id: id, + journal: self.journal.clone(), + } + } +} + +impl Default for AccessList { + fn default() -> Self { + AccessList::new(false) + } +} + +impl std::fmt::Display for AccessList { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let journal = self.journal.as_ref().borrow(); + for (addr, id) in journal.addresses.iter() { + write!(f, "| ADDR {} -> {}\n", addr, id)?; + } + for ((addr, slot), id) in journal.storage_keys.iter() { + write!(f, "| SLOT {}:{} -> {}\n", addr, slot, id)?; + } + Ok(()) + } +} + +impl AccessList { + /// Returns if the list is enabled + pub fn new(enabled: bool) -> Self { + let journal = Journal { + enabled, + last_id: 0, + addresses: HashMap::new(), + storage_keys: HashMap::new(), + }; + Self { + id: 0, + journal: Rc::new(RefCell::new(journal)), + } + } + + /// Returns if the list is enabled + pub fn is_enabled(&self) -> bool { + let journal = self.journal.as_ref().borrow(); + journal.enabled + } + + /// Enable the access list control + pub fn enable(&mut self) { + let mut journal = self.journal.as_ref().borrow_mut(); + journal.enabled = true; + } + + /// Checks if contains an storage key + pub fn contains_storage_key(&self, address: &Address, key: &H256) -> bool { + let journal = self.journal.as_ref().borrow(); + if journal.enabled { + journal + .storage_keys + .contains_key(&(address, key) as &dyn KeyPair) + } else { + false + } + } + + /// Inserts a storage key + pub fn insert_storage_key(&mut self, address: Address, key: H256) { + let mut journal = self.journal.as_ref().borrow_mut(); + if journal.enabled + && !journal + .storage_keys + .contains_key(&(address, key) as &dyn KeyPair) + { + journal.storage_keys.insert((address, key), self.id); + } + } + + /// Checks if contains an address + pub fn contains_address(&self, address: &Address) -> bool { + let journal = self.journal.as_ref().borrow(); + if journal.enabled { + journal.addresses.contains_key(&address) + } else { + false + } + } + /// Inserts an address + pub fn insert_address(&mut self, address: Address) { + let mut journal = self.journal.as_ref().borrow_mut(); + if journal.enabled && !journal.addresses.contains_key(&address) { + journal.addresses.insert(address, self.id); + } + } + /// Removes all changes in journal + pub fn rollback(&self) { + let mut journal = self.journal.as_ref().borrow_mut(); + // `id < self.id` instead `id != self.if` is to take care about recursive calls + journal.addresses.retain(|_, id| *id < self.id); + journal.storage_keys.retain(|_, id| *id < self.id); + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn default_accesslist_is_disabled() { + let access_list = AccessList::default(); + assert_eq!(false, access_list.is_enabled()); + } + + #[test] + fn default_disabled_accesslist_does_nothing() { + let mut access_list = AccessList::default(); + access_list.insert_address(Address::from(1)); + access_list.insert_storage_key(Address::from(2), H256::from(3)); + assert_eq!(false, access_list.contains_address(&Address::from(1))); + assert_eq!( + false, + access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + ); + } + + #[test] + fn default_enabled_accesslist_registers() { + let mut access_list = AccessList::default(); + access_list.enable(); + assert_eq!(true, access_list.is_enabled()); + access_list.insert_address(Address::from(1)); + access_list.insert_storage_key(Address::from(2), H256::from(3)); + assert_eq!(true, access_list.contains_address(&Address::from(1))); + assert_eq!( + true, + access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + ); + } + + #[test] + fn cloned_accesslist_registers_in_parent() { + let mut access_list = AccessList::default(); + access_list.enable(); + assert_eq!(true, access_list.is_enabled()); + access_list.insert_address(Address::from(1)); + access_list.insert_storage_key(Address::from(2), H256::from(3)); + + let mut access_list_call = access_list.clone(); + assert_eq!(true, access_list_call.contains_address(&Address::from(1))); + assert_eq!( + true, + access_list_call.contains_storage_key(&Address::from(2), &H256::from(3)) + ); + access_list.insert_address(Address::from(4)); + assert_eq!(true, access_list_call.contains_address(&Address::from(4))); + + assert_eq!(true, access_list.contains_address(&Address::from(4))); + } + #[test] + fn cloned_accesslist_rollbacks_in_parent() { + let mut access_list = AccessList::default(); + access_list.enable(); + assert_eq!(true, access_list.is_enabled()); + access_list.insert_address(Address::from(1)); + access_list.insert_storage_key(Address::from(2), H256::from(3)); + + let mut access_list_call = access_list.clone(); + access_list_call.insert_address(Address::from(1)); + access_list_call.insert_storage_key(Address::from(2), H256::from(3)); + access_list_call.insert_address(Address::from(4)); + + let mut access_list_call_call = access_list.clone(); + access_list_call_call.insert_address(Address::from(1)); + access_list_call_call.insert_storage_key(Address::from(2), H256::from(3)); + access_list_call_call.insert_address(Address::from(5)); + access_list_call_call.insert_storage_key(Address::from(6), H256::from(7)); + + access_list_call.rollback(); + + assert_eq!(true, access_list.contains_address(&Address::from(1))); + assert_eq!(false, access_list.contains_address(&Address::from(4))); + assert_eq!(false, access_list.contains_address(&Address::from(5))); + assert_eq!( + true, + access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + ); + assert_eq!( + false, + access_list.contains_storage_key(&Address::from(6), &H256::from(7)) + ); + } +} diff --git a/ethcore/vm/src/action_params.rs b/ethcore/vm/src/action_params.rs index b46dc919b1..b9aaf38bc4 100644 --- a/ethcore/vm/src/action_params.rs +++ b/ethcore/vm/src/action_params.rs @@ -15,13 +15,13 @@ // along with OpenEthereum. If not, see . //! Evm input params. +use super::access_list::AccessList; use bytes::Bytes; +use call_type::CallType; use ethereum_types::{Address, H256, U256}; use ethjson; use hash::{keccak, KECCAK_EMPTY}; -use call_type::CallType; - use std::sync::Arc; /// Transaction value @@ -90,6 +90,8 @@ pub struct ActionParams { pub call_type: CallType, /// Param types encoding pub params_type: ParamsType, + /// Current access list + pub access_list: AccessList, } impl Default for ActionParams { @@ -108,6 +110,7 @@ impl Default for ActionParams { data: None, call_type: CallType::None, params_type: ParamsType::Separate, + access_list: AccessList::default(), } } } @@ -131,6 +134,7 @@ impl From for ActionParams { false => CallType::Call, }, // TODO @debris is this correct? params_type: ParamsType::Separate, + access_list: AccessList::default(), } } } diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 752b60a2bf..fccb42e78c 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -101,6 +101,9 @@ pub trait Ext { trap: bool, ) -> ::std::result::Result; + /// Returns the address that will be created in the create call + fn calc_address(&self, code: &[u8], address: CreateContractAddress) -> Option
; + /// Message call. /// /// Returns Err, if we run out of gas. @@ -184,4 +187,19 @@ pub trait Ext { /// Check if running in static context. fn is_static(&self) -> bool; + + /// Returns if the list is enabled + fn al_is_enabled(&self) -> bool; + + /// Checks if contains an storage key + fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool; + + /// Inserts an storage key into the list + fn al_insert_storage_key(&mut self, address: Address, key: H256); + + /// Checks if contains an address + fn al_contains_address(&self, address: &Address) -> bool; + + /// Inserts an address into the list + fn al_insert_address(&mut self, address: Address); } diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index 4f9b747efd..f662921c7f 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -23,16 +23,18 @@ extern crate parity_bytes as bytes; extern crate patricia_trie_ethereum as ethtrie; extern crate rlp; +pub mod access_list; mod action_params; mod call_type; mod env_info; mod error; mod ext; mod return_data; -mod schedule; +pub mod schedule; pub mod tests; +pub use access_list::AccessList; pub use action_params::{ActionParams, ActionValue, ParamsType}; pub use call_type::CallType; pub use env_info::{EnvInfo, LastHashes}; @@ -42,7 +44,7 @@ pub use return_data::{GasLeft, ReturnData}; pub use schedule::{CleanDustMode, Schedule, WasmCosts}; /// Virtual Machine interface -pub trait Exec: Send { +pub trait Exec { /// This function should be used to execute transaction. /// It returns either an error, a known amount of gas left, or parameters to be used /// to compute the final gas left. @@ -50,13 +52,13 @@ pub trait Exec: Send { } /// Resume call interface -pub trait ResumeCall: Send { +pub trait ResumeCall { /// Resume an execution for call, returns back the Vm interface. fn resume_call(self: Box, result: MessageCallResult) -> Box; } /// Resume create interface -pub trait ResumeCreate: Send { +pub trait ResumeCreate { /// Resume an execution from create, returns back the Vm interface. fn resume_create(self: Box, result: ContractCreateResult) -> Box; } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 50a5d5e6e9..b6b27bd210 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -16,6 +16,15 @@ //! Cost schedule and other parameterisations for the EVM. +// Gas per non accessed address when sload +pub const EIP2929_COLD_SLOAD_COST: usize = 2100; +// Gas per non accessed address accessing account from other opcodes defined in EIP2929 +pub const EIP2929_COLD_ACCOUNT_ACCESS_COST: usize = 2600; +// Gas per already accessed address +pub const EIP2929_WARM_STORAGE_READ_COST: usize = 100; +// Gas per sstore reset +pub const EIP2929_SSTORE_RESET_GAS: usize = 5000 - EIP2929_COLD_SLOAD_COST; + /// Definition of the cost schedule and other parameterisations for the EVM. #[derive(Debug)] pub struct Schedule { @@ -63,6 +72,12 @@ pub struct Schedule { pub create_gas: usize, /// Gas price for `*CALL*` opcodes pub call_gas: usize, + /// EIP-2929 COLD_SLOAD_COST + pub cold_sload_cost: usize, + /// EIP-2929 COLD_ACCOUNT_ACCESS_COST + pub cold_account_access_cost: usize, + /// EIP-2929 WARM_STORAGE_READ_COST + pub warm_storage_read_cost: usize, /// Stipend for transfer for `CALL|CALLCODE` opcode when `value>0` pub call_stipend: usize, /// Additional gas required for value transfer (`CALL|CALLCODE`) @@ -132,6 +147,8 @@ pub struct Schedule { pub keep_unsigned_nonce: bool, /// Wasm extra schedule settings, if wasm activated pub wasm: Option, + /// Enable EIP-2929 rules + pub eip2929: bool, } /// Wasm cost table @@ -245,6 +262,9 @@ impl Schedule { log_topic_gas: 375, create_gas: 32000, call_gas: 700, + cold_account_access_cost: 0, + cold_sload_cost: 0, + warm_storage_read_cost: 0, call_stipend: 2300, call_value_transfer_gas: 9000, call_new_account_gas: 25000, @@ -274,6 +294,7 @@ impl Schedule { eip1706: false, keep_unsigned_nonce: false, wasm: None, + eip2929: false, } } @@ -290,7 +311,8 @@ impl Schedule { /// Schedule for the Constantinople fork of the Ethereum main net. pub fn new_constantinople() -> Schedule { let mut schedule = Self::new_byzantium(); - schedule.have_bitwise_shifting = true; + schedule.have_bitwise_shifting = true; // EIP 145 + schedule.have_extcodehash = true; // EIP 1052 schedule } @@ -310,6 +332,30 @@ impl Schedule { pub fn new_berlin() -> Schedule { let mut schedule = Self::new_istanbul(); schedule.have_subs = true; // EIP 2315 + + schedule + } + + /// Schedule for the Yolov3 testnet of the Ethereum main net. + pub fn new_yolo3() -> Schedule { + let mut schedule = Self::new_istanbul(); + schedule.have_subs = true; // EIP 2315 + + schedule.eip1283 = true; + schedule.eip2929 = true; + + schedule.cold_sload_cost = EIP2929_COLD_SLOAD_COST; + schedule.cold_account_access_cost = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.warm_storage_read_cost = EIP2929_WARM_STORAGE_READ_COST; + + schedule.sload_gas = EIP2929_WARM_STORAGE_READ_COST; + schedule.call_gas = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.balance_gas = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodecopy_base_gas = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodehash_gas = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.extcodesize_gas = EIP2929_COLD_ACCOUNT_ACCESS_COST; + schedule.sstore_reset_gas = EIP2929_SSTORE_RESET_GAS; + schedule } @@ -342,6 +388,9 @@ impl Schedule { log_topic_gas: 375, create_gas: 32000, call_gas: 40, + cold_account_access_cost: 0, + cold_sload_cost: 0, + warm_storage_read_cost: 0, call_stipend: 2300, call_value_transfer_gas: 9000, call_new_account_gas: 25000, @@ -371,6 +420,7 @@ impl Schedule { eip1706: false, keep_unsigned_nonce: false, wasm: None, + eip2929: false, } } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index a5ada1dd2c..17a3f09d7b 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -19,6 +19,7 @@ use std::{ sync::Arc, }; +use crate::access_list::AccessList; use bytes::Bytes; use error::TrapKind; use ethereum_types::{Address, H256, U256}; @@ -75,6 +76,7 @@ pub struct FakeExt { pub balances: HashMap, pub tracing: bool, pub is_static: bool, + pub access_list: AccessList, chain_id: u64, } @@ -122,6 +124,19 @@ impl FakeExt { ext } + /// New fake externalities with YoloV2 schedule rules + pub fn new_yolo3(from: Address, to: Address, builtins: &[Address]) -> Self { + let mut ext = FakeExt::default(); + ext.schedule = Schedule::new_yolo3(); + ext.access_list.enable(); + ext.access_list.insert_address(from); + ext.access_list.insert_address(to); + for builtin in builtins { + ext.access_list.insert_address(*builtin); + } + ext + } + /// Alter fake externalities to allow wasm pub fn with_wasm(mut self) -> Self { self.schedule.wasm = Some(Default::default()); @@ -162,7 +177,7 @@ impl Ext for FakeExt { } fn balance(&self, address: &Address) -> Result { - Ok(self.balances[address]) + Ok(self.balances.get(address).cloned().unwrap_or(U256::zero())) } fn blockhash(&mut self, number: &U256) -> H256 { @@ -191,6 +206,10 @@ impl Ext for FakeExt { Ok(ContractCreateResult::Failed) } + fn calc_address(&self, _code: &[u8], _address: CreateContractAddress) -> Option
{ + None + } + fn call( &mut self, gas: &U256, @@ -276,4 +295,24 @@ impl Ext for FakeExt { fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _gas: U256) -> bool { self.tracing } + + fn al_is_enabled(&self) -> bool { + self.access_list.is_enabled() + } + + fn al_contains_storage_key(&self, address: &Address, key: &H256) -> bool { + self.access_list.contains_storage_key(address, key) + } + + fn al_insert_storage_key(&mut self, address: Address, key: H256) { + self.access_list.insert_storage_key(address, key) + } + + fn al_contains_address(&self, address: &Address) -> bool { + self.access_list.contains_address(address) + } + + fn al_insert_address(&mut self, address: Address) { + self.access_list.insert_address(address) + } } diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 7853788c71..46585818e9 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -84,7 +84,7 @@ State test options: --chain CHAIN Run only from specific chain name (i.e. one of EIP150, EIP158, Frontier, Homestead, Byzantium, Constantinople, ConstantinopleFix, Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5, - HomesteadToDaoAt5, HomesteadToEIP150At5). + HomesteadToDaoAt5, HomesteadToEIP150At5, Berlin, Yolo3). --only NAME Runs only a single test matching the name. General options: @@ -197,7 +197,6 @@ fn run_state_test(args: Args) { { continue; } - for (idx, state) in states.into_iter().enumerate() { let post_root = state.hash.into(); let transaction = multitransaction.select(&state.indexes).into(); @@ -287,8 +286,16 @@ fn run_call(args: Args, informant: T) { if code.is_none() && to == Address::default() { die("Either --code or --to is required."); } - let mut params = ActionParams::default(); + if spec.engine.params().eip2929_transition == 0 { + params.access_list.enable(); + params.access_list.insert_address(from); + params.access_list.insert_address(to); + for (builtin, _) in spec.engine.builtins() { + params.access_list.insert_address(*builtin); + } + } + params.call_type = if code.is_none() { CallType::Call } else { @@ -378,9 +385,16 @@ impl Args { pub fn spec(&self) -> Result { Ok(match self.flag_chain { - Some(ref filename) => { - let file = fs::File::open(filename).map_err(|e| format!("{}", e))?; - spec::Spec::load(&::std::env::temp_dir(), file)? + Some(ref spec_name) => { + let fork_spec: Result = + serde_json::from_str(&format!("{:?}", spec_name)); + if let Ok(fork_spec) = fork_spec { + ethcore::client::EvmTestClient::spec_from_json(&fork_spec) + .expect("this forkspec is not defined") + } else { + let file = fs::File::open(spec_name).map_err(|e| format!("{}", e))?; + spec::Spec::load(&::std::env::temp_dir(), file)? + } } None => ethcore::ethereum::new_foundation(&::std::env::temp_dir()), }) diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 150e9ce1a8..6366ebcb7f 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -106,6 +106,8 @@ pub struct Params { /// See `CommonParams` docs. pub eip2315_transition: Option, /// See `CommonParams` docs. + pub eip2929_transition: Option, + /// See `CommonParams` docs. pub dust_protection_transition: Option, /// See `CommonParams` docs. pub nonce_cap_increment: Option, diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index e5e23be778..250562d86d 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -38,6 +38,7 @@ pub enum ForkSpec { ByzantiumToConstantinopleAt5, ByzantiumToConstantinopleFixAt5, Berlin, + Yolo3, } /// Spec deserialization. diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index f940351e0b..c3dd68198f 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -27,7 +27,6 @@ use parking_lot::Mutex; use types::transaction::{Action, Transaction}; use ethkey::Secret; -use rustc_hex::ToHex; use serde_json::to_value; use v1::{ helpers::{ @@ -92,6 +91,9 @@ fn setup_with(c: Config) -> PersonalTester { tester } +#[cfg(test)] +use rustc_hex::ToHex; + #[test] fn accounts() { let tester = setup(); From 910bb78f0d818c6a6fe0f6deb37adcd41a4182d2 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Thu, 12 Nov 2020 12:57:35 +0100 Subject: [PATCH 012/107] Downgrade sccache to 1.1.2 (#93) --- .github/workflows/build.yml | 12 ++++++------ .github/workflows/check.yml | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c44e0fc739..a57c758797 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,35 +35,35 @@ jobs: profile: minimal override: true - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/registry key: ${{ runner.os }}-cargo-registry-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/git key: ${{ runner.os }}-cargo-git-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo build - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: target key: ${{ runner.os }}-cargo-build-target-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache linux if: matrix.platform == 'ubuntu-16.04' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "/home/runner/.cache/sccache" key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache MacOS if: matrix.platform == 'macos-latest' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "/Users/runner/Library/Caches/Mozilla.sccache" key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} - name: Cache sccache Windows if: matrix.platform == 'windows-latest' - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache" key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 0f46773dab..5f5359b4ca 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -25,23 +25,23 @@ jobs: profile: minimal override: true - name: Cache cargo registry - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/registry key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo index - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: ~/.cargo/git key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo build - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: target key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} # Install sccache based on https://github.com/denoland/rusty_v8/blob/master/.github/workflows/ci.yml#L69 - name: Cache sccache - uses: actions/cache@v2 + uses: actions/cache@v1.1.2 with: path: "/home/runner/.cache/sccache" key: ${{ runner.os }}-sccache-check-${{ hashFiles('**/Cargo.lock') }} From 81ae80b7f123b10e45996d98ffb478ee1f5771be Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Thu, 12 Nov 2020 14:31:24 +0100 Subject: [PATCH 013/107] EIP2565 impl (#82) EIP2565 implementation --- Cargo.lock | 1 + ethcore/builtin/Cargo.toml | 1 + ethcore/builtin/src/lib.rs | 161 ++++++++++++++++++++++---- ethcore/res/ethereum/berlin_test.json | 145 +++++++++++++++++++---- ethcore/res/ethereum/yolo3_test.json | 108 ++++++++++++++--- json/src/spec/builtin.rs | 34 +++++- 6 files changed, 389 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccb225e0ea..4d0ccc04ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1100,6 +1100,7 @@ dependencies = [ "num", "parity-bytes", "parity-crypto 0.4.2", + "rustc-hex 1.0.0", ] [[package]] diff --git a/ethcore/builtin/Cargo.toml b/ethcore/builtin/Cargo.toml index 83bc87128f..4a204f46fd 100644 --- a/ethcore/builtin/Cargo.toml +++ b/ethcore/builtin/Cargo.toml @@ -22,4 +22,5 @@ eth_pairings = { git = "https://github.com/matter-labs/eip1962.git", default-fea [dev-dependencies] hex-literal = "0.2.1" +rustc-hex = "1.0" maplit = "1.0.2" diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 36d8c990f0..62caf5e381 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -81,6 +81,7 @@ enum Pricing { Blake2F(Blake2FPricer), Linear(Linear), Modexp(ModexpPricer), + Modexp2565(Modexp2565Pricer), Bls12Pairing(Bls12PairingPricer), Bls12ConstOperations(Bls12ConstOperations), Bls12MultiexpG1(Bls12MultiexpPricerG1), @@ -95,6 +96,7 @@ impl Pricer for Pricing { Pricing::Blake2F(inner) => inner.cost(input), Pricing::Linear(inner) => inner.cost(input), Pricing::Modexp(inner) => inner.cost(input), + Pricing::Modexp2565(inner) => inner.cost(input), Pricing::Bls12Pairing(inner) => inner.cost(input), Pricing::Bls12ConstOperations(inner) => inner.cost(input), Pricing::Bls12MultiexpG1(inner) => inner.cost(input), @@ -116,6 +118,10 @@ struct ModexpPricer { divisor: u64, } +/// The EIP2565 pricing model of modular exponentiation. +#[derive(Debug)] +struct Modexp2565Pricer {} + impl Pricer for Linear { fn cost(&self, input: &[u8]) -> U256 { U256::from(self.base) + U256::from(self.word) * U256::from((input.len() + 31) / 32) @@ -156,6 +162,28 @@ impl Pricer for AltBn128PairingPricer { impl Pricer for ModexpPricer { fn cost(&self, input: &[u8]) -> U256 { + let (base_len, exp_len, exp_low, mod_len) = Self::parse_input(input); + + if let Some(cost) = Self::check_input_boundaries(&base_len, &exp_len, &mod_len) { + return cost; + } + + let (base_len, exp_len, mod_len) = + (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); + + let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low); + + let m = max(mod_len, base_len); + let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1)); + if overflow { + return U256::max_value(); + } + (gas / self.divisor as u64).into() + } +} + +impl ModexpPricer { + pub fn parse_input(input: &[u8]) -> (U256, U256, U256, U256) { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -166,22 +194,12 @@ impl Pricer for ModexpPricer { .expect("reading from zero-extended memory cannot fail; qed"); U256::from(H256::from_slice(&buf[..])) }; - let base_len = read_len(); - let exp_len = read_len(); - let mod_len = read_len(); + let base_len_u256 = read_len(); + let exp_len_u256 = read_len(); + let mod_len_u256 = read_len(); - if mod_len.is_zero() && base_len.is_zero() { - return U256::zero(); - } - - let max_len = U256::from(u32::max_value() / 2); - if base_len > max_len || mod_len > max_len || exp_len > max_len { - return U256::max_value(); - } - let (base_len, exp_len, mod_len) = - (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); + let (base_len, exp_len) = (base_len_u256.low_u64(), exp_len_u256.low_u64()); - let m = max(mod_len, base_len); // read fist 32-byte word of the exponent. let exp_low = if base_len + 96 >= input.len() as u64 { U256::zero() @@ -195,17 +213,21 @@ impl Pricer for ModexpPricer { U256::from(H256::from_slice(&buf[..])) }; - let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low); + (base_len_u256, exp_len_u256, exp_low, mod_len_u256) + } - let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1)); - if overflow { - return U256::max_value(); + pub fn check_input_boundaries(base_len: &U256, exp_len: &U256, mod_len: &U256) -> Option { + if mod_len.is_zero() && base_len.is_zero() { + return Some(U256::zero()); } - (gas / self.divisor as u64).into() + + let max_len = U256::from(u32::max_value() / 2); + if base_len > &max_len || mod_len > &max_len || exp_len > &max_len { + return Some(U256::max_value()); + } + None } -} -impl ModexpPricer { fn adjusted_exp_len(len: u64, exp_low: U256) -> u64 { let bit_index = if exp_low.is_zero() { 0 @@ -228,6 +250,53 @@ impl ModexpPricer { } } +impl Pricer for Modexp2565Pricer { + fn cost(&self, input: &[u8]) -> U256 { + fn bit_length(a: &U256) -> u64 { + let mut bit_no = 255u64; + while bit_no > 0 { + if a.bit(bit_no as usize) { + return 1 + bit_no as u64; + } + bit_no -= 1; + } + 0 + } + + fn calculate_multiplication_complexity(base_len: u64, modulus_len: u64) -> f64 { + let max_len = std::cmp::max(base_len, modulus_len); + let words = (max_len as f64 / 8f64).ceil(); + words.powi(2) + } + + fn calculate_iteration_count(exponent_len: u64, exponent_low: &U256) -> u64 { + let mut iteration_count = 0; + if exponent_len <= 32 && exponent_low.is_zero() { + iteration_count = 0 + } else if exponent_len <= 32 { + iteration_count = bit_length(exponent_low) - 1 + } else if exponent_len > 32 { + iteration_count = (8 * (exponent_len - 32)) + bit_length(exponent_low) - 1 + }; + std::cmp::max(iteration_count, 1) + } + + let (base_len, exp_len, exp_low, mod_len) = ModexpPricer::parse_input(input); + + if let Some(cost) = ModexpPricer::check_input_boundaries(&base_len, &exp_len, &mod_len) { + return cost; + } + + let (base_len, exp_len, mod_len) = + (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); + + let multiplication_complexity = calculate_multiplication_complexity(base_len, mod_len); + let iteration_count = calculate_iteration_count(exp_len, &exp_low); + let computed = (multiplication_complexity * iteration_count as f64 / 3f64).floor() as u64; + U256::from(std::cmp::max(200, computed)) + } +} + /// Bls12 pairing price #[derive(Debug, Copy, Clone)] struct Bls12PairingPrice { @@ -527,6 +596,9 @@ impl From for Pricing { exp.divisor }, }), + ethjson::spec::builtin::Pricing::Modexp2565(_) => { + Pricing::Modexp2565(Modexp2565Pricer {}) + } ethjson::spec::builtin::Pricing::AltBn128Pairing(pricer) => { Pricing::AltBn128Pairing(AltBn128PairingPricer { price: AltBn128PairingPrice { @@ -1286,7 +1358,8 @@ impl Bn128Pairing { mod tests { use super::{ modexp as me, BTreeMap, Bls12ConstOperations, Bls12PairingPrice, Bls12PairingPricer, - Builtin, EthereumBuiltin, FromStr, Implementation, Linear, ModexpPricer, Pricing, + Builtin, EthereumBuiltin, FromStr, Implementation, Linear, Modexp2565Pricer, ModexpPricer, + Pricer, Pricing, }; use ethereum_types::U256; use ethjson::spec::builtin::{ @@ -1298,6 +1371,7 @@ mod tests { use maplit::btreemap; use num::{BigUint, One, Zero}; use parity_bytes::BytesRef; + use rustc_hex::FromHex; use std::convert::TryFrom; #[test] @@ -2587,4 +2661,47 @@ mod tests { } } } + + #[test] + fn modexp_test_pricing() { + let testvectors = vec![ + ("modexp_nagydani_1_square",204,200,"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b"), + ("modexp_nagydani_1_qube",204,200,"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b"), + ("modexp_nagydani_1_pow0x10001",3276,341,"000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b"), + + ("modexp_nagydani_2_square",665,200,"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087"), + ("modexp_nagydani_2_qube",665,200,"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087"), + ("modexp_nagydani_2_pow0x10001",10649,1365,"000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087"), + + ("modexp_nagydani_3_square",1894,341,"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d"), + ("modexp_nagydani_3_qube",1894,341,"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d"), + ("modexp_nagydani_3_pow0x10001",30310,5461,"000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d"), + + ("modexp_nagydani_4_square",5580,1365,"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f"), + ("modexp_nagydani_4_qube",5580,1365,"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f"), + ("modexp_nagydani_4_pow0x10001",89292,21845,"000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f"), + + ("modexp_nagydani_5_square",17868,5461,"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad"), + ("modexp_nagydani_5_qube",17868,5461,"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad"), + ("modexp_nagydani_5_pow0x10001",285900,87381,"000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad"), + ]; + + let eip198pricer = ModexpPricer { divisor: 20 }; + let eip2565pricer = Modexp2565Pricer {}; + for (name, eip198gas, eip2565gas, input) in testvectors { + let input = input.from_hex().unwrap(); + assert_eq!( + eip198pricer.cost(&input).as_u64(), + U256::from(eip198gas).low_u64(), + "eip198 gas estimates not equal for {}", + name + ); + assert_eq!( + eip2565pricer.cost(&input).as_u64(), + U256::from(eip2565gas).low_u64(), + "eip2565 gas estimates not equal for {}", + name + ); + } + } } diff --git a/ethcore/res/ethereum/berlin_test.json b/ethcore/res/ethereum/berlin_test.json index 6e161c8b21..d08e8e6f67 100644 --- a/ethcore/res/ethereum/berlin_test.json +++ b/ethcore/res/ethereum/berlin_test.json @@ -17,11 +17,11 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x1", + "networkID": "0x1", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", "eip150Transition": "0x0", @@ -60,21 +60,83 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x00", + "pricing": { + "0": { + "price" : { "modexp2565": { } } + } + } + } + }, "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -84,11 +146,19 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -98,11 +168,21 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } @@ -123,7 +203,9 @@ "name": "bls12_381_g1_add", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 600 } + "bls12_const_operations": { + "price": 600 + } } } }, @@ -132,7 +214,9 @@ "name": "bls12_381_g1_mul", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 12000 } + "bls12_const_operations": { + "price": 12000 + } } } }, @@ -141,7 +225,9 @@ "name": "bls12_381_g1_multiexp", "activate_at": "0", "pricing": { - "bls12_g1_multiexp": { "base": 12000 } + "bls12_g1_multiexp": { + "base": 12000 + } } } }, @@ -150,7 +236,9 @@ "name": "bls12_381_g2_add", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 4500 } + "bls12_const_operations": { + "price": 4500 + } } } }, @@ -159,7 +247,9 @@ "name": "bls12_381_g2_mul", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 55000 } + "bls12_const_operations": { + "price": 55000 + } } } }, @@ -168,7 +258,9 @@ "name": "bls12_381_g2_multiexp", "activate_at": "0", "pricing": { - "bls12_g2_multiexp": { "base": 55000 } + "bls12_g2_multiexp": { + "base": 55000 + } } } }, @@ -177,7 +269,10 @@ "name": "bls12_381_pairing", "activate_at": "0", "pricing": { - "bls12_pairing": { "base": 115000, "pair": 23000 } + "bls12_pairing": { + "base": 115000, + "pair": 23000 + } } } }, @@ -186,7 +281,9 @@ "name": "bls12_381_fp_to_g1", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 5500 } + "bls12_const_operations": { + "price": 5500 + } } } }, @@ -195,9 +292,11 @@ "name": "bls12_381_fp2_to_g2", "activate_at": "0", "pricing": { - "bls12_const_operations": { "price": 110000 } + "bls12_const_operations": { + "price": 110000 + } } } } } -} +} \ No newline at end of file diff --git a/ethcore/res/ethereum/yolo3_test.json b/ethcore/res/ethereum/yolo3_test.json index d8767f6a34..e50c2ace32 100644 --- a/ethcore/res/ethereum/yolo3_test.json +++ b/ethcore/res/ethereum/yolo3_test.json @@ -17,11 +17,11 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x1", + "networkID": "0x1", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", "eip150Transition": "0x0", @@ -61,21 +61,83 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000001": { + "balance": "1", + "builtin": { + "name": "ecrecover", + "pricing": { + "linear": { + "base": 3000, + "word": 0 + } + } + } + }, + "0000000000000000000000000000000000000002": { + "balance": "1", + "builtin": { + "name": "sha256", + "pricing": { + "linear": { + "base": 60, + "word": 12 + } + } + } + }, + "0000000000000000000000000000000000000003": { + "balance": "1", + "builtin": { + "name": "ripemd160", + "pricing": { + "linear": { + "base": 600, + "word": 120 + } + } + } + }, + "0000000000000000000000000000000000000004": { + "balance": "1", + "builtin": { + "name": "identity", + "pricing": { + "linear": { + "base": 15, + "word": 3 + } + } + } + }, + "0000000000000000000000000000000000000005": { + "builtin": { + "name": "modexp", + "activate_at": "0x00", + "pricing": { + "0": { + "price" : { "modexp2565": { } } + } + } + } + }, "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -85,11 +147,19 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -99,11 +169,21 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "0": { "info": "EIP 1108 transition", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } @@ -120,4 +200,4 @@ } } } -} +} \ No newline at end of file diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index c106f69134..5c0adb45e1 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -37,6 +37,11 @@ pub struct Modexp { pub divisor: u64, } +/// Pricing for EIP2565 modular exponentiation. +#[derive(Debug, PartialEq, Deserialize, Clone)] +#[serde(deny_unknown_fields)] +pub struct Modexp2565 {} + /// Pricing for constant alt_bn128 operations (ECADD and ECMUL) #[derive(Debug, PartialEq, Deserialize, Clone)] #[serde(deny_unknown_fields)] @@ -101,8 +106,10 @@ pub enum Pricing { }, /// Linear pricing. Linear(Linear), - /// Pricing for modular exponentiation. + /// Pricing for EIP198 modular exponentiation. Modexp(Modexp), + /// Pricing for EIP2565 modular exponentiation. + Modexp2565(Modexp2565), /// Pricing for alt_bn128_pairing exponentiation. AltBn128Pairing(AltBn128Pairing), /// Pricing for constant alt_bn128 operations @@ -190,7 +197,7 @@ pub struct PricingAt { mod tests { use super::{ AltBn128ConstOperations, BTreeMap, Bls12G1Multiexp, Bls12G2Multiexp, Builtin, - BuiltinCompat, Linear, Modexp, Pricing, PricingAt, + BuiltinCompat, Linear, Modexp, Modexp2565, Pricing, PricingAt, }; use macros::map; use serde_json; @@ -359,4 +366,27 @@ mod tests { ] ); } + + #[test] + fn deserialization_modexp2565() { + let s = r#"{ + "name": "modexp", + "pricing": { + "10000000": { + "price": { "modexp2565": { } } + } + } + }"#; + let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); + assert_eq!(builtin.name, "modexp"); + assert_eq!( + builtin.pricing, + btreemap![ + 10000000 => PricingAt { + info: None, + price: Pricing::Modexp2565(Modexp2565{}), + } + ] + ); + } } From 01e72efb80ef0252a407a97795aa558e1362fece Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 13 Nov 2020 16:00:42 +0100 Subject: [PATCH 014/107] Feature/improve dockerhub deployment (#98) * Add docker deployment for Github actions * Add docker specs for the release of tagged and latest versions, also add specs for nightly builds Co-authored-by: Denis Granha --- .github/workflows/deploy-docker-nightly.yml | 29 ++++++++++++++++++++ .github/workflows/deploy-docker-tag.yml | 30 +++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 .github/workflows/deploy-docker-nightly.yml create mode 100644 .github/workflows/deploy-docker-tag.yml diff --git a/.github/workflows/deploy-docker-nightly.yml b/.github/workflows/deploy-docker-nightly.yml new file mode 100644 index 0000000000..b80691b155 --- /dev/null +++ b/.github/workflows/deploy-docker-nightly.yml @@ -0,0 +1,29 @@ +name: Docker Image Nightly Release + +# Run "nightly" build on each commit to "dev" branch. +on: + push: + branches: + - dev + +jobs: + deploy-docker: + name: Build Release + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@master + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Deploy to docker hub + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openethereum/openethereum + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: scripts/docker/alpine/Dockerfile + tags: "nightly" diff --git a/.github/workflows/deploy-docker-tag.yml b/.github/workflows/deploy-docker-tag.yml new file mode 100644 index 0000000000..84beb5decc --- /dev/null +++ b/.github/workflows/deploy-docker-tag.yml @@ -0,0 +1,30 @@ +name: Docker Image Tag and Latest Release + +on: + push: + tags: + - v* + +jobs: + deploy-docker: + name: Build Release + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@master + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Deploy to docker hub + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openethereum/openethereum + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: scripts/docker/alpine/Dockerfile + tags: "latest,${{ env.RELEASE_VERSION }}" From 26ab00b6c7016b3492a09333b1b2325fc4e22c85 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 17 Nov 2020 11:16:24 +0100 Subject: [PATCH 015/107] Fix deprecated set-env declaration (#106) * Fix deprecated set-env declaration * Fix add-path and set-env in install-sscache.ps1 --- .github/workflows/build.yml | 6 +++--- scripts/actions/install-sccache.ps1 | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a57c758797..8e6214f35a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ on: env: AWS_REGION: "us-east-1" AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" - + jobs: build: name: Build Release @@ -133,7 +133,7 @@ jobs: runs-on: ubuntu-16.04 steps: - name: Set env - run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/} + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV # ============================== # Create ZIP files @@ -254,7 +254,7 @@ jobs: runs-on: ubuntu-16.04 steps: - name: Set env - run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/} + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV # ============================== # Download artifacts diff --git a/scripts/actions/install-sccache.ps1 b/scripts/actions/install-sccache.ps1 index b170f473da..a8ad24990a 100755 --- a/scripts/actions/install-sccache.ps1 +++ b/scripts/actions/install-sccache.ps1 @@ -15,5 +15,5 @@ curl -LO $url tar -xzvf "$basename.tar.gz" ls $basename/ . $basename/sccache --start-server -echo "::add-path::$(pwd)/$basename" -echo "::set-env name=RUSTC_WRAPPER::sccache" +echo "$(pwd)/$basename" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append +echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV From fed80cc07542def81e8e844332dbeb1bfba1779b Mon Sep 17 00:00:00 2001 From: Lachezar Lechev <8925621+elpiel@users.noreply.github.com> Date: Mon, 23 Nov 2020 14:49:32 +0200 Subject: [PATCH 016/107] ethstore - remove unnecessary dir & tiny-keccak dependencies from the lib (#107) * ethstore - remove unnecessary dir & tiny-keccak dependencies --- .github/ISSUE_TEMPLATE.md | 2 +- Cargo.lock | 8 +++----- accounts/ethstore/Cargo.toml | 2 -- accounts/ethstore/src/lib.rs | 2 -- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9308be5bca..cb7ec9abe9 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,6 @@ _Before filing a new issue, please **provide the following information**._ -- **OpenEthereum version**: 0.0.0 +- **OpenEthereum version (>=3.1.0)**: 0.0.0 - **Operating system**: Windows / MacOS / Linux - **Installation**: homebrew / one-line installer / built from source - **Fully synchronized**: no / yes diff --git a/Cargo.lock b/Cargo.lock index 4d0ccc04ca..2b13efd9aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1461,7 +1461,6 @@ dependencies = [ name = "ethstore" version = "0.2.1" dependencies = [ - "dir", "ethereum-types 0.4.2", "ethkey", "itertools 0.5.10", @@ -1480,7 +1479,6 @@ dependencies = [ "smallvec 0.6.13", "tempdir", "time", - "tiny-keccak 1.5.0", ] [[package]] @@ -3005,7 +3003,7 @@ dependencies = [ "rustc-hex 2.0.1", "scrypt 0.2.0", "sha2 0.8.0", - "subtle 2.1.0", + "subtle 2.3.0", "tiny-keccak 1.5.0", "zeroize", ] @@ -4458,9 +4456,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01dca13cf6c3b179864ab3292bd794e757618d35a7766b7c46050c614ba00829" +checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" [[package]] name = "syn" diff --git a/accounts/ethstore/Cargo.toml b/accounts/ethstore/Cargo.toml index af497bcff3..cdcae98e43 100644 --- a/accounts/ethstore/Cargo.toml +++ b/accounts/ethstore/Cargo.toml @@ -13,13 +13,11 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" rustc-hex = "1.0" -tiny-keccak = "1.4" time = "0.1.34" itertools = "0.5" parking_lot = "0.7" parity-crypto = "0.3.0" ethereum-types = "0.4" -dir = { path = "../../util/dir" } smallvec = "0.6" parity-wordlist = "1.3" tempdir = "0.3" diff --git a/accounts/ethstore/src/lib.rs b/accounts/ethstore/src/lib.rs index 0197229ca2..5830ab998d 100644 --- a/accounts/ethstore/src/lib.rs +++ b/accounts/ethstore/src/lib.rs @@ -18,7 +18,6 @@ #![warn(missing_docs)] -extern crate dir; extern crate itertools; extern crate libc; extern crate parking_lot; @@ -29,7 +28,6 @@ extern crate serde_json; extern crate smallvec; extern crate tempdir; extern crate time; -extern crate tiny_keccak; extern crate ethereum_types; extern crate ethkey as _ethkey; From 233bab2ee7c760327abbab85e5f82affea1a9f99 Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Tue, 24 Nov 2020 18:11:29 +0000 Subject: [PATCH 017/107] Update linked-hash-map to 0.5.3 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b13efd9aa..d4f626d92c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2438,9 +2438,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "local-encoding" From cb91b7e8285a630677bc69193483e93b75981496 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Wed, 25 Nov 2020 18:28:17 +0100 Subject: [PATCH 018/107] Fix CI problems (#127) * Temporally Fix CI compilation --- .github/workflows/build-test.yml | 18 +- .github/workflows/build.yml | 339 -------------------- .github/workflows/check.yml | 1 + .github/workflows/deploy-docker-nightly.yml | 29 -- .github/workflows/deploy-docker-tag.yml | 30 -- ethcore/sync/src/api.rs | 18 +- 6 files changed, 10 insertions(+), 425 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/deploy-docker-nightly.yml delete mode 100644 .github/workflows/deploy-docker-tag.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index edd0cdabd0..52a27a92c8 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -12,12 +12,12 @@ jobs: env: SCCACHE_CACHE_SIZE: "1G" SCCACHE_IDLE_TIMEOUT: 0 + ACTIONS_ALLOW_UNSECURE_COMMANDS: true strategy: matrix: platform: - ubuntu-16.04 - macos-latest - - windows-latest toolchain: - stable runs-on: ${{ matrix.platform }} @@ -59,18 +59,9 @@ jobs: with: path: "/Users/runner/Library/Caches/Mozilla.sccache" key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache Windows - if: matrix.platform == 'windows-latest' - uses: actions/cache@v1.1.2 - with: - path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache" - key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - name: Install sccache for ${{ matrix.platform }} shell: pwsh run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}} - - name: Install LLVM for Windows - if: matrix.platform == 'windows-latest' - run: choco install llvm - name: Sccache statistics run: sccache --show-stats - name: Build tests @@ -78,13 +69,6 @@ jobs: with: command: test args: --locked --all --release --features "json-tests" --verbose --no-run - - name: Run tests for ${{ matrix.platform }} - if: matrix.platform == 'windows-latest' - continue-on-error: true #Skip step if Windows tests failure - uses: actions-rs/cargo@v1 - with: - command: test - args: --locked --all --release --features "json-tests" --verbose - name: Run tests for ${{ matrix.platform }} if: matrix.platform != 'windows-latest' uses: actions-rs/cargo@v1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 8e6214f35a..0000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,339 +0,0 @@ -name: Build Release Suite - -on: - push: - tags: - - v* - -# Global vars -env: - AWS_REGION: "us-east-1" - AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" - -jobs: - build: - name: Build Release - env: - SCCACHE_CACHE_SIZE: "1G" - SCCACHE_IDLE_TIMEOUT: 0 - strategy: - matrix: - platform: - - ubuntu-16.04 - - macos-latest - - windows-latest - toolchain: - - stable - runs-on: ${{ matrix.platform }} - steps: - - name: Checkout sources - uses: actions/checkout@main - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - profile: minimal - override: true - - name: Cache cargo registry - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-build-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo index - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-git-build-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo build - uses: actions/cache@v1.1.2 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-build-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache linux - if: matrix.platform == 'ubuntu-16.04' - uses: actions/cache@v1.1.2 - with: - path: "/home/runner/.cache/sccache" - key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache MacOS - if: matrix.platform == 'macos-latest' - uses: actions/cache@v1.1.2 - with: - path: "/Users/runner/Library/Caches/Mozilla.sccache" - key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache Windows - if: matrix.platform == 'windows-latest' - uses: actions/cache@v1.1.2 - with: - path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache" - key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }} - - name: Install sccache for ${{ matrix.platform }} - shell: pwsh - run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}} - - # ============================== - # Windows Build - # ============================== - - - name: Install LLVM for Windows - if: matrix.platform == 'windows-latest' - run: choco install llvm - - - name: Sccache statistics - run: sccache --show-stats - - - name: Build OpenEthereum for Windows - if: matrix.platform == 'windows-latest' - run: sh scripts/actions/build-windows.sh ${{matrix.platform}} - - - name: Upload Windows build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'windows-latest' - with: - name: windows-artifacts - path: artifacts - - # ============================== - # Linux/Macos Build - # ============================== - - - name: Build OpenEthereum for ${{matrix.platform}} - if: matrix.platform != 'windows-latest' - run: sh scripts/actions/build-linux.sh ${{matrix.platform}} - - - name: Upload Linux build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'ubuntu-16.04' - with: - name: linux-artifacts - path: artifacts - - - name: Upload MacOS build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'macos-latest' - with: - name: macos-artifacts - path: artifacts - - # ============================== - # End builds - # ============================== - - - name: Stop sccache - if: always() - run: sccache --stop-server - - - name: Prepare build directory for cache - shell: bash - run: bash scripts/actions/clean-target.sh - - zip-artifacts-creator: - name: Create zip artifacts - needs: build - runs-on: ubuntu-16.04 - steps: - - name: Set env - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - # ============================== - # Create ZIP files - # ============================== - - - name: Download Windows artifacts - uses: actions/download-artifact@v2 - with: - name: windows-artifacts - path: windows-artifacts - - - name: Download Linux artifacts - uses: actions/download-artifact@v2 - with: - name: linux-artifacts - path: linux-artifacts - - - name: Download MacOS artifacts - uses: actions/download-artifact@v2 - with: - name: macos-artifacts - path: macos-artifacts - - - name: Display structure of downloaded files - run: ls - - - name: Create zip Linux - id: create_zip_linux - run: | - cd linux-artifacts/ - zip -rT openethereum-linux-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-linux-${{ env.RELEASE_VERSION }}.zip - cd .. - mv linux-artifacts/openethereum-linux-${{ env.RELEASE_VERSION }}.zip . - - echo "Setting outputs..." - echo ::set-output name=LINUX_ARTIFACT::openethereum-linux-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=LINUX_SHASUM::$(shasum -a 256 openethereum-linux-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - - name: Create zip MacOS - id: create_zip_macos - run: | - cd macos-artifacts/ - zip -rT openethereum-macos-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-macos-${{ env.RELEASE_VERSION }}.zip - cd .. - mv macos-artifacts/openethereum-macos-${{ env.RELEASE_VERSION }}.zip . - - echo "Setting outputs..." - echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - - name: Create zip Windows - id: create_zip_windows - run: | - cd windows-artifacts/ - zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - cd .. - mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - - echo "Setting outputs..." - echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - # ======================================================================= - # Upload artifacts - # This is required to share artifacts between different jobs - # ======================================================================= - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip - path: openethereum-linux-${{ env.RELEASE_VERSION }}.zip - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - - # ======================================================================= - # Upload artifacts to S3 - # This is required by some software distribution systems which require - # artifacts to be downloadable, like Brew on MacOS. - # ======================================================================= - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ env.AWS_REGION }} - - - name: Copy files to S3 with the AWS CLI - run: | - # Deploy zip artifacts to S3 bucket to a directory whose name is the tagged release version. - # Deploy macos binary artifact (if required, add more `aws s3 cp` commands to deploy specific OS versions) - aws s3 cp macos-artifacts/openethereum s3://${{ env.AWS_S3_ARTIFACTS_BUCKET }}/${{ env.RELEASE_VERSION }}/macos/ --region ${{ env.AWS_REGION }} - - outputs: - linux-artifact: ${{ steps.create_zip_linux.outputs.LINUX_ARTIFACT }} - linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} - macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} - macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} - - draft-release: - name: Draft Release - needs: zip-artifacts-creator - runs-on: ubuntu-16.04 - steps: - - name: Set env - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - # ============================== - # Download artifacts - # ============================== - - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip - - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - - - name: Display structure of downloaded files - run: ls - - # ============================== - # Create release draft - # ============================== - - - name: Create Release Draft - id: create_release_draft - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ github.ref }} - release_name: OpenEthereum ${{ github.ref }} - body: | - This release contains - - | System | Architecture | Binary | Sha256 Checksum | - |:---:|:---:|:---:|:---| - | Apple Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.macos-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.macos-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.macos-shasum }}` | - | Linux Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.linux-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.linux-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.linux-shasum }}` | - | Windows Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.windows-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.windows-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.windows-shasum }}` | - | | | | | - | **System** | **Option** | - | **Resource** | - | Settings Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | Docker | - | [hub.docker.com/r/openethereum/openethereum](https://hub.docker.com/r/openethereum/openethereum) | - - draft: true - prerelease: true - - - name: Upload Release Asset - Linux - id: upload_release_asset_linux - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-linux-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip - - - name: Upload Release Asset - MacOS - id: upload_release_asset_macos - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-macos-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip - - - name: Upload Release Asset - Windows - id: upload_release_asset_windows - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 5f5359b4ca..af0e005c54 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -13,6 +13,7 @@ jobs: env: SCCACHE_CACHE_SIZE: "1G" SCCACHE_IDLE_TIMEOUT: 0 + ACTIONS_ALLOW_UNSECURE_COMMANDS: true steps: - name: Checkout sources uses: actions/checkout@main diff --git a/.github/workflows/deploy-docker-nightly.yml b/.github/workflows/deploy-docker-nightly.yml deleted file mode 100644 index b80691b155..0000000000 --- a/.github/workflows/deploy-docker-nightly.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Docker Image Nightly Release - -# Run "nightly" build on each commit to "dev" branch. -on: - push: - branches: - - dev - -jobs: - deploy-docker: - name: Build Release - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@master - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - name: Deploy to docker hub - uses: elgohr/Publish-Docker-Github-Action@master - with: - name: openethereum/openethereum - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - dockerfile: scripts/docker/alpine/Dockerfile - tags: "nightly" diff --git a/.github/workflows/deploy-docker-tag.yml b/.github/workflows/deploy-docker-tag.yml deleted file mode 100644 index 84beb5decc..0000000000 --- a/.github/workflows/deploy-docker-tag.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Docker Image Tag and Latest Release - -on: - push: - tags: - - v* - -jobs: - deploy-docker: - name: Build Release - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@master - - name: Set env - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - name: Deploy to docker hub - uses: elgohr/Publish-Docker-Github-Action@master - with: - name: openethereum/openethereum - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - dockerfile: scripts/docker/alpine/Dockerfile - tags: "latest,${{ env.RELEASE_VERSION }}" diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index a9e8a2470f..139d4faea8 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -554,16 +554,14 @@ impl ChainNotify for EthSync { fn start(&self) { match self.network.start() { - Err((err, listen_address)) => { - match err.into() { - ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { - warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", listen_address.expect("Listen address is not set.")) - }, - err => warn!("Error starting network: {}", err), - } - }, - _ => {}, - } + Err((err, listen_address)) => match err.into() { + ErrorKind::Io(ref e) if e.kind() == io::ErrorKind::AddrInUse => { + warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", listen_address.expect("Listen address is not set.")) + } + err => warn!("Error starting network: {}", err), + }, + _ => {} + } self.network .register_protocol( From 1225ff2c5ae361ca4004613d9581a97922f649f2 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 26 Nov 2020 08:31:44 +0100 Subject: [PATCH 019/107] Add flag to disable storage output in openethereum-evm tool #97 (#115) --- evmbin/README.md | 24 ++++++++++------- evmbin/src/display/config.rs | 40 +++++++++++++++++++++++++++ evmbin/src/display/json.rs | 39 ++++++++++++++++++++------- evmbin/src/display/mod.rs | 1 + evmbin/src/display/simple.rs | 15 ++++++++--- evmbin/src/display/std_json.rs | 47 +++++++++++++++++++++++--------- evmbin/src/main.rs | 49 +++++++++++++++++++++------------- 7 files changed, 161 insertions(+), 54 deletions(-) create mode 100644 evmbin/src/display/config.rs diff --git a/evmbin/README.md b/evmbin/README.md index 1610187b41..e6f62de3c7 100644 --- a/evmbin/README.md +++ b/evmbin/README.md @@ -5,11 +5,11 @@ EVM implementation for OpenEthereum. ### Usage ``` -EVM implementation for OpenEthereum. +EVM implementation for Parity. Copyright 2015-2020 Parity Technologies (UK) Ltd. Usage: - openethereum-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only] + openethereum-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only --omit-storage-output --omit-memory-output] openethereum-evm stats [options] openethereum-evm stats-jsontests-vm openethereum-evm [options] @@ -30,16 +30,22 @@ Transaction options: --gas-price WEI Supplied gas price as hex (without 0x). State test options: + --chain CHAIN Run only from specific chain name (i.e. one of EIP150, EIP158, + Frontier, Homestead, Byzantium, Constantinople, + ConstantinopleFix, Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5, + HomesteadToDaoAt5, HomesteadToEIP150At5, Berlin, Yolo3). --only NAME Runs only a single test matching the name. - --chain CHAIN Run only tests from specific chain. General options: - --json Display verbose results in JSON. - --std-json Display results in standardized JSON format. - --std-err-only With --std-json redirect to err output only. - --std-out-only With --std-json redirect to out output only. - --std-dump-json Display results in standardized JSON format - with additional state dump. + --json Display verbose results in JSON. + --std-json Display results in standardized JSON format. + --std-err-only With --std-json redirect to err output only. + --std-out-only With --std-json redirect to out output only. + --omit-storage-output With --std-json omit storage output. + --omit-memory-output With --std-json omit memory output. + --std-dump-json Display results in standardized JSON format + with additional state dump. + Display result state dump in standardized JSON format. --chain CHAIN Chain spec file path. -h, --help Display this message and exit. diff --git a/evmbin/src/display/config.rs b/evmbin/src/display/config.rs new file mode 100644 index 0000000000..1080919667 --- /dev/null +++ b/evmbin/src/display/config.rs @@ -0,0 +1,40 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! Config used by display informants + +#[derive(Default, Copy, Clone)] +pub struct Config { + omit_storage_output: bool, + omit_memory_output: bool, +} + +impl Config { + pub fn new(omit_storage_output: bool, omit_memory_output: bool) -> Config { + Config { + omit_storage_output, + omit_memory_output, + } + } + + pub fn omit_storage_output(&self) -> bool { + self.omit_storage_output + } + + pub fn omit_memory_output(&self) -> bool { + self.omit_memory_output + } +} diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index f8e3ebae0d..e3fc820574 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -18,11 +18,11 @@ use std::{collections::HashMap, mem}; +use super::config::Config; use bytes::ToPretty; +use display; use ethcore::trace; use ethereum_types::{H256, U256}; - -use display; use info as vm; /// JSON formatting informant. @@ -44,9 +44,16 @@ pub struct Informant { subinfos: Vec, subdepth: usize, unmatched: bool, + config: Config, } impl Informant { + pub fn new(config: Config) -> Informant { + let mut def = Informant::default(); + def.config = config; + def + } + fn with_informant_in_depth( informant: &mut Informant, depth: usize, @@ -67,17 +74,26 @@ impl Informant { } fn informant_trace(informant: &Informant, gas_used: U256) -> String { + let memory = if informant.config.omit_memory_output() { + "".to_string() + } else { + format!("0x{}", informant.memory.to_hex()) + }; + let storage = if informant.config.omit_storage_output() { + None + } else { + Some(&informant.storage) + }; let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info()); - json!({ "pc": informant.pc, "op": informant.instruction, "opName": info.map(|i| i.name).unwrap_or(""), "gas": format!("{:#x}", gas_used.saturating_add(informant.gas_cost)), "gasCost": format!("{:#x}", informant.gas_cost), - "memory": format!("0x{}", informant.memory.to_hex()), + "memory": memory, "stack": informant.stack, - "storage": informant.storage, + "storage": storage, "depth": informant.depth, }) .to_string() @@ -85,7 +101,7 @@ impl Informant { } impl vm::Informant for Informant { - type Sink = (); + type Sink = Config; fn before_test(&mut self, name: &str, action: &str) { println!("{}", json!({"action": action, "test": name})); @@ -96,10 +112,10 @@ impl vm::Informant for Informant { } fn clone_sink(&self) -> Self::Sink { - () + self.config } - fn finish(result: vm::RunResult, _sink: &mut Self::Sink) { + fn finish(result: vm::RunResult, config: &mut Self::Sink) { match result { Ok(success) => { for trace in success.traces.unwrap_or_else(Vec::new) { @@ -115,8 +131,10 @@ impl vm::Informant for Informant { println!("{}", success_msg) } Err(failure) => { - for trace in failure.traces.unwrap_or_else(Vec::new) { - println!("{}", trace); + if !config.omit_storage_output() { + for trace in failure.traces.unwrap_or_else(Vec::new) { + println!("{}", trace); + } } let failure_msg = json!({ @@ -205,6 +223,7 @@ impl trace::VMTracer for Informant { let subdepth = self.subdepth; Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { let mut vm = Informant::default(); + vm.config = informant.config; vm.depth = informant.depth + 1; vm.code = code.to_vec(); vm.gas_used = informant.gas_used; diff --git a/evmbin/src/display/mod.rs b/evmbin/src/display/mod.rs index 9131f436cf..abd9c42ca9 100644 --- a/evmbin/src/display/mod.rs +++ b/evmbin/src/display/mod.rs @@ -18,6 +18,7 @@ use std::time::Duration; +pub mod config; pub mod json; pub mod simple; pub mod std_json; diff --git a/evmbin/src/display/simple.rs b/evmbin/src/display/simple.rs index 264205768a..76043d54ea 100644 --- a/evmbin/src/display/simple.rs +++ b/evmbin/src/display/simple.rs @@ -16,6 +16,7 @@ //! Simple VM output. +use super::config::Config; use bytes::ToPretty; use ethcore::trace; @@ -24,17 +25,25 @@ use info as vm; /// Simple formatting informant. #[derive(Default)] -pub struct Informant; +pub struct Informant { + config: Config, +} + +impl Informant { + pub fn new(config: Config) -> Informant { + Informant { config } + } +} impl vm::Informant for Informant { - type Sink = (); + type Sink = Config; fn before_test(&mut self, name: &str, action: &str) { println!("Test: {} ({})", name, action); } fn clone_sink(&self) -> Self::Sink { - () + self.config } fn finish(result: vm::RunResult, _sink: &mut Self::Sink) { diff --git a/evmbin/src/display/std_json.rs b/evmbin/src/display/std_json.rs index 33638aa8ed..b6efa4c0c1 100644 --- a/evmbin/src/display/std_json.rs +++ b/evmbin/src/display/std_json.rs @@ -18,11 +18,11 @@ use std::{collections::HashMap, io}; +use super::config::Config; use bytes::ToPretty; +use display; use ethcore::{pod_state, trace}; use ethereum_types::{H256, U256}; - -use display; use info as vm; pub trait Writer: io::Write + Send + Sized { @@ -61,30 +61,39 @@ pub struct Informant { subdepth: usize, trace_sink: Trace, out_sink: Out, + config: Config, } impl Default for Informant { fn default() -> Self { - Self::new(io::stderr(), io::stdout()) + Self::new(io::stderr(), io::stdout(), Config::default()) } } impl Informant { /// std json informant using out only. - pub fn out_only() -> Self { - Self::new(io::stdout(), io::stdout()) + pub fn out_only(config: Config) -> Self { + Self::new(io::stdout(), io::stdout(), config) } } impl Informant { /// std json informant using err only. - pub fn err_only() -> Self { - Self::new(io::stderr(), io::stderr()) + pub fn err_only(config: Config) -> Self { + Self::new(io::stderr(), io::stderr(), config) + } +} + +impl Informant { + pub fn new_default(config: Config) -> Self { + let mut informant = Self::default(); + informant.config = config; + informant } } impl Informant { - pub fn new(trace_sink: Trace, out_sink: Out) -> Self { + pub fn new(trace_sink: Trace, out_sink: Out, config: Config) -> Self { Informant { code: Default::default(), instruction: Default::default(), @@ -95,6 +104,7 @@ impl Informant { subdepth: 0, trace_sink, out_sink, + config, } } @@ -133,7 +143,7 @@ impl Informant { } impl vm::Informant for Informant { - type Sink = (Trace, Out); + type Sink = (Trace, Out, Config); fn before_test(&mut self, name: &str, action: &str) { let out_data = json!({ @@ -147,11 +157,15 @@ impl vm::Informant for Informant { fn set_gas(&mut self, _gas: U256) {} fn clone_sink(&self) -> Self::Sink { - (self.trace_sink.clone(), self.out_sink.clone()) + ( + self.trace_sink.clone(), + self.out_sink.clone(), + self.config.clone(), + ) } fn finish( result: vm::RunResult<::Output>, - (ref mut trace_sink, ref mut out_sink): &mut Self::Sink, + (ref mut trace_sink, ref mut out_sink, _): &mut Self::Sink, ) { match result { Ok(success) => { @@ -240,7 +254,11 @@ impl trace::VMTracer for Informant { fn prepare_subtrace(&mut self, code: &[u8]) { let subdepth = self.subdepth; Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { - let mut vm = Informant::new(informant.trace_sink.clone(), informant.out_sink.clone()); + let mut vm = Informant::new( + informant.trace_sink.clone(), + informant.out_sink.clone(), + informant.config, + ); vm.depth = informant.depth + 1; vm.code = code.to_vec(); informant.subinfos.push(vm); @@ -293,7 +311,10 @@ pub mod tests { let trace_writer: TestWriter = Default::default(); let out_writer: TestWriter = Default::default(); let res = trace_writer.0.clone(); - (Informant::new(trace_writer, out_writer), res) + ( + Informant::new(trace_writer, out_writer, Config::default()), + res, + ) } #[test] diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 46585818e9..a7a63474b1 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -57,10 +57,10 @@ use info::Informant; const USAGE: &'static str = r#" EVM implementation for Parity. - Copyright 2015-2019 Parity Technologies (UK) Ltd. + Copyright 2015-2020 Parity Technologies (UK) Ltd. Usage: - openethereum-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only] + openethereum-evm state-test [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only --omit-storage-output --omit-memory-output] openethereum-evm stats [options] openethereum-evm stats-jsontests-vm openethereum-evm [options] @@ -88,12 +88,15 @@ State test options: --only NAME Runs only a single test matching the name. General options: - --json Display verbose results in JSON. - --std-json Display results in standardized JSON format. - --std-err-only With --std-json redirect to err output only. - --std-out-only With --std-json redirect to out output only. - --std-dump-json Display results in standardized JSON format - with additional state dump. + --json Display verbose results in JSON. + --std-json Display results in standardized JSON format. + --std-err-only With --std-json redirect to err output only. + --std-out-only With --std-json redirect to out output only. + --omit-storage-output With --std-json omit storage output. + --omit-memory-output With --std-json omit memory output. + --std-dump-json Display results in standardized JSON format + with additional state dump. + Display result state dump in standardized JSON format. --chain CHAIN Chain spec file path. -h, --help Display this message and exit. @@ -107,22 +110,24 @@ fn main() { .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); + let config = args.config(); + if args.cmd_state_test { run_state_test(args) } else if args.cmd_stats_jsontests_vm { run_stats_jsontests_vm(args) } else if args.flag_json { - run_call(args, display::json::Informant::default()) + run_call(args, display::json::Informant::new(config)) } else if args.flag_std_dump_json || args.flag_std_json { if args.flag_std_err_only { - run_call(args, display::std_json::Informant::err_only()) + run_call(args, display::std_json::Informant::err_only(config)) } else if args.flag_std_out_only { - run_call(args, display::std_json::Informant::out_only()) + run_call(args, display::std_json::Informant::out_only(config)) } else { - run_call(args, display::std_json::Informant::default()) + run_call(args, display::std_json::Informant::new_default(config)) }; } else { - run_call(args, display::simple::Informant::default()) + run_call(args, display::simple::Informant::new(config)) } } @@ -165,7 +170,7 @@ fn run_stats_jsontests_vm(args: Args) { fn run_state_test(args: Args) { use ethjson::state::test::Test; - + let config = args.config(); let file = args.arg_file.expect("FILE is required"); let mut file = match fs::File::open(&file) { Err(err) => die(format!("Unable to open: {:?}: {}", file, err)), @@ -215,7 +220,7 @@ fn run_state_test(args: Args) { post_root, &env_info, transaction, - display::json::Informant::default(), + display::json::Informant::new(config), trie_spec, ) } else if args.flag_std_dump_json || args.flag_std_json { @@ -228,7 +233,7 @@ fn run_state_test(args: Args) { post_root, &env_info, transaction, - display::std_json::Informant::err_only(), + display::std_json::Informant::err_only(config), trie_spec, ) } else if args.flag_std_out_only { @@ -240,7 +245,7 @@ fn run_state_test(args: Args) { post_root, &env_info, transaction, - display::std_json::Informant::out_only(), + display::std_json::Informant::out_only(config), trie_spec, ) } else { @@ -252,7 +257,7 @@ fn run_state_test(args: Args) { post_root, &env_info, transaction, - display::std_json::Informant::default(), + display::std_json::Informant::new_default(config), trie_spec, ) } @@ -265,7 +270,7 @@ fn run_state_test(args: Args) { post_root, &env_info, transaction, - display::simple::Informant::default(), + display::simple::Informant::new(config), trie_spec, ) } @@ -338,6 +343,8 @@ struct Args { flag_std_dump_json: bool, flag_std_err_only: bool, flag_std_out_only: bool, + flag_omit_storage_output: bool, + flag_omit_memory_output: bool, } impl Args { @@ -399,6 +406,10 @@ impl Args { None => ethcore::ethereum::new_foundation(&::std::env::temp_dir()), }) } + + pub fn config(&self) -> display::config::Config { + display::config::Config::new(self.flag_omit_storage_output, self.flag_omit_memory_output) + } } fn arg(v: Result, param: &str) -> T { From 51d824fbdc43011c29ef9a8de0c9786fb35315f3 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 1 Dec 2020 16:40:06 +0100 Subject: [PATCH 020/107] Remove sscache (#138) --- .github/workflows/build-test.yml | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 52a27a92c8..b8c014c436 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -32,38 +32,6 @@ jobs: toolchain: ${{ matrix.toolchain }} profile: minimal override: true - - name: Cache cargo registry - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo index - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-git-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo build - uses: actions/cache@v1.1.2 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache linux - if: matrix.platform == 'ubuntu-16.04' - uses: actions/cache@v1.1.2 - with: - path: "/home/runner/.cache/sccache" - key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Cache sccache MacOS - if: matrix.platform == 'macos-latest' - uses: actions/cache@v1.1.2 - with: - path: "/Users/runner/Library/Caches/Mozilla.sccache" - key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }} - - name: Install sccache for ${{ matrix.platform }} - shell: pwsh - run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}} - - name: Sccache statistics - run: sccache --show-stats - name: Build tests uses: actions-rs/cargo@v1 with: @@ -75,9 +43,3 @@ jobs: with: command: test args: --locked --all --release --features "json-tests" --verbose - - name: Stop sccache - if: always() - run: sccache --stop-server - - name: Prepare build directory for cache - shell: bash - run: bash scripts/actions/clean-target.sh From 56131b6d9212dc73d4bddc5658072afb286eb6eb Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 2 Dec 2020 11:31:11 +0100 Subject: [PATCH 021/107] Trace comment on new block inclusion (#100) --- ethcore/blockchain/src/blockchain.rs | 2 +- ethcore/src/block.rs | 25 +++++++-- ethcore/src/client/client.rs | 53 +++++++++++++++---- ethcore/src/engines/authority_round/mod.rs | 3 +- ethcore/src/engines/mod.rs | 6 +-- ethcore/src/machine/impls.rs | 2 +- ethcore/src/miner/miner.rs | 20 ++++--- ethcore/src/snapshot/watcher.rs | 1 + ethcore/src/state/backend.rs | 2 +- ethcore/src/state/mod.rs | 4 +- ethcore/src/state_db.rs | 3 +- ethcore/src/verification/queue/kind.rs | 2 + ethcore/src/verification/queue/mod.rs | 11 ++-- ethcore/src/verification/verification.rs | 24 +++++++-- ethcore/sync/src/api.rs | 1 + ethcore/sync/src/chain/handler.rs | 4 ++ ethcore/sync/src/chain/mod.rs | 6 ++- ethcore/sync/src/chain/propagator.rs | 11 ++-- ethcore/types/src/transaction/transaction.rs | 2 +- miner/src/pool/queue.rs | 3 +- parity/informant.rs | 1 + rpc/src/v1/impls/eth_pubsub.rs | 1 + secret-store/src/acl_storage.rs | 1 + secret-store/src/key_server_set.rs | 1 + .../src/listener/service_contract_listener.rs | 1 + util/journaldb/src/overlayrecentdb.rs | 1 + 26 files changed, 146 insertions(+), 45 deletions(-) diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index 389b95c492..b863ff29e5 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -1476,7 +1476,7 @@ impl BlockChain { } } - /// Apply pending insertion updates + // t_nb 9.12 commit changed to become current greatest by applying pending insertion updates pub fn commit(&self) { let mut pending_best_ancient_block = self.pending_best_ancient_block.write(); let mut pending_best_block = self.pending_best_block.write(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 0b49a267c6..640a92578e 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -161,7 +161,7 @@ pub trait Drain { } impl<'x> OpenBlock<'x> { - /// Create a new `OpenBlock` ready for transaction pushing. + // t_nb 8.1 Create a new `OpenBlock` ready for transaction pushing. pub fn new<'a, I: IntoIterator>( engine: &'x dyn EthEngine, factories: Factories, @@ -176,6 +176,8 @@ impl<'x> OpenBlock<'x> { ancestry: I, ) -> Result { let number = parent.number() + 1; + + // t_nb 8.1.1 get parent StateDB. let state = State::from_existing( db, parent.state_root().clone(), @@ -198,14 +200,17 @@ impl<'x> OpenBlock<'x> { let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit); let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target); + // t_nb 8.1.2 It calculated child gas limits should be. engine.machine().populate_from_parent( &mut r.block.header, parent, gas_floor_target, gas_ceil_target, ); + // t_nb 8.1.3 this adds engine specific things engine.populate_from_parent(&mut r.block.header, parent); + // t_nb 8.1.3 updating last hashes and the DAO fork, for ethash. engine.machine().on_new_block(&mut r.block)?; engine.on_new_block(&mut r.block, is_epoch_begin, &mut ancestry.into_iter())?; @@ -222,7 +227,7 @@ impl<'x> OpenBlock<'x> { self.block.header.set_gas_limit(U256::max_value()); } - /// Add an uncle to the block, if possible. + // t_nb 8.4 Add an uncle to the block, if possible. /// /// NOTE Will check chain constraints and the uncle number but will NOT check /// that the header itself is actually valid. @@ -343,13 +348,17 @@ impl<'x> OpenBlock<'x> { }) } - /// Turn this into a `LockedBlock`. + // t_nb 8.5 Turn this into a `LockedBlock`. pub fn close_and_lock(self) -> Result { let mut s = self; + // t_nb 8.5.1 engine applies block rewards (Ethash and AuRa do.Clique is empty) s.engine.on_close_block(&mut s.block)?; + + // t_nb 8.5.2 commit account changes from cache to tree s.block.state.commit()?; + // t_nb 8.5.3 fill open block header with all other fields s.block.header.set_transactions_root(ordered_trie_root( s.block.transactions.iter().map(|e| e.rlp_bytes()), )); @@ -506,7 +515,7 @@ impl Drain for SealedBlock { } } -/// Enact the block given by block header, transactions and uncles +// t_nb 8.0 Enact the block given by block header, transactions and uncles pub(crate) fn enact( header: Header, transactions: Vec, @@ -532,6 +541,7 @@ pub(crate) fn enact( None }; + // t_nb 8.1 Created new OpenBlock let mut b = OpenBlock::new( engine, factories, @@ -556,17 +566,22 @@ pub(crate) fn enact( b.block.header.number(), root, env.author, author_balance); } + // t_nb 8.2 transfer all field from current header to OpenBlock header that we created b.populate_from(&header); + + // t_nb 8.3 execute transactions one by one b.push_transactions(transactions)?; + // t_nb 8.4 Push uncles to OpenBlock and check if we have more then max uncles for u in uncles { b.push_uncle(u)?; } + // t_nb 8.5 close block b.close_and_lock() } -/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +// t_nb 8.0 Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header pub fn enact_verified( block: PreverifiedBlock, engine: &dyn EthEngine, diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6164f2799c..6a025ec2c4 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -275,7 +275,7 @@ impl Importer { }) } - /// This is triggered by a message coming from a block queue when the block is ready for insertion + // t_nb 6.0 This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. if !client.enabled.load(AtomicOrdering::Relaxed) { @@ -315,11 +315,13 @@ impl Importer { invalid_blocks.insert(hash); continue; } - + // t_nb 7.0 check and lock block match self.check_and_lock_block(&bytes, block, client) { Ok((closed_block, pending)) => { imported_blocks.push(hash); let transactions_len = closed_block.transactions.len(); + + // t_nb 8.0 commit block to db let route = self.commit_block( closed_block, &header, @@ -362,6 +364,7 @@ impl Importer { if !imported_blocks.is_empty() { let route = ChainRoute::from(import_results.as_ref()); + // t_nb 10 Notify miner about new included block. if !has_more_blocks_to_import { self.miner.chain_new_blocks( client, @@ -373,6 +376,7 @@ impl Importer { ); } + // t_nb 11 notify rest of system about new block inclusion client.notify(|notify| { notify.new_blocks(NewBlocks::new( imported_blocks.clone(), @@ -394,6 +398,7 @@ impl Importer { imported } + // t_nb 6.0.1 check and lock block, fn check_and_lock_block( &self, bytes: &[u8], @@ -404,13 +409,14 @@ impl Importer { let header = block.header.clone(); // Check the block isn't so old we won't be able to enact it. + // t_nb 7.1 check if block is older then last pruned block let best_block_number = client.chain.read().best_block_number(); if client.pruning_info().earliest_state > header.number() { warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); bail!("Block is ancient"); } - // Check if parent is in chain + // t_nb 7.2 Check if parent is in chain let parent = match client.block_header_decoded(BlockId::Hash(*header.parent_hash())) { Some(h) => h, None => { @@ -420,7 +426,7 @@ impl Importer { }; let chain = client.chain.read(); - // Verify Block Family + // t_nb 7.3 verify block family let verify_family_result = self.verifier.verify_block_family( &header, &parent, @@ -437,6 +443,7 @@ impl Importer { bail!(e); }; + // t_nb 7.4 verify block external let verify_external_result = self.verifier.verify_block_external(&header, engine); if let Err(e) = verify_external_result { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); @@ -444,7 +451,9 @@ impl Importer { }; // Enact Verified Block + // t_nb 7.5 Get build last hashes. Get parent state db. Get epoch_transition let last_hashes = client.build_last_hashes(header.parent_hash()); + let db = client .state_db .read() @@ -454,6 +463,7 @@ impl Importer { .epoch_transition(parent.number(), *header.parent_hash()) .is_some(); + // t_nb 8.0 Block enacting. Execution of transactions. let enact_result = enact_verified( block, engine, @@ -474,7 +484,7 @@ impl Importer { } }; - // Strip receipts for blocks before validate_receipts_transition, + // t_nb 7.6 Strip receipts for blocks before validate_receipts_transition, // if the expected receipts root header does not match. // (i.e. allow inconsistency in receipts outcome before the transition block) if header.number() < engine.params().validate_receipts_transition @@ -483,7 +493,7 @@ impl Importer { locked_block.strip_receipts_outcomes(); } - // Final Verification + // t_nb 7.7 Final Verification. See if block that we created (executed) matches exactly with block that we received. if let Err(e) = self .verifier .verify_block_final(&header, &locked_block.header) @@ -570,6 +580,7 @@ impl Importer { let mut batch = DBTransaction::new(); + // t_nb 9.1 Gather all ancestry actions. (Used only by AuRa) let ancestry_actions = self .engine .ancestry_actions(&header, &mut chain.ancestry_with_metadata_iter(*parent)); @@ -605,24 +616,28 @@ impl Importer { } }; + // t_nb 9.2 calcuate route between current and latest block. let route = chain.tree_route(best_hash, *parent).expect("forks are only kept when it has common ancestors; tree route from best to prospective's parent always exists; qed"); + + // t_nb 9.3 Check block total difficulty let fork_choice = if route.is_from_route_finalized { ForkChoice::Old } else { self.engine.fork_choice(&new, &best) }; - // CHECK! I *think* this is fine, even if the state_root is equal to another + // t_nb 9.4 CHECK! I *think* this is fine, even if the state_root is equal to another // already-imported block of the same number. // TODO: Prove it with a test. let mut state = block.state.drop().1; - // check epoch end signal, potentially generating a proof on the current - // state. + // t_nb 9.5 check epoch end signal, potentially generating a proof on the current + // state. Write transition into db. if let Some(pending) = pending { chain.insert_pending_transition(&mut batch, header.hash(), pending); } + // t_nb 9.6 push state to database Transaction. (It calls journal_under from JournalDB) state .journal_under(&mut batch, number, hash) .expect("DB commit failed"); @@ -633,6 +648,7 @@ impl Importer { let AncestryAction::MarkFinalized(a) = ancestry_action; if a != header.hash() { + // t_nb 9.7 if there are finalized ancester, mark that chainge in block in db. (Used by AuRa) chain .mark_finalized(&mut batch, a) .expect("Engine's ancestry action must be known blocks; qed"); @@ -645,6 +661,7 @@ impl Importer { }) .collect(); + // t_nb 9.8 insert block let route = chain.insert_block( &mut batch, block_data, @@ -655,6 +672,7 @@ impl Importer { }, ); + // t_nb 9.9 insert traces (if they are enabled) client.tracedb.read().import( &mut batch, TraceImportRequest { @@ -667,15 +685,22 @@ impl Importer { ); let is_canon = route.enacted.last().map_or(false, |h| h == hash); + + // t_nb 9.10 sync cache state.sync_cache(&route.enacted, &route.retracted, is_canon); // Final commit to the DB + // t_nb 9.11 Write Transaction to database (cached) client.db.read().key_value().write_buffered(batch); + // t_nb 9.12 commit changed to become current greatest by applying pending insertion updates (Sync point) chain.commit(); + // t_nb 9.13 check epoch end. Related only to AuRa and it seems light engine self.check_epoch_end(&header, &finalized, &chain, client); + // t_nb 9.14 update last hashes. They are build in step 7.5 client.update_last_hashes(&parent, hash); + // t_nb 9.15 prune ancient states if let Err(e) = client.prune_ancient(state, &chain) { warn!("Failed to prune ancient state data: {}", e); } @@ -1098,7 +1123,7 @@ impl Client { with_call(&call) } - // prune ancient states until below the memory limit or only the minimum amount remain. + // t_nb 9.15 prune ancient states until below the memory limit or only the minimum amount remain. fn prune_ancient( &self, mut state_db: StateDB, @@ -1138,6 +1163,7 @@ impl Client { Ok(()) } + // t_nb 9.14 update last hashes. They are build in step 7.5 fn update_last_hashes(&self, parent: &H256, hash: &H256) { let mut hashes = self.last_hashes.write(); if hashes.front().map_or(false, |h| h == parent) { @@ -1721,11 +1747,14 @@ impl CallContract for Client { } impl ImportBlock for Client { + // t_nb 2.0 import block to client fn import_block(&self, unverified: Unverified) -> EthcoreResult { + // t_nb 2.1 check if header hash is known to us. if self.chain.read().is_known(&unverified.hash()) { bail!(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain)); } + // t_nb 2.2 check if parent is known let status = self.block_status(BlockId::Hash(unverified.parent_hash())); if status == BlockStatus::Unknown { bail!(EthcoreErrorKind::Block(BlockError::UnknownParent( @@ -1743,14 +1772,16 @@ impl ImportBlock for Client { None }; + // t_nb 2.3 match self.importer.block_queue.import(unverified) { Ok(hash) => { + // t_nb 2.4 If block is okay and the queue is empty we propagate the block in a `PriorityTask` to be rebrodcasted if let Some((raw, hash, difficulty)) = raw { self.notify(move |n| n.block_pre_import(&raw, &hash, &difficulty)); } Ok(hash) } - // we only care about block errors (not import errors) + // t_nb 2.5 if block is not okay print error. we only care about block errors (not import errors) Err((Some(block), EthcoreError(EthcoreErrorKind::Block(err), _))) => { self.importer .bad_blocks diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 3022dc8df3..e730655877 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1307,6 +1307,7 @@ impl Engine for AuthorityRound { Ok(()) } + // t_nb 8.1.5 fn on_new_block( &self, block: &mut ExecutedBlock, @@ -1531,7 +1532,7 @@ impl Engine for AuthorityRound { Ok(()) } - // Check the validators. + // t_nb 6.4 Check the validators. fn verify_block_external(&self, header: &Header) -> Result<(), Error> { let (validators, set_number) = self.epoch_set(header)?; diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index e979f40666..0113a4589b 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -488,7 +488,7 @@ pub trait Engine: Sync + Send { header_timestamp > parent_timestamp } - /// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that + // t_nb 9.1 Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that /// the ancestry exists. fn ancestry_actions( &self, @@ -507,7 +507,7 @@ pub trait Engine: Sync + Send { } } -/// Check whether a given block is the best block based on the default total difficulty rule. +// t_nb 9.3 Check whether a given block is the best block based on the default total difficulty rule. pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice { if new.total_score() > best.total_score() { ForkChoice::New @@ -562,7 +562,7 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { self.machine().create_address_scheme(number) } - /// Verify a particular transaction is valid. + // t_nb 5.3.1 Verify a particular transaction is valid. /// /// Unordered verification doesn't rely on the transaction execution order, /// i.e. it should only verify stuff that doesn't assume any previous transactions diff --git a/ethcore/src/machine/impls.rs b/ethcore/src/machine/impls.rs index 8b98cf08d6..890b2854f7 100644 --- a/ethcore/src/machine/impls.rs +++ b/ethcore/src/machine/impls.rs @@ -238,7 +238,7 @@ impl EthereumMachine { Ok(()) } - /// Logic to perform on a new block: updating last hashes and the DAO + // t_nb 8.1.3 Logic to perform on a new block: updating last hashes and the DAO /// fork, for ethash. pub fn on_new_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { self.push_last_hash(block)?; diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 96141f1d5b..c65f97a1af 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1230,7 +1230,7 @@ impl miner::MinerService for Miner { ) } - /// Update sealing if required. + // t_nb 10.4 Update sealing if required. /// Prepare the block and work if the Engine does not seal internally. fn update_sealing(&self, chain: &C, force: ForceUpdateSealing) where @@ -1339,6 +1339,7 @@ impl miner::MinerService for Miner { }) } + // t_nb 10 notify miner about new include blocks fn chain_new_blocks( &self, chain: &C, @@ -1363,11 +1364,11 @@ impl miner::MinerService for Miner { self.nonce_cache.clear(); } - // First update gas limit in transaction queue and minimal gas price. + // t_nb 10.1 First update gas limit in transaction queue and minimal gas price. let gas_limit = *chain.best_block_header().gas_limit(); self.update_transaction_queue_limits(gas_limit); - // Then import all transactions from retracted blocks. + // t_nb 10.2 Then import all transactions from retracted blocks (retracted means from side chain). let client = self.pool_client(chain); { retracted @@ -1378,7 +1379,8 @@ impl miner::MinerService for Miner { let txs = block.transactions() .into_iter() .map(pool::verifier::Transaction::Retracted) - .collect(); + .collect(); + // t_nb 10.2 let _ = self.transaction_queue.import( client.clone(), txs, @@ -1387,12 +1389,13 @@ impl miner::MinerService for Miner { } if has_new_best_block || (imported.len() > 0 && self.options.reseal_on_uncle) { - // Reset `next_allowed_reseal` in case a block is imported. + // t_nb 10.3 Reset `next_allowed_reseal` in case a block is imported. // Even if min_period is high, we will always attempt to create // new pending block. self.sealing.lock().next_allowed_reseal = Instant::now(); if !is_internal_import { + // t_nb 10.4 if it is internal import update sealing // -------------------------------------------------------------------------- // | NOTE Code below requires sealing locks. | // | Make sure to release the locks before calling that method. | @@ -1402,7 +1405,7 @@ impl miner::MinerService for Miner { } if has_new_best_block { - // Make sure to cull transactions after we update sealing. + // t_nb 10.5 Make sure to cull transactions after we update sealing. // Not culling won't lead to old transactions being added to the block // (thanks to Ready), but culling can take significant amount of time, // so best to leave it after we create some work for miners to prevent increased @@ -1424,7 +1427,9 @@ impl miner::MinerService for Miner { &*accounts, service_transaction_checker.as_ref(), ); + // t_nb 10.5 do culling queue.cull(client); + // reseal is only used by InstaSeal engine if engine.should_reseal_on_update() { // force update_sealing here to skip `reseal_required` checks chain.update_sealing(ForceUpdateSealing::Yes); @@ -1435,13 +1440,16 @@ impl miner::MinerService for Miner { warn!(target: "miner", "Error queueing cull: {:?}", e); } } else { + // t_nb 10.5 do culling self.transaction_queue.cull(client); + // reseal is only used by InstaSeal engine if self.engine.should_reseal_on_update() { // force update_sealing here to skip `reseal_required` checks self.update_sealing(chain, ForceUpdateSealing::Yes); } } } + // t_nb 10.6 For service transaction checker update addresses to latest block if let Some(ref service_transaction_checker) = self.service_transaction_checker { match service_transaction_checker.refresh_cache(chain) { Ok(true) => { diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index 8f1bced373..d949c1c4ab 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -111,6 +111,7 @@ impl Watcher { } impl ChainNotify for Watcher { + // t_nb 11.1 check number of block and trigger snapshot creation if needed. fn new_blocks(&self, new_blocks: NewBlocks) { if self.oracle.is_major_importing() || new_blocks.has_more_blocks_to_import { return; diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index 167884cd01..2e81189469 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -43,7 +43,7 @@ pub trait Backend: Send { /// Treat the backend as a writeable hashdb. fn as_hash_db_mut(&mut self) -> &mut dyn HashDB; - /// Add an account entry to the cache. + // t_nb 9.4 Add an account entry to the cache. fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool); /// Add a global code cache entry. This doesn't need to worry about canonicality because diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 7a63687570..740c666e77 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -996,7 +996,7 @@ impl State { Ok(()) } - /// Commits our cached account changes into the trie. + // t_nb 8.5.2 Commits our cached account changes into the trie. pub fn commit(&mut self) -> Result<(), Error> { assert!(self.checkpoints.borrow().is_empty()); // first, commit the sub trees. @@ -1036,7 +1036,7 @@ impl State { Ok(()) } - /// Propagate local cache into shared canonical state cache. + // t_nb 9.4 Propagate local cache into shared canonical state cache. fn propagate_to_global_cache(&mut self) { let mut addresses = self.cache.borrow_mut(); trace!("Committing cache {:?} entries", addresses.len()); diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index 306851b9f9..78942399d4 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -147,6 +147,7 @@ impl StateDB { Ok(records) } + // t_nb 9.15 /// Mark a given candidate from an ancient era as canonical, enacting its removals from the /// backing database and reverting any non-canonical historical commit's insertions. pub fn mark_canonical( @@ -158,7 +159,7 @@ impl StateDB { self.db.mark_canonical(batch, end_era, canon_id) } - /// Propagate local cache into the global cache and synchonize + // t_nb 9.10 Propagate local cache into the global cache and synchonize /// the global cache with the best block state. /// This function updates the global cache by removing entries /// that are invalidated by chain reorganization. `sync_cache` diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 0c5b42afec..e789137a78 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -95,6 +95,7 @@ pub mod blocks { type Unverified = Unverified; type Verified = PreverifiedBlock; + // t_nb 4.0 verify_block_basic fn create( input: Self::Input, engine: &dyn EthEngine, @@ -113,6 +114,7 @@ pub mod blocks { } } + // t_nb 5.0 verify standalone block fn verify( un: Self::Unverified, engine: &dyn EthEngine, diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index fff62d4292..cb67d689c4 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -364,7 +364,7 @@ impl VerificationQueue { } } - // do work. + // do work on this item. let item = { // acquire these locks before getting the item to verify. let mut unverified = verification.unverified.lock(); @@ -387,10 +387,12 @@ impl VerificationQueue { }; let hash = item.hash(); + // t_nb 5.0 verify standalone block (this verification is done in VerificationQueue thread pool) let is_ready = match K::verify(item, &*engine, verification.check_seal) { Ok(verified) => { let mut verifying = verification.verifying.lock(); let mut idx = None; + // find item again and remove it from verified queue for (i, e) in verifying.iter_mut().enumerate() { if e.hash == hash { idx = Some(i); @@ -515,17 +517,20 @@ impl VerificationQueue { } /// Add a block to the queue. + // t_nb 3.0 import block to verification queue pub fn import(&self, input: K::Input) -> Result, Error)> { let hash = input.hash(); let raw_hash = input.raw_hash(); + // t_nb 3.1 check if block is currently processing or marked as bad. { + // t_nb 3.1.0 is currently processing if self.processing.read().contains_key(&hash) { bail!(( Some(input), ErrorKind::Import(ImportErrorKind::AlreadyQueued).into() )); } - + // t_nb 3.1.1 is marked as bad let mut bad = self.verification.bad.lock(); if bad.contains(&hash) || bad.contains(&raw_hash) { bail!(( @@ -533,7 +538,7 @@ impl VerificationQueue { ErrorKind::Import(ImportErrorKind::KnownBad).into() )); } - + // t_nb 3.1.2 its parent is marked as bad if bad.contains(&input.parent_hash()) { bad.insert(hash); bail!(( diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index a4437c719d..012e7ba2bb 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -63,26 +63,36 @@ impl HeapSizeOf for PreverifiedBlock { } } -/// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block +// t_nb 4.0 Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block pub fn verify_block_basic( block: &Unverified, engine: &dyn EthEngine, check_seal: bool, ) -> Result<(), Error> { + // t_nb 4.1 verify header params verify_header_params(&block.header, engine, true, check_seal)?; + // t_nb 4.2 verify header time (addded in new OE version) + // t_nb 4.3 verify block integrity verify_block_integrity(block)?; if check_seal { + // t_nb 4.4 Check block seal. It calls engine to verify block basic engine.verify_block_basic(&block.header)?; } + // t_nb 4.5 for all uncled verify header and call engine to verify block basic for uncle in &block.uncles { + // t_nb 4.5.1 verify_header_params(uncle, engine, false, check_seal)?; if check_seal { + // t_nb 4.5.2 engine.verify_block_basic(uncle)?; } } + // t_nb 4.6 call engine.gas_limit_override (Used only by Aura) TODO added in new version + + // t_nb 4.7 for every transaction call engine.verify_transaction_basic for t in &block.transactions { engine.verify_transaction_basic(t, &block.header)?; } @@ -90,7 +100,7 @@ pub fn verify_block_basic( Ok(()) } -/// Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash. +// t_nb 5.0 Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash. /// Still operates on a individual block /// Returns a `PreverifiedBlock` structure populated with transactions pub fn verify_block_unordered( @@ -100,8 +110,10 @@ pub fn verify_block_unordered( ) -> Result { let header = block.header; if check_seal { + // t_nb 5.1 engine.verify_block_unordered(&header)?; for uncle in &block.uncles { + // t_nb 5.2 engine.verify_block_unordered(uncle)?; } } @@ -112,11 +124,14 @@ pub fn verify_block_unordered( None }; + // t_nb 5.3 iterate over all transactions let transactions = block .transactions .into_iter() .map(|t| { + // t_nb 5.3.1 call verify_unordered. Check signatures and calculate address let t = engine.verify_transaction_unordered(t, &header)?; + // t_nb 5.3.2 check if nonce is more then max nonce (EIP-168 and EIP169) if let Some(max_nonce) = nonce_cap { if t.nonce >= max_nonce { return Err(BlockError::TooManyTransactions(t.sender()).into()); @@ -146,7 +161,7 @@ pub struct FullFamilyParams<'a, C: BlockInfo + CallContract + 'a> { pub client: &'a C, } -/// Phase 3 verification. Check block information against parent and uncles. +// t_nb 6.3 Phase 3 verification. Check block information against parent and uncles. pub fn verify_block_family( header: &Header, parent: &Header, @@ -154,6 +169,7 @@ pub fn verify_block_family( do_full: Option>, ) -> Result<(), Error> { // TODO: verify timestamp + // t_nb 6.3.1 verify parent verify_parent(&header, &parent, engine)?; engine.verify_block_family(&header, &parent)?; @@ -162,8 +178,10 @@ pub fn verify_block_family( None => return Ok(()), }; + // t_nb 6.3.2 verify uncles verify_uncles(params.block, params.block_provider, engine)?; + // t_nb 6.3.3 verify all transactions for tx in ¶ms.block.transactions { // transactions are verified against the parent header since the current // state wasn't available when the tx was created diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 139d4faea8..5cea92488b 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -529,6 +529,7 @@ impl ChainNotify for EthSync { } } + // t_nb 11.4 fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 12e0db9739..2b3dbf655d 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -155,6 +155,7 @@ impl SyncHandler { trace!(target: "sync", "Ignoring new block from unconfirmed peer {}", peer_id); return Ok(()); } + // t_nb 1.0 decode RLP let block = Unverified::from_rlp(r.at(0)?.as_raw().to_vec())?; let hash = block.header.hash(); let number = block.header.number(); @@ -166,7 +167,9 @@ impl SyncHandler { let difficulty: U256 = r.val_at(1)?; // Most probably the sent block is being imported by peer right now // Use td and hash, that peer must have for now + // t_nb 1.1 check new block diffuculty it can be found as second item in RLP and update peer diffuculty let parent_td = difficulty.checked_sub(*block.header.difficulty()); + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { if peer .difficulty @@ -181,6 +184,7 @@ impl SyncHandler { peer.latest_hash = *parent_hash; } + // t_nb 1.2 if block number is to older then 20 dont process it let last_imported_number = sync.new_blocks.last_imported_block_number(); if last_imported_number > number && last_imported_number - number > MAX_NEW_BLOCK_AGE { trace!(target: "sync", "Ignored ancient new block {:?}", hash); diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 9a5b1f5fe8..889b6ef3fa 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -1421,7 +1421,7 @@ impl ChainSync { self.check_resume(io); } - /// called when block is imported to chain - propagates the blocks and updates transactions sent to peers + // t_nb 11.4 called when block is imported to chain - propagates the blocks and updates transactions sent to peers pub fn chain_new_blocks( &mut self, io: &mut dyn SyncIo, @@ -1437,7 +1437,9 @@ impl ChainSync { if !is_syncing || !sealed.is_empty() || !proposed.is_empty() { trace!(target: "sync", "Propagating blocks, state={:?}", self.state); + // t_nb 11.4.1 propagate latest blocks SyncPropagator::propagate_latest_blocks(self, io, sealed); + // t_nb 11.4.4 propagate proposed blocks SyncPropagator::propagate_proposed_blocks(self, io, proposed); } if !invalid.is_empty() { @@ -1446,7 +1448,7 @@ impl ChainSync { } if !is_syncing && !enacted.is_empty() && !self.peers.is_empty() { - // Select random peer to re-broadcast transactions to. + // t_nb 11.4.5 Select random peer to re-broadcast transactions to. let peer = random::new().gen_range(0, self.peers.len()); trace!(target: "sync", "Re-broadcasting transactions to a random peer."); self.peers.values_mut().nth(peer).map(|peer_info| { diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index cd28f7fe85..a70fc813d7 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -39,7 +39,7 @@ use super::{ pub struct SyncPropagator; impl SyncPropagator { - /// propagates latest block to a set of peers + // t_nb 11.4.3 propagates latest block to a set of peers pub fn propagate_blocks( sync: &mut ChainSync, chain_info: &BlockChainInfo, @@ -72,7 +72,7 @@ impl SyncPropagator { sent } - /// propagates new known hashes to all peers + // t_nb 11.4.2 propagates new known hashes to all peers pub fn propagate_new_hashes( sync: &mut ChainSync, chain_info: &BlockChainInfo, @@ -279,6 +279,7 @@ impl SyncPropagator { sent_to_peers } + // t_nb 11.4.1 propagate latest blocks to peers pub fn propagate_latest_blocks(sync: &mut ChainSync, io: &mut dyn SyncIo, sealed: &[H256]) { let chain_info = io.chain().chain_info(); if (((chain_info.best_block_number as i64) - (sync.last_sent_block_number as i64)).abs() @@ -287,15 +288,19 @@ impl SyncPropagator { { let peers = sync.get_lagging_peers(&chain_info); if sealed.is_empty() { + // t_nb 11.4.2 let hashes = SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); let peers = ChainSync::select_random_peers(&peers); + // t_nb 11.4.3 let blocks = SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); if blocks != 0 || hashes != 0 { trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes); } } else { + // t_nb 11.4.3 SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); + // t_nb 11.4.2 SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); trace!(target: "sync", "Sent sealed block to all peers"); }; @@ -303,7 +308,7 @@ impl SyncPropagator { sync.last_sent_block_number = chain_info.best_block_number; } - /// Distribute valid proposed blocks to subset of current peers. + // t_nb 11.4.4 Distribute valid proposed blocks to subset of current peers. (if there is any proposed) pub fn propagate_proposed_blocks( sync: &mut ChainSync, io: &mut dyn SyncIo, diff --git a/ethcore/types/src/transaction/transaction.rs b/ethcore/types/src/transaction/transaction.rs index 55320d21d5..f4de8fbcd7 100644 --- a/ethcore/types/src/transaction/transaction.rs +++ b/ethcore/types/src/transaction/transaction.rs @@ -468,7 +468,7 @@ impl From for UnverifiedTransaction { } impl SignedTransaction { - /// Try to verify transaction and recover sender. + // t_nb 5.3.1 Try to verify transaction and recover sender. pub fn new(transaction: UnverifiedTransaction) -> Result { if transaction.is_unsigned() { return Err(ethkey::Error::InvalidSignature); diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index cf8a1f3802..45d17090b4 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -251,6 +251,7 @@ impl TransactionQueue { self.pool.write().listener_mut().0.set_in_chain_checker(f) } + // t_nb 10.2 /// Import a set of transactions to the pool. /// /// Given blockchain and state access (Client) @@ -471,7 +472,7 @@ impl TransactionQueue { (pending_readiness, state_readiness) } - /// Culls all stalled transactions from the pool. + // t_nb 10.5.1 Culls all stalled transactions from the pool. pub fn cull(&self, client: C) { trace_time!("pool::cull"); // We don't care about future transactions, so nonce_cap is not important. diff --git a/parity/informant.rs b/parity/informant.rs index 4f09c137a5..59bd915ba5 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -336,6 +336,7 @@ impl Informant { } impl ChainNotify for Informant { + // t_nb 11.2 Informant. Prints new block inclusiong to console/log. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index e5d0deefb8..c8199d4633 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -175,6 +175,7 @@ impl ChainNotificationHandler { } impl ChainNotify for ChainNotificationHandler { + // t_nb 11.3 RPC. Notify subscriber header/logs about new block fn new_blocks(&self, new_blocks: NewBlocks) { if self.heads_subscribers.read().is_empty() && self.logs_subscribers.read().is_empty() { return; diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs index d853145d7c..47a826800d 100644 --- a/secret-store/src/acl_storage.rs +++ b/secret-store/src/acl_storage.rs @@ -83,6 +83,7 @@ impl AclStorage for OnChainAclStorage { } impl ChainNotify for OnChainAclStorage { + // t_nb 11.5 SecretStore OnChainAclStorage. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs index 158e6cc0a9..137e1b0dd9 100644 --- a/secret-store/src/key_server_set.rs +++ b/secret-store/src/key_server_set.rs @@ -168,6 +168,7 @@ impl KeyServerSet for OnChainKeyServerSet { } impl ChainNotify for OnChainKeyServerSet { + // t_nb 11.6 SecretStore OnChainKeyServerSet. fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs index 6e8fb7eb1d..8b6490d9a0 100644 --- a/secret-store/src/listener/service_contract_listener.rs +++ b/secret-store/src/listener/service_contract_listener.rs @@ -624,6 +624,7 @@ impl Drop for ServiceContractListener { } impl ChainNotify for ServiceContractListener { + // t_nb 11.7 SecretStore ServiceContractListener fn new_blocks(&self, new_blocks: NewBlocks) { if new_blocks.has_more_blocks_to_import { return; diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index 5c919dfecd..8a51161c74 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -332,6 +332,7 @@ impl JournalDB for OverlayRecentDB { self.journal_overlay.read().earliest_era } + // t_nb 9.6 fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> io::Result { trace!(target: "journaldb", "entry: #{} ({})", now, id); From 647ff319425d28022f172deb735c2564693ce5e4 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 9 Dec 2020 11:48:27 +0100 Subject: [PATCH 022/107] Add ws-max-paxload (#155) --- parity/cli/mod.rs | 7 +++++++ parity/configuration.rs | 2 ++ parity/rpc.rs | 3 +++ rpc/src/lib.rs | 2 ++ rpc/src/tests/ws.rs | 1 + 5 files changed, 15 insertions(+) diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 2508398e05..871b4fc466 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -466,6 +466,10 @@ usage! { "--ws-max-connections=[CONN]", "Maximum number of allowed concurrent WebSockets JSON-RPC connections.", + ARG arg_ws_max_payload: (usize) = 5usize, or |c: &Config| c.websockets.as_ref()?.max_payload, + "--ws-max-payload=[MB]", + "Specify maximum size for WS JSON-RPC requests in megabytes.", + ["Metrics"] FLAG flag_metrics: (bool) = false, or |c: &Config| c.metrics.as_ref()?.enable.clone(), "--metrics", @@ -903,6 +907,7 @@ struct Ws { origins: Option>, hosts: Option>, max_connections: Option, + max_payload: Option, } #[derive(Default, Debug, PartialEq, Deserialize)] @@ -1323,6 +1328,7 @@ mod tests { arg_ws_origins: "none".into(), arg_ws_hosts: "none".into(), arg_ws_max_connections: 100, + arg_ws_max_payload: 5, // IPC flag_no_ipc: false, @@ -1512,6 +1518,7 @@ mod tests { origins: Some(vec!["none".into()]), hosts: None, max_connections: None, + max_payload: None, }), rpc: Some(Rpc { disable: Some(true), diff --git a/parity/configuration.rs b/parity/configuration.rs index c2f3d3c107..5982594e53 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -951,6 +951,7 @@ impl Configuration { signer_path: self.directories().signer.into(), support_token_api, max_connections: self.args.arg_ws_max_connections, + max_payload: self.args.arg_ws_max_payload, }; Ok(conf) @@ -1483,6 +1484,7 @@ mod tests { signer_path: expected.into(), support_token_api: true, max_connections: 100, + max_payload: 5, }, LogConfig { color: !cfg!(windows), diff --git a/parity/rpc.rs b/parity/rpc.rs index 1022cfc9cb..4cd639ba6b 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -97,6 +97,7 @@ pub struct WsConfiguration { pub hosts: Option>, pub signer_path: PathBuf, pub support_token_api: bool, + pub max_payload: usize, } impl Default for WsConfiguration { @@ -116,6 +117,7 @@ impl Default for WsConfiguration { hosts: Some(Vec::new()), signer_path: replace_home(&data_dir, "$BASE/signer").into(), support_token_api: true, + max_payload: 5, } } } @@ -194,6 +196,7 @@ pub fn new_ws( rpc::WsExtractor::new(path.clone()), rpc::WsExtractor::new(path.clone()), rpc::WsStats::new(deps.stats.clone()), + conf.max_payload, ); // match start_result { diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 6a83c80434..09b8bb4a63 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -223,6 +223,7 @@ pub fn start_ws( extractor: T, middleware: V, stats: U, + max_payload: usize, ) -> Result where M: jsonrpc_core::Metadata, @@ -237,6 +238,7 @@ where .allowed_origins(allowed_origins) .allowed_hosts(allowed_hosts) .max_connections(max_connections) + .max_payload(max_payload * 1024 * 1024) .session_stats(stats) .start(addr) } diff --git a/rpc/src/tests/ws.rs b/rpc/src/tests/ws.rs index ef6991afca..d2953066b0 100644 --- a/rpc/src/tests/ws.rs +++ b/rpc/src/tests/ws.rs @@ -44,6 +44,7 @@ pub fn serve() -> (Server, usize, GuardedAuthCodes) { extractors::WsExtractor::new(Some(&authcodes.path)), extractors::WsExtractor::new(Some(&authcodes.path)), extractors::WsStats::new(stats), + 5 * 1024 * 1024, ) .unwrap() }); From 3f01b69084e1cb0a43254ec5b186375d1544245e Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 9 Dec 2020 12:43:32 +0100 Subject: [PATCH 023/107] Fix broken doc comments (#151) --- ethcore/blockchain/src/blockchain.rs | 2 +- ethcore/src/block.rs | 6 +++--- ethcore/src/engines/mod.rs | 2 +- ethcore/src/state/backend.rs | 2 +- ethcore/src/state/mod.rs | 2 +- ethcore/src/verification/verification.rs | 4 ++-- miner/src/pool/queue.rs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index b863ff29e5..c5872ac1fe 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -1476,7 +1476,7 @@ impl BlockChain { } } - // t_nb 9.12 commit changed to become current greatest by applying pending insertion updates + /// t_nb 9.12 commit changed to become current greatest by applying pending insertion updates pub fn commit(&self) { let mut pending_best_ancient_block = self.pending_best_ancient_block.write(); let mut pending_best_block = self.pending_best_block.write(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 640a92578e..57a3414d3e 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -161,7 +161,7 @@ pub trait Drain { } impl<'x> OpenBlock<'x> { - // t_nb 8.1 Create a new `OpenBlock` ready for transaction pushing. + /// t_nb 8.1 Create a new `OpenBlock` ready for transaction pushing. pub fn new<'a, I: IntoIterator>( engine: &'x dyn EthEngine, factories: Factories, @@ -348,7 +348,7 @@ impl<'x> OpenBlock<'x> { }) } - // t_nb 8.5 Turn this into a `LockedBlock`. + /// t_nb 8.5 Turn this into a `LockedBlock`. pub fn close_and_lock(self) -> Result { let mut s = self; @@ -581,7 +581,7 @@ pub(crate) fn enact( b.close_and_lock() } -// t_nb 8.0 Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +/// t_nb 8.0 Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header pub fn enact_verified( block: PreverifiedBlock, engine: &dyn EthEngine, diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 0113a4589b..ca362859dc 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -507,7 +507,7 @@ pub trait Engine: Sync + Send { } } -// t_nb 9.3 Check whether a given block is the best block based on the default total difficulty rule. +/// t_nb 9.3 Check whether a given block is the best block based on the default total difficulty rule. pub fn total_difficulty_fork_choice(new: &ExtendedHeader, best: &ExtendedHeader) -> ForkChoice { if new.total_score() > best.total_score() { ForkChoice::New diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index 2e81189469..53e8ee4a48 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -43,7 +43,7 @@ pub trait Backend: Send { /// Treat the backend as a writeable hashdb. fn as_hash_db_mut(&mut self) -> &mut dyn HashDB; - // t_nb 9.4 Add an account entry to the cache. + /// t_nb 9.4 Add an account entry to the cache. fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool); /// Add a global code cache entry. This doesn't need to worry about canonicality because diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 740c666e77..66da05f270 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -996,7 +996,7 @@ impl State { Ok(()) } - // t_nb 8.5.2 Commits our cached account changes into the trie. + /// t_nb 8.5.2 Commits our cached account changes into the trie. pub fn commit(&mut self) -> Result<(), Error> { assert!(self.checkpoints.borrow().is_empty()); // first, commit the sub trees. diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 012e7ba2bb..9cdc837549 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -63,7 +63,7 @@ impl HeapSizeOf for PreverifiedBlock { } } -// t_nb 4.0 Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block +/// t_nb 4.0 Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block pub fn verify_block_basic( block: &Unverified, engine: &dyn EthEngine, @@ -161,7 +161,7 @@ pub struct FullFamilyParams<'a, C: BlockInfo + CallContract + 'a> { pub client: &'a C, } -// t_nb 6.3 Phase 3 verification. Check block information against parent and uncles. +/// t_nb 6.3 Phase 3 verification. Check block information against parent and uncles. pub fn verify_block_family( header: &Header, parent: &Header, diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index 45d17090b4..92bdf2f07e 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -472,7 +472,7 @@ impl TransactionQueue { (pending_readiness, state_readiness) } - // t_nb 10.5.1 Culls all stalled transactions from the pool. + /// t_nb 10.5.1 Culls all stalled transactions from the pool. pub fn cull(&self, client: C) { trace_time!("pool::cull"); // We don't care about future transactions, so nonce_cap is not important. From ea3efd926ec1641c17d511e988e1cce70b4578a9 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 10 Dec 2020 16:42:05 +0100 Subject: [PATCH 024/107] TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135) --- Cargo.lock | 14 + ethcore/blockchain/src/blockchain.rs | 72 +- ethcore/blockchain/src/generator.rs | 22 +- ethcore/db/src/keys.rs | 24 +- ethcore/res/ethereum/yolo3_test.json | 3 +- ethcore/src/block.rs | 16 +- ethcore/src/client/client.rs | 69 +- ethcore/src/client/evm_test_client.rs | 12 +- ethcore/src/client/test_client.rs | 42 +- ethcore/src/engines/authority_round/mod.rs | 6 +- ethcore/src/engines/mod.rs | 4 +- .../engines/validator_set/safe_contract.rs | 35 +- ethcore/src/executive.rs | 129 +-- ethcore/src/json_tests/transaction.rs | 14 +- ethcore/src/machine/impls.rs | 28 +- ethcore/src/miner/miner.rs | 15 +- ethcore/src/miner/pool_client.rs | 3 +- ethcore/src/snapshot/block.rs | 31 +- ethcore/src/snapshot/consensus/authority.rs | 12 +- ethcore/src/snapshot/consensus/work.rs | 11 +- .../src/snapshot/tests/proof_of_authority.rs | 10 +- ethcore/src/snapshot/tests/service.rs | 2 +- ethcore/src/spec/spec.rs | 12 +- ethcore/src/state/mod.rs | 74 +- ethcore/src/test_helpers.rs | 8 +- ethcore/src/tests/client.rs | 14 +- ethcore/src/tests/trace.rs | 6 +- ethcore/src/tx_filter.rs | 54 +- ethcore/src/verification/queue/kind.rs | 7 +- ethcore/src/verification/verification.rs | 45 +- ethcore/sync/src/block_sync.rs | 32 +- ethcore/sync/src/blocks.rs | 37 +- ethcore/sync/src/chain/handler.rs | 9 +- ethcore/sync/src/chain/propagator.rs | 20 +- ethcore/sync/src/tests/consensus.rs | 6 +- ethcore/types/Cargo.toml | 3 + ethcore/types/src/block.rs | 6 +- ethcore/types/src/lib.rs | 1 + ethcore/types/src/receipt.rs | 290 +++++-- ethcore/types/src/transaction/error.rs | 5 + ethcore/types/src/transaction/mod.rs | 3 +- ethcore/types/src/transaction/transaction.rs | 787 ++++++++++++++---- .../types/src/transaction/transaction_id.rs | 45 + ethcore/types/src/views/block.rs | 21 +- ethcore/types/src/views/body.rs | 21 +- ethcore/vm/src/access_list.rs | 2 +- ethcore/vm/src/schedule.rs | 9 + evmbin/src/info.rs | 2 +- json/src/spec/params.rs | 2 + miner/local-store/src/lib.rs | 22 +- miner/src/pool/listener.rs | 16 +- miner/src/pool/local_transactions.rs | 4 +- miner/src/pool/mod.rs | 4 +- miner/src/pool/queue.rs | 6 +- miner/src/pool/ready.rs | 8 +- miner/src/pool/scoring.rs | 2 +- miner/src/pool/tests/client.rs | 6 +- miner/src/pool/tests/mod.rs | 8 +- miner/src/pool/tests/tx.rs | 14 +- miner/src/pool/verifier.rs | 40 +- miner/src/service_transaction_checker.rs | 2 +- rpc/src/v1/helpers/dispatch/full.rs | 2 + rpc/src/v1/helpers/dispatch/signing.rs | 23 +- rpc/src/v1/helpers/errors.rs | 3 +- .../helpers/external_signer/signing_queue.rs | 2 + rpc/src/v1/helpers/fake_sign.rs | 18 +- rpc/src/v1/helpers/requests.rs | 15 + rpc/src/v1/impls/eth.rs | 6 +- rpc/src/v1/impls/signer.rs | 11 +- rpc/src/v1/impls/traces.rs | 8 +- rpc/src/v1/tests/mocked/eth.rs | 33 +- rpc/src/v1/tests/mocked/parity.rs | 11 +- rpc/src/v1/tests/mocked/parity_set.rs | 8 +- rpc/src/v1/tests/mocked/personal.rs | 23 +- rpc/src/v1/tests/mocked/signer.rs | 69 +- rpc/src/v1/tests/mocked/signing.rs | 20 +- rpc/src/v1/tests/mocked/signing_unsafe.rs | 25 +- rpc/src/v1/types/call_request.rs | 16 +- rpc/src/v1/types/confirmations.rs | 4 + rpc/src/v1/types/receipt.rs | 18 +- rpc/src/v1/types/transaction.rs | 69 +- rpc/src/v1/types/transaction_request.rs | 24 +- secret-store/src/trusted_client.rs | 10 +- 83 files changed, 1849 insertions(+), 796 deletions(-) create mode 100644 ethcore/types/src/transaction/transaction_id.rs diff --git a/Cargo.lock b/Cargo.lock index d4f626d92c..4a52e12943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,9 @@ dependencies = [ "rlp 0.3.0", "rlp_derive", "rustc-hex 1.0.0", + "serde", + "serde_json", + "serde_repr", "unexpected", ] @@ -4274,6 +4277,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" +dependencies = [ + "proc-macro2 1.0.20", + "quote 1.0.7", + "syn 1.0.40", +] + [[package]] name = "sha-1" version = "0.8.1" diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index c5872ac1fe..e952d1938f 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -34,7 +34,7 @@ use common_types::{ }, header::{ExtendedHeader, Header}, log_entry::{LocalizedLogEntry, LogEntry}, - receipt::Receipt, + receipt::TypedReceipt, transaction::LocalizedTransaction, tree_route::TreeRoute, view, @@ -460,13 +460,13 @@ impl BlockProvider for BlockChain { warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len()); assert!(false); } - let mut log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len()); + let mut log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.receipt().logs.len()); let receipts_len = receipts.len(); hashes.reverse(); receipts.reverse(); receipts.into_iter() - .map(|receipt| receipt.logs) + .map(|receipt| receipt.receipt().logs.clone()) .zip(hashes) .enumerate() .flat_map(move |(index, (mut logs, tx_hash))| { @@ -895,7 +895,7 @@ impl BlockChain { &self, batch: &mut DBTransaction, block: encoded::Block, - receipts: Vec, + receipts: Vec, parent_td: Option, is_best: bool, is_ancient: bool, @@ -1265,7 +1265,7 @@ impl BlockChain { &self, batch: &mut DBTransaction, block: encoded::Block, - receipts: Vec, + receipts: Vec, extras: ExtrasInsert, ) -> ImportRoute { let parent_hash = block.header_view().parent_hash(); @@ -1283,7 +1283,7 @@ impl BlockChain { &self, batch: &mut DBTransaction, block: encoded::Block, - receipts: Vec, + receipts: Vec, route: TreeRoute, extras: ExtrasInsert, ) -> ImportRoute { @@ -1659,7 +1659,7 @@ impl BlockChain { /// This function returns modified block receipts. fn prepare_block_receipts_update( &self, - receipts: Vec, + receipts: Vec, info: &BlockInfo, ) -> HashMap { let mut block_receipts = HashMap::new(); @@ -1921,8 +1921,8 @@ mod tests { use crate::generator::{BlockBuilder, BlockGenerator, BlockOptions}; use common_types::{ - receipt::{Receipt, TransactionOutcome}, - transaction::{Action, Transaction}, + receipt::{LegacyReceipt, TransactionOutcome, TypedReceipt}, + transaction::{Action, Transaction, TypedTransaction}, }; use ethkey::Secret; use keccak_hash::keccak; @@ -1975,7 +1975,7 @@ mod tests { db: &Arc, bc: &BlockChain, block: encoded::Block, - receipts: Vec, + receipts: Vec, ) -> ImportRoute { insert_block_commit(db, bc, block, receipts, true) } @@ -1984,7 +1984,7 @@ mod tests { db: &Arc, bc: &BlockChain, block: encoded::Block, - receipts: Vec, + receipts: Vec, commit: bool, ) -> ImportRoute { let mut batch = db.key_value().transaction(); @@ -2000,7 +2000,7 @@ mod tests { batch: &mut DBTransaction, bc: &BlockChain, block: encoded::Block, - receipts: Vec, + receipts: Vec, ) -> ImportRoute { let fork_choice = { let header = block.header_view(); @@ -2157,7 +2157,7 @@ mod tests { #[test] fn test_fork_transaction_addresses() { - let t1 = Transaction { + let t1 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2166,7 +2166,7 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); let t1_hash = t1.hash(); @@ -2211,7 +2211,7 @@ mod tests { #[test] fn test_overwriting_transaction_addresses() { - let t1 = Transaction { + let t1 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2220,10 +2220,10 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); - let t2 = Transaction { + let t2 = TypedTransaction::Legacy(Transaction { nonce: 1.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2232,10 +2232,10 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); - let t3 = Transaction { + let t3 = TypedTransaction::Legacy(Transaction { nonce: 2.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2244,7 +2244,7 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); let genesis = BlockBuilder::genesis(); @@ -2509,7 +2509,7 @@ mod tests { #[test] fn test_logs() { - let t1 = Transaction { + let t1 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2518,9 +2518,9 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); - let t2 = Transaction { + let t2 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2529,9 +2529,9 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); - let t3 = Transaction { + let t3 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2540,9 +2540,9 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); - let t4 = Transaction { + let t4 = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -2551,7 +2551,7 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555" .from_hex() .unwrap(), - } + }) .sign(&secret(), None); let tx_hash1 = t1.hash(); let tx_hash2 = t2.hash(); @@ -2580,7 +2580,7 @@ mod tests { &bc, b1.last().encoded(), vec![ - Receipt { + TypedReceipt::Legacy(LegacyReceipt { outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), @@ -2596,8 +2596,8 @@ mod tests { data: vec![2], }, ], - }, - Receipt { + }), + TypedReceipt::Legacy(LegacyReceipt { outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), @@ -2606,14 +2606,14 @@ mod tests { topics: vec![], data: vec![3], }], - }, + }), ], ); insert_block( &db, &bc, b2.last().encoded(), - vec![Receipt { + vec![TypedReceipt::Legacy(LegacyReceipt { outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), @@ -2622,13 +2622,13 @@ mod tests { topics: vec![], data: vec![4], }], - }], + })], ); insert_block( &db, &bc, b3.last().encoded(), - vec![Receipt { + vec![TypedReceipt::Legacy(LegacyReceipt { outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), @@ -2637,7 +2637,7 @@ mod tests { topics: vec![], data: vec![5], }], - }], + })], ); // when diff --git a/ethcore/blockchain/src/generator.rs b/ethcore/blockchain/src/generator.rs index fc3fbd20d5..817ecf2232 100644 --- a/ethcore/blockchain/src/generator.rs +++ b/ethcore/blockchain/src/generator.rs @@ -22,17 +22,16 @@ use std::collections::VecDeque; use common_types::{ encoded, header::Header, - transaction::{Action, SignedTransaction, Transaction}, + transaction::{Action, SignedTransaction, Transaction, TypedTransaction}, view, views::BlockView, }; use keccak_hash::keccak; -use rlp::encode; -use rlp_derive::RlpEncodable; +use rlp::{encode, RlpStream}; use triehash_ethereum::ordered_trie_root; /// Helper structure, used for encoding blocks. -#[derive(Default, Clone, RlpEncodable)] +#[derive(Default, Clone)] pub struct Block { /// Block header pub header: Header, @@ -42,6 +41,15 @@ pub struct Block { pub uncles: Vec
, } +impl rlp::Encodable for Block { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(3); + s.append(&self.header); + SignedTransaction::rlp_append_list(s, &self.transactions); + s.append_list(&self.uncles); + } +} + impl Block { /// Get a copy of the header #[inline] @@ -154,14 +162,14 @@ impl BlockBuilder { let data = std::iter::repeat_with(|| rand::random::()) .take(data_len as usize) .collect::>(); - Transaction { + TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Create, value: 100.into(), data, - } + }) .sign(&keccak("").into(), None) }) .take(count); @@ -205,7 +213,7 @@ impl BlockBuilder { let metadata = get_metadata(); let block_number = parent_number + 1; let transactions = metadata.transactions; - let transactions_root = ordered_trie_root(transactions.iter().map(rlp::encode)); + let transactions_root = ordered_trie_root(transactions.iter().map(|tx| tx.encode())); block.header.set_parent_hash(parent_hash); block.header.set_number(block_number); diff --git a/ethcore/db/src/keys.rs b/ethcore/db/src/keys.rs index bd76559905..ded42045f3 100644 --- a/ethcore/db/src/keys.rs +++ b/ethcore/db/src/keys.rs @@ -18,12 +18,14 @@ use std::{io::Write, ops}; -use common_types::{engines::epoch::Transition as EpochTransition, receipt::Receipt, BlockNumber}; +use common_types::{ + engines::epoch::Transition as EpochTransition, receipt::TypedReceipt, BlockNumber, +}; use ethereum_types::{H256, H264, U256}; use heapsize::HeapSizeOf; use kvdb::PREFIX_LEN as DB_PREFIX_LEN; use rlp; -use rlp_derive::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; +use rlp_derive::{RlpDecodable, RlpEncodable}; use crate::db::Key; @@ -235,15 +237,27 @@ impl HeapSizeOf for TransactionAddress { } /// Contains all block receipts. -#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)] +#[derive(Clone)] pub struct BlockReceipts { /// Block receipts - pub receipts: Vec, + pub receipts: Vec, +} + +impl rlp::Encodable for BlockReceipts { + fn rlp_append(&self, s: &mut rlp::RlpStream) { + TypedReceipt::rlp_append_list(s, &self.receipts); + } +} + +impl rlp::Decodable for BlockReceipts { + fn decode(rlp: &rlp::Rlp) -> Result { + Ok(BlockReceipts::new(TypedReceipt::decode_rlp_list(rlp)?)) + } } impl BlockReceipts { /// Create new block receipts wrapper. - pub fn new(receipts: Vec) -> Self { + pub fn new(receipts: Vec) -> Self { BlockReceipts { receipts: receipts } } } diff --git a/ethcore/res/ethereum/yolo3_test.json b/ethcore/res/ethereum/yolo3_test.json index e50c2ace32..bb04f77482 100644 --- a/ethcore/res/ethereum/yolo3_test.json +++ b/ethcore/res/ethereum/yolo3_test.json @@ -44,7 +44,8 @@ "eip1884Transition": "0x0", "eip2028Transition": "0x0", "eip2315Transition": "0x0", - "eip2929Transition": "0x0" + "eip2929Transition": "0x0", + "eip2930Transition": "0x0" }, "genesis": { "seal": { diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 57a3414d3e..eee50c46d9 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -48,10 +48,10 @@ use verification::PreverifiedBlock; use vm::{EnvInfo, LastHashes}; use hash::keccak; -use rlp::{encode_list, Encodable, RlpStream}; +use rlp::{encode_list, RlpStream}; use types::{ header::{ExtendedHeader, Header}, - receipt::{Receipt, TransactionOutcome}, + receipt::{TransactionOutcome, TypedReceipt}, transaction::{Error as TransactionError, SignedTransaction}, }; @@ -99,7 +99,7 @@ pub struct ExecutedBlock { /// Uncles. pub uncles: Vec
, /// Transaction receipts. - pub receipts: Vec, + pub receipts: Vec, /// Hashes of already executed transactions. pub transactions_set: HashSet, /// Underlaying state. @@ -253,7 +253,7 @@ impl<'x> OpenBlock<'x> { &mut self, t: SignedTransaction, h: Option, - ) -> Result<&Receipt, Error> { + ) -> Result<&TypedReceipt, Error> { if self.block.transactions_set.contains(&t.hash()) { return Err(TransactionError::AlreadyImported.into()); } @@ -360,13 +360,13 @@ impl<'x> OpenBlock<'x> { // t_nb 8.5.3 fill open block header with all other fields s.block.header.set_transactions_root(ordered_trie_root( - s.block.transactions.iter().map(|e| e.rlp_bytes()), + s.block.transactions.iter().map(|e| e.encode()), )); let uncle_bytes = encode_list(&s.block.uncles); s.block.header.set_uncles_hash(keccak(&uncle_bytes)); s.block.header.set_state_root(s.block.state.root().clone()); s.block.header.set_receipts_root(ordered_trie_root( - s.block.receipts.iter().map(|r| r.rlp_bytes()), + s.block.receipts.iter().map(|r| r.encode()), )); s.block .header @@ -453,7 +453,7 @@ impl LockedBlock { receipt.outcome = TransactionOutcome::Unknown; } self.block.header.set_receipts_root(ordered_trie_root( - self.block.receipts.iter().map(|r| r.rlp_bytes()), + self.block.receipts.iter().map(|r| r.encode()), )); } @@ -503,7 +503,7 @@ impl SealedBlock { pub fn rlp_bytes(&self) -> Bytes { let mut block_rlp = RlpStream::new_list(3); block_rlp.append(&self.block.header); - block_rlp.append_list(&self.block.transactions); + SignedTransaction::rlp_append_list(&mut block_rlp, &self.block.transactions); block_rlp.append_list(&self.block.uncles); block_rlp.out() } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6a025ec2c4..0a61d20075 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -41,7 +41,7 @@ use itertools::Itertools; use kvdb::{DBTransaction, DBValue, KeyValueDB}; use parking_lot::{Mutex, RwLock}; use rand::OsRng; -use rlp::PayloadInfo; +use rlp::{PayloadInfo, Rlp}; use rustc_hex::FromHex; use trie::{Trie, TrieFactory, TrieSpec}; use types::{ @@ -51,8 +51,11 @@ use types::{ filter::Filter, header::{ExtendedHeader, Header}, log_entry::LocalizedLogEntry, - receipt::{LocalizedReceipt, Receipt}, - transaction::{self, Action, LocalizedTransaction, SignedTransaction, UnverifiedTransaction}, + receipt::{LocalizedReceipt, TypedReceipt}, + transaction::{ + self, Action, LocalizedTransaction, SignedTransaction, TypedTransaction, + UnverifiedTransaction, + }, BlockNumber, }; use vm::{EnvInfo, LastHashes}; @@ -524,7 +527,8 @@ impl Importer { db: &dyn KeyValueDB, chain: &BlockChain, ) -> EthcoreResult<()> { - let receipts = ::rlp::decode_list(receipts_bytes); + let receipts = TypedReceipt::decode_rlp_list(&Rlp::new(receipts_bytes)) + .unwrap_or_else(|e| panic!("Receipt bytes should be valid: {:?}", e)); let _import_lock = self.import_lock.lock(); { @@ -714,7 +718,7 @@ impl Importer { &self, header: &Header, block_bytes: &[u8], - receipts: &[Receipt], + receipts: &[TypedReceipt], state_db: &StateDB, client: &Client, ) -> EthcoreResult> { @@ -1436,7 +1440,7 @@ impl Client { data: Bytes, ) -> SignedTransaction { let from = Address::default(); - transaction::Transaction { + TypedTransaction::Legacy(transaction::Transaction { nonce: self .nonce(&from, block_id) .unwrap_or_else(|| self.engine.account_start_nonce(0)), @@ -1445,7 +1449,7 @@ impl Client { gas_price: U256::default(), value: U256::default(), data: data, - } + }) .fake_sign(from) } @@ -1889,7 +1893,7 @@ impl Call for Client { let exec = |gas| { let mut tx = t.as_unsigned().clone(); - tx.gas = gas; + tx.tx_mut().gas = gas; let tx = tx.fake_sign(sender); let mut clone = state.clone(); @@ -1920,6 +1924,7 @@ impl Call for Client { } } let lower = t + .tx() .gas_required(&self.engine.schedule(env_info.number)) .into(); if cond(lower) { @@ -2571,18 +2576,18 @@ impl BlockChainClient for Client { } else { self.importer.miner.sensible_gas_price() }; - let transaction = transaction::Transaction { + let transaction = TypedTransaction::Legacy(transaction::Transaction { nonce: self.latest_nonce(&authoring_params.author), action: Action::Call(address), gas: self.importer.miner.sensible_gas_limit(), gas_price, value: U256::zero(), data: data, - }; + }); let chain_id = self.engine.signing_chain_id(&self.latest_env_info()); let signature = self .engine - .sign(transaction.hash(chain_id)) + .sign(transaction.signature_hash(chain_id)) .map_err(|e| transaction::Error::InvalidSignature(e.to_string()))?; let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; self.importer @@ -2602,10 +2607,15 @@ impl IoClient for Client { self.queue_transactions .queue(&self.io_channel.read(), len, move |client| { trace_time!("import_queued_transactions"); - + let best_block_number = client.best_block_header().number(); let txs: Vec = transactions .iter() - .filter_map(|bytes| client.engine.decode_transaction(bytes).ok()) + .filter_map(|bytes| { + client + .engine + .decode_transaction(bytes, best_block_number) + .ok() + }) .collect(); client.notify(|notify| { @@ -2954,7 +2964,7 @@ impl ProvingBlockChainClient for Client { _ => return None, }; - env_info.gas_limit = transaction.gas.clone(); + env_info.gas_limit = transaction.tx().gas.clone(); let mut jdb = self.state_db.read().journal_db().boxed_clone(); state::prove_transaction_virtual( @@ -3112,7 +3122,7 @@ impl ImportExportBlocks for Client { fn transaction_receipt( machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, - receipt: Receipt, + receipt: TypedReceipt, prior_gas_used: U256, prior_no_of_logs: usize, ) -> LocalizedReceipt { @@ -3121,27 +3131,31 @@ fn transaction_receipt( let block_hash = tx.block_hash; let block_number = tx.block_number; let transaction_index = tx.transaction_index; + let transaction_type = tx.tx_type(); + + let receipt = receipt.receipt().clone(); LocalizedReceipt { from: sender, - to: match tx.action { + to: match tx.tx().action { Action::Create => None, Action::Call(ref address) => Some(address.clone().into()), }, transaction_hash: transaction_hash, transaction_index: transaction_index, + transaction_type: transaction_type, block_hash: block_hash, block_number: block_number, cumulative_gas_used: receipt.gas_used, gas_used: receipt.gas_used - prior_gas_used, - contract_address: match tx.action { + contract_address: match tx.tx().action { Action::Call(_) => None, Action::Create => Some( contract_address( machine.create_address_scheme(block_number), &sender, - &tx.nonce, - &tx.data, + &tx.tx().nonce, + &tx.tx().data, ) .0, ), @@ -3161,7 +3175,7 @@ fn transaction_receipt( }) .collect(), log_bloom: receipt.log_bloom, - outcome: receipt.outcome, + outcome: receipt.outcome.clone(), } } @@ -3457,8 +3471,8 @@ mod tests { use hash::keccak; use types::{ log_entry::{LocalizedLogEntry, LogEntry}, - receipt::{LocalizedReceipt, Receipt, TransactionOutcome}, - transaction::{Action, LocalizedTransaction, Transaction}, + receipt::{LegacyReceipt, LocalizedReceipt, TransactionOutcome, TypedReceipt}, + transaction::{Action, LocalizedTransaction, Transaction, TypedTransaction}, }; // given @@ -3470,14 +3484,14 @@ mod tests { let block_hash = 5.into(); let state_root = 99.into(); let gas_used = 10.into(); - let raw_tx = Transaction { + let raw_tx = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(10.into()), value: 0.into(), data: vec![], - }; + }); let tx1 = raw_tx.clone().sign(secret, None); let transaction = LocalizedTransaction { signed: tx1.clone().into(), @@ -3498,12 +3512,12 @@ mod tests { data: vec![], }, ]; - let receipt = Receipt { + let receipt = TypedReceipt::Legacy(LegacyReceipt { outcome: TransactionOutcome::StateRoot(state_root), gas_used: gas_used, log_bloom: Default::default(), logs: logs.clone(), - }; + }); // when let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1); @@ -3513,12 +3527,13 @@ mod tests { receipt, LocalizedReceipt { from: tx1.sender().into(), - to: match tx1.action { + to: match tx1.tx().action { Action::Create => None, Action::Call(ref address) => Some(address.clone().into()), }, transaction_hash: tx1.hash(), transaction_index: 1, + transaction_type: tx1.tx_type(), block_hash: block_hash, block_number: block_number, cumulative_gas_used: gas_used, diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 8a9327f752..d55e9faf45 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -281,7 +281,7 @@ impl<'a> EvmTestClient<'a> { tracer: T, vm_tracer: V, ) -> std::result::Result, TransactErr> { - let initial_gas = transaction.gas; + let initial_gas = transaction.tx().gas; // Verify transaction let is_ok = transaction.verify_basic(true, None); if let Err(error) = is_ok { @@ -342,18 +342,18 @@ impl<'a> EvmTestClient<'a> { Ok(result) => Ok(TransactSuccess { state_root, gas_left: initial_gas - result.receipt.gas_used, - outcome: result.receipt.outcome, + outcome: result.receipt.outcome.clone(), output: result.output, trace: result.trace, vm_trace: result.vm_trace, - logs: result.receipt.logs, - contract_address: if let transaction::Action::Create = transaction.action { + logs: result.receipt.logs.clone(), + contract_address: if let transaction::Action::Create = transaction.tx().action { Some( executive::contract_address( scheme, &transaction.sender(), - &transaction.nonce, - &transaction.data, + &transaction.tx().nonce, + &transaction.tx().data, ) .0, ) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index f48fc477ae..2de1b62920 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -36,7 +36,7 @@ use itertools::Itertools; use kvdb::DBValue; use kvdb_memorydb; use parking_lot::RwLock; -use rlp::{Rlp, RlpStream}; +use rlp::RlpStream; use rustc_hex::FromHex; use types::{ basic_account::BasicAccount, @@ -45,8 +45,11 @@ use types::{ header::Header, log_entry::LocalizedLogEntry, pruning_info::PruningInfo, - receipt::{LocalizedReceipt, Receipt, TransactionOutcome}, - transaction::{self, Action, LocalizedTransaction, SignedTransaction, Transaction}, + receipt::{LegacyReceipt, LocalizedReceipt, TransactionOutcome, TypedReceipt}, + transaction::{ + self, Action, LocalizedTransaction, SignedTransaction, Transaction, TypedTransaction, + TypedTxId, + }, view, views::BlockView, BlockNumber, @@ -296,16 +299,16 @@ impl TestBlockChainClient { for _ in 0..num_transactions { // Update nonces value - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: U256::from(200_000_000_000u64), nonce: nonce, - }; + }); let signed_tx = tx.sign(keypair.secret(), None); - txs.append(&signed_tx); + signed_tx.rlp_append(&mut txs); nonce += U256::one(); } @@ -369,14 +372,14 @@ impl TestBlockChainClient { /// Inserts a transaction with given gas price to miners transactions queue. pub fn insert_transaction_with_gas_price_to_queue(&self, gas_price: U256) -> H256 { let keypair = Random.generate().unwrap(); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: gas_price, nonce: U256::zero(), - }; + }); let signed_tx = tx.sign(keypair.secret(), None); self.set_balance(signed_tx.sender(), 10_000_000_000_000_000_000u64.into()); let hash = signed_tx.hash(); @@ -938,10 +941,13 @@ impl BlockChainClient for TestBlockChainClient { fn block_receipts(&self, hash: &H256) -> Option { // starts with 'f' ? if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { - let receipt = BlockReceipts::new(vec![Receipt::new( - TransactionOutcome::StateRoot(H256::zero()), - U256::zero(), - vec![], + let receipt = BlockReceipts::new(vec![TypedReceipt::new( + TypedTxId::Legacy, + LegacyReceipt::new( + TransactionOutcome::StateRoot(H256::zero()), + U256::zero(), + vec![], + ), )]); return Some(receipt); } @@ -1027,16 +1033,20 @@ impl BlockChainClient for TestBlockChainClient { } fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> { - let transaction = Transaction { + let transaction = TypedTransaction::Legacy(Transaction { nonce: self.latest_nonce(&self.miner.authoring_params().author), action: Action::Call(address), gas: self.spec.gas_limit, gas_price: U256::zero(), value: U256::default(), data: data, - }; + }); let chain_id = Some(self.spec.chain_id()); - let sig = self.spec.engine.sign(transaction.hash(chain_id)).unwrap(); + let sig = self + .spec + .engine + .sign(transaction.signature_hash(chain_id)) + .unwrap(); let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap(); self.miner.import_own_transaction(self, signed.into()) } @@ -1051,7 +1061,7 @@ impl IoClient for TestBlockChainClient { // import right here let txs = transactions .into_iter() - .filter_map(|bytes| Rlp::new(&bytes).as_val().ok()) + .filter_map(|bytes| TypedTransaction::decode(&bytes).ok()) .collect(); self.miner.import_external_transactions(self, txs); } diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index e730655877..dc232c2f9d 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1765,7 +1765,7 @@ mod tests { use test_helpers::{generate_dummy_client_with_spec, get_temp_state_db, TestNotify}; use types::{ header::Header, - transaction::{Action, Transaction}, + transaction::{Action, Transaction, TypedTransaction}, }; fn aura(f: F) -> Arc @@ -2287,14 +2287,14 @@ mod tests { ) .unwrap(); b2.push_transaction( - Transaction { + TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(0), gas_price: U256::from(3000), gas: U256::from(53_000), value: U256::from(1), data: vec![], - } + }) .fake_sign(addr2), None, ) diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index ca362859dc..7c49fea562 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -605,8 +605,10 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { fn decode_transaction( &self, transaction: &[u8], + best_block_number: BlockNumber, ) -> Result { - self.machine().decode_transaction(transaction) + let schedule = self.schedule(best_block_number); + self.machine().decode_transaction(transaction, &schedule) } } diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 569510a8d8..39256c360e 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -25,7 +25,7 @@ use kvdb::DBValue; use memory_cache::MemoryLruCache; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; -use types::{header::Header, ids::BlockId, log_entry::LogEntry, receipt::Receipt}; +use types::{header::Header, ids::BlockId, log_entry::LogEntry, receipt::TypedReceipt}; use unexpected::Mismatch; use super::{simple_list::SimpleList, SystemCall, ValidatorSet}; @@ -91,7 +91,7 @@ fn check_first_proof( old_header: Header, state_items: &[DBValue], ) -> Result, String> { - use types::transaction::{Action, Transaction}; + use types::transaction::{Action, Transaction, TypedTransaction}; // TODO: match client contract_call_tx more cleanly without duplication. const PROVIDED_GAS: u64 = 50_000_000; @@ -116,14 +116,14 @@ fn check_first_proof( let (data, decoder) = validator_set::functions::get_validators::call(); let from = Address::default(); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: machine.account_start_nonce(number), action: Action::Call(contract_address), gas: PROVIDED_GAS.into(), gas_price: U256::default(), value: U256::default(), data, - } + }) .fake_sign(from); let res = ::state::check_proof( @@ -161,14 +161,15 @@ fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Erro // inter-contract proofs are a header and receipts. // checking will involve ensuring that the receipts match the header and // extracting the validator set from the receipts. -fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes { +fn encode_proof(header: &Header, receipts: &[TypedReceipt]) -> Bytes { let mut stream = RlpStream::new_list(2); - stream.append(header).append_list(receipts); + stream.append(header); + TypedReceipt::rlp_append_list(&mut stream, receipts); stream.drain() } -fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { - Ok((rlp.val_at(0)?, rlp.list_at(1)?)) +fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { + Ok((rlp.val_at(0)?, TypedReceipt::decode_rlp_list(&rlp.at(1)?)?)) } // given a provider and caller, generate proof. this will just be a state proof @@ -265,7 +266,7 @@ impl ValidatorSafeContract { &self, bloom: Bloom, header: &Header, - receipts: &[Receipt], + receipts: &[TypedReceipt], ) -> Option { let check_log = |log: &LogEntry| { log.address == self.contract_address @@ -406,7 +407,7 @@ impl ValidatorSet for ValidatorSafeContract { // ensure receipts match header. // TODO: optimize? these were just decoded. - let found_root = ::triehash::ordered_trie_root(receipts.iter().map(::rlp::encode)); + let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| r.encode())); if found_root != *old_header.receipts_root() { return Err(::error::BlockError::InvalidReceiptsRoot(Mismatch { expected: *old_header.receipts_root(), @@ -491,7 +492,7 @@ mod tests { use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; use types::{ ids::BlockId, - transaction::{Action, Transaction}, + transaction::{Action, Transaction, TypedTransaction}, }; use verification::queue::kind::blocks::Unverified; @@ -537,7 +538,7 @@ mod tests { client.miner().set_author(miner::Author::Sealer(signer)); // Remove "1" validator. - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 500_000.into(), @@ -546,7 +547,7 @@ mod tests { data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1" .from_hex() .unwrap(), - } + }) .sign(&s0, Some(chain_id)); client .miner() @@ -555,7 +556,7 @@ mod tests { EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 1); // Add "1" validator back in. - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: 1.into(), gas_price: 0.into(), gas: 500_000.into(), @@ -564,7 +565,7 @@ mod tests { data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1" .from_hex() .unwrap(), - } + }) .sign(&s0, Some(chain_id)); client .miner() @@ -582,14 +583,14 @@ mod tests { // Switch back to the added validator, since the state is updated. let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: 2.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(Address::default()), value: 0.into(), data: Vec::new(), - } + }) .sign(&s0, Some(chain_id)); client .miner() diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 85394fa3d2..dddc53ec70 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -28,7 +28,7 @@ use state::{Backend as StateBackend, CleanupMode, State, Substate}; use std::{cmp, sync::Arc}; use trace::{self, Tracer, VMTracer}; use transaction_ext::Transaction; -use types::transaction::{Action, SignedTransaction}; +use types::transaction::{Action, SignedTransaction, TypedTransaction}; use vm::{ self, AccessList, ActionParams, ActionValue, CleanDustMode, CreateContractAddress, EnvInfo, ResumeCall, ResumeCreate, ReturnData, Schedule, TrapError, @@ -1109,7 +1109,10 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { { let sender = t.sender(); let balance = self.state.balance(&sender)?; - let needed_balance = t.value.saturating_add(t.gas.saturating_mul(t.gas_price)); + let needed_balance = t + .tx() + .value + .saturating_add(t.tx().gas.saturating_mul(t.tx().gas_price)); if balance < needed_balance { // give the sender a sufficient balance self.state @@ -1132,16 +1135,51 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { T: Tracer, V: VMTracer, { + let schedule = self.schedule; + + // check if particualar transaction type is enabled at this block number in schedule + match t.as_unsigned() { + TypedTransaction::AccessList(_) => { + if !schedule.eip2930 { + return Err(ExecutionError::TransactionMalformed( + "OptionalAccessList EIP-2930 or EIP-2929 not enabled".into(), + )); + } + } + TypedTransaction::Legacy(_) => (), //legacy transactions are allways valid + }; + let sender = t.sender(); let nonce = self.state.nonce(&sender)?; - let schedule = self.schedule; - let base_gas_required = U256::from(t.gas_required(&schedule)); + let mut base_gas_required = U256::from(t.tx().gas_required(&schedule)); + + let mut access_list = AccessList::new(schedule.eip2929); - if t.gas < base_gas_required { + if schedule.eip2929 { + for (address, _) in self.machine.builtins() { + access_list.insert_address(*address); + } + if schedule.eip2930 { + // optional access list + if let TypedTransaction::AccessList(al_tx) = t.as_unsigned() { + for item in al_tx.access_list.iter() { + access_list.insert_address(item.0); + base_gas_required += vm::schedule::EIP2930_ACCESS_LIST_ADDRESS_COST.into(); + for key in item.1.iter() { + access_list.insert_storage_key(item.0, *key); + base_gas_required += + vm::schedule::EIP2930_ACCESS_LIST_STORAGE_KEY_COST.into(); + } + } + } + } + } + + if t.tx().gas < base_gas_required { return Err(ExecutionError::NotEnoughBaseGas { required: base_gas_required, - got: t.gas, + got: t.tx().gas, }); } @@ -1153,29 +1191,29 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { return Err(ExecutionError::SenderMustExist); } - let init_gas = t.gas - base_gas_required; + let init_gas = t.tx().gas - base_gas_required; // validate transaction nonce - if check_nonce && t.nonce != nonce { + if check_nonce && t.tx().nonce != nonce { return Err(ExecutionError::InvalidNonce { expected: nonce, - got: t.nonce, + got: t.tx().nonce, }); } // validate if transaction fits into given block - if self.info.gas_used + t.gas > self.info.gas_limit { + if self.info.gas_used + t.tx().gas > self.info.gas_limit { return Err(ExecutionError::BlockGasLimitReached { gas_limit: self.info.gas_limit, gas_used: self.info.gas_used, - gas: t.gas, + gas: t.tx().gas, }); } // TODO: we might need bigints here, or at least check overflows. let balance = self.state.balance(&sender)?; - let gas_cost = t.gas.full_mul(t.gas_price); - let total_cost = U512::from(t.value) + gas_cost; + let gas_cost = t.tx().gas.full_mul(t.tx().gas_price); + let total_cost = U512::from(t.tx().value) + gas_cost; // avoid unaffordable transactions let balance512 = U512::from(balance); @@ -1186,13 +1224,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { }); } - let mut access_list = AccessList::new(schedule.eip2929); - if schedule.eip2929 { - for (address, _) in self.machine.builtins() { - access_list.insert_address(*address); - } - } - let mut substate = Substate::from_access_list(&access_list); // NOTE: there can be no invalid transactions from this point. @@ -1205,13 +1236,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { &mut substate.to_cleanup_mode(&schedule), )?; - let (result, output) = match t.action { + let (result, output) = match t.tx().action { Action::Create => { let (new_address, code_hash) = contract_address( self.machine.create_address_scheme(self.info.number), &sender, &nonce, - &t.data, + &t.tx().data, ); let params = ActionParams { code_address: new_address.clone(), @@ -1220,9 +1251,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { sender: sender.clone(), origin: sender.clone(), gas: init_gas, - gas_price: t.gas_price, - value: ActionValue::Transfer(t.value), - code: Some(Arc::new(t.data.clone())), + gas_price: t.tx().gas_price, + value: ActionValue::Transfer(t.tx().value), + code: Some(Arc::new(t.tx().data.clone())), data: None, call_type: CallType::None, params_type: vm::ParamsType::Embedded, @@ -1242,11 +1273,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { sender: sender.clone(), origin: sender.clone(), gas: init_gas, - gas_price: t.gas_price, - value: ActionValue::Transfer(t.value), + gas_price: t.tx().gas_price, + value: ActionValue::Transfer(t.tx().value), code: self.state.code(address)?, code_hash: self.state.code_hash(address)?, - data: Some(t.data.clone()), + data: Some(t.tx().data.clone()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, access_list: access_list, @@ -1445,12 +1476,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { Ok(FinalizationResult { gas_left, .. }) => gas_left, _ => 0.into(), }; - let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1); + let refunded = cmp::min(refunds_bound, (t.tx().gas - gas_left_prerefund) >> 1); let gas_left = gas_left_prerefund + refunded; - let gas_used = t.gas.saturating_sub(gas_left); - let (refund_value, overflow_1) = gas_left.overflowing_mul(t.gas_price); - let (fees_value, overflow_2) = gas_used.overflowing_mul(t.gas_price); + let gas_used = t.tx().gas.saturating_sub(gas_left); + let (refund_value, overflow_1) = gas_left.overflowing_mul(t.tx().gas_price); + let (fees_value, overflow_2) = gas_used.overflowing_mul(t.tx().gas_price); if overflow_1 || overflow_2 { return Err(ExecutionError::TransactionMalformed( "U256 Overflow".to_string(), @@ -1458,7 +1489,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { } trace!("exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={}\n", - t.gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value); + t.tx().gas, sstore_refunds, suicide_refunds, refunds_bound, gas_left_prerefund, refunded, gas_left, gas_used, refund_value, fees_value); let sender = t.sender(); trace!( @@ -1487,7 +1518,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { // perform garbage-collection let min_balance = if schedule.kill_dust != CleanDustMode::Off { - Some(U256::from(schedule.tx_gas).overflowing_mul(t.gas_price).0) + Some( + U256::from(schedule.tx_gas) + .overflowing_mul(t.tx().gas_price) + .0, + ) } else { None }; @@ -1502,10 +1537,10 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { Err(vm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)), Err(exception) => Ok(Executed { exception: Some(exception), - gas: t.gas, - gas_used: t.gas, + gas: t.tx().gas, + gas_used: t.tx().gas, refunded: U256::zero(), - cumulative_gas_used: self.info.gas_used + t.gas, + cumulative_gas_used: self.info.gas_used + t.tx().gas, logs: vec![], contracts_created: vec![], output: output, @@ -1519,7 +1554,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { } else { Some(vm::Error::Reverted) }, - gas: t.gas, + gas: t.tx().gas, gas_used: gas_used, refunded: refunded, cumulative_gas_used: self.info.gas_used + gas_used, @@ -1551,7 +1586,7 @@ mod tests { trace, ExecutiveTracer, ExecutiveVMTracer, FlatTrace, MemoryDiff, NoopTracer, NoopVMTracer, StorageDiff, Tracer, VMExecutedOperation, VMOperation, VMTrace, VMTracer, }; - use types::transaction::{Action, Transaction}; + use types::transaction::{Action, Transaction, TypedTransaction}; use vm::{ActionParams, ActionValue, CallType, CreateContractAddress, EnvInfo}; fn make_frontier_machine(max_depth: usize) -> EthereumMachine { @@ -2445,14 +2480,14 @@ mod tests { evm_test_ignore! {test_transact_simple: test_transact_simple_int} fn test_transact_simple(factory: Factory) { let keypair = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: U256::zero(), nonce: U256::zero(), - } + }) .sign(keypair.secret(), None); let sender = t.sender(); let contract = contract_address( @@ -2496,14 +2531,14 @@ mod tests { evm_test! {test_transact_invalid_nonce: test_transact_invalid_nonce_int} fn test_transact_invalid_nonce(factory: Factory) { let keypair = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: U256::zero(), nonce: U256::one(), - } + }) .sign(keypair.secret(), None); let sender = t.sender(); @@ -2535,14 +2570,14 @@ mod tests { evm_test! {test_transact_gas_limit_reached: test_transact_gas_limit_reached_int} fn test_transact_gas_limit_reached(factory: Factory) { let keypair = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), data: "3331600055".from_hex().unwrap(), gas: U256::from(80_001), gas_price: U256::zero(), nonce: U256::zero(), - } + }) .sign(keypair.secret(), None); let sender = t.sender(); @@ -2580,14 +2615,14 @@ mod tests { evm_test! {test_not_enough_cash: test_not_enough_cash_int} fn test_not_enough_cash(factory: Factory) { let keypair = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(18), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: U256::one(), nonce: U256::zero(), - } + }) .sign(keypair.secret(), None); let sender = t.sender(); diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index 1146e24e3a..1d22bccb81 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -17,10 +17,12 @@ use super::test_common::*; use client::EvmTestClient; use ethjson; -use rlp::Rlp; use std::path::Path; use transaction_ext::Transaction; -use types::{header::Header, transaction::UnverifiedTransaction}; +use types::{ + header::Header, + transaction::{TypedTransaction, UnverifiedTransaction}, +}; pub fn json_transaction_test( path: &Path, @@ -65,8 +67,7 @@ pub fn json_transaction_test( }; let rlp: Vec = test.rlp.clone().into(); - let res = Rlp::new(&rlp) - .as_val() + let res = TypedTransaction::decode(&rlp) .map_err(::error::Error::from) .and_then(|t: UnverifiedTransaction| { let mut header: Header = Default::default(); @@ -74,12 +75,13 @@ pub fn json_transaction_test( header.set_number(BLOCK_NUMBER); let minimal = t + .tx() .gas_required(&spec.engine.schedule(header.number())) .into(); - if t.gas < minimal { + if t.tx().gas < minimal { return Err(::types::transaction::Error::InsufficientGas { minimal, - got: t.gas, + got: t.tx().gas, } .into()); } diff --git a/ethcore/src/machine/impls.rs b/ethcore/src/machine/impls.rs index 890b2854f7..5bfaba1d33 100644 --- a/ethcore/src/machine/impls.rs +++ b/ethcore/src/machine/impls.rs @@ -23,11 +23,11 @@ use std::{ }; use ethereum_types::{Address, H256, U256}; -use rlp::Rlp; use types::{ header::Header, transaction::{ - self, SignedTransaction, UnverifiedTransaction, SYSTEM_ADDRESS, UNSIGNED_SENDER, + self, SignedTransaction, TypedTransaction, UnverifiedTransaction, SYSTEM_ADDRESS, + UNSIGNED_SENDER, }, BlockNumber, }; @@ -455,17 +455,27 @@ impl EthereumMachine { pub fn decode_transaction( &self, transaction: &[u8], + schedule: &Schedule, ) -> Result { - let rlp = Rlp::new(&transaction); - if rlp.as_raw().len() > self.params().max_transaction_size { + if transaction.len() > self.params().max_transaction_size { debug!( "Rejected oversized transaction of {} bytes", - rlp.as_raw().len() + transaction.len() ); return Err(transaction::Error::TooBig); } - rlp.as_val() - .map_err(|e| transaction::Error::InvalidRlp(e.to_string())) + + let tx = TypedTransaction::decode(transaction) + .map_err(|e| transaction::Error::InvalidRlp(e.to_string()))?; + + match tx.tx_type() { + transaction::TypedTxId::AccessList if schedule.eip2930 => { + return Err(transaction::Error::TransactionTypeNotEnabled) + } + _ => (), + }; + + Ok(tx) } } @@ -476,7 +486,7 @@ pub struct AuxiliaryData<'a> { /// The full block bytes, including the header. pub bytes: Option<&'a [u8]>, /// The block receipts. - pub receipts: Option<&'a [::types::receipt::Receipt]>, + pub receipts: Option<&'a [::types::receipt::TypedReceipt]>, } /// Type alias for a function we can make calls through synchronously. @@ -550,7 +560,7 @@ mod tests { fn should_disallow_unsigned_transactions() { let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080"; let transaction: UnverifiedTransaction = - ::rlp::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap(); + TypedTransaction::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap(); let spec = ::ethereum::new_ropsten_test(); let ethparams = get_default_ethash_extensions(); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c65f97a1af..919059d20b 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1195,15 +1195,16 @@ impl miner::MinerService for Miner { let receipt = &receipts[index]; RichReceipt { from: tx.sender(), - to: match tx.action { + to: match tx.tx().action { Action::Create => None, Action::Call(ref address) => Some(*address), }, transaction_hash: tx.hash(), + transaction_type: tx.tx_type(), transaction_index: index, cumulative_gas_used: receipt.gas_used, gas_used: receipt.gas_used - prev_gas, - contract_address: match tx.action { + contract_address: match tx.tx().action { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); @@ -1212,8 +1213,8 @@ impl miner::MinerService for Miner { self.engine .create_address_scheme(pending.header.number()), &sender, - &tx.nonce, - &tx.data, + &tx.tx().nonce, + &tx.tx().data, ) .0, ) @@ -1509,7 +1510,7 @@ mod tests { use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient}; use miner::{MinerService, PendingOrdering}; use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec}; - use types::transaction::Transaction; + use types::transaction::{Transaction, TypedTransaction}; #[test] fn should_prepare_block_to_seal() { @@ -1583,14 +1584,14 @@ mod tests { fn transaction_with_chain_id(chain_id: u64) -> SignedTransaction { let keypair = Random.generate().unwrap(); - Transaction { + TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::zero(), data: "3331600055".from_hex().unwrap(), gas: U256::from(100_000), gas_price: U256::zero(), nonce: U256::zero(), - } + }) .sign(keypair.secret(), Some(chain_id)) } diff --git a/ethcore/src/miner/pool_client.rs b/ethcore/src/miner/pool_client.rs index b3eb6d229f..d4e9f198a6 100644 --- a/ethcore/src/miner/pool_client.rs +++ b/ethcore/src/miner/pool_client.rs @@ -195,7 +195,8 @@ where &self, transaction: &[u8], ) -> Result { - self.engine.decode_transaction(transaction) + let number = self.chain.best_block_header().number(); + self.engine.decode_transaction(transaction, number) } } diff --git a/ethcore/src/snapshot/block.rs b/ethcore/src/snapshot/block.rs index 5d29fccd1d..c602f6088c 100644 --- a/ethcore/src/snapshot/block.rs +++ b/ethcore/src/snapshot/block.rs @@ -21,7 +21,7 @@ use ethereum_types::H256; use hash::keccak; use rlp::{DecoderError, Rlp, RlpStream}; use triehash::ordered_trie_root; -use types::{block::Block, header::Header, views::BlockView}; +use types::{block::Block, header::Header, transaction::TypedTransaction, views::BlockView}; const HEADER_FIELDS: usize = 8; const BLOCK_FIELDS: usize = 2; @@ -62,9 +62,9 @@ impl AbridgedBlock { .append(&header.extra_data()); // write block values. - stream - .append_list(&block_view.transactions()) - .append_list(&block_view.uncles()); + + TypedTransaction::rlp_append_list(&mut stream, &block_view.transactions()); + stream.append_list(&block_view.uncles()); // write seal fields. for field in seal_fields { @@ -97,10 +97,17 @@ impl AbridgedBlock { header.set_timestamp(rlp.val_at(6)?); header.set_extra_data(rlp.val_at(7)?); - let transactions = rlp.list_at(8)?; + let transactions = TypedTransaction::decode_rlp_list(&rlp.at(8)?)?; let uncles: Vec
= rlp.list_at(9)?; - header.set_transactions_root(ordered_trie_root(rlp.at(8)?.iter().map(|r| r.as_raw()))); + header.set_transactions_root(ordered_trie_root(rlp.at(8)?.iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + // We already checked if list is valid with decode_rlp_list above + r.data().expect("To raw rlp list to be valid") + } + }))); header.set_receipts_root(receipts_root); let mut uncles_rlp = RlpStream::new(); @@ -131,7 +138,7 @@ mod tests { use ethereum_types::{Address, H256, U256}; use types::{ block::Block, - transaction::{Action, Transaction}, + transaction::{Action, Transaction, TypedTransaction}, view, views::BlockView, }; @@ -165,24 +172,24 @@ mod tests { fn with_transactions() { let mut b = Block::default(); - let t1 = Transaction { + let t1 = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), gas_price: U256::from(3000), gas: U256::from(50_000), value: U256::from(1), data: b"Hello!".to_vec(), - } + }) .fake_sign(Address::from(0x69)); - let t2 = Transaction { + let t2 = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(88), gas_price: U256::from(12345), gas: U256::from(300000), value: U256::from(1000000000), data: "Eep!".into(), - } + }) .fake_sign(Address::from(0x55)); b.transactions.push(t1.into()); @@ -191,7 +198,7 @@ mod tests { let receipts_root = b.header.receipts_root().clone(); b.header .set_transactions_root(::triehash::ordered_trie_root( - b.transactions.iter().map(::rlp::encode), + b.transactions.iter().map(|tx| tx.encode()), )); let encoded = encode_block(&b); diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 6d4c1daf05..9c74e9ec02 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -36,7 +36,9 @@ use ethereum_types::{H256, U256}; use itertools::{Itertools, Position}; use kvdb::KeyValueDB; use rlp::{Rlp, RlpStream}; -use types::{encoded, header::Header, ids::BlockId, receipt::Receipt}; +use types::{ + encoded, header::Header, ids::BlockId, receipt::TypedReceipt, transaction::TypedTransaction, +}; /// Snapshot creation and restoration for PoA chains. /// Chunk format: @@ -114,9 +116,9 @@ impl SnapshotComponents for PoaSnapshot { rlps.push({ let mut stream = RlpStream::new_list(5); + stream.append(&block.header); + TypedTransaction::rlp_append_list(&mut stream, &block.transactions); stream - .append(&block.header) - .append_list(&block.transactions) .append_list(&block.uncles) .append(&receipts) .append(&parent_td); @@ -349,11 +351,11 @@ impl Rebuilder for ChunkRebuilder { let last_rlp = rlp.at(num_items - 1)?; let block = Block { header: last_rlp.val_at(0)?, - transactions: last_rlp.list_at(1)?, + transactions: TypedTransaction::decode_rlp_list(&last_rlp.at(1)?)?, uncles: last_rlp.list_at(2)?, }; let block_data = block.rlp_bytes(); - let receipts: Vec = last_rlp.list_at(3)?; + let receipts = TypedReceipt::decode_rlp_list(&last_rlp.at(3)?)?; { let hash = block.header.hash(); diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 8bbb06fca7..46d4edd85a 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -291,8 +291,15 @@ impl Rebuilder for PowRebuilder { let pair = rlp.at(idx)?; let abridged_rlp = pair.at(0)?.as_raw().to_owned(); let abridged_block = AbridgedBlock::from_raw(abridged_rlp); - let receipts: Vec<::types::receipt::Receipt> = pair.list_at(1)?; - let receipts_root = ordered_trie_root(pair.at(1)?.iter().map(|r| r.as_raw())); + let receipts = ::types::receipt::TypedReceipt::decode_rlp_list(&pair.at(1)?)?; + let receipts_root = ordered_trie_root(pair.at(1)?.iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + // We have allready checked validity by decoding rlp list in line above + r.data().expect("Expect for raw receipts list to be valid.") + } + })); let block = abridged_block.to_block(parent_hash, cur_number, receipts_root)?; let block_bytes = encoded::Block::new(block.rlp_bytes()); diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 229a9f4341..a68e90cb90 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -25,7 +25,7 @@ use snapshot::tests::helpers as snapshot_helpers; use spec::Spec; use tempdir::TempDir; use test_helpers::generate_dummy_client_with_spec; -use types::transaction::{Action, SignedTransaction, Transaction}; +use types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction}; use ethereum_types::Address; use test_helpers; @@ -128,14 +128,14 @@ fn make_chain( // and force sealing. let make_useless_transactions = || { let mut nonce = nonce.borrow_mut(); - let transaction = Transaction { + let transaction = TypedTransaction::Legacy(Transaction { nonce: *nonce, gas_price: 1.into(), gas: 21_000.into(), action: Action::Call(Address::new()), value: 1.into(), data: Vec::new(), - } + }) .sign(&*RICH_SECRET, client.signing_chain_id()); *nonce = *nonce + 1; @@ -171,14 +171,14 @@ fn make_chain( let data = test_validator_set::functions::set_validators::encode_input(new_set.clone()); let mut nonce = nonce.borrow_mut(); - let transaction = Transaction { + let transaction = TypedTransaction::Legacy(Transaction { nonce: *nonce, gas_price: 0.into(), gas: 1_000_000.into(), action: Action::Call(*address), value: 0.into(), data, - } + }) .sign(&*RICH_SECRET, client.signing_chain_id()); *nonce = *nonce + 1; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 7ca2cd1baf..90bdc19235 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -301,7 +301,7 @@ fn recover_aborted_recovery() { generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, 5, &gas_prices); let spec = Spec::new_null(); - let tempdir = TempDir::new("").unwrap(); + let tempdir = TempDir::new("oe_snapshot").unwrap(); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let client_db = new_db(); let client2 = Client::new( diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 85a7589e4c..bdc60714fc 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -137,6 +137,8 @@ pub struct CommonParams { pub eip2315_transition: BlockNumber, /// Number of first block where EIP-2929 rules begin. pub eip2929_transition: BlockNumber, + /// Number of first block where EIP-2930 rules begin. + pub eip2930_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -212,6 +214,7 @@ impl CommonParams { schedule.eip1706 = block_number >= self.eip1706_transition; schedule.have_subs = block_number >= self.eip2315_transition; schedule.eip2929 = block_number >= self.eip2929_transition; + schedule.eip2930 = block_number >= self.eip2930_transition; if block_number >= self.eip1884_transition { schedule.have_selfbalance = true; @@ -370,6 +373,9 @@ impl From for CommonParams { eip2929_transition: p .eip2929_transition .map_or_else(BlockNumber::max_value, Into::into), + eip2930_transition: p + .eip2930_transition + .map_or_else(BlockNumber::max_value, Into::into), dust_protection_transition: p .dust_protection_transition .map_or_else(BlockNumber::max_value, Into::into), @@ -956,7 +962,7 @@ impl Spec { /// initialize genesis epoch data, using in-memory database for /// constructor. pub fn genesis_epoch_data(&self) -> Result, String> { - use types::transaction::{Action, Transaction}; + use types::transaction::{Action, Transaction, TypedTransaction}; let genesis = self.genesis_header(); @@ -983,14 +989,14 @@ impl Spec { }; let from = Address::default(); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: self.engine.account_start_nonce(0), action: Action::Call(a), gas: U256::max_value(), gas_price: U256::default(), value: U256::default(), data: d, - } + }) .fake_sign(from); let res = ::state::prove_transaction_virtual( diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 66da05f270..5759f5f4fd 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -38,10 +38,11 @@ use state_db::StateDB; use trace::{self, FlatTrace, VMTrace}; use types::{ basic_account::BasicAccount, - receipt::{Receipt, TransactionOutcome}, + receipt::{LegacyReceipt, TransactionOutcome, TypedReceipt}, state_diff::StateDiff, transaction::SignedTransaction, }; + use vm::EnvInfo; use bytes::Bytes; @@ -63,7 +64,7 @@ pub use self::{account::Account, backend::Backend, substate::Substate}; /// Used to return information about an `State::apply` operation. pub struct ApplyOutcome { /// The receipt for the applied transaction. - pub receipt: Receipt, + pub receipt: TypedReceipt, /// The output of the applied transaction. pub output: Bytes, /// The trace for the applied transaction, empty if tracing was not produced. @@ -955,7 +956,10 @@ impl State { }; let output = e.output; - let receipt = Receipt::new(outcome, e.cumulative_gas_used, e.logs); + let receipt = TypedReceipt::new( + t.tx_type(), + LegacyReceipt::new(outcome, e.cumulative_gas_used, e.logs), + ); trace!(target: "state", "Transaction receipt: {:?}", receipt); Ok(ApplyOutcome { @@ -1602,7 +1606,7 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), @@ -1610,7 +1614,7 @@ mod tests { value: 100.into(), data: FromHex::from_hex("601080600c6000396000f3006000355415600957005b60203560003555") .unwrap(), - } + }) .sign(&secret(), None); state @@ -1667,14 +1671,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Create, value: 100.into(), data: FromHex::from_hex("5b600056").unwrap(), - } + }) .sign(&secret(), None); state @@ -1706,14 +1710,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -1753,14 +1757,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -1797,14 +1801,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = Spec::new_test_machine(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0x1.into()), value: 0.into(), data: vec![], - } + }) .sign(&secret(), None); let result = state.apply(&info, &machine, &t, true).unwrap(); @@ -1839,14 +1843,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = Spec::new_test_machine(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 0.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -1887,14 +1891,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = Spec::new_test_machine(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 0.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -1957,14 +1961,14 @@ mod tests { info.number = 0x789b0; let machine = Spec::new_test_machine(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 0.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2029,14 +2033,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2073,14 +2077,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2145,14 +2149,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2210,14 +2214,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2260,14 +2264,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], //600480600b6000396000f35b600056 - } + }) .sign(&secret(), None); state @@ -2328,14 +2332,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state @@ -2421,14 +2425,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], //600480600b6000396000f35b600056 - } + }) .sign(&secret(), None); state @@ -2512,14 +2516,14 @@ mod tests { info.gas_limit = 1_000_000.into(); let machine = make_frontier_machine(5); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), action: Action::Call(0xa.into()), value: 100.into(), data: vec![], - } + }) .sign(&secret(), None); state diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 2bf3a8410b..a8b54e234e 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -36,7 +36,7 @@ use tempdir::TempDir; use types::{ encoded, header::Header, - transaction::{Action, SignedTransaction, Transaction}, + transaction::{Action, SignedTransaction, Transaction, TypedTransaction}, view, views::BlockView, }; @@ -104,7 +104,7 @@ pub fn create_test_block_with_data( rlp.append(header); rlp.begin_list(transactions.len()); for t in transactions { - rlp.append_raw(&rlp::encode(t), 1); + t.rlp_append(&mut rlp); } rlp.append_list(&uncles); rlp.out() @@ -197,14 +197,14 @@ where // first block we don't have any balance, so can't send any transactions. for _ in 0..txs_per_block { b.push_transaction( - Transaction { + TypedTransaction::Legacy(Transaction { nonce: n.into(), gas_price: tx_gas_prices[n % tx_gas_prices.len()], gas: 100000.into(), action: Action::Create, data: vec![], value: U256::zero(), - } + }) .sign(kp.secret(), Some(test_spec.chain_id())), None, ) diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 58ae5eeac4..a5f0b2d882 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -45,7 +45,7 @@ use types::{ data_format::DataFormat, filter::Filter, ids::BlockId, - transaction::{Action, Condition, PendingTransaction, Transaction}, + transaction::{Action, Condition, PendingTransaction, Transaction, TypedTransaction}, view, views::BlockView, }; @@ -362,26 +362,26 @@ fn does_not_propagate_delayed_transactions() { let key = KeyPair::from_secret(keccak("test").into()).unwrap(); let secret = key.secret(); let tx0 = PendingTransaction::new( - Transaction { + TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(Address::default()), value: 0.into(), data: Vec::new(), - } + }) .sign(secret, None), Some(Condition::Number(2)), ); let tx1 = PendingTransaction::new( - Transaction { + TypedTransaction::Legacy(Transaction { nonce: 1.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(Address::default()), value: 0.into(), data: Vec::new(), - } + }) .sign(secret, None), None, ); @@ -443,14 +443,14 @@ fn transaction_proof() { client.import_sealed_block(b).unwrap(); // account change is in the journal overlay } - let transaction = Transaction { + let transaction = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(Address::default()), value: 5.into(), data: Vec::new(), - } + }) .fake_sign(address); let proof = client diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 4b21dd06f8..3835a6a034 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -29,7 +29,7 @@ use test_helpers::{self, get_temp_state_db}; use trace::{trace::Action::Reward, LocalizedTrace, RewardType}; use types::{ header::Header, - transaction::{Action, Transaction}, + transaction::{Action, Transaction, TypedTransaction}, view, views::BlockView, }; @@ -171,14 +171,14 @@ fn can_trace_block_and_uncle_reward() { for _ in 0..1 { block .push_transaction( - Transaction { + TypedTransaction::Legacy(Transaction { nonce: n.into(), gas_price: 10000.into(), gas: 100000.into(), action: Action::Create, data: vec![], value: U256::zero(), - } + }) .sign(kp.secret(), Some(spec.network_id())), None, ) diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index d4e7abb93b..2a7da20e91 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -83,7 +83,7 @@ impl TransactionFilter { let mut permission_cache = self.permission_cache.lock(); let mut contract_version_cache = self.contract_version_cache.lock(); - let (tx_type, to) = match transaction.action { + let (tx_type, to) = match transaction.tx().action { Action::Create => (tx_permissions::CREATE, Address::new()), Action::Call(address) => { if client @@ -98,7 +98,7 @@ impl TransactionFilter { }; let sender = transaction.sender(); - let value = transaction.value; + let value = transaction.tx().value; let key = (*parent_hash, sender); if let Some(permissions) = permission_cache.get_mut(&key) { @@ -181,7 +181,7 @@ mod test { use std::sync::Arc; use tempdir::TempDir; use test_helpers; - use types::transaction::{Action, Transaction}; + use types::transaction::{Action, Transaction, TypedTransaction}; /// Contract code: https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f #[test] @@ -230,28 +230,30 @@ mod test { .unwrap(); let filter = TransactionFilter::from_params(spec.params()).unwrap(); - let mut basic_tx = Transaction::default(); - basic_tx.action = Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb")); - let create_tx = Transaction::default(); - let mut call_tx = Transaction::default(); - call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005")); - - let mut basic_tx_with_ether_and_to_key7 = Transaction::default(); - basic_tx_with_ether_and_to_key7.action = + let mut basic_tx = TypedTransaction::Legacy(Transaction::default()); + basic_tx.tx_mut().action = Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb")); - basic_tx_with_ether_and_to_key7.value = U256::from(123123); - let mut call_tx_with_ether = Transaction::default(); - call_tx_with_ether.action = + let create_tx = TypedTransaction::Legacy(Transaction::default()); + let mut call_tx = TypedTransaction::Legacy(Transaction::default()); + call_tx.tx_mut().action = Action::Call(Address::from("0000000000000000000000000000000000000005")); - call_tx_with_ether.value = U256::from(123123); - let mut basic_tx_to_key6 = Transaction::default(); - basic_tx_to_key6.action = + let mut basic_tx_with_ether_and_to_key7 = TypedTransaction::Legacy(Transaction::default()); + basic_tx_with_ether_and_to_key7.tx_mut().action = + Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb")); + basic_tx_with_ether_and_to_key7.tx_mut().value = U256::from(123123); + let mut call_tx_with_ether = TypedTransaction::Legacy(Transaction::default()); + call_tx_with_ether.tx_mut().action = + Action::Call(Address::from("0000000000000000000000000000000000000005")); + call_tx_with_ether.tx_mut().value = U256::from(123123); + + let mut basic_tx_to_key6 = TypedTransaction::Legacy(Transaction::default()); + basic_tx_to_key6.tx_mut().action = Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141")); - let mut basic_tx_with_ether_and_to_key6 = Transaction::default(); - basic_tx_with_ether_and_to_key6.action = + let mut basic_tx_with_ether_and_to_key6 = TypedTransaction::Legacy(Transaction::default()); + basic_tx_with_ether_and_to_key6.tx_mut().action = Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141")); - basic_tx_with_ether_and_to_key6.value = U256::from(123123); + basic_tx_with_ether_and_to_key6.tx_mut().value = U256::from(123123); let genesis = client.block_hash(BlockId::Latest).unwrap(); let block_number = 1; @@ -444,11 +446,13 @@ mod test { .unwrap(); let filter = TransactionFilter::from_params(spec.params()).unwrap(); - let mut basic_tx = Transaction::default(); - basic_tx.action = Action::Call(Address::from("000000000000000000000000000000000000032")); - let create_tx = Transaction::default(); - let mut call_tx = Transaction::default(); - call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005")); + let mut basic_tx = TypedTransaction::Legacy(Transaction::default()); + basic_tx.tx_mut().action = + Action::Call(Address::from("000000000000000000000000000000000000032")); + let create_tx = TypedTransaction::Legacy(Transaction::default()); + let mut call_tx = TypedTransaction::Legacy(Transaction::default()); + call_tx.tx_mut().action = + Action::Call(Address::from("0000000000000000000000000000000000000005")); let genesis = client.block_hash(BlockId::Latest).unwrap(); let block_number = 1; diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index e789137a78..8bbcc46bdd 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -80,7 +80,10 @@ pub mod blocks { use engines::EthEngine; use error::{BlockError, Error, ErrorKind}; - use types::{header::Header, transaction::UnverifiedTransaction}; + use types::{ + header::Header, + transaction::{TypedTransaction, UnverifiedTransaction}, + }; use verification::{verify_block_basic, verify_block_unordered, PreverifiedBlock}; use bytes::Bytes; @@ -151,7 +154,7 @@ pub mod blocks { let (header, transactions, uncles) = { let rlp = Rlp::new(&bytes); let header = rlp.val_at(0)?; - let transactions = rlp.list_at(1)?; + let transactions = TypedTransaction::decode_rlp_list(&rlp.at(1)?)?; let uncles = rlp.list_at(2)?; (header, transactions, uncles) }; diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 9cdc837549..0cafaf8415 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -133,7 +133,7 @@ pub fn verify_block_unordered( let t = engine.verify_transaction_unordered(t, &header)?; // t_nb 5.3.2 check if nonce is more then max nonce (EIP-168 and EIP169) if let Some(max_nonce) = nonce_cap { - if t.nonce >= max_nonce { + if t.tx().nonce >= max_nonce { return Err(BlockError::TooManyTransactions(t.sender()).into()); } } @@ -493,7 +493,16 @@ fn verify_parent(header: &Header, parent: &Header, engine: &dyn EthEngine) -> Re fn verify_block_integrity(block: &Unverified) -> Result<(), Error> { let block_rlp = Rlp::new(&block.bytes); let tx = block_rlp.at(1)?; - let expected_root = ordered_trie_root(tx.iter().map(|r| r.as_raw())); + let expected_root = ordered_trie_root(tx.iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + // This is already checked in Unverified structure and that is why we are okay to asume that data is valid. + r.data().expect( + "Unverified block should already check if raw list of transactions is valid", + ) + } + })); if &expected_root != block.header.transactions_root() { bail!(BlockError::InvalidTransactionsRoot(Mismatch { expected: expected_root, @@ -531,7 +540,7 @@ mod tests { use types::{ encoded, log_entry::{LocalizedLogEntry, LogEntry}, - transaction::{Action, SignedTransaction, Transaction, UnverifiedTransaction}, + transaction::{Action, SignedTransaction, Transaction, TypedTransaction}, }; fn check_ok(result: Result<(), Error>) { @@ -764,34 +773,34 @@ mod tests { let keypair = Random.generate().unwrap(); - let tr1 = Transaction { + let tr1 = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(0), data: Bytes::new(), gas: U256::from(30_000), gas_price: U256::from(40_000), nonce: U256::one(), - } + }) .sign(keypair.secret(), None); - let tr2 = Transaction { + let tr2 = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(0), data: Bytes::new(), gas: U256::from(30_000), gas_price: U256::from(40_000), nonce: U256::from(2), - } + }) .sign(keypair.secret(), None); - let tr3 = Transaction { + let tr3 = TypedTransaction::Legacy(Transaction { action: Action::Call(0x0.into()), value: U256::from(0), data: Bytes::new(), gas: U256::from(30_000), gas_price: U256::from(0), nonce: U256::zero(), - } + }) .null_sign(0); let good_transactions = [tr1.clone(), tr2.clone()]; @@ -834,16 +843,10 @@ mod tests { let mut uncles_rlp = RlpStream::new(); uncles_rlp.append_list(&good_uncles); let good_uncles_hash = keccak(uncles_rlp.as_raw()); - let good_transactions_root = ordered_trie_root( - good_transactions - .iter() - .map(|t| ::rlp::encode::(t)), - ); - let eip86_transactions_root = ordered_trie_root( - eip86_transactions - .iter() - .map(|t| ::rlp::encode::(t)), - ); + let good_transactions_root = + ordered_trie_root(good_transactions.iter().map(|t| t.encode())); + let eip86_transactions_root = + ordered_trie_root(eip86_transactions.iter().map(|t| t.encode())); let mut parent = good.clone(); parent.set_number(9); @@ -1114,14 +1117,14 @@ mod tests { let keypair = Random.generate().unwrap(); let bad_transactions: Vec<_> = (0..3) .map(|i| { - Transaction { + TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::zero(), data: Vec::new(), gas: 0.into(), gas_price: U256::zero(), nonce: i.into(), - } + }) .sign(keypair.secret(), None) }) .collect(); diff --git a/ethcore/sync/src/block_sync.rs b/ethcore/sync/src/block_sync.rs index 1e7f00a338..7172bdfe92 100644 --- a/ethcore/sync/src/block_sync.rs +++ b/ethcore/sync/src/block_sync.rs @@ -762,7 +762,7 @@ mod tests { use triehash_ethereum::ordered_trie_root; use types::{ header::Header as BlockHeader, - transaction::{SignedTransaction, Transaction}, + transaction::{SignedTransaction, Transaction, TypedTransaction}, }; fn dummy_header(number: u64, parent_hash: H256) -> BlockHeader { @@ -778,7 +778,7 @@ mod tests { fn dummy_signed_tx() -> SignedTransaction { let keypair = Random.generate().unwrap(); - Transaction::default().sign(keypair.secret(), None) + TypedTransaction::Legacy(Transaction::default()).sign(keypair.secret(), None) } fn import_headers( @@ -949,8 +949,16 @@ mod tests { ::rlp::EMPTY_LIST_RLP.to_vec() }; - let txs = encode_list(&[dummy_signed_tx()]); - let tx_root = ordered_trie_root(Rlp::new(&txs).iter().map(|r| r.as_raw())); + let mut rlp_strem = RlpStream::new(); + SignedTransaction::rlp_append_list(&mut rlp_strem, &[dummy_signed_tx()]); + let txs = rlp_strem.drain(); + let tx_root = ordered_trie_root(Rlp::new(&txs).iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + r.data().expect("It is expected that raw rlp list is valid") + } + })); let mut rlp = RlpStream::new_list(2); rlp.append_raw(&txs, 1); @@ -1019,14 +1027,20 @@ mod tests { // Construct the receipts. Receipt root for the first two blocks is the same. // // The RLP-encoded integers are clearly not receipts, but the BlockDownloader treats - // all receipts as byte blobs, so it does not matter. + // all receipts as byte blobs, so it does not matter. It is just important that they are + // represended as list (0xc1) so that they passes as legacy list let receipts_rlp = if i < 2 { - encode_list(&[0u32]) + vec![0xC1, 0] } else { - encode_list(&[i as u32]) + vec![0xC1, i as u8] }; - let receipts_root = - ordered_trie_root(Rlp::new(&receipts_rlp).iter().map(|r| r.as_raw())); + let receipts_root = ordered_trie_root(Rlp::new(&receipts_rlp).iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + r.data().expect("expect proper test data") + } + })); receipts.push(receipts_rlp); // Construct the block header. diff --git a/ethcore/sync/src/blocks.rs b/ethcore/sync/src/blocks.rs index 9ae323cbe6..a4e5b61d81 100644 --- a/ethcore/sync/src/blocks.rs +++ b/ethcore/sync/src/blocks.rs @@ -23,7 +23,10 @@ use network; use rlp::{DecoderError, Rlp, RlpStream}; use std::collections::{hash_map, BTreeMap, HashMap, HashSet}; use triehash_ethereum::ordered_trie_root; -use types::{header::Header as BlockHeader, transaction::UnverifiedTransaction}; +use types::{ + header::Header as BlockHeader, + transaction::{TypedTransaction, UnverifiedTransaction}, +}; known_heap_size!(0, HeaderId); @@ -65,7 +68,7 @@ impl SyncBody { let result = SyncBody { transactions_bytes: transactions_rlp.as_raw().to_vec(), - transactions: transactions_rlp.as_list()?, + transactions: TypedTransaction::decode_rlp_list(&transactions_rlp)?, uncles_bytes: uncles_rlp.as_raw().to_vec(), uncles: uncles_rlp.as_list()?, }; @@ -454,11 +457,14 @@ impl BlockCollection { fn insert_body(&mut self, body: SyncBody) -> Result { let header_id = { - let tx_root = ordered_trie_root( - Rlp::new(&body.transactions_bytes) - .iter() - .map(|r| r.as_raw()), - ); + let tx_root = ordered_trie_root(Rlp::new(&body.transactions_bytes).iter().map(|r| { + if r.is_list() { + r.as_raw() + } else { + // this list is already decoded and passed validation, for this we are okay to expect proper data + r.data().expect("Expect raw transaction list to be valid") + } + })); let uncles = keccak(&body.uncles_bytes); HeaderId { transactions_root: tx_root, @@ -491,7 +497,22 @@ impl BlockCollection { fn insert_receipt(&mut self, r: Bytes) -> Result, network::Error> { let receipt_root = { let receipts = Rlp::new(&r); - ordered_trie_root(receipts.iter().map(|r| r.as_raw())) + //check receipts data before calculating trie root + let mut temp_receipts: Vec<&[u8]> = Vec::new(); + for receipt_byte in receipts.iter() { + if receipt_byte.is_list() { + temp_receipts.push(receipt_byte.as_raw()) + } else { + temp_receipts.push( + receipt_byte + .data() + .map_err(|e| network::ErrorKind::Rlp(e))?, + ); + } + } + + // calculate trie root and use it as hash + ordered_trie_root(temp_receipts.iter()) }; self.downloading_receipts.remove(&receipt_root); match self.receipt_ids.entry(receipt_root) { diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 2b3dbf655d..2aa9c5c6e9 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -837,9 +837,12 @@ impl SyncHandler { let item_count = r.item_count()?; trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count); let mut transactions = Vec::with_capacity(item_count); - for i in 0..item_count { - let rlp = r.at(i)?; - let tx = rlp.as_raw().to_vec(); + for i in r.iter() { + let tx = if i.is_list() { + i.as_raw().to_vec() // legacy transaction. just add it raw + } else { + i.data()?.to_vec() // typed transaction. remove header from start and send only payload. + }; transactions.push(tx); } io.chain().queue_transactions(transactions, peer_id); diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs index a70fc813d7..de79c12073 100644 --- a/ethcore/sync/src/chain/propagator.rs +++ b/ethcore/sync/src/chain/propagator.rs @@ -21,7 +21,7 @@ use ethereum_types::H256; use fastmap::H256FastSet; use network::{client_version::ClientCapabilities, PeerId}; use rand::Rng; -use rlp::{Encodable, RlpStream}; +use rlp::RlpStream; use sync_io::SyncIo; use types::{blockchain_info::BlockChainInfo, transaction::SignedTransaction, BlockNumber}; @@ -121,7 +121,7 @@ impl SyncPropagator { let (transactions, service_transactions): (Vec<_>, Vec<_>) = transactions .iter() .map(|tx| tx.signed()) - .partition(|tx| !tx.gas_price.is_zero()); + .partition(|tx| !tx.tx().gas_price.is_zero()); // usual transactions could be propagated to all peers let mut affected_peers = HashSet::new(); @@ -171,7 +171,7 @@ impl SyncPropagator { let all_transactions_rlp = { let mut packet = RlpStream::new_list(transactions.len()); for tx in &transactions { - packet.append(&**tx); + tx.rlp_append(&mut packet); } packet.out() }; @@ -238,13 +238,8 @@ impl SyncPropagator { for tx in &transactions { let hash = tx.hash(); if to_send.contains(&hash) { - let mut transaction = RlpStream::new(); - tx.rlp_append(&mut transaction); - let appended = packet.append_raw_checked( - &transaction.drain(), - 1, - MAX_TRANSACTION_PACKET_SIZE, - ); + let appended = + packet.append_raw_checked(&tx.encode(), 1, MAX_TRANSACTION_PACKET_SIZE); if !appended { // Maximal packet size reached just proceed with sending debug!(target: "sync", "Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len()); @@ -373,6 +368,7 @@ mod tests { use rlp::Rlp; use std::collections::VecDeque; use tests::{helpers::TestIo, snapshot::TestSnapshotService}; + use types::transaction::TypedTransaction; use super::{ super::{tests::*, *}, @@ -707,7 +703,9 @@ mod tests { return None; } - rlp.at(0).ok().and_then(|r| r.as_val().ok()) + rlp.at(0) + .ok() + .and_then(|r| TypedTransaction::decode_rlp(&r).ok()) }) .collect(); assert_eq!(sent_transactions.len(), 2); diff --git a/ethcore/sync/src/tests/consensus.rs b/ethcore/sync/src/tests/consensus.rs index 089c7c5859..6af66ec295 100644 --- a/ethcore/sync/src/tests/consensus.rs +++ b/ethcore/sync/src/tests/consensus.rs @@ -26,18 +26,18 @@ use ethkey::{KeyPair, Secret}; use hash::keccak; use io::{IoChannel, IoHandler}; use std::sync::Arc; -use types::transaction::{Action, PendingTransaction, Transaction}; +use types::transaction::{Action, PendingTransaction, Transaction, TypedTransaction}; use SyncConfig; fn new_tx(secret: &Secret, nonce: U256, chain_id: u64) -> PendingTransaction { - let signed = Transaction { + let signed = TypedTransaction::Legacy(Transaction { nonce: nonce.into(), gas_price: 0.into(), gas: 21000.into(), action: Action::Call(Address::default()), value: 0.into(), data: Vec::new(), - } + }) .sign(secret, Some(chain_id)); PendingTransaction::new(signed, None) } diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml index 1d831278f8..5fa288cc9c 100644 --- a/ethcore/types/Cargo.toml +++ b/ethcore/types/Cargo.toml @@ -14,6 +14,9 @@ parity-bytes = "0.1" rlp = { version = "0.3.0", features = ["ethereum"] } rlp_derive = { path = "../../util/rlp-derive" } unexpected = { path = "../../util/unexpected" } +serde = "1.0" +serde_json = "1.0" +serde_repr = "0.1" [dev-dependencies] rustc-hex = "1.0" diff --git a/ethcore/types/src/block.rs b/ethcore/types/src/block.rs index dea92ad5b2..221d4d64e9 100644 --- a/ethcore/types/src/block.rs +++ b/ethcore/types/src/block.rs @@ -35,7 +35,7 @@ use bytes::Bytes; use header::Header; use rlp::{Decodable, DecoderError, Rlp, RlpStream}; -use transaction::UnverifiedTransaction; +use transaction::{TypedTransaction, UnverifiedTransaction}; /// A block, encoded as it is on the block chain. #[derive(Default, Debug, Clone, PartialEq)] @@ -53,7 +53,7 @@ impl Block { pub fn rlp_bytes(&self) -> Bytes { let mut block_rlp = RlpStream::new_list(3); block_rlp.append(&self.header); - block_rlp.append_list(&self.transactions); + TypedTransaction::rlp_append_list(&mut block_rlp, &self.transactions); block_rlp.append_list(&self.uncles); block_rlp.out() } @@ -69,7 +69,7 @@ impl Decodable for Block { } Ok(Block { header: rlp.val_at(0)?, - transactions: rlp.list_at(1)?, + transactions: TypedTransaction::decode_rlp_list(&rlp.at(1)?)?, uncles: rlp.list_at(2)?, }) } diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index cfd301eb72..833e5a61c3 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -41,6 +41,7 @@ extern crate heapsize; extern crate keccak_hash as hash; extern crate parity_bytes as bytes; extern crate rlp; +extern crate serde_repr; extern crate unexpected; #[macro_use] diff --git a/ethcore/types/src/receipt.rs b/ethcore/types/src/receipt.rs index 916ab60251..6e361e4ac2 100644 --- a/ethcore/types/src/receipt.rs +++ b/ethcore/types/src/receipt.rs @@ -16,9 +16,14 @@ //! Receipt +use super::transaction::TypedTxId; use ethereum_types::{Address, Bloom, H160, H256, U256}; use heapsize::HeapSizeOf; -use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; +use rlp::{DecoderError, Rlp, RlpStream}; +use std::{ + convert::TryInto, + ops::{Deref, DerefMut}, +}; use log_entry::{LocalizedLogEntry, LogEntry}; use BlockNumber; @@ -36,7 +41,7 @@ pub enum TransactionOutcome { /// Information describing execution of a transaction. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Receipt { +pub struct LegacyReceipt { /// The total gas used in the block following execution of the transaction. pub gas_used: U256, /// The OR-wide combination of all logs' blooms for this transaction. @@ -47,10 +52,9 @@ pub struct Receipt { pub outcome: TransactionOutcome, } -impl Receipt { - /// Create a new receipt. +impl LegacyReceipt { pub fn new(outcome: TransactionOutcome, gas_used: U256, logs: Vec) -> Self { - Self { + LegacyReceipt { gas_used, log_bloom: logs.iter().fold(Bloom::default(), |mut b, l| { b.accrue_bloom(&l.bloom()); @@ -60,10 +64,32 @@ impl Receipt { outcome, } } -} + pub fn decode(rlp: &Rlp) -> Result { + match rlp.item_count()? { + 3 => Ok(LegacyReceipt { + outcome: TransactionOutcome::Unknown, + gas_used: rlp.val_at(0)?, + log_bloom: rlp.val_at(1)?, + logs: rlp.list_at(2)?, + }), + 4 => Ok(LegacyReceipt { + gas_used: rlp.val_at(1)?, + log_bloom: rlp.val_at(2)?, + logs: rlp.list_at(3)?, + outcome: { + let first = rlp.at(0)?; + if first.is_data() && first.data()?.len() <= 1 { + TransactionOutcome::StatusCode(first.as_val()?) + } else { + TransactionOutcome::StateRoot(first.as_val()?) + } + }, + }), + _ => Err(DecoderError::RlpIncorrectListLen), + } + } -impl Encodable for Receipt { - fn rlp_append(&self, s: &mut RlpStream) { + pub fn rlp_append(&self, s: &mut RlpStream) { match self.outcome { TransactionOutcome::Unknown => { s.begin_list(3); @@ -83,42 +109,142 @@ impl Encodable for Receipt { } } -impl Decodable for Receipt { - fn decode(rlp: &Rlp) -> Result { - if rlp.item_count()? == 3 { - Ok(Receipt { - outcome: TransactionOutcome::Unknown, - gas_used: rlp.val_at(0)?, - log_bloom: rlp.val_at(1)?, - logs: rlp.list_at(2)?, - }) +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TypedReceipt { + Legacy(LegacyReceipt), + AccessList(LegacyReceipt), +} + +impl TypedReceipt { + /// Create a new receipt. + pub fn new(type_id: TypedTxId, legacy_receipt: LegacyReceipt) -> Self { + //curently we are using same receipt for both legacy and typed transaction + match type_id { + TypedTxId::AccessList => Self::AccessList(legacy_receipt), + TypedTxId::Legacy => Self::Legacy(legacy_receipt), + } + } + + pub fn tx_type(&self) -> TypedTxId { + match self { + Self::Legacy(_) => TypedTxId::Legacy, + Self::AccessList(_) => TypedTxId::AccessList, + } + } + + pub fn receipt(&self) -> &LegacyReceipt { + match self { + Self::Legacy(receipt) => receipt, + Self::AccessList(receipt) => receipt, + } + } + + pub fn receipt_mut(&mut self) -> &mut LegacyReceipt { + match self { + Self::Legacy(receipt) => receipt, + Self::AccessList(receipt) => receipt, + } + } + + fn decode(tx: &[u8]) -> Result { + if tx.is_empty() { + // at least one byte needs to be present + return Err(DecoderError::RlpIncorrectListLen); + } + let id = tx[0].try_into(); + if id.is_err() { + return Err(DecoderError::Custom("Unknown transaction")); + } + //other transaction types + match id.unwrap() { + TypedTxId::AccessList => { + let rlp = Rlp::new(&tx[1..]); + Ok(Self::AccessList(LegacyReceipt::decode(&rlp)?)) + } + TypedTxId::Legacy => Ok(Self::Legacy(LegacyReceipt::decode(&Rlp::new(tx))?)), + } + } + + pub fn decode_rlp(rlp: &Rlp) -> Result { + if rlp.is_list() { + //legacy transaction wrapped around RLP encoding + Ok(Self::Legacy(LegacyReceipt::decode(rlp)?)) } else { - Ok(Receipt { - gas_used: rlp.val_at(1)?, - log_bloom: rlp.val_at(2)?, - logs: rlp.list_at(3)?, - outcome: { - let first = rlp.at(0)?; - if first.is_data() && first.data()?.len() <= 1 { - TransactionOutcome::StatusCode(first.as_val()?) - } else { - TransactionOutcome::StateRoot(first.as_val()?) - } - }, - }) + Self::decode(rlp.data()?) + } + } + + pub fn decode_rlp_list(rlp: &Rlp) -> Result, DecoderError> { + if !rlp.is_list() { + // at least one byte needs to be present + return Err(DecoderError::RlpIncorrectListLen); + } + let mut output = Vec::with_capacity(rlp.item_count()?); + for tx in rlp.iter() { + output.push(Self::decode_rlp(&tx)?); } + Ok(output) + } + + pub fn rlp_append(&self, s: &mut RlpStream) { + match self { + Self::Legacy(receipt) => receipt.rlp_append(s), + Self::AccessList(receipt) => { + let mut rlps = RlpStream::new(); + receipt.rlp_append(&mut rlps); + s.append(&[&[TypedTxId::AccessList as u8], rlps.as_raw()].concat()); + } + } + } + + pub fn rlp_append_list(s: &mut RlpStream, list: &[TypedReceipt]) { + s.begin_list(list.len()); + for rec in list.iter() { + rec.rlp_append(s) + } + } + + pub fn encode(&self) -> Vec { + match self { + Self::Legacy(receipt) => { + let mut s = RlpStream::new(); + receipt.rlp_append(&mut s); + s.drain() + } + Self::AccessList(receipt) => { + let mut rlps = RlpStream::new(); + receipt.rlp_append(&mut rlps); + [&[TypedTxId::AccessList as u8], rlps.as_raw()].concat() + } + } + } +} + +impl Deref for TypedReceipt { + type Target = LegacyReceipt; + + fn deref(&self) -> &Self::Target { + self.receipt() + } +} + +impl DerefMut for TypedReceipt { + fn deref_mut(&mut self) -> &mut LegacyReceipt { + self.receipt_mut() } } -impl HeapSizeOf for Receipt { +impl HeapSizeOf for TypedReceipt { fn heap_size_of_children(&self) -> usize { - self.logs.heap_size_of_children() + self.receipt().logs.heap_size_of_children() } } /// Receipt with additional info. #[derive(Debug, Clone, PartialEq)] pub struct RichReceipt { + /// Transaction type + pub transaction_type: TypedTxId, /// Transaction hash. pub transaction_hash: H256, /// Transaction index. @@ -146,6 +272,8 @@ pub struct RichReceipt { /// Receipt with additional info. #[derive(Debug, Clone, PartialEq)] pub struct LocalizedReceipt { + /// Transaction type + pub transaction_type: TypedTxId, /// Transaction hash. pub transaction_hash: H256, /// Transaction index. @@ -176,59 +304,91 @@ pub struct LocalizedReceipt { #[cfg(test)] mod tests { - use super::{Receipt, TransactionOutcome}; + use super::{LegacyReceipt, TransactionOutcome, TypedReceipt, TypedTxId}; use log_entry::LogEntry; #[test] fn test_no_state_root() { let expected = ::rustc_hex::FromHex::from_hex("f9014183040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let r = Receipt::new( - TransactionOutcome::Unknown, - 0x40cae.into(), - vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), - topics: vec![], - data: vec![0u8; 32], - }], + let r = TypedReceipt::new( + TypedTxId::Legacy, + LegacyReceipt::new( + TransactionOutcome::Unknown, + 0x40cae.into(), + vec![LogEntry { + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + topics: vec![], + data: vec![0u8; 32], + }], + ), ); - assert_eq!(&::rlp::encode(&r)[..], &expected[..]); + assert_eq!(r.encode(), expected); } #[test] - fn test_basic() { + fn test_basic_legacy() { let expected = ::rustc_hex::FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let r = Receipt::new( - TransactionOutcome::StateRoot( - "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + let r = TypedReceipt::new( + TypedTxId::Legacy, + LegacyReceipt::new( + TransactionOutcome::StateRoot( + "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + ), + 0x40cae.into(), + vec![LogEntry { + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + topics: vec![], + data: vec![0u8; 32], + }], ), - 0x40cae.into(), - vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), - topics: vec![], - data: vec![0u8; 32], - }], ); - let encoded = ::rlp::encode(&r); - assert_eq!(&encoded[..], &expected[..]); - let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed"); + let encoded = r.encode(); + assert_eq!(encoded, expected); + let decoded = TypedReceipt::decode(&encoded).expect("decoding receipt failed"); + assert_eq!(decoded, r); + } + + #[test] + fn test_basic_access_list() { + let expected = ::rustc_hex::FromHex::from_hex("01f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let r = TypedReceipt::new( + TypedTxId::AccessList, + LegacyReceipt::new( + TransactionOutcome::StateRoot( + "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + ), + 0x40cae.into(), + vec![LogEntry { + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + topics: vec![], + data: vec![0u8; 32], + }], + ), + ); + let encoded = r.encode(); + assert_eq!(&encoded, &expected); + let decoded = TypedReceipt::decode(&encoded).expect("decoding receipt failed"); assert_eq!(decoded, r); } #[test] fn test_status_code() { let expected = ::rustc_hex::FromHex::from_hex("f901428083040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let r = Receipt::new( - TransactionOutcome::StatusCode(0), - 0x40cae.into(), - vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), - topics: vec![], - data: vec![0u8; 32], - }], + let r = TypedReceipt::new( + TypedTxId::Legacy, + LegacyReceipt::new( + TransactionOutcome::StatusCode(0), + 0x40cae.into(), + vec![LogEntry { + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + topics: vec![], + data: vec![0u8; 32], + }], + ), ); - let encoded = ::rlp::encode(&r); + let encoded = r.encode(); assert_eq!(&encoded[..], &expected[..]); - let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed"); + let decoded = TypedReceipt::decode(&encoded).expect("decoding receipt failed"); assert_eq!(decoded, r); } } diff --git a/ethcore/types/src/transaction/error.rs b/ethcore/types/src/transaction/error.rs index 4d62868c2e..c4813eba30 100644 --- a/ethcore/types/src/transaction/error.rs +++ b/ethcore/types/src/transaction/error.rs @@ -84,6 +84,8 @@ pub enum Error { TooBig, /// Invalid RLP encoding InvalidRlp(String), + /// Transaciton is still not enabled. + TransactionTypeNotEnabled, } impl From for Error { @@ -133,6 +135,9 @@ impl fmt::Display for Error { } TooBig => "Transaction too big".into(), InvalidRlp(ref err) => format!("Transaction has invalid RLP structure: {}.", err), + TransactionTypeNotEnabled => { + format!("Transaction type is not enabled for current block") + } }; f.write_fmt(format_args!("Transaction error ({})", msg)) diff --git a/ethcore/types/src/transaction/mod.rs b/ethcore/types/src/transaction/mod.rs index 5af69712d2..3a8afd07d8 100644 --- a/ethcore/types/src/transaction/mod.rs +++ b/ethcore/types/src/transaction/mod.rs @@ -18,5 +18,6 @@ mod error; mod transaction; +mod transaction_id; -pub use self::{error::Error, transaction::*}; +pub use self::{error::Error, transaction::*, transaction_id::*}; diff --git a/ethcore/types/src/transaction/transaction.rs b/ethcore/types/src/transaction/transaction.rs index f4de8fbcd7..ae8bf75b09 100644 --- a/ethcore/types/src/transaction/transaction.rs +++ b/ethcore/types/src/transaction/transaction.rs @@ -16,14 +16,17 @@ //! Transaction data structure. -use std::ops::Deref; - use ethereum_types::{Address, H160, H256, U256}; use ethjson; use ethkey::{self, public_to_address, recover, Public, Secret, Signature}; use hash::keccak; use heapsize::HeapSizeOf; -use rlp::{self, DecoderError, Encodable, Rlp, RlpStream}; +use rlp::{self, DecoderError, Rlp, RlpStream}; +use std::{convert::TryInto, ops::Deref}; + +pub type AccessList = Vec<(H160, Vec)>; + +use super::TypedTxId; use transaction::error; @@ -90,17 +93,18 @@ pub enum Condition { /// Replay protection logic for v part of transaction's signature pub mod signature { /// Adds chain id into v - pub fn add_chain_replay_protection(v: u64, chain_id: Option) -> u64 { - v + if let Some(n) = chain_id { - 35 + n * 2 - } else { - 27 - } + pub fn add_chain_replay_protection(v: u8, chain_id: Option) -> u64 { + v as u64 + + if let Some(n) = chain_id { + 35 + n * 2 + } else { + 27 + } } /// Returns refined v /// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid. - pub fn check_replay_protection(v: u64) -> u8 { + pub fn extract_standard_v(v: u64) -> u8 { match v { v if v == 27 => 0, v if v == 28 => 1, @@ -108,6 +112,14 @@ pub mod signature { _ => 4, } } + + pub fn extract_chain_id_from_legacy_v(v: u64) -> Option { + if v >= 35 { + Some((v - 35) / 2 as u64) + } else { + None + } + } } /// A set of information describing an externally-originating message call @@ -129,20 +141,96 @@ pub struct Transaction { } impl Transaction { - /// Append object with a without signature into RLP stream - pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, chain_id: Option) { - s.begin_list(if chain_id.is_none() { 6 } else { 9 }); + /// The message hash of the transaction. This hash is used for signing transaction + pub fn signature_hash(&self, chain_id: Option) -> H256 { + keccak(self.encode(chain_id, None)) + } + + /// encode raw transaction + fn encode(&self, chain_id: Option, signature: Option<&SignatureComponents>) -> Vec { + let mut stream = RlpStream::new(); + self.encode_rlp(&mut stream, chain_id, signature); + stream.drain() + } + + pub fn rlp_append( + &self, + rlp: &mut RlpStream, + chain_id: Option, + signature: &SignatureComponents, + ) { + self.encode_rlp(rlp, chain_id, Some(signature)); + } + + fn encode_rlp( + &self, + rlp: &mut RlpStream, + chain_id: Option, + signature: Option<&SignatureComponents>, + ) { + let list_size = if chain_id.is_some() || signature.is_some() { + 9 + } else { + 6 + }; + rlp.begin_list(list_size); + + self.rlp_append_data_open(rlp); + + //append signature if given. If not, try to append chainId. + if let Some(signature) = signature { + signature.rlp_append_with_chain_id(rlp, chain_id); + } else { + if let Some(n) = chain_id { + rlp.append(&n); + rlp.append(&0u8); + rlp.append(&0u8); + } + } + } + + fn rlp_append_data_open(&self, s: &mut RlpStream) { s.append(&self.nonce); s.append(&self.gas_price); s.append(&self.gas); s.append(&self.action); s.append(&self.value); s.append(&self.data); - if let Some(n) = chain_id { - s.append(&n); - s.append(&0u8); - s.append(&0u8); + } + + fn decode(d: &Rlp) -> Result { + if d.item_count()? != 9 { + return Err(DecoderError::RlpIncorrectListLen); } + let hash = keccak(d.as_raw()); + + let transaction = TypedTransaction::Legacy(Self::decode_data(d, 0)?); + + // take V from signatuere and decompose it into chain_id and standard V. + let legacy_v: u64 = d.val_at(6)?; + + let signature = SignatureComponents { + standard_v: signature::extract_standard_v(legacy_v), + r: d.val_at(7)?, + s: d.val_at(8)?, + }; + Ok(UnverifiedTransaction::new( + transaction, + signature::extract_chain_id_from_legacy_v(legacy_v), + signature, + hash, + )) + } + + fn decode_data(d: &Rlp, offset: usize) -> Result { + Ok(Transaction { + nonce: d.val_at(offset)?, + gas_price: d.val_at(offset + 1)?, + gas: d.val_at(offset + 2)?, + action: d.val_at(offset + 3)?, + value: d.val_at(offset + 4)?, + data: d.val_at(offset + 5)?, + }) } } @@ -152,64 +240,180 @@ impl HeapSizeOf for Transaction { } } -#[cfg(any(test, feature = "test-helpers"))] -impl From for SignedTransaction { - fn from(t: ethjson::state::Transaction) -> Self { - let to: Option = t.to.into(); - let secret = t.secret.map(|s| Secret::from(s.0)); - let tx = Transaction { - nonce: t.nonce.into(), - gas_price: t.gas_price.into(), - gas: t.gas_limit.into(), - action: match to { - Some(to) => Action::Call(to.into()), - None => Action::Create, - }, - value: t.value.into(), - data: t.data.into(), +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct AccessListTx { + pub transaction: Transaction, + //optional access list + pub access_list: AccessList, +} + +impl AccessListTx { + pub fn new(transaction: Transaction, access_list: AccessList) -> AccessListTx { + AccessListTx { + transaction, + access_list, + } + } + + pub fn tx_type(&self) -> TypedTxId { + TypedTxId::AccessList + } + + pub fn tx(&self) -> &Transaction { + &self.transaction + } + + pub fn tx_mut(&mut self) -> &mut Transaction { + &mut self.transaction + } + + // decode bytes by this payload spec: rlp([3, [chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]]) + pub fn decode(tx: &[u8]) -> Result { + let tx_rlp = &Rlp::new(tx); + + // we need to have 11 items in this list + if tx_rlp.item_count()? != 11 { + return Err(DecoderError::RlpIncorrectListLen); + } + + let chain_id = Some(tx_rlp.val_at(0)?); + //let chain_id = if chain_id == 0 { None } else { Some(chain_id) }; + + // first part of list is same as legacy transaction and we are reusing that part. + let transaction = Transaction::decode_data(&tx_rlp, 1)?; + + // access list we get from here + let accl_rlp = tx_rlp.at(7)?; + + // access_list pattern: [[{20 bytes}, [{32 bytes}...]]...] + let mut accl: AccessList = Vec::new(); + + for i in 0..accl_rlp.item_count()? { + let accounts = accl_rlp.at(i)?; + + // check if there is list of 2 items + if accounts.item_count()? != 2 { + return Err(DecoderError::Custom("Unknown access list length")); + } + accl.push((accounts.val_at(0)?, accounts.list_at(1)?)); + } + + // we get signature part from here + let signature = SignatureComponents { + standard_v: tx_rlp.val_at(8)?, + r: tx_rlp.val_at(9)?, + s: tx_rlp.val_at(10)?, }; - match secret { - Some(s) => tx.sign(&s, None), - None => tx.null_sign(1), + + // and here we create UnverifiedTransaction and calculate its hash + Ok(UnverifiedTransaction::new( + TypedTransaction::AccessList(AccessListTx { + transaction, + access_list: accl, + }), + chain_id, + signature, + 0.into(), + ) + .compute_hash()) + } + + fn encode_payload( + &self, + tx_type: Option, //used only for signature hashing for EIP-2930 + chain_id: Option, + signature: Option<&SignatureComponents>, + ) -> RlpStream { + let mut stream = RlpStream::new(); + + let mut list_size = if signature.is_some() { 11 } else { 8 }; + list_size += if tx_type.is_some() { 1 } else { 0 }; + stream.begin_list(list_size); + + // append tx_type at beggining of list, this is used only for data hash for signature. + if let Some(tx_type) = tx_type { + stream.append(&tx_type); } + + // append chain_id. from EIP-2930: chainId is defined to be an integer of arbitrary size. + stream.append(&(if let Some(n) = chain_id { n } else { 0 })); + + // append legacy transaction + self.transaction.rlp_append_data_open(&mut stream); + + // access list + stream.begin_list(self.access_list.len()); + for access in self.access_list.iter() { + stream.begin_list(2); + stream.append(&access.0); + stream.begin_list(access.1.len()); + for storage_key in access.1.iter() { + stream.append(storage_key); + } + } + + // append signature + if let Some(signature) = signature { + signature.rlp_append(&mut stream); + } + stream + } + + // encode by this payload spec: 0x01 | rlp([1, [chain_id, nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]]) + pub fn encode( + &self, + chain_id: Option, + signature: Option<&SignatureComponents>, + ) -> Vec { + let stream = self.encode_payload(None, chain_id, signature); + // make as vector of bytes + [&[TypedTxId::AccessList as u8], stream.as_raw()].concat() + } + + pub fn rlp_append( + &self, + rlp: &mut RlpStream, + chain_id: Option, + signature: &SignatureComponents, + ) { + rlp.append(&self.encode(chain_id, Some(signature))); + } + + pub fn signature_hash(&self, chain_id: Option) -> H256 { + keccak( + &self + .encode_payload(Some(TypedTxId::AccessList as u8), chain_id, None) + .as_raw(), + ) } } -impl From for UnverifiedTransaction { - fn from(t: ethjson::transaction::Transaction) -> Self { - let to: Option = t.to.into(); - UnverifiedTransaction { - unsigned: Transaction { - nonce: t.nonce.into(), - gas_price: t.gas_price.into(), - gas: t.gas_limit.into(), - action: match to { - Some(to) => Action::Call(to.into()), - None => Action::Create, - }, - value: t.value.into(), - data: t.data.into(), - }, - r: t.r.into(), - s: t.s.into(), - v: t.v.into(), - hash: 0.into(), +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum TypedTransaction { + Legacy(Transaction), // old legacy RLP encoded transaction + AccessList(AccessListTx), // EIP-2930 Transaction with a list of addresses and storage keys that the transaction plans to access. + // Accesses outside the list are possible, but become more expensive. +} + +impl TypedTransaction { + pub fn tx_type(&self) -> TypedTxId { + match self { + Self::Legacy(_) => TypedTxId::Legacy, + Self::AccessList(_) => TypedTxId::AccessList, } - .compute_hash() } -} -impl Transaction { /// The message hash of the transaction. - pub fn hash(&self, chain_id: Option) -> H256 { - let mut stream = RlpStream::new(); - self.rlp_append_unsigned_transaction(&mut stream, chain_id); - keccak(stream.as_raw()) + pub fn signature_hash(&self, chain_id: Option) -> H256 { + match self { + Self::Legacy(tx) => tx.signature_hash(chain_id), + Self::AccessList(tx) => tx.signature_hash(chain_id), + } } /// Signs the transaction as coming from `sender`. pub fn sign(self, secret: &Secret, chain_id: Option) -> SignedTransaction { - let sig = ::ethkey::sign(secret, &self.hash(chain_id)) + let sig = ::ethkey::sign(secret, &self.signature_hash(chain_id)) .expect("data is valid and context has signing capabilities; qed"); SignedTransaction::new(self.with_signature(sig, chain_id)) .expect("secret is valid so it's recoverable") @@ -219,22 +423,12 @@ impl Transaction { pub fn with_signature(self, sig: Signature, chain_id: Option) -> UnverifiedTransaction { UnverifiedTransaction { unsigned: self, - r: sig.r().into(), - s: sig.s().into(), - v: signature::add_chain_replay_protection(sig.v() as u64, chain_id), - hash: 0.into(), - } - .compute_hash() - } - - /// Useful for test incorrectly signed transactions. - #[cfg(test)] - pub fn invalid_sign(self) -> UnverifiedTransaction { - UnverifiedTransaction { - unsigned: self, - r: U256::one(), - s: U256::one(), - v: 0, + chain_id, + signature: SignatureComponents { + r: sig.r().into(), + s: sig.s().into(), + standard_v: sig.v().into(), + }, hash: 0.into(), } .compute_hash() @@ -245,9 +439,12 @@ impl Transaction { SignedTransaction { transaction: UnverifiedTransaction { unsigned: self, - r: U256::one(), - s: U256::one(), - v: 0, + chain_id: None, + signature: SignatureComponents { + r: U256::one(), + s: U256::one(), + standard_v: 4, + }, hash: 0.into(), } .compute_hash(), @@ -264,9 +461,12 @@ impl Transaction { SignedTransaction { transaction: UnverifiedTransaction { unsigned: self, - r: U256::zero(), - s: U256::zero(), - v: chain_id, + chain_id: Some(chain_id), + signature: SignatureComponents { + r: U256::zero(), + s: U256::zero(), + standard_v: 0, + }, hash: 0.into(), } .compute_hash(), @@ -274,20 +474,216 @@ impl Transaction { public: None, } } + + /// Useful for test incorrectly signed transactions. + #[cfg(test)] + pub fn invalid_sign(self) -> UnverifiedTransaction { + UnverifiedTransaction { + unsigned: self, + chain_id: None, + signature: SignatureComponents { + r: U256::one(), + s: U256::one(), + standard_v: 0, + }, + hash: 0.into(), + } + .compute_hash() + } + + // Next functions are for encoded/decode + + pub fn tx(&self) -> &Transaction { + match self { + Self::Legacy(tx) => tx, + Self::AccessList(ocl) => ocl.tx(), + } + } + + pub fn tx_mut(&mut self) -> &mut Transaction { + match self { + Self::Legacy(tx) => tx, + Self::AccessList(ocl) => ocl.tx_mut(), + } + } + + fn decode_new(tx: &[u8]) -> Result { + if tx.is_empty() { + // at least one byte needs to be present + return Err(DecoderError::RlpIncorrectListLen); + } + let id = tx[0].try_into(); + if id.is_err() { + return Err(DecoderError::Custom("Unknown transaction")); + } + // other transaction types + match id.unwrap() { + TypedTxId::AccessList => AccessListTx::decode(&tx[1..]), + TypedTxId::Legacy => return Err(DecoderError::Custom("Unknown transaction legacy")), + } + } + + pub fn decode(tx: &[u8]) -> Result { + if tx.is_empty() { + // at least one byte needs to be present + return Err(DecoderError::RlpIncorrectListLen); + } + let header = tx[0]; + // type of transaction can be obtained from first byte. If first bit is 1 it means we are dealing with RLP list. + // if it is 0 it means that we are dealing with custom transaction defined in EIP-2718. + if (header & 0x80) != 0x00 { + Transaction::decode(&Rlp::new(tx)) + } else { + Self::decode_new(tx) + } + } + + pub fn decode_rlp_list(rlp: &Rlp) -> Result, DecoderError> { + if !rlp.is_list() { + // at least one byte needs to be present + return Err(DecoderError::RlpIncorrectListLen); + } + let mut output = Vec::with_capacity(rlp.item_count()?); + for tx in rlp.iter() { + output.push(Self::decode_rlp(&tx)?); + } + Ok(output) + } + + pub fn decode_rlp(tx: &Rlp) -> Result { + if tx.is_list() { + //legacy transaction wrapped around RLP encoding + Transaction::decode(tx) + } else { + Self::decode_new(tx.data()?) + } + } + + fn rlp_append( + &self, + s: &mut RlpStream, + chain_id: Option, + signature: &SignatureComponents, + ) { + match self { + Self::Legacy(tx) => tx.rlp_append(s, chain_id, signature), + Self::AccessList(opt) => opt.rlp_append(s, chain_id, signature), + } + } + + pub fn rlp_append_list(s: &mut RlpStream, tx_list: &[UnverifiedTransaction]) { + s.begin_list(tx_list.len()); + for tx in tx_list.iter() { + tx.unsigned.rlp_append(s, tx.chain_id, &tx.signature); + } + } + + fn encode(&self, chain_id: Option, signature: &SignatureComponents) -> Vec { + let signature = Some(signature); + match self { + Self::Legacy(tx) => tx.encode(chain_id, signature), + Self::AccessList(opt) => opt.encode(chain_id, signature), + } + } } -/// Signed transaction information without verified signature. +impl HeapSizeOf for TypedTransaction { + fn heap_size_of_children(&self) -> usize { + match self { + TypedTransaction::Legacy(legacy) => legacy.heap_size_of_children(), + TypedTransaction::AccessList(oal) => oal.tx().heap_size_of_children(), + } + } +} + +/// Components that constitute transaction signature #[derive(Debug, Clone, Eq, PartialEq)] -pub struct UnverifiedTransaction { - /// Plain Transaction. - unsigned: Transaction, +pub struct SignatureComponents { /// The V field of the signature; the LS bit described which half of the curve our point falls - /// in. The MS bits describe which chain this transaction is for. If 27/28, its for all chains. - v: u64, + /// in. It can be 0 or 1. + standard_v: u8, /// The R field of the signature; helps describe the point on the curve. r: U256, /// The S field of the signature; helps describe the point on the curve. s: U256, +} + +impl SignatureComponents { + pub fn rlp_append(&self, s: &mut RlpStream) { + s.append(&self.standard_v); + s.append(&self.r); + s.append(&self.s); + } + + pub fn rlp_append_with_chain_id(&self, s: &mut RlpStream, chain_id: Option) { + s.append(&signature::add_chain_replay_protection( + self.standard_v, + chain_id, + )); + s.append(&self.r); + s.append(&self.s); + } +} + +#[cfg(any(test, feature = "test-helpers"))] +impl From for SignedTransaction { + fn from(t: ethjson::state::Transaction) -> Self { + let to: Option = t.to.into(); + let secret = t.secret.map(|s| Secret::from(s.0)); + let tx = TypedTransaction::Legacy(Transaction { + nonce: t.nonce.into(), + gas_price: t.gas_price.into(), + gas: t.gas_limit.into(), + action: match to { + Some(to) => Action::Call(to.into()), + None => Action::Create, + }, + value: t.value.into(), + data: t.data.into(), + }); + match secret { + Some(s) => tx.sign(&s, None), + None => tx.null_sign(1), + } + } +} + +impl From for UnverifiedTransaction { + fn from(t: ethjson::transaction::Transaction) -> Self { + let to: Option = t.to.into(); + UnverifiedTransaction { + unsigned: TypedTransaction::Legacy(Transaction { + nonce: t.nonce.into(), + gas_price: t.gas_price.into(), + gas: t.gas_limit.into(), + action: match to { + Some(to) => Action::Call(to.into()), + None => Action::Create, + }, + value: t.value.into(), + data: t.data.into(), + }), + chain_id: signature::extract_chain_id_from_legacy_v(t.v.into()), + signature: SignatureComponents { + r: t.r.into(), + s: t.s.into(), + standard_v: signature::extract_standard_v(t.v.into()), + }, + hash: 0.into(), + } + .compute_hash() + } +} + +/// Signed transaction information without verified signature. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct UnverifiedTransaction { + /// Plain Transaction. + unsigned: TypedTransaction, + /// Transaction signature + signature: SignatureComponents, + /// chain_id recover from signature in legacy transaction. For TypedTransaction it is probably separate field. + chain_id: Option, /// Hash of the transaction hash: H256, } @@ -299,96 +695,75 @@ impl HeapSizeOf for UnverifiedTransaction { } impl Deref for UnverifiedTransaction { - type Target = Transaction; + type Target = TypedTransaction; fn deref(&self) -> &Self::Target { &self.unsigned } } -impl rlp::Decodable for UnverifiedTransaction { - fn decode(d: &Rlp) -> Result { - if d.item_count()? != 9 { - return Err(DecoderError::RlpIncorrectListLen); - } - let hash = keccak(d.as_raw()); - Ok(UnverifiedTransaction { - unsigned: Transaction { - nonce: d.val_at(0)?, - gas_price: d.val_at(1)?, - gas: d.val_at(2)?, - action: d.val_at(3)?, - value: d.val_at(4)?, - data: d.val_at(5)?, - }, - v: d.val_at(6)?, - r: d.val_at(7)?, - s: d.val_at(8)?, - hash, - }) +impl UnverifiedTransaction { + pub fn rlp_append(&self, s: &mut RlpStream) { + self.unsigned.rlp_append(s, self.chain_id, &self.signature); } -} -impl rlp::Encodable for UnverifiedTransaction { - fn rlp_append(&self, s: &mut RlpStream) { - self.rlp_append_sealed_transaction(s) + pub fn encode(&self) -> Vec { + self.unsigned.encode(self.chain_id, &self.signature) } -} -impl UnverifiedTransaction { - /// Used to compute hash of created transactions + /// Used to compute hash of created transactions. fn compute_hash(mut self) -> UnverifiedTransaction { - let hash = keccak(&*self.rlp_bytes()); + let hash = keccak(&*self.encode()); self.hash = hash; self } + /// Used by TypedTransaction to create UnverifiedTransaction. + fn new( + transaction: TypedTransaction, + chain_id: Option, + signature: SignatureComponents, + hash: H256, + ) -> UnverifiedTransaction { + UnverifiedTransaction { + unsigned: transaction, + chain_id, + signature, + hash, + } + } /// Checks if the signature is empty. pub fn is_unsigned(&self) -> bool { - self.r.is_zero() && self.s.is_zero() - } - - /// Append object with a signature into RLP stream - fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) { - s.begin_list(9); - s.append(&self.nonce); - s.append(&self.gas_price); - s.append(&self.gas); - s.append(&self.action); - s.append(&self.value); - s.append(&self.data); - s.append(&self.v); - s.append(&self.r); - s.append(&self.s); + self.signature.r.is_zero() && self.signature.s.is_zero() } /// Reference to unsigned part of this transaction. - pub fn as_unsigned(&self) -> &Transaction { + pub fn as_unsigned(&self) -> &TypedTransaction { &self.unsigned } /// Returns standardized `v` value (0, 1 or 4 (invalid)) pub fn standard_v(&self) -> u8 { - signature::check_replay_protection(self.v) + self.signature.standard_v } /// The `v` value that appears in the RLP. pub fn original_v(&self) -> u64 { - self.v + signature::add_chain_replay_protection(self.signature.standard_v, self.chain_id) } /// The chain ID, or `None` if this is a global transaction. pub fn chain_id(&self) -> Option { - match self.v { - v if self.is_unsigned() => Some(v), - v if v >= 35 => Some((v - 35) / 2), - _ => None, - } + self.chain_id } /// Construct a signature object from the sig. pub fn signature(&self) -> Signature { - Signature::from_rsv(&self.r.into(), &self.s.into(), self.standard_v()) + Signature::from_rsv( + &self.signature.r.into(), + &self.signature.s.into(), + self.standard_v(), + ) } /// Checks whether the signature has a low 's' value. @@ -409,7 +784,7 @@ impl UnverifiedTransaction { pub fn recover_public(&self) -> Result { Ok(recover( &self.signature(), - &self.unsigned.hash(self.chain_id()), + &self.unsigned.signature_hash(self.chain_id()), )?) } @@ -448,12 +823,6 @@ impl HeapSizeOf for SignedTransaction { } } -impl rlp::Encodable for SignedTransaction { - fn rlp_append(&self, s: &mut RlpStream) { - self.transaction.rlp_append_sealed_transaction(s) - } -} - impl Deref for SignedTransaction { type Target = UnverifiedTransaction; fn deref(&self) -> &Self::Target { @@ -501,6 +870,13 @@ impl SignedTransaction { pub fn deconstruct(self) -> (UnverifiedTransaction, Address, Option) { (self.transaction, self.sender, self.public) } + + pub fn rlp_append_list(s: &mut RlpStream, tx_list: &[SignedTransaction]) { + s.begin_list(tx_list.len()); + for tx in tx_list.iter() { + tx.unsigned.rlp_append(s, tx.chain_id, &tx.signature); + } + } } /// Signed Transaction that is a part of canon blockchain. @@ -588,18 +964,17 @@ mod tests { #[test] fn sender_test() { let bytes = ::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap(); - let t: UnverifiedTransaction = - rlp::decode(&bytes).expect("decoding UnverifiedTransaction failed"); - assert_eq!(t.data, b""); - assert_eq!(t.gas, U256::from(0x5208u64)); - assert_eq!(t.gas_price, U256::from(0x01u64)); - assert_eq!(t.nonce, U256::from(0x00u64)); - if let Action::Call(ref to) = t.action { + let t = TypedTransaction::decode(&bytes).expect("decoding UnverifiedTransaction failed"); + assert_eq!(t.tx().data, b""); + assert_eq!(t.tx().gas, U256::from(0x5208u64)); + assert_eq!(t.tx().gas_price, U256::from(0x01u64)); + assert_eq!(t.tx().nonce, U256::from(0x00u64)); + if let Action::Call(ref to) = t.tx().action { assert_eq!(*to, "095e7baea6a6c7c4c2dfeb977efac326af552d87".into()); } else { panic!(); } - assert_eq!(t.value, U256::from(0x0au64)); + assert_eq!(t.tx().value, U256::from(0x0au64)); assert_eq!( public_to_address(&t.recover_public().unwrap()), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into() @@ -626,16 +1001,16 @@ mod tests { use ethkey::{Generator, Random}; let key = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), gas_price: U256::from(3000), gas: U256::from(50_000), value: U256::from(1), data: b"Hello!".to_vec(), - }; + }); - let hash = t.hash(Some(0)); + let hash = t.signature_hash(Some(0)); let sig = ::ethkey::sign(&key.secret(), &hash).unwrap(); let u = t.with_signature(sig, Some(0)); @@ -647,14 +1022,14 @@ mod tests { use ethkey::{Generator, Random}; let key = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), gas_price: U256::from(3000), gas: U256::from(50_000), value: U256::from(1), data: b"Hello!".to_vec(), - } + }) .sign(&key.secret(), None); assert_eq!(Address::from(keccak(key.public())), t.sender()); assert_eq!(t.chain_id(), None); @@ -662,14 +1037,14 @@ mod tests { #[test] fn fake_signing() { - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), gas_price: U256::from(3000), gas: U256::from(50_000), value: U256::from(1), data: b"Hello!".to_vec(), - } + }) .fake_sign(Address::from(0x69)); assert_eq!(Address::from(0x69), t.sender()); assert_eq!(t.chain_id(), None); @@ -682,7 +1057,7 @@ mod tests { #[test] fn should_reject_null_signature() { use std::str::FromStr; - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(10000000000u64), gas: U256::from(21000), @@ -691,9 +1066,11 @@ mod tests { ), value: U256::from(1), data: vec![], - } + }) .null_sign(1); + println!("transaction {:?}", t); + let res = SignedTransaction::new(t.transaction); match res { Err(ethkey::Error::InvalidSignature) => {} @@ -705,26 +1082,94 @@ mod tests { fn should_recover_from_chain_specific_signing() { use ethkey::{Generator, Random}; let key = Random.generate().unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), gas_price: U256::from(3000), gas: U256::from(50_000), value: U256::from(1), data: b"Hello!".to_vec(), - } + }) .sign(&key.secret(), Some(69)); assert_eq!(Address::from(keccak(key.public())), t.sender()); assert_eq!(t.chain_id(), Some(69)); } + #[test] + fn should_encode_decode_access_list_tx() { + use ethkey::{Generator, Random}; + let key = Random.generate().unwrap(); + let t = TypedTransaction::AccessList(AccessListTx::new( + Transaction { + action: Action::Create, + nonce: U256::from(42), + gas_price: U256::from(3000), + gas: U256::from(50_000), + value: U256::from(1), + data: b"Hello!".to_vec(), + }, + vec![ + (H160::from(10), vec![H256::from(102), H256::from(103)]), + (H160::from(400), vec![]), + ], + )) + .sign(&key.secret(), Some(69)); + let encoded = t.encode(); + + let t_new = + TypedTransaction::decode(&encoded).expect("Error on UnverifiedTransaction decoder"); + if t_new.unsigned != t.unsigned { + assert!(true, "encoded/decoded tx differs from original"); + } + } + + #[test] + fn should_decode_access_list_in_rlp() { + use rustc_hex::FromHex; + let encoded_tx = "b8cb01f8a7802a820bb882c35080018648656c6c6f21f872f85994000000000000000000000000000000000000000af842a00000000000000000000000000000000000000000000000000000000000000066a00000000000000000000000000000000000000000000000000000000000000067d6940000000000000000000000000000000000000190c080a00ea0f1fda860320f51e182fe68ea90a8e7611653d3975b9301580adade6b8aa4a023530a1a96e0f15f90959baf1cd2d9114f7c7568ac7d77f4413c0a6ca6cdac74"; + let _ = TypedTransaction::decode_rlp(&Rlp::new(&FromHex::from_hex(encoded_tx).unwrap())) + .expect("decoding tx data failed"); + } + + #[test] + fn should_decode_access_list_solo() { + use rustc_hex::FromHex; + let encoded_tx = "01f8630103018261a894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a825544c001a0cb51495c66325615bcd591505577c9dde87bd59b04be2e6ba82f6d7bdea576e3a049e4f02f37666bd91a052a56e91e71e438590df861031ee9a321ce058df3dc2b"; + let _ = TypedTransaction::decode(&FromHex::from_hex(encoded_tx).unwrap()) + .expect("decoding tx data failed"); + } + + #[test] + fn test_rlp_data() { + let mut rlp_list = RlpStream::new(); + rlp_list.begin_list(3); + rlp_list.append(&100u8); + rlp_list.append(&"0000000"); + rlp_list.append(&5u8); + let rlp_list = Rlp::new(rlp_list.as_raw()); + println!("rlp list data: {:?}", rlp_list.as_raw()); + + let mut rlp = RlpStream::new(); + rlp.append(&"1111111"); + let rlp = Rlp::new(rlp.as_raw()); + println!("rlp list data: {:?}", rlp.data()); + } + + #[test] + fn should_agree_with_geth_test() { + use rustc_hex::FromHex; + let encoded_tx = "01f8630103018261a894b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a825544c001a0cb51495c66325615bcd591505577c9dde87bd59b04be2e6ba82f6d7bdea576e3a049e4f02f37666bd91a052a56e91e71e438590df861031ee9a321ce058df3dc2b"; + let _ = TypedTransaction::decode(&FromHex::from_hex(encoded_tx).unwrap()) + .expect("decoding tx data failed"); + } + #[test] fn should_agree_with_vitalik() { use rustc_hex::FromHex; let test_vector = |tx_data: &str, address: &'static str| { - let signed = - rlp::decode(&FromHex::from_hex(tx_data).unwrap()).expect("decoding tx data failed"); + let signed = TypedTransaction::decode(&FromHex::from_hex(tx_data).unwrap()) + .expect("decoding tx data failed"); let signed = SignedTransaction::new(signed).unwrap(); assert_eq!(signed.sender(), address.into()); println!("chainid: {:?}", signed.chain_id()); diff --git a/ethcore/types/src/transaction/transaction_id.rs b/ethcore/types/src/transaction/transaction_id.rs new file mode 100644 index 0000000000..833a678cd0 --- /dev/null +++ b/ethcore/types/src/transaction/transaction_id.rs @@ -0,0 +1,45 @@ +// Copyright 2020-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! Transaction Id. + +use serde_repr::*; +use std::convert::TryFrom; + +#[derive(Serialize_repr, Eq, Hash, Deserialize_repr, Debug, Clone, PartialEq)] +#[repr(u8)] +pub enum TypedTxId { + AccessList = 0x01, + Legacy = 0x80, // With 0x80 we are sure that all other types will not overlap +} + +impl Default for TypedTxId { + fn default() -> TypedTxId { + TypedTxId::Legacy + } +} + +impl TryFrom for TypedTxId { + type Error = (); + + fn try_from(v: u8) -> Result { + match v { + x if x == TypedTxId::AccessList as u8 => Ok(TypedTxId::AccessList), + x if (x & 0x80) != 0x00 => Ok(TypedTxId::Legacy), + _ => Err(()), + } + } +} diff --git a/ethcore/types/src/views/block.rs b/ethcore/types/src/views/block.rs index 8db0a364c5..237cf8694c 100644 --- a/ethcore/types/src/views/block.rs +++ b/ethcore/types/src/views/block.rs @@ -21,7 +21,7 @@ use bytes::Bytes; use ethereum_types::H256; use hash::keccak; use header::Header; -use transaction::{LocalizedTransaction, UnverifiedTransaction}; +use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; use views::{HeaderView, TransactionView}; /// View onto block rlp. @@ -77,7 +77,12 @@ impl<'a> BlockView<'a> { /// Return List of transactions in given block. pub fn transactions(&self) -> Vec { - self.rlp.list_at(1) + TypedTransaction::decode_rlp_list(&self.rlp.at(1).rlp).unwrap_or_else(|e| { + panic!( + "block transactions, view rlp is trusted and should be valid: {:?}", + e + ) + }) } /// Return List of transactions with additional localization info. @@ -126,10 +131,14 @@ impl<'a> BlockView<'a> { /// Returns transaction at given index without deserializing unnecessary data. pub fn transaction_at(&self, index: usize) -> Option { - self.transactions_rlp() - .iter() - .nth(index) - .map(|rlp| rlp.as_val()) + self.transactions_rlp().iter().nth(index).map(|rlp| { + TypedTransaction::decode_rlp(&rlp.rlp).unwrap_or_else(|e| { + panic!( + "block transaction_at, view rlp is trusted and should be valid.{:?}", + e + ) + }) + }) } /// Returns localized transaction at given index. diff --git a/ethcore/types/src/views/body.rs b/ethcore/types/src/views/body.rs index 8805f029ad..0fcc8eb38a 100644 --- a/ethcore/types/src/views/body.rs +++ b/ethcore/types/src/views/body.rs @@ -21,7 +21,7 @@ use bytes::Bytes; use ethereum_types::H256; use hash::keccak; use header::Header; -use transaction::{LocalizedTransaction, UnverifiedTransaction}; +use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; use views::{HeaderView, TransactionView}; use BlockNumber; @@ -58,7 +58,12 @@ impl<'a> BodyView<'a> { /// Return List of transactions in given block. pub fn transactions(&self) -> Vec { - self.rlp.list_at(0) + TypedTransaction::decode_rlp_list(&self.rlp.at(0).rlp).unwrap_or_else(|e| { + panic!( + "body transactions, view rlp is trusted and should be valid: {:?}", + e + ) + }) } /// Return List of transactions with additional localization info. @@ -107,10 +112,14 @@ impl<'a> BodyView<'a> { /// Returns transaction at given index without deserializing unnecessary data. pub fn transaction_at(&self, index: usize) -> Option { - self.transactions_rlp() - .iter() - .nth(index) - .map(|rlp| rlp.as_val()) + self.transactions_rlp().iter().nth(index).map(|rlp| { + TypedTransaction::decode_rlp(&rlp.rlp).unwrap_or_else(|e| { + panic!( + "body transaction_a, view rlp is trusted and should be valid: {:?}", + e + ) + }) + }) } /// Returns localized transaction at given index. diff --git a/ethcore/vm/src/access_list.rs b/ethcore/vm/src/access_list.rs index a4a4343687..3d3545604a 100644 --- a/ethcore/vm/src/access_list.rs +++ b/ethcore/vm/src/access_list.rs @@ -213,7 +213,7 @@ mod tests { access_list.insert_address(Address::from(1)); access_list.insert_storage_key(Address::from(2), H256::from(3)); - let mut access_list_call = access_list.clone(); + let access_list_call = access_list.clone(); assert_eq!(true, access_list_call.contains_address(&Address::from(1))); assert_eq!( true, diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index b6b27bd210..cd258b69ce 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -24,6 +24,10 @@ pub const EIP2929_COLD_ACCOUNT_ACCESS_COST: usize = 2600; pub const EIP2929_WARM_STORAGE_READ_COST: usize = 100; // Gas per sstore reset pub const EIP2929_SSTORE_RESET_GAS: usize = 5000 - EIP2929_COLD_SLOAD_COST; +/// Gas per received storage key +pub const EIP2930_ACCESS_LIST_STORAGE_KEY_COST: usize = 1900; +/// Gas per received address +pub const EIP2930_ACCESS_LIST_ADDRESS_COST: usize = 2400; /// Definition of the cost schedule and other parameterisations for the EVM. #[derive(Debug)] @@ -149,6 +153,8 @@ pub struct Schedule { pub wasm: Option, /// Enable EIP-2929 rules pub eip2929: bool, + /// Enable EIP-2930 rules for optional access list transactions. it depends on EIP-2929 + pub eip2930: bool, } /// Wasm cost table @@ -295,6 +301,7 @@ impl Schedule { keep_unsigned_nonce: false, wasm: None, eip2929: false, + eip2930: false, } } @@ -343,6 +350,7 @@ impl Schedule { schedule.eip1283 = true; schedule.eip2929 = true; + schedule.eip2930 = true; schedule.cold_sload_cost = EIP2929_COLD_SLOAD_COST; schedule.cold_account_access_cost = EIP2929_COLD_ACCOUNT_ACCESS_COST; @@ -421,6 +429,7 @@ impl Schedule { keep_unsigned_nonce: false, wasm: None, eip2929: false, + eip2930: false, } } diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index d2b0b6bc78..9ebe02a4e3 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -141,7 +141,7 @@ pub fn run_transaction( let result = run( &spec, trie_spec, - transaction.gas, + transaction.tx().gas, pre_state, |mut client| { let result = client.transact(env_info, transaction, trace::NoopTracer, informant); diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 6366ebcb7f..15c1747d48 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -108,6 +108,8 @@ pub struct Params { /// See `CommonParams` docs. pub eip2929_transition: Option, /// See `CommonParams` docs. + pub eip2930_transition: Option, + /// See `CommonParams` docs. pub dust_protection_transition: Option, /// See `CommonParams` docs. pub nonce_cap_increment: Option, diff --git a/miner/local-store/src/lib.rs b/miner/local-store/src/lib.rs index b05efe2e00..9dd80dc356 100644 --- a/miner/local-store/src/lib.rs +++ b/miner/local-store/src/lib.rs @@ -20,9 +20,9 @@ use std::{fmt, sync::Arc, time::Duration}; use io::IoHandler; use kvdb::KeyValueDB; -use rlp::Rlp; use types::transaction::{ - Condition as TransactionCondition, PendingTransaction, SignedTransaction, UnverifiedTransaction, + Condition as TransactionCondition, PendingTransaction, SignedTransaction, TypedTransaction, + UnverifiedTransaction, }; extern crate common_types as types; @@ -98,7 +98,7 @@ struct TransactionEntry { impl TransactionEntry { fn into_pending(self) -> Option { - let tx: UnverifiedTransaction = match Rlp::new(&self.rlp_bytes).as_val() { + let tx: UnverifiedTransaction = match TypedTransaction::decode(&self.rlp_bytes) { Err(e) => { warn!(target: "local_store", "Invalid persistent transaction stored: {}", e); return None; @@ -120,7 +120,7 @@ impl TransactionEntry { impl From for TransactionEntry { fn from(pending: PendingTransaction) -> Self { TransactionEntry { - rlp_bytes: ::rlp::encode(&pending.transaction), + rlp_bytes: pending.transaction.encode(), condition: pending.condition.map(Into::into), } } @@ -239,7 +239,7 @@ mod tests { use ethkey::{Brain, Generator}; use std::sync::Arc; - use types::transaction::{Condition, PendingTransaction, Transaction}; + use types::transaction::{Condition, PendingTransaction, Transaction, TypedTransaction}; // we want to test: round-trip of good transactions. // failure to roundtrip bad transactions (but that it doesn't panic) @@ -271,8 +271,8 @@ mod tests { let keypair = Brain::new("abcd".into()).generate().unwrap(); let transactions: Vec<_> = (0..10u64) .map(|nonce| { - let mut tx = Transaction::default(); - tx.nonce = nonce.into(); + let mut tx = TypedTransaction::Legacy(Transaction::default()); + tx.tx_mut().nonce = nonce.into(); let signed = tx.sign(keypair.secret(), None); let condition = match nonce { @@ -308,8 +308,8 @@ mod tests { let keypair = Brain::new("abcd".into()).generate().unwrap(); let mut transactions: Vec<_> = (0..10u64) .map(|nonce| { - let mut tx = Transaction::default(); - tx.nonce = nonce.into(); + let mut tx = TypedTransaction::Legacy(Transaction::default()); + tx.tx_mut().nonce = nonce.into(); let signed = tx.sign(keypair.secret(), None); @@ -318,8 +318,8 @@ mod tests { .collect(); transactions.push({ - let mut tx = Transaction::default(); - tx.nonce = 10.into(); + let mut tx = TypedTransaction::Legacy(Transaction::default()); + tx.tx_mut().nonce = 10.into(); let signed = tx.fake_sign(Default::default()); PendingTransaction::new(signed, None) diff --git a/miner/src/pool/listener.rs b/miner/src/pool/listener.rs index 35f94d6007..6cb190ca9c 100644 --- a/miner/src/pool/listener.rs +++ b/miner/src/pool/listener.rs @@ -79,11 +79,11 @@ impl txpool::Listener for Logger { "[{hash:?}] Sender: {sender}, nonce: {nonce}, gasPrice: {gas_price}, gas: {gas}, value: {value}, dataLen: {data}))", hash = tx.hash(), sender = tx.sender(), - nonce = tx.signed().nonce, - gas_price = tx.signed().gas_price, - gas = tx.signed().gas, - value = tx.signed().value, - data = tx.signed().data.len(), + nonce = tx.signed().tx().nonce, + gas_price = tx.signed().tx().gas_price, + gas = tx.signed().tx().gas, + value = tx.signed().tx().value, + data = tx.signed().tx().data.len(), ); if let Some(old) = old { @@ -150,7 +150,7 @@ mod tests { assert_eq!( *received.lock(), vec![ - "13aff4201ac1dc49daf6a7cf07b558ed956511acbaabf9502bdacc353953766d" + "de96bdcdf864c95eb7f81eff1e3290be24a0f327732e0c4251c1896a565a80db" .parse() .unwrap() ] @@ -158,14 +158,14 @@ mod tests { } fn new_tx() -> Arc { - let signed = transaction::Transaction { + let signed = transaction::TypedTransaction::Legacy(transaction::Transaction { action: transaction::Action::Create, data: vec![1, 2, 3], nonce: 5.into(), gas: 21_000.into(), gas_price: 5.into(), value: 0.into(), - } + }) .fake_sign(5.into()); Arc::new(Transaction::from_pending_block_transaction(signed)) diff --git a/miner/src/pool/local_transactions.rs b/miner/src/pool/local_transactions.rs index 89f1476248..8c0037c58d 100644 --- a/miner/src/pool/local_transactions.rs +++ b/miner/src/pool/local_transactions.rs @@ -340,14 +340,14 @@ mod tests { fn new_tx>(nonce: T) -> Arc { let keypair = Random.generate().unwrap(); - let signed = transaction::Transaction { + let signed = transaction::TypedTransaction::Legacy(transaction::Transaction { action: transaction::Action::Create, value: U256::from(100), data: Default::default(), gas: U256::from(10), gas_price: U256::from(1245), nonce: nonce.into(), - } + }) .sign(keypair.secret(), None); let mut tx = Transaction::from_pending_block_transaction(signed); diff --git a/miner/src/pool/mod.rs b/miner/src/pool/mod.rs index 306189d13c..8d11c43d93 100644 --- a/miner/src/pool/mod.rs +++ b/miner/src/pool/mod.rs @@ -192,11 +192,11 @@ impl ScoredTransaction for VerifiedTransaction { /// Gets transaction gas price. fn gas_price(&self) -> &U256 { - &self.transaction.gas_price + &self.transaction.tx().gas_price } /// Gets transaction nonce. fn nonce(&self) -> U256 { - self.transaction.nonce + self.transaction.tx().nonce } } diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index 92bdf2f07e..d9a72e3da5 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -519,7 +519,7 @@ impl TransactionQueue { .read() .pending_from_sender(state_readiness, address) .last() - .map(|tx| tx.signed().nonce.saturating_add(U256::from(1))) + .map(|tx| tx.signed().tx().nonce.saturating_add(U256::from(1))) } /// Retrieve a transaction from the pool. @@ -573,7 +573,7 @@ impl TransactionQueue { /// Returns gas price of currently the worst transaction in the pool. pub fn current_worst_gas_price(&self) -> U256 { match self.pool.read().worst_transaction() { - Some(tx) => tx.signed().gas_price, + Some(tx) => tx.signed().tx().gas_price, None => self.options.read().minimal_gas_price, } } @@ -660,7 +660,7 @@ mod tests { ); for tx in pending { - assert!(tx.signed().nonce > 0.into()); + assert!(tx.signed().tx().nonce > 0.into()); } } } diff --git a/miner/src/pool/ready.rs b/miner/src/pool/ready.rs index 75d54bf8ff..d8914be5c9 100644 --- a/miner/src/pool/ready.rs +++ b/miner/src/pool/ready.rs @@ -71,7 +71,7 @@ impl txpool::Ready for State { fn is_ready(&mut self, tx: &VerifiedTransaction) -> txpool::Readiness { // Check max nonce match self.max_nonce { - Some(nonce) if tx.transaction.nonce > nonce => { + Some(nonce) if tx.transaction.tx().nonce > nonce => { return txpool::Readiness::Future; } _ => {} @@ -81,7 +81,7 @@ impl txpool::Ready for State { let state = &self.state; let state_nonce = || state.account_nonce(sender); let nonce = self.nonces.entry(*sender).or_insert_with(state_nonce); - match tx.transaction.nonce.cmp(nonce) { + match tx.transaction.tx().nonce.cmp(nonce) { // Before marking as future check for stale ids cmp::Ordering::Greater => match self.stale_id { Some(id) if tx.insertion_id() < id => txpool::Readiness::Stale, @@ -150,8 +150,8 @@ impl Option> txpool::Ready for Opt let nonce = self .nonces .entry(*sender) - .or_insert_with(|| state(sender).unwrap_or_else(|| tx.transaction.nonce)); - match tx.transaction.nonce.cmp(nonce) { + .or_insert_with(|| state(sender).unwrap_or_else(|| tx.transaction.tx().nonce)); + match tx.transaction.tx().nonce.cmp(nonce) { cmp::Ordering::Greater => txpool::Readiness::Future, cmp::Ordering::Less => txpool::Readiness::Stale, cmp::Ordering::Equal => { diff --git a/miner/src/pool/scoring.rs b/miner/src/pool/scoring.rs index 1b5e164179..d27ada1241 100644 --- a/miner/src/pool/scoring.rs +++ b/miner/src/pool/scoring.rs @@ -67,7 +67,7 @@ impl NonceAndGasPrice { return true; } - &old.transaction.gas_price > new.gas_price() + &old.transaction.tx().gas_price > new.gas_price() } } diff --git a/miner/src/pool/tests/client.rs b/miner/src/pool/tests/client.rs index fc0413690f..05d99f3ed4 100644 --- a/miner/src/pool/tests/client.rs +++ b/miner/src/pool/tests/client.rs @@ -18,7 +18,9 @@ use std::sync::{atomic, Arc}; use ethereum_types::{Address, H256, U256}; use rlp::Rlp; -use types::transaction::{self, SignedTransaction, Transaction, UnverifiedTransaction}; +use types::transaction::{ + self, SignedTransaction, Transaction, TypedTransaction, UnverifiedTransaction, +}; use pool::{self, client::AccountDetails}; @@ -150,7 +152,7 @@ impl pool::client::Client for TestClient { if rlp.as_raw().len() > self.max_transaction_size { return Err(transaction::Error::TooBig); } - rlp.as_val() + TypedTransaction::decode(transaction) .map_err(|e| transaction::Error::InvalidRlp(e.to_string())) } } diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index fb25d66ac9..8d0fc94820 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -69,7 +69,7 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { ); let (tx1, tx2) = Tx::gas_price(2).signed_pair(); let sender = tx1.sender(); - let nonce = tx1.nonce; + let nonce = tx1.tx().nonce; // when let r1 = txq.import(TestClient::new(), vec![tx1].retracted()); @@ -129,7 +129,7 @@ fn should_never_drop_local_transactions_from_different_senders() { ); let (tx1, tx2) = Tx::gas_price(2).signed_pair(); let sender = tx1.sender(); - let nonce = tx1.nonce; + let nonce = tx1.tx().nonce; // when let r1 = txq.import(TestClient::new(), vec![tx1].local()); @@ -662,12 +662,14 @@ fn should_not_replace_same_transaction_if_the_fee_is_less_than_minimal_bump() { assert_eq!( txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[0] .signed() + .tx() .gas_price, U256::from(20) ); assert_eq!( txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[1] .signed() + .tx() .gas_price, U256::from(2) ); @@ -688,7 +690,7 @@ fn should_return_correct_nonce_when_transactions_from_given_address_exist() { let txq = new_queue(); let tx = Tx::default().signed(); let from = tx.sender(); - let nonce = tx.nonce; + let nonce = tx.tx().nonce; // when txq.import(TestClient::new(), vec![tx.local()]); diff --git a/miner/src/pool/tests/tx.rs b/miner/src/pool/tests/tx.rs index 2e46fe28ef..51c276d445 100644 --- a/miner/src/pool/tests/tx.rs +++ b/miner/src/pool/tests/tx.rs @@ -17,7 +17,9 @@ use ethereum_types::{H256, U256}; use ethkey::{Generator, Random}; use rustc_hex::FromHex; -use types::transaction::{self, SignedTransaction, Transaction, UnverifiedTransaction}; +use types::transaction::{ + self, SignedTransaction, Transaction, TypedTransaction, UnverifiedTransaction, +}; use pool::{verifier, VerifiedTransaction}; @@ -76,20 +78,20 @@ impl Tx { (tx1, tx2) } - pub fn unsigned(self) -> Transaction { - Transaction { + pub fn unsigned(self) -> TypedTransaction { + TypedTransaction::Legacy(Transaction { action: transaction::Action::Create, value: U256::from(100), data: "3331600055".from_hex().unwrap(), gas: self.gas.into(), gas_price: self.gas_price.into(), nonce: self.nonce.into(), - } + }) } pub fn big_one(self) -> SignedTransaction { let keypair = Random.generate().unwrap(); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { action: transaction::Action::Create, value: U256::from(100), data: include_str!("../res/big_transaction.data") @@ -98,7 +100,7 @@ impl Tx { gas: self.gas.into(), gas_price: self.gas_price.into(), nonce: self.nonce.into(), - }; + }); tx.sign(keypair.secret(), None) } } diff --git a/miner/src/pool/verifier.rs b/miner/src/pool/verifier.rs index cf4e116de8..aa19991214 100644 --- a/miner/src/pool/verifier.rs +++ b/miner/src/pool/verifier.rs @@ -31,7 +31,6 @@ use std::{ }; use ethereum_types::{H256, U256}; -use rlp::Encodable; use txpool; use types::transaction; @@ -97,21 +96,21 @@ impl Transaction { /// Return transaction gas price pub fn gas_price(&self) -> &U256 { match *self { - Transaction::Unverified(ref tx) => &tx.gas_price, - Transaction::Retracted(ref tx) => &tx.gas_price, - Transaction::Local(ref tx) => &tx.gas_price, + Transaction::Unverified(ref tx) => &tx.tx().gas_price, + Transaction::Retracted(ref tx) => &tx.tx().gas_price, + Transaction::Local(ref tx) => &tx.tx().gas_price, } } fn gas(&self) -> &U256 { match *self { - Transaction::Unverified(ref tx) => &tx.gas, - Transaction::Retracted(ref tx) => &tx.gas, - Transaction::Local(ref tx) => &tx.gas, + Transaction::Unverified(ref tx) => &tx.tx().gas, + Transaction::Retracted(ref tx) => &tx.tx().gas, + Transaction::Local(ref tx) => &tx.tx().gas, } } - fn transaction(&self) -> &transaction::Transaction { + fn transaction(&self) -> &transaction::TypedTransaction { match *self { Transaction::Unverified(ref tx) => &*tx, Transaction::Retracted(ref tx) => &*tx, @@ -198,7 +197,7 @@ impl txpool::Verifier }); } - let minimal_gas = self.client.required_gas(tx.transaction()); + let minimal_gas = self.client.required_gas(tx.transaction().tx()); if tx.gas() < &minimal_gas { trace!(target: "txqueue", "[{:?}] Rejected transaction with insufficient gas: {} < {}", @@ -240,10 +239,10 @@ impl txpool::Verifier "[{:?}] Rejected tx early, cause it doesn't have any chance to get to the pool: (gas price: {} < {})", hash, tx.gas_price(), - vtx.transaction.gas_price, + vtx.transaction.tx().gas_price, ); return Err(transaction::Error::TooCheapToReplace { - prev: Some(vtx.transaction.gas_price), + prev: Some(vtx.transaction.tx().gas_price), new: Some(*tx.gas_price()), }); } @@ -273,7 +272,7 @@ impl txpool::Verifier }; // Verify RLP payload - if let Err(err) = self.client.decode_transaction(&transaction.rlp_bytes()) { + if let Err(err) = self.client.decode_transaction(&transaction.encode()) { debug!(target: "txqueue", "[{:?}] Rejected transaction's rlp payload", err); bail!(err) } @@ -281,7 +280,7 @@ impl txpool::Verifier let sender = transaction.sender(); let account_details = self.client.account_details(&sender); - if transaction.gas_price < self.options.minimal_gas_price { + if transaction.tx().gas_price < self.options.minimal_gas_price { let transaction_type = self.client.transaction_type(&transaction); if let TransactionType::Service = transaction_type { debug!(target: "txqueue", "Service tx {:?} below minimal gas price accepted", hash); @@ -292,18 +291,21 @@ impl txpool::Verifier target: "txqueue", "[{:?}] Rejected tx below minimal gas price threshold: {} < {}", hash, - transaction.gas_price, + transaction.tx().gas_price, self.options.minimal_gas_price, ); bail!(transaction::Error::InsufficientGasPrice { minimal: self.options.minimal_gas_price, - got: transaction.gas_price, + got: transaction.tx().gas_price, }); } } - let (full_gas_price, overflow_1) = transaction.gas_price.overflowing_mul(transaction.gas); - let (cost, overflow_2) = transaction.value.overflowing_add(full_gas_price); + let (full_gas_price, overflow_1) = transaction + .tx() + .gas_price + .overflowing_mul(transaction.tx().gas); + let (cost, overflow_2) = transaction.tx().value.overflowing_add(full_gas_price); if overflow_1 || overflow_2 { trace!( target: "txqueue", @@ -329,12 +331,12 @@ impl txpool::Verifier }); } - if transaction.nonce < account_details.nonce { + if transaction.tx().nonce < account_details.nonce { debug!( target: "txqueue", "[{:?}] Rejected tx with old nonce ({} < {})", hash, - transaction.nonce, + transaction.tx().nonce, account_details.nonce, ); bail!(transaction::Error::Old); diff --git a/miner/src/service_transaction_checker.rs b/miner/src/service_transaction_checker.rs index e6917568c4..f426571fa6 100644 --- a/miner/src/service_transaction_checker.rs +++ b/miner/src/service_transaction_checker.rs @@ -45,7 +45,7 @@ impl ServiceTransactionChecker { ) -> Result { let sender = tx.sender(); // Skip checking the contract if the transaction does not have zero gas price - if !tx.gas_price.is_zero() { + if !tx.tx().gas_price.is_zero() { return Ok(false); } diff --git a/rpc/src/v1/helpers/dispatch/full.rs b/rpc/src/v1/helpers/dispatch/full.rs index fda6d4701f..36874e6d1c 100644 --- a/rpc/src/v1/helpers/dispatch/full.rs +++ b/rpc/src/v1/helpers/dispatch/full.rs @@ -120,6 +120,7 @@ impl Dispatcher }; Box::new(future::ok(FilledTransactionRequest { + tx_type: request.tx_type, from, used_default_from: request.from.is_none(), to: request.to, @@ -133,6 +134,7 @@ impl Dispatcher value: request.value.unwrap_or_else(|| 0.into()), data: request.data.unwrap_or_else(Vec::new), condition: request.condition, + access_list: request.access_list, })) } diff --git a/rpc/src/v1/helpers/dispatch/signing.rs b/rpc/src/v1/helpers/dispatch/signing.rs index 55b03b2faa..d07cb3eccd 100644 --- a/rpc/src/v1/helpers/dispatch/signing.rs +++ b/rpc/src/v1/helpers/dispatch/signing.rs @@ -21,7 +21,10 @@ use bytes::Bytes; use crypto::DEFAULT_MAC; use ethereum_types::{Address, H256, U256}; use ethkey::Signature; -use types::transaction::{Action, SignedTransaction, Transaction}; +use jsonrpc_core::{Error, ErrorCode}; +use types::transaction::{ + AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction, TypedTxId, +}; use jsonrpc_core::Result; use v1::helpers::{errors, FilledTransactionRequest}; @@ -48,16 +51,28 @@ impl super::Accounts for Signer { nonce: U256, password: SignWith, ) -> Result> { - let t = Transaction { - nonce: nonce, + let legacy_tx = Transaction { + nonce, action: filled.to.map_or(Action::Create, Action::Call), gas: filled.gas, gas_price: filled.gas_price, value: filled.value, data: filled.data, }; + let t = match filled.tx_type { + TypedTxId::Legacy => TypedTransaction::Legacy(legacy_tx), + TypedTxId::AccessList => { + if filled.access_list.is_none() { + return Err(Error::new(ErrorCode::InvalidParams)); + } + TypedTransaction::AccessList(AccessListTx::new( + legacy_tx, + filled.access_list.unwrap(), + )) + } + }; - let hash = t.hash(chain_id); + let hash = t.signature_hash(chain_id); let signature = signature(&*self.accounts, filled.from, hash, password)?; Ok(signature.map(|sig| { diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index bb3d71c70f..c9d04995f4 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -399,7 +399,8 @@ pub fn transaction_message(error: &TransactionError) -> String { CodeBanned => "Code is banned in local queue.".into(), NotAllowed => "Transaction is not permitted.".into(), TooBig => "Transaction is too big, see chain specification for the limit.".into(), - InvalidRlp(ref descr) => format!("Invalid RLP data: {}", descr), + InvalidRlp(ref descr) => format!("Invalid RLP data: {}", descr), + TransactionTypeNotEnabled => format!("Transaction type is not enabled for current block"), } } diff --git a/rpc/src/v1/helpers/external_signer/signing_queue.rs b/rpc/src/v1/helpers/external_signer/signing_queue.rs index 745304836b..deec5c3b4e 100644 --- a/rpc/src/v1/helpers/external_signer/signing_queue.rs +++ b/rpc/src/v1/helpers/external_signer/signing_queue.rs @@ -256,6 +256,7 @@ mod test { fn request() -> ConfirmationPayload { ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from(2)), @@ -265,6 +266,7 @@ mod test { data: vec![], nonce: None, condition: None, + access_list: None, }) } diff --git a/rpc/src/v1/helpers/fake_sign.rs b/rpc/src/v1/helpers/fake_sign.rs index de9ae57089..b692f502f7 100644 --- a/rpc/src/v1/helpers/fake_sign.rs +++ b/rpc/src/v1/helpers/fake_sign.rs @@ -15,7 +15,9 @@ // along with OpenEthereum. If not, see . use std::cmp::min; -use types::transaction::{Action, SignedTransaction, Transaction}; +use types::transaction::{ + AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction, TypedTxId, +}; use ethereum_types::U256; use jsonrpc_core::Error; @@ -25,14 +27,20 @@ pub fn sign_call(request: CallRequest) -> Result { let max_gas = U256::from(500_000_000); let gas = min(request.gas.unwrap_or(max_gas), max_gas); let from = request.from.unwrap_or_default(); - - Ok(Transaction { + let tx_legacy = Transaction { nonce: request.nonce.unwrap_or_default(), action: request.to.map_or(Action::Create, Action::Call), gas, gas_price: request.gas_price.unwrap_or_default(), value: request.value.unwrap_or_default(), data: request.data.unwrap_or_default(), - } - .fake_sign(from)) + }; + let tx_typed = match request.tx_type { + TypedTxId::Legacy => TypedTransaction::Legacy(tx_legacy), + TypedTxId::AccessList => TypedTransaction::AccessList(AccessListTx::new( + tx_legacy, + request.access_list.unwrap_or_default(), + )), + }; + Ok(tx_typed.fake_sign(from)) } diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs index eeb1654d84..848a8d4156 100644 --- a/rpc/src/v1/helpers/requests.rs +++ b/rpc/src/v1/helpers/requests.rs @@ -16,12 +16,15 @@ use bytes::Bytes; use ethereum_types::{Address, H256, U256}; +use types::transaction::{AccessList, TypedTxId}; use v1::types::{Origin, TransactionCondition}; /// Transaction request coming from RPC #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct TransactionRequest { + /// type of transaction. + pub tx_type: TypedTxId, /// Sender pub from: Option
, /// Recipient @@ -38,11 +41,15 @@ pub struct TransactionRequest { pub nonce: Option, /// Delay until this condition is met. pub condition: Option, + /// Access list + pub access_list: Option, } /// Transaction request coming from RPC with default values filled in. #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct FilledTransactionRequest { + /// type of transaction. + pub tx_type: TypedTxId, /// Sender pub from: Address, /// Indicates if the sender was filled by default value. @@ -61,11 +68,14 @@ pub struct FilledTransactionRequest { pub nonce: Option, /// Delay until this condition is met. pub condition: Option, + /// Access list + pub access_list: Option, } impl From for TransactionRequest { fn from(r: FilledTransactionRequest) -> Self { TransactionRequest { + tx_type: r.tx_type, from: Some(r.from), to: r.to, gas_price: Some(r.gas_price), @@ -74,6 +84,7 @@ impl From for TransactionRequest { data: Some(r.data), nonce: r.nonce, condition: r.condition, + access_list: r.access_list, } } } @@ -81,6 +92,8 @@ impl From for TransactionRequest { /// Call request #[derive(Debug, Default, PartialEq)] pub struct CallRequest { + /// type of transaction. + pub tx_type: TypedTxId, /// From pub from: Option
, /// To @@ -95,6 +108,8 @@ pub struct CallRequest { pub data: Option>, /// Nonce pub nonce: Option, + /// Access list + pub access_list: Option, } /// Confirmation object diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 613a2815b9..2896edf8d1 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -24,7 +24,6 @@ use std::{ use ethereum_types::{Address, H160, H256, H64, U256, U64}; use parking_lot::Mutex; -use rlp::Rlp; use ethash::{self, SeedHashCompute}; use ethcore::{ @@ -42,7 +41,7 @@ use types::{ encoded, filter::Filter as EthcoreFilter, header::Header, - transaction::{LocalizedTransaction, SignedTransaction}, + transaction::{LocalizedTransaction, SignedTransaction, TypedTransaction}, BlockNumber as EthBlockNumber, }; @@ -1065,8 +1064,7 @@ where } fn send_raw_transaction(&self, raw: Bytes) -> Result { - Rlp::new(&raw.into_vec()) - .as_val() + TypedTransaction::decode(&raw.into_vec()) .map_err(errors::rlp) .and_then(|tx| SignedTransaction::new(tx).map_err(errors::transaction)) .and_then(|signed_transaction| { diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index b7dca6998a..049ed2ab6b 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -22,8 +22,7 @@ use ethereum_types::U256; use ethkey; use parity_runtime::Executor; use parking_lot::Mutex; -use rlp::Rlp; -use types::transaction::{PendingTransaction, SignedTransaction}; +use types::transaction::{PendingTransaction, SignedTransaction, TypedTransaction}; use jsonrpc_core::{ futures::{future, future::Either, Future, IntoFuture}, @@ -161,17 +160,17 @@ impl SignerClient { where F: FnOnce(PendingTransaction) -> Result, { - let signed_transaction = Rlp::new(&bytes.0).as_val().map_err(errors::rlp)?; + let signed_transaction = TypedTransaction::decode(&bytes.0).map_err(errors::rlp)?; let signed_transaction = SignedTransaction::new(signed_transaction) .map_err(|e| errors::invalid_params("Invalid signature.", e))?; let sender = signed_transaction.sender(); // Verification let sender_matches = sender == request.from; - let data_matches = signed_transaction.data == request.data; - let value_matches = signed_transaction.value == request.value; + let data_matches = signed_transaction.tx().data == request.data; + let value_matches = signed_transaction.tx().value == request.value; let nonce_matches = match request.nonce { - Some(nonce) => signed_transaction.nonce == nonce, + Some(nonce) => signed_transaction.tx().nonce == nonce, None => true, }; diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index d685e40caa..329e0547ec 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -22,8 +22,7 @@ use ethcore::client::{ BlockChainClient, BlockId, Call, CallAnalytics, StateClient, StateInfo, TraceId, TransactionId, }; use ethereum_types::H256; -use rlp::Rlp; -use types::transaction::SignedTransaction; +use types::transaction::{SignedTransaction, TypedTransaction}; use jsonrpc_core::Result; use v1::{ @@ -194,9 +193,8 @@ where ) -> Result { let block = block.unwrap_or_default(); - let tx = Rlp::new(&raw_transaction.into_vec()) - .as_val() - .map_err(|e| errors::invalid_params("Transaction is not valid RLP", e))?; + let tx = TypedTransaction::decode(&raw_transaction.0) + .map_err(|e| errors::invalid_params("Transaction is not in valid Format", e))?; let signed = SignedTransaction::new(tx).map_err(errors::transaction)?; let id = match block { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index c50a61f9de..00ea5c6c2d 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -30,14 +30,13 @@ use ethereum_types::{Address, Bloom, H160, H256, U256}; use miner::external::ExternalMiner; use parity_runtime::Runtime; use parking_lot::Mutex; -use rlp; use rustc_hex::{FromHex, ToHex}; use sync::SyncState; use types::{ ids::{BlockId, TransactionId}, log_entry::{LocalizedLogEntry, LogEntry}, receipt::{LocalizedReceipt, RichReceipt, TransactionOutcome}, - transaction::{Action, Transaction}, + transaction::{Action, Transaction, TypedTransaction, TypedTxId}, }; use jsonrpc_core::IoHandler; @@ -694,13 +693,12 @@ fn rpc_eth_transaction_count_by_number_pending() { #[test] fn rpc_eth_pending_transaction_by_hash() { use ethereum_types::H256; - use rlp; use types::transaction::SignedTransaction; let tester = EthTester::default(); { let bytes = FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap(); - let tx = rlp::decode(&bytes).expect("decoding failure"); + let tx = TypedTransaction::decode(&bytes).expect("decoding failure"); let tx = SignedTransaction::new(tx).unwrap(); tester .miner @@ -1050,6 +1048,23 @@ fn rpc_eth_estimate_gas_default_block() { fn rpc_eth_send_raw_transaction_error() { let tester = EthTester::default(); + let req = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendRawTransaction", + "params": [ + "0x1123" + ], + "id": 1 + }"#; + let res = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid RLP.","data":"Custom(\"Unknown transaction\")"},"id":1}"#.into(); + + assert_eq!(tester.io.handle_request_sync(&req), Some(res)); +} + +#[test] +fn rpc_eth_send_raw_01_transaction_error() { + let tester = EthTester::default(); + let req = r#"{ "jsonrpc": "2.0", "method": "eth_sendRawTransaction", @@ -1075,7 +1090,7 @@ fn rpc_eth_send_raw_transaction() { .unlock_account_permanently(address, "abcd".into()) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -1084,14 +1099,14 @@ fn rpc_eth_send_raw_transaction() { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); let signature = tester .accounts_provider - .sign(address, None, t.hash(None)) + .sign(address, None, t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); - let rlp = rlp::encode(&t).to_hex(); + let rlp = t.encode().to_hex(); let req = r#"{ "jsonrpc": "2.0", @@ -1118,6 +1133,7 @@ fn rpc_eth_transaction_receipt() { to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), transaction_hash: H256::zero(), transaction_index: 0, + transaction_type: TypedTxId::Legacy, block_hash: H256::from_str( "ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5", ) @@ -1204,6 +1220,7 @@ fn rpc_eth_pending_receipt() { ) .unwrap(), transaction_index: 0, + transaction_type: TypedTxId::Legacy, cumulative_gas_used: U256::from(0x20), gas_used: U256::from(0x10), contract_address: None, diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index f3ec851ad6..ea1b7c31a5 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -21,7 +21,10 @@ use ethstore::ethkey::{Generator, Random}; use miner::pool::local_transactions::Status as LocalTransactionStatus; use std::sync::Arc; use sync::ManageNetwork; -use types::receipt::{LocalizedReceipt, TransactionOutcome}; +use types::{ + receipt::{LocalizedReceipt, TransactionOutcome}, + transaction::TypedTxId, +}; use super::manage_network::TestManageNetwork; use jsonrpc_core::IoHandler; @@ -368,16 +371,17 @@ fn rpc_parity_transactions_stats() { #[test] fn rpc_parity_local_transactions() { + use types::transaction::{Transaction, TypedTransaction}; let deps = Dependencies::new(); let io = deps.default_client(); - let tx = ::types::transaction::Transaction { + let tx = TypedTransaction::Legacy(Transaction { value: 5.into(), gas: 3.into(), gas_price: 2.into(), action: ::types::transaction::Action::Create, data: vec![1, 2, 3], nonce: 0.into(), - } + }) .fake_sign(3.into()); let tx = Arc::new(::miner::pool::VerifiedTransaction::from_pending_block_transaction(tx)); deps.miner @@ -466,6 +470,7 @@ fn rpc_parity_block_receipts() { TransactionId::Hash(1.into()), LocalizedReceipt { transaction_hash: 1.into(), + transaction_type: TypedTxId::Legacy, transaction_index: 0, block_hash: 3.into(), block_number: 0, diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 18a3f930ce..bea2000a3a 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -178,7 +178,7 @@ fn rpc_parity_set_hash_content() { #[test] fn rpc_parity_remove_transaction() { - use types::transaction::{Action, Transaction}; + use types::transaction::{Action, Transaction, TypedTransaction}; let miner = miner_service(); let client = client_service(); @@ -187,14 +187,14 @@ fn rpc_parity_remove_transaction() { let mut io = IoHandler::new(); io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); - let tx = Transaction { + let tx = TypedTransaction::Legacy(Transaction { nonce: 1.into(), gas_price: 0x9184e72a000u64.into(), gas: 0x76c0.into(), action: Action::Call(5.into()), value: 0x9184e72au64.into(), data: vec![], - }; + }); let signed = tx.fake_sign(2.into()); let hash = signed.hash(); @@ -202,7 +202,7 @@ fn rpc_parity_remove_transaction() { .to_owned() + &format!("0x{:x}", hash) + r#""], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x1f","value":"0x9184e72a"},"id":1}"#; miner.pending_transactions.lock().insert(hash, signed); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index c3dd68198f..3a7743220a 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -24,7 +24,7 @@ use hash::keccak; use jsonrpc_core::IoHandler; use parity_runtime::Runtime; use parking_lot::Mutex; -use types::transaction::{Action, Transaction}; +use types::transaction::{Action, Transaction, TypedTransaction}; use ethkey::Secret; use serde_json::to_value; @@ -91,9 +91,6 @@ fn setup_with(c: Config) -> PersonalTester { tester } -#[cfg(test)] -use rustc_hex::ToHex; - #[test] fn accounts() { let tester = setup(); @@ -265,7 +262,7 @@ fn sign_and_send_test(method: &str) { "id": 1 }"#; - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -274,12 +271,15 @@ fn sign_and_send_test(method: &str) { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); tester .accounts .unlock_account_temporarily(address, "password123".into()) .unwrap(); - let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap(); + let signature = tester + .accounts + .sign(address, None, t.signature_hash(None)) + .unwrap(); let t = t.with_signature(signature, None); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() @@ -293,7 +293,7 @@ fn sign_and_send_test(method: &str) { tester.miner.increment_nonce(&address); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::one(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -302,12 +302,15 @@ fn sign_and_send_test(method: &str) { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); tester .accounts .unlock_account_temporarily(address, "password123".into()) .unwrap(); - let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap(); + let signature = tester + .accounts + .sign(address, None, t.signature_hash(None)) + .unwrap(); let t = t.with_signature(signature, None); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 3d9f6f9bf4..6ef3eb1e7a 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -22,8 +22,7 @@ use accounts::AccountProvider; use ethcore::client::TestBlockChainClient; use parity_runtime::Runtime; use parking_lot::Mutex; -use rlp::encode; -use types::transaction::{Action, SignedTransaction, Transaction}; +use types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction}; use jsonrpc_core::IoHandler; use serde_json; @@ -92,6 +91,7 @@ fn should_return_list_of_items_to_confirm() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -101,6 +101,7 @@ fn should_return_list_of_items_to_confirm() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) @@ -137,6 +138,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -146,6 +148,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) @@ -173,6 +176,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -182,6 +186,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) @@ -237,6 +242,7 @@ fn should_confirm_transaction_and_dispatch() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -246,24 +252,28 @@ fn should_confirm_transaction_and_dispatch() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(0x50505), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); tester .accounts .unlock_account_temporarily(address, "test".into()) .unwrap(); - let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap(); + let signature = tester + .accounts + .sign(address, None, t.signature_hash(None)) + .unwrap(); let t = t.with_signature(signature, None); assert_eq!(tester.signer.requests().len(), 1); @@ -297,6 +307,7 @@ fn should_alter_the_sender_and_nonce() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: 0.into(), used_default_from: false, to: Some(recipient), @@ -306,24 +317,25 @@ fn should_alter_the_sender_and_nonce() { data: vec![], nonce: Some(10.into()), condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(0x50505), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); let address = tester.accounts.new_account(&"test".into()).unwrap(); let signature = tester .accounts - .sign(address, Some("test".into()), t.hash(None)) + .sign(address, Some("test".into()), t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); @@ -361,6 +373,7 @@ fn should_confirm_transaction_with_token() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -370,22 +383,23 @@ fn should_confirm_transaction_with_token() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(10_000_000), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); let (signature, token) = tester .accounts - .sign_with_token(address, "test".into(), t.hash(None)) + .sign_with_token(address, "test".into(), t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); @@ -427,6 +441,7 @@ fn should_confirm_transaction_with_rlp() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -436,25 +451,26 @@ fn should_confirm_transaction_with_rlp() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(10_000_000), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); let signature = tester .accounts - .sign(address, Some("test".into()), t.hash(None)) + .sign(address, Some("test".into()), t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); - let rlp = encode(&t); + let rlp = t.encode(); assert_eq!(tester.signer.requests().len(), 1); @@ -491,6 +507,7 @@ fn should_return_error_when_sender_does_not_match() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: Address::default(), used_default_from: false, to: Some(recipient), @@ -500,26 +517,30 @@ fn should_return_error_when_sender_does_not_match() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(10_000_000), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); tester .accounts .unlock_account_temporarily(address, "test".into()) .unwrap(); - let signature = tester.accounts.sign(address, None, t.hash(None)).unwrap(); + let signature = tester + .accounts + .sign(address, None, t.signature_hash(None)) + .unwrap(); let t = t.with_signature(signature, None); - let rlp = encode(&t); + let rlp = t.encode(); assert_eq!(tester.signer.requests().len(), 1); @@ -553,6 +574,7 @@ fn should_confirm_sign_transaction_with_rlp() { .signer .add_request( ConfirmationPayload::SignTransaction(FilledTransactionRequest { + tx_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -562,26 +584,27 @@ fn should_confirm_sign_transaction_with_rlp() { data: vec![], nonce: None, condition: None, + access_list: None, }), Origin::Unknown, ) .unwrap(); assert_eq!(tester.signer.requests().len(), 1); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), gas: U256::from(10_000_000), action: Action::Call(recipient), value: U256::from(0x1), data: vec![], - }; + }); let signature = tester .accounts - .sign(address, Some("test".into()), t.hash(None)) + .sign(address, Some("test".into()), t.signature_hash(None)) .unwrap(); let t = SignedTransaction::new(t.with_signature(signature.clone(), None)).unwrap(); - let rlp = encode(&t); + let rlp = t.encode(); // when let request = r#"{ diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 9d8734a3ca..fdeb9b4963 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use rlp; use std::{str::FromStr, sync::Arc, thread, time::Duration}; use jsonrpc_core::{futures::Future, IoHandler, Success}; @@ -40,7 +39,7 @@ use ethstore::ethkey::{Generator, Random}; use parity_runtime::{Executor, Runtime}; use parking_lot::Mutex; use serde_json; -use types::transaction::{Action, SignedTransaction, Transaction}; +use types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction}; struct SigningTester { pub runtime: Runtime, @@ -379,7 +378,7 @@ fn should_add_sign_transaction_to_the_queue() { "id": 1 }"#; - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::one(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -388,15 +387,15 @@ fn should_add_sign_transaction_to_the_queue() { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); let signature = tester .accounts - .sign(address, Some("test".into()), t.hash(None)) + .sign(address, Some("test".into()), t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); let t = SignedTransaction::new(t).unwrap(); let signature = t.signature(); - let rlp = rlp::encode(&t); + let rlp = t.encode(); let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + r#""raw":"0x"# @@ -459,7 +458,7 @@ fn should_dispatch_transaction_if_account_is_unlock() { .unlock_account_permanently(acc, "test".into()) .unwrap(); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -468,8 +467,11 @@ fn should_dispatch_transaction_if_account_is_unlock() { ), value: U256::from(0x9184e72au64), data: vec![], - }; - let signature = tester.accounts.sign(acc, None, t.hash(None)).unwrap(); + }); + let signature = tester + .accounts + .sign(acc, None, t.signature_hash(None)) + .unwrap(); let t = t.with_signature(signature, None); // when diff --git a/rpc/src/v1/tests/mocked/signing_unsafe.rs b/rpc/src/v1/tests/mocked/signing_unsafe.rs index bb67b42b88..c52127736f 100644 --- a/rpc/src/v1/tests/mocked/signing_unsafe.rs +++ b/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -21,9 +21,7 @@ use ethcore::client::TestBlockChainClient; use ethereum_types::{Address, U256}; use parity_runtime::Runtime; use parking_lot::Mutex; -use rlp; -use rustc_hex::ToHex; -use types::transaction::{Action, Transaction}; +use types::transaction::{Action, Transaction, TypedTransaction}; use jsonrpc_core::IoHandler; use v1::{ @@ -117,7 +115,7 @@ fn rpc_eth_send_transaction() { "id": 1 }"#; - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::zero(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -126,10 +124,10 @@ fn rpc_eth_send_transaction() { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); let signature = tester .accounts_provider - .sign(address, None, t.hash(None)) + .sign(address, None, t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); @@ -141,7 +139,7 @@ fn rpc_eth_send_transaction() { tester.miner.increment_nonce(&address); - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::one(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -150,10 +148,10 @@ fn rpc_eth_send_transaction() { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); let signature = tester .accounts_provider - .sign(address, None, t.hash(None)) + .sign(address, None, t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); @@ -166,6 +164,7 @@ fn rpc_eth_send_transaction() { #[test] fn rpc_eth_sign_transaction() { + use rustc_hex::ToHex; let tester = EthTester::default(); let address = tester.accounts_provider.new_account(&"".into()).unwrap(); tester @@ -188,7 +187,7 @@ fn rpc_eth_sign_transaction() { "id": 1 }"#; - let t = Transaction { + let t = TypedTransaction::Legacy(Transaction { nonce: U256::one(), gas_price: U256::from(0x9184e72a000u64), gas: U256::from(0x76c0), @@ -197,14 +196,14 @@ fn rpc_eth_sign_transaction() { ), value: U256::from(0x9184e72au64), data: vec![], - }; + }); let signature = tester .accounts_provider - .sign(address, None, t.hash(None)) + .sign(address, None, t.signature_hash(None)) .unwrap(); let t = t.with_signature(signature, None); let signature = t.signature(); - let rlp = rlp::encode(&t); + let rlp = t.encode(); let response = r#"{"jsonrpc":"2.0","result":{"#.to_owned() + r#""raw":"0x"# diff --git a/rpc/src/v1/types/call_request.rs b/rpc/src/v1/types/call_request.rs index ac465d3ca3..d27125eedc 100644 --- a/rpc/src/v1/types/call_request.rs +++ b/rpc/src/v1/types/call_request.rs @@ -15,6 +15,7 @@ // along with OpenEthereum. If not, see . use ethereum_types::{H160, U256}; +use types::transaction::{AccessList, TypedTxId}; use v1::{helpers::CallRequest as Request, types::Bytes}; /// Call request @@ -22,6 +23,9 @@ use v1::{helpers::CallRequest as Request, types::Bytes}; #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct CallRequest { + /// transaction type + #[serde(default)] + pub tx_type: TypedTxId, /// From pub from: Option, /// To @@ -36,11 +40,14 @@ pub struct CallRequest { pub data: Option, /// Nonce pub nonce: Option, + /// Access list + pub access_list: Option, } impl Into for CallRequest { fn into(self) -> Request { Request { + tx_type: self.tx_type, from: self.from.map(Into::into), to: self.to.map(Into::into), gas_price: self.gas_price.map(Into::into), @@ -48,6 +55,7 @@ impl Into for CallRequest { value: self.value.map(Into::into), data: self.data.map(Into::into), nonce: self.nonce.map(Into::into), + access_list: self.access_list.map(Into::into), } } } @@ -76,6 +84,7 @@ mod tests { assert_eq!( deserialized, CallRequest { + tx_type: Default::default(), from: Some(H160::from(1)), to: Some(H160::from(2)), gas_price: Some(U256::from(1)), @@ -83,6 +92,7 @@ mod tests { value: Some(U256::from(3)), data: Some(vec![0x12, 0x34, 0x56].into()), nonce: Some(U256::from(4)), + access_list: None, } ); } @@ -100,13 +110,15 @@ mod tests { let deserialized: CallRequest = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, CallRequest { + tx_type: Default::default(), from: Some(H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap()), to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: Some(U256::from_str("9184e72a000").unwrap()), gas: Some(U256::from_str("76c0").unwrap()), value: Some(U256::from_str("9184e72a").unwrap()), data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()), - nonce: None + nonce: None, + access_list: None, }); } @@ -118,6 +130,7 @@ mod tests { assert_eq!( deserialized, CallRequest { + tx_type: Default::default(), from: Some(H160::from(1)), to: None, gas_price: None, @@ -125,6 +138,7 @@ mod tests { value: None, data: None, nonce: None, + access_list: None, } ); } diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index b64f1a5a3c..200c0afcba 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -331,6 +331,7 @@ mod tests { id: 15.into(), payload: helpers::ConfirmationPayload::SendTransaction( helpers::FilledTransactionRequest { + tx_type: Default::default(), from: 0.into(), used_default_from: false, to: None, @@ -340,6 +341,7 @@ mod tests { data: vec![1, 2, 3], nonce: Some(1.into()), condition: None, + access_list: None, }, ), origin: Origin::Signer { session: 5.into() }, @@ -360,6 +362,7 @@ mod tests { id: 15.into(), payload: helpers::ConfirmationPayload::SignTransaction( helpers::FilledTransactionRequest { + tx_type: Default::default(), from: 0.into(), used_default_from: false, to: None, @@ -369,6 +372,7 @@ mod tests { data: vec![1, 2, 3], nonce: Some(1.into()), condition: None, + access_list: None, }, ), origin: Origin::Unknown, diff --git a/rpc/src/v1/types/receipt.rs b/rpc/src/v1/types/receipt.rs index a524d19156..9a978af499 100644 --- a/rpc/src/v1/types/receipt.rs +++ b/rpc/src/v1/types/receipt.rs @@ -15,13 +15,19 @@ // along with OpenEthereum. If not, see . use ethereum_types::{Bloom as H2048, H160, H256, U256, U64}; -use types::receipt::{LocalizedReceipt, Receipt as EthReceipt, RichReceipt, TransactionOutcome}; +use types::{ + receipt::{LocalizedReceipt, RichReceipt, TransactionOutcome, TypedReceipt}, + transaction::TypedTxId, +}; use v1::types::Log; /// Receipt #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct Receipt { + /// Transaction Type + #[serde(skip_serializing)] + pub transaction_type: TypedTxId, /// Transaction Hash pub transaction_hash: Option, /// Transaction index @@ -75,6 +81,7 @@ impl From for Receipt { Receipt { to: r.to.map(Into::into), from: Some(r.from), + transaction_type: r.transaction_type, transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: Some(r.block_hash), @@ -95,6 +102,7 @@ impl From for Receipt { Receipt { from: Some(r.from), to: r.to.map(Into::into), + transaction_type: r.transaction_type, transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: None, @@ -110,11 +118,14 @@ impl From for Receipt { } } -impl From for Receipt { - fn from(r: EthReceipt) -> Self { +impl From for Receipt { + fn from(r: TypedReceipt) -> Self { + let transaction_type = r.tx_type(); + let r = r.receipt().clone(); Receipt { from: None, to: None, + transaction_type, transaction_hash: None, transaction_index: None, block_hash: None, @@ -142,6 +153,7 @@ mod tests { let receipt = Receipt { from: None, to: None, + transaction_type: Default::default(), transaction_hash: Some(0.into()), transaction_index: Some(0.into()), block_hash: Some( diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index a0d78ff44d..86bb7278c1 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -20,7 +20,10 @@ use ethcore::{contract_address, CreateContractAddress}; use ethereum_types::{H160, H256, H512, U256, U64}; use miner; use serde::{ser::SerializeStruct, Serialize, Serializer}; -use types::transaction::{Action, LocalizedTransaction, PendingTransaction, SignedTransaction}; +use types::transaction::{ + AccessList, Action, LocalizedTransaction, PendingTransaction, SignedTransaction, + TypedTransaction, +}; use v1::types::{Bytes, TransactionCondition}; /// Transaction @@ -67,6 +70,12 @@ pub struct Transaction { pub s: U256, /// Transaction activates at specified block. pub condition: Option, + /// transaction type + #[serde(skip_serializing)] + pub transaction_type: u8, + /// optional access list + #[serde(skip_serializing)] + pub access_list: AccessList, } /// Local Transaction Status @@ -176,26 +185,35 @@ impl Transaction { pub fn from_localized(mut t: LocalizedTransaction) -> Transaction { let signature = t.signature(); let scheme = CreateContractAddress::FromSenderAndNonce; + + let access_list = if let TypedTransaction::AccessList(al) = t.as_unsigned() { + al.access_list.clone() + } else { + Vec::new() + }; + Transaction { hash: t.hash(), - nonce: t.nonce, + nonce: t.tx().nonce, block_hash: Some(t.block_hash), block_number: Some(t.block_number.into()), transaction_index: Some(t.transaction_index.into()), from: t.sender(), - to: match t.action { + to: match t.tx().action { Action::Create => None, Action::Call(ref address) => Some(*address), }, - value: t.value, - gas_price: t.gas_price, - gas: t.gas, - input: Bytes::new(t.data.clone()), - creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0), + value: t.tx().value, + gas_price: t.tx().gas_price, + gas: t.tx().gas, + input: Bytes::new(t.tx().data.clone()), + creates: match t.tx().action { + Action::Create => { + Some(contract_address(scheme, &t.sender(), &t.tx().nonce, &t.tx().data).0) + } Action::Call(_) => None, }, - raw: ::rlp::encode(&t.signed).into(), + raw: Bytes::new(t.signed.encode()), public_key: t.recover_public().ok().map(Into::into), chain_id: t.chain_id().map(U64::from), standard_v: t.standard_v().into(), @@ -203,6 +221,8 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, + transaction_type: t.signed.tx_type() as u8, + access_list, } } @@ -210,26 +230,33 @@ impl Transaction { pub fn from_signed(t: SignedTransaction) -> Transaction { let signature = t.signature(); let scheme = CreateContractAddress::FromSenderAndNonce; + let access_list = if let TypedTransaction::AccessList(al) = t.as_unsigned() { + al.access_list.clone() + } else { + Vec::new() + }; Transaction { hash: t.hash(), - nonce: t.nonce, + nonce: t.tx().nonce, block_hash: None, block_number: None, transaction_index: None, from: t.sender(), - to: match t.action { + to: match t.tx().action { Action::Create => None, Action::Call(ref address) => Some(*address), }, - value: t.value, - gas_price: t.gas_price, - gas: t.gas, - input: Bytes::new(t.data.clone()), - creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0), + value: t.tx().value, + gas_price: t.tx().gas_price, + gas: t.tx().gas, + input: Bytes::new(t.tx().data.clone()), + creates: match t.tx().action { + Action::Create => { + Some(contract_address(scheme, &t.sender(), &t.tx().nonce, &t.tx().data).0) + } Action::Call(_) => None, }, - raw: ::rlp::encode(&t).into(), + raw: t.encode().into(), public_key: t.public_key().map(Into::into), chain_id: t.chain_id().map(U64::from), standard_v: t.standard_v().into(), @@ -237,6 +264,8 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, + transaction_type: t.tx_type() as u8, + access_list, } } @@ -265,7 +294,7 @@ impl LocalTransactionStatus { Canceled(tx) => LocalTransactionStatus::Canceled(convert(tx)), Replaced { old, new } => LocalTransactionStatus::Replaced( convert(old), - new.signed().gas_price, + new.signed().tx().gas_price, new.signed().hash(), ), } diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index 8b896dc3c9..7995244086 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -18,6 +18,7 @@ use ansi_term::Colour; use ethereum_types::{H160, U256}; +use types::transaction::{AccessList, TypedTxId}; use v1::{ helpers, types::{Bytes, TransactionCondition}, @@ -30,6 +31,10 @@ use std::fmt; #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct TransactionRequest { + /// type of transaction. If none we assume it is legacy + #[serde(default)] + #[serde(skip_serializing)] + pub tx_type: TypedTxId, /// Sender pub from: Option, /// Recipient @@ -46,6 +51,9 @@ pub struct TransactionRequest { pub nonce: Option, /// Delay until this block condition. pub condition: Option, + /// Access list + #[serde(skip_serializing)] + pub access_list: Option, } pub fn format_ether(i: U256) -> String { @@ -97,6 +105,7 @@ impl fmt::Display for TransactionRequest { impl From for TransactionRequest { fn from(r: helpers::TransactionRequest) -> Self { TransactionRequest { + tx_type: r.tx_type, from: r.from.map(Into::into), to: r.to.map(Into::into), gas_price: r.gas_price.map(Into::into), @@ -105,6 +114,7 @@ impl From for TransactionRequest { data: r.data.map(Into::into), nonce: r.nonce.map(Into::into), condition: r.condition.map(Into::into), + access_list: r.access_list.map(Into::into), } } } @@ -112,6 +122,7 @@ impl From for TransactionRequest { impl From for TransactionRequest { fn from(r: helpers::FilledTransactionRequest) -> Self { TransactionRequest { + tx_type: r.tx_type, from: Some(r.from), to: r.to, gas_price: Some(r.gas_price), @@ -120,6 +131,7 @@ impl From for TransactionRequest { data: Some(r.data.into()), nonce: r.nonce, condition: r.condition, + access_list: r.access_list, } } } @@ -127,6 +139,7 @@ impl From for TransactionRequest { impl Into for TransactionRequest { fn into(self) -> helpers::TransactionRequest { helpers::TransactionRequest { + tx_type: self.tx_type, from: self.from.map(Into::into), to: self.to.map(Into::into), gas_price: self.gas_price.map(Into::into), @@ -135,6 +148,7 @@ impl Into for TransactionRequest { data: self.data.map(Into::into), nonce: self.nonce.map(Into::into), condition: self.condition.map(Into::into), + access_list: self.access_list.map(Into::into), } } } @@ -165,6 +179,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { + tx_type: Default::default(), from: Some(H160::from(1)), to: Some(H160::from(2)), gas_price: Some(U256::from(1)), @@ -173,6 +188,7 @@ mod tests { data: Some(vec![0x12, 0x34, 0x56].into()), nonce: Some(U256::from(4)), condition: Some(TransactionCondition::Number(0x13)), + access_list: None, } ); } @@ -190,6 +206,7 @@ mod tests { let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, TransactionRequest { + tx_type: Default::default(), from: Some(H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap()), to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: Some(U256::from_str("9184e72a000").unwrap()), @@ -197,7 +214,8 @@ mod tests { value: Some(U256::from_str("9184e72a").unwrap()), data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()), nonce: None, - condition: None, + condition: None, + access_list: None, }); } @@ -209,6 +227,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { + tx_type: Default::default(), from: Some(H160::from(1).into()), to: None, gas_price: None, @@ -217,6 +236,7 @@ mod tests { data: None, nonce: None, condition: None, + access_list: None, } ); } @@ -236,6 +256,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { + tx_type: Default::default(), from: Some(H160::from_str("b5f7502a2807cb23615c7456055e1d65b2508625").unwrap()), to: Some(H160::from_str("895d32f2db7d01ebb50053f9e48aacf26584fe40").unwrap()), gas_price: Some(U256::from_str("0ba43b7400").unwrap()), @@ -244,6 +265,7 @@ mod tests { data: Some(vec![0x85, 0x95, 0xba, 0xb1].into()), nonce: None, condition: None, + access_list: None, } ); } diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs index 1098443dff..4aa2c6771d 100644 --- a/secret-store/src/trusted_client.rs +++ b/secret-store/src/trusted_client.rs @@ -16,7 +16,7 @@ use bytes::Bytes; use call_contract::RegistryInfo; -use common_types::transaction::{Action, SignedTransaction, Transaction}; +use common_types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction}; use ethcore::{ client::{BlockChainClient, BlockId, ChainInfo, Client, Nonce}, miner::{Miner, MinerService}, @@ -89,16 +89,18 @@ impl TrustedClient { .upgrade() .ok_or_else(|| Error::Internal("cannot submit tx when miner is offline".into()))?; let engine = client.engine(); - let transaction = Transaction { + let transaction = TypedTransaction::Legacy(Transaction { nonce: client.latest_nonce(&self.self_key_pair.address()), action: Action::Call(contract), gas: miner.authoring_params().gas_range_target.0, gas_price: miner.sensible_gas_price(), value: Default::default(), data: tx_data, - }; + }); let chain_id = engine.signing_chain_id(&client.latest_env_info()); - let signature = self.self_key_pair.sign(&transaction.hash(chain_id))?; + let signature = self + .self_key_pair + .sign(&transaction.signature_hash(chain_id))?; let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; miner .import_own_transaction(&*client, signed.into()) From 837e8b8725b87914ff43335d907411ad4c2a4669 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 10 Dec 2020 17:57:26 +0100 Subject: [PATCH 025/107] Ancient target set. InvalidStateRoot bug (#69) (#149) --- ethcore/blockchain/src/blockchain.rs | 2 +- ethcore/src/client/client.rs | 34 ++++++++++++++++++++------- ethcore/sync/src/block_sync.rs | 35 +++++++++++++++++++++------- ethcore/sync/src/chain/mod.rs | 26 ++++++++++++++------- parity/informant.rs | 14 ++++++----- 5 files changed, 78 insertions(+), 33 deletions(-) diff --git a/ethcore/blockchain/src/blockchain.rs b/ethcore/blockchain/src/blockchain.rs index e952d1938f..a03b25aae6 100644 --- a/ethcore/blockchain/src/blockchain.rs +++ b/ethcore/blockchain/src/blockchain.rs @@ -749,7 +749,7 @@ impl BlockChain { } if hash != bc.genesis_hash() { - trace!("First block calculated: {:?}", hash); + info!("First new block calculated: {:?}", hash); let mut batch = db.key_value().transaction(); batch.put(db::COL_EXTRA, b"first", &hash); db.key_value().write(batch).expect("Low level database error when writing 'first' block. Some issue with disk?"); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 0a61d20075..e7ca0fd6f7 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -531,6 +531,10 @@ impl Importer { .unwrap_or_else(|e| panic!("Receipt bytes should be valid: {:?}", e)); let _import_lock = self.import_lock.lock(); + if unverified.header.number() >= chain.best_block_header().number() { + panic!("Ancient block number is higher then best block number"); + } + { trace_time!("import_old_block"); // verify the block, passing the chain for updating the epoch verifier. @@ -1201,15 +1205,27 @@ impl Client { /// Get a copy of the best block's state. pub fn latest_state_and_header(&self) -> (State, Header) { - let header = self.best_block_header(); - let state = State::from_existing( - self.state_db.read().boxed_clone_canon(&header.hash()), - *header.state_root(), - self.engine.account_start_nonce(header.number()), - self.factories.clone(), - ) - .expect("State root of best block header always valid."); - (state, header) + let mut nb_tries = 5; + // Here, we are taking latest block and then latest state. If in between those two calls `best` block got prunned app will panic. + // This is something that should not happend often and it is edge case. + // Locking read best_block lock would be more straighforward, but can introduce overlaping locks, + // because of this we are just taking 5 tries to get best state in most cases it will work on first try. + while nb_tries != 0 { + let header = self.best_block_header(); + match State::from_existing( + self.state_db.read().boxed_clone_canon(&header.hash()), + *header.state_root(), + self.engine.account_start_nonce(header.number()), + self.factories.clone(), + ) { + Ok(ret) => return (ret, header), + Err(_) => { + warn!("Couldn't fetch state of best block header: {:?}", header); + nb_tries -= 1; + } + } + } + panic!("Couldn't get latest state in 5 tries"); } /// Attempt to get a copy of a specific block's final state. diff --git a/ethcore/sync/src/block_sync.rs b/ethcore/sync/src/block_sync.rs index 7172bdfe92..44f33dd198 100644 --- a/ethcore/sync/src/block_sync.rs +++ b/ethcore/sync/src/block_sync.rs @@ -241,7 +241,7 @@ impl BlockDownloader { self.last_round_start_hash = start_hash.clone(); self.imported_this_round = None; self.round_parents = VecDeque::new(); - self.target_hash = None; + //self.target_hash = None; // target_hash is only used for old (ancient) block download. And once set should not be reseted in any way. self.retract_step = 1; } @@ -516,8 +516,24 @@ impl BlockDownloader { self.last_imported_hash ); } else { - let best = io.chain().chain_info().best_block_number; - let best_hash = io.chain().chain_info().best_block_hash; + let (best, best_hash) = match self.block_set { + BlockSet::NewBlocks => ( + io.chain().chain_info().best_block_number, + io.chain().chain_info().best_block_hash, + ), + BlockSet::OldBlocks => { + if let (Some(best), Some(best_hash)) = ( + io.chain().chain_info().ancient_block_number, + io.chain().chain_info().ancient_block_hash, + ) { + (best, best_hash) // best ancient block number and hash. + } else { + // None on ancient block/hash means that all ancient are already downloaded and stored in DB. + self.state = State::Complete; + return; + } + } + }; let oldest_reorg = io.chain().pruning_info().earliest_state; if self.block_set == BlockSet::NewBlocks && best > start && start < oldest_reorg { @@ -531,7 +547,7 @@ impl BlockDownloader { } else { let n = start - cmp::min(self.retract_step, start); if n == 0 { - debug_sync!(self, "Header not found, bottom line reached, resetting, last imported: {}", self.last_imported_hash); + info!("Header not found, bottom line reached, resetting, last imported: {}", self.last_imported_hash); self.reset_to_block(&best_hash, best); } else { self.retract_step *= 2; @@ -547,11 +563,9 @@ impl BlockDownloader { ); } None => { - debug_sync!( - self, + info!( "Could not revert to previous block, last: {} ({})", - start, - self.last_imported_hash + start, self.last_imported_hash ); self.reset_to_block(&best_hash, best); } @@ -661,7 +675,10 @@ impl BlockDownloader { if self.target_hash.as_ref().map_or(false, |t| t == &h) { self.state = State::Complete; - trace_sync!(self, "Sync target reached"); + info!( + "Sync target {:?} for old blocks reached. Syncing ancient blocks finished.", + self.target_hash + ); return download_action; } diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 889b6ef3fa..e6a869d719 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -969,15 +969,17 @@ impl ChainSync { if let (Some(ancient_block_hash), Some(ancient_block_number)) = (chain.ancient_block_hash, chain.ancient_block_number) { - trace!(target: "sync", "Downloading old blocks from {:?} (#{}) till {:?} (#{:?})", ancient_block_hash, ancient_block_number, chain.first_block_hash, chain.first_block_number); + info!(target: "sync", "Downloading old blocks from {:?} (#{}) till {:?} (#{:?})", ancient_block_hash, ancient_block_number, chain.first_block_hash, chain.first_block_number); let mut downloader = BlockDownloader::new( BlockSet::OldBlocks, &ancient_block_hash, ancient_block_number, ); if let Some(hash) = chain.first_block_hash { - trace!(target: "sync", "Downloader target set to {:?}", hash); + trace!(target: "sync", "Downloader target for old blocks is set to {:?}", hash); downloader.set_target(&hash); + } else { + trace!(target: "sync", "Downloader target could not be found"); } self.old_blocks = Some(downloader); } @@ -1114,10 +1116,18 @@ impl ChainSync { let equal_or_higher_difficulty = peer_difficulty.map_or(true, |pd| pd >= syncing_difficulty); if force || equal_or_higher_difficulty { - if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(peer_id, io, num_active_peers)) { - SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); - return; - } + let mut is_complete = false; + if let Some(old_blocks) = self.old_blocks.as_mut() { + if let Some(request) = old_blocks.request_blocks(peer_id, io, num_active_peers) { + SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); + return; + } + is_complete = old_blocks.is_complete(); + + } + if is_complete { // if old_blocks is in complete state, set it to None. + self.old_blocks = None; + } } else { trace!( target: "sync", @@ -1344,7 +1354,7 @@ impl ChainSync { }, SyncState::SnapshotWaiting => match io.snapshot_service().restoration_status() { RestorationStatus::Inactive => { - trace!(target:"sync", "Snapshot restoration is complete"); + info!(target:"sync", "Snapshot restoration is complete"); self.restart(io); } RestorationStatus::Initializing { .. } => { @@ -1443,7 +1453,7 @@ impl ChainSync { SyncPropagator::propagate_proposed_blocks(self, io, proposed); } if !invalid.is_empty() { - trace!(target: "sync", "Bad blocks in the queue, restarting"); + info!(target: "sync", "Bad blocks in the queue, restarting sync"); self.restart(io); } diff --git a/parity/informant.rs b/parity/informant.rs index 59bd915ba5..0112d1e97e 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -92,7 +92,6 @@ impl CacheSizes { pub struct SyncInfo { last_imported_block_number: BlockNumber, - last_imported_old_block_number: Option, num_peers: usize, max_peers: u32, snapshot_sync: bool, @@ -160,7 +159,6 @@ impl InformantData for FullNodeInformantData { last_imported_block_number: status .last_imported_block_number .unwrap_or(chain_info.best_block_number), - last_imported_old_block_number: status.last_imported_old_block_number, num_peers: status.num_peers, max_peers: status .current_max_peers(*num_peers_range.start(), *num_peers_range.end()), @@ -265,7 +263,7 @@ impl Informant { false => t, }; - info!(target: "import", "{} {} {} {}", + info!(target: "import", "{}{} {} {} {}", match importing { true => match snapshot_sync { false => format!("Syncing {} {} {} {}+{} Qed", @@ -301,18 +299,22 @@ impl Informant { }, false => String::new(), }, + match chain_info.ancient_block_number { + Some(ancient_number) => format!(" (Ancient:#{})", ancient_number), + None => String::new(), + }, match sync_info.as_ref() { Some(ref sync_info) => format!("{}{}/{} peers", match importing { true => format!("{}", if self.target.executes_transactions() { - paint(Green.bold(), format!("{:>8} ", format!("#{}", sync_info.last_imported_block_number))) + paint(Green.bold(), format!("{:>8} ", format!("LI:#{}", sync_info.last_imported_block_number))) } else { String::new() } ), - false => match sync_info.last_imported_old_block_number { - Some(number) => format!("{} ", paint(Yellow.bold(), format!("{:>8}", format!("#{}", number)))), + false => match chain_info.ancient_block_number { + Some(number) => format!("{} ", paint(Yellow.bold(), format!("{:>8}", format!("AB:#{}", number)))), None => String::new(), } }, From 06fc61d7c5ce29877348014db85cfeabe5b9c807 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 11 Dec 2020 11:18:18 +0100 Subject: [PATCH 026/107] Add custom windows runner (#162) --- .github/workflows/build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index b8c014c436..4b37985cc5 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -18,6 +18,7 @@ jobs: platform: - ubuntu-16.04 - macos-latest + - windows2019 # custom runner toolchain: - stable runs-on: ${{ matrix.platform }} @@ -38,7 +39,7 @@ jobs: command: test args: --locked --all --release --features "json-tests" --verbose --no-run - name: Run tests for ${{ matrix.platform }} - if: matrix.platform != 'windows-latest' + if: matrix.platform != 'windows2019' uses: actions-rs/cargo@v1 with: command: test From 612a71ecb251c7f9908f010f963ae9d6409c0656 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Mon, 30 Nov 2020 09:58:04 +0100 Subject: [PATCH 027/107] Update ISSUE_TEMPLATE.md (#124) Tell users to ask questions in discord instead of opening an issue. --- .github/ISSUE_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index cb7ec9abe9..890cdb2516 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,3 +1,5 @@ +For questions please use https://discord.io/openethereum, issues are for bugs and feature requests. + _Before filing a new issue, please **provide the following information**._ - **OpenEthereum version (>=3.1.0)**: 0.0.0 From 832fc444b640e4125f192b43589d06e1545151fd Mon Sep 17 00:00:00 2001 From: draganrakita Date: Tue, 15 Dec 2020 15:59:08 +0100 Subject: [PATCH 028/107] Tweaks in informer log --- parity/informant.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/parity/informant.rs b/parity/informant.rs index 0112d1e97e..a4b27a59f0 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -92,6 +92,7 @@ impl CacheSizes { pub struct SyncInfo { last_imported_block_number: BlockNumber, + last_imported_ancient_number: Option, num_peers: usize, max_peers: u32, snapshot_sync: bool, @@ -159,6 +160,7 @@ impl InformantData for FullNodeInformantData { last_imported_block_number: status .last_imported_block_number .unwrap_or(chain_info.best_block_number), + last_imported_ancient_number: status.last_imported_old_block_number, num_peers: status.num_peers, max_peers: status .current_max_peers(*num_peers_range.start(), *num_peers_range.end()), @@ -300,7 +302,7 @@ impl Informant { false => String::new(), }, match chain_info.ancient_block_number { - Some(ancient_number) => format!(" (Ancient:#{})", ancient_number), + Some(ancient_number) => format!(" Ancient:#{}", ancient_number), None => String::new(), }, match sync_info.as_ref() { @@ -313,7 +315,7 @@ impl Informant { String::new() } ), - false => match chain_info.ancient_block_number { + false => match sync_info.last_imported_ancient_number { Some(number) => format!("{} ", paint(Yellow.bold(), format!("{:>8}", format!("AB:#{}", number)))), None => String::new(), } From 8a9d14141ae42bab028654bf5a51d3677684d329 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 17 Dec 2020 13:59:59 +0100 Subject: [PATCH 029/107] Revert "Fix CI problems (#127)" and Remove sscache This reverts commit 12afb13e9b04c0fed06f4a2897a3b22972fab721. --- .github/workflows/build-test.yml | 4 - .github/workflows/build.yml | 285 ++++++++++++++++++++ .github/workflows/check.yml | 37 --- .github/workflows/deploy-docker-nightly.yml | 29 ++ .github/workflows/deploy-docker-tag.yml | 30 +++ scripts/actions/validate-chainspecs.sh | 2 +- 6 files changed, 345 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/deploy-docker-nightly.yml create mode 100644 .github/workflows/deploy-docker-tag.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 4b37985cc5..425ec34e57 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -9,10 +9,6 @@ on: jobs: build-tests: name: Test and Build - env: - SCCACHE_CACHE_SIZE: "1G" - SCCACHE_IDLE_TIMEOUT: 0 - ACTIONS_ALLOW_UNSECURE_COMMANDS: true strategy: matrix: platform: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..9dda2d4aa8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,285 @@ +name: Build Release Suite + +on: + push: + tags: + - v* + +# Global vars +env: + AWS_REGION: "us-east-1" + AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" + +jobs: + build: + name: Build Release + strategy: + matrix: + platform: + - ubuntu-16.04 + - macos-latest + - windows2019 + toolchain: + - stable + runs-on: ${{ matrix.platform }} + steps: + - name: Checkout sources + uses: actions/checkout@main + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + profile: minimal + override: true + + # ============================== + # Windows Build + # ============================== + + - name: Install LLVM for Windows + if: matrix.platform == 'windows2019' + run: choco install llvm + + - name: Build OpenEthereum for Windows + if: matrix.platform == 'windows2019' + run: sh scripts/actions/build-windows.sh ${{matrix.platform}} + + - name: Upload Windows build + uses: actions/upload-artifact@v2 + if: matrix.platform == 'windows2019' + with: + name: windows-artifacts + path: artifacts + + # ============================== + # Linux/Macos Build + # ============================== + + - name: Build OpenEthereum for ${{matrix.platform}} + if: matrix.platform != 'windows2019' + run: sh scripts/actions/build-linux.sh ${{matrix.platform}} + + - name: Upload Linux build + uses: actions/upload-artifact@v2 + if: matrix.platform == 'ubuntu-16.04' + with: + name: linux-artifacts + path: artifacts + + - name: Upload MacOS build + uses: actions/upload-artifact@v2 + if: matrix.platform == 'macos-latest' + with: + name: macos-artifacts + path: artifacts + + zip-artifacts-creator: + name: Create zip artifacts + needs: build + runs-on: ubuntu-16.04 + steps: + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + # ============================== + # Create ZIP files + # ============================== + + - name: Download Windows artifacts + uses: actions/download-artifact@v2 + with: + name: windows-artifacts + path: windows-artifacts + + - name: Download Linux artifacts + uses: actions/download-artifact@v2 + with: + name: linux-artifacts + path: linux-artifacts + + - name: Download MacOS artifacts + uses: actions/download-artifact@v2 + with: + name: macos-artifacts + path: macos-artifacts + + - name: Display structure of downloaded files + run: ls + + - name: Create zip Linux + id: create_zip_linux + run: | + cd linux-artifacts/ + zip -rT openethereum-linux-${{ env.RELEASE_VERSION }}.zip * + ls openethereum-linux-${{ env.RELEASE_VERSION }}.zip + cd .. + mv linux-artifacts/openethereum-linux-${{ env.RELEASE_VERSION }}.zip . + + echo "Setting outputs..." + echo ::set-output name=LINUX_ARTIFACT::openethereum-linux-${{ env.RELEASE_VERSION }}.zip + echo ::set-output name=LINUX_SHASUM::$(shasum -a 256 openethereum-linux-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + + - name: Create zip MacOS + id: create_zip_macos + run: | + cd macos-artifacts/ + zip -rT openethereum-macos-${{ env.RELEASE_VERSION }}.zip * + ls openethereum-macos-${{ env.RELEASE_VERSION }}.zip + cd .. + mv macos-artifacts/openethereum-macos-${{ env.RELEASE_VERSION }}.zip . + + echo "Setting outputs..." + echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip + echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + + - name: Create zip Windows + id: create_zip_windows + run: | + cd windows-artifacts/ + zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + cd .. + mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + + echo "Setting outputs..." + echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + + # ======================================================================= + # Upload artifacts + # This is required to share artifacts between different jobs + # ======================================================================= + + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip + path: openethereum-linux-${{ env.RELEASE_VERSION }}.zip + + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip + path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip + + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + + # ======================================================================= + # Upload artifacts to S3 + # This is required by some software distribution systems which require + # artifacts to be downloadable, like Brew on MacOS. + # ======================================================================= + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Copy files to S3 with the AWS CLI + run: | + # Deploy zip artifacts to S3 bucket to a directory whose name is the tagged release version. + # Deploy macos binary artifact (if required, add more `aws s3 cp` commands to deploy specific OS versions) + aws s3 cp macos-artifacts/openethereum s3://${{ env.AWS_S3_ARTIFACTS_BUCKET }}/${{ env.RELEASE_VERSION }}/macos/ --region ${{ env.AWS_REGION }} + + outputs: + linux-artifact: ${{ steps.create_zip_linux.outputs.LINUX_ARTIFACT }} + linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} + macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} + macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} + windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + + draft-release: + name: Draft Release + needs: zip-artifacts-creator + runs-on: ubuntu-16.04 + steps: + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + # ============================== + # Download artifacts + # ============================== + + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip + + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip + + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + + - name: Display structure of downloaded files + run: ls + + # ============================== + # Create release draft + # ============================== + + - name: Create Release Draft + id: create_release_draft + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ github.ref }} + release_name: OpenEthereum ${{ github.ref }} + body: | + This release contains + + | System | Architecture | Binary | Sha256 Checksum | + |:---:|:---:|:---:|:---| + | Apple Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.macos-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.macos-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.macos-shasum }}` | + | Linux Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.linux-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.linux-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.linux-shasum }}` | + | Windows Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | x64 | [${{ needs.zip-artifacts-creator.outputs.windows-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.windows-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.windows-shasum }}` | + | | | | | + | **System** | **Option** | - | **Resource** | + | Settings Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect | Docker | - | [hub.docker.com/r/openethereum/openethereum](https://hub.docker.com/r/openethereum/openethereum) | + + draft: true + prerelease: true + + - name: Upload Release Asset - Linux + id: upload_release_asset_linux + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./openethereum-linux-${{ env.RELEASE_VERSION }}.zip + asset_name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip + + - name: Upload Release Asset - MacOS + id: upload_release_asset_macos + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./openethereum-macos-${{ env.RELEASE_VERSION }}.zip + asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip + + - name: Upload Release Asset - Windows + id: upload_release_asset_windows + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index af0e005c54..06d660c1eb 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,10 +10,6 @@ jobs: check: name: Check runs-on: ubuntu-16.04 - env: - SCCACHE_CACHE_SIZE: "1G" - SCCACHE_IDLE_TIMEOUT: 0 - ACTIONS_ALLOW_UNSECURE_COMMANDS: true steps: - name: Checkout sources uses: actions/checkout@main @@ -25,32 +21,6 @@ jobs: toolchain: stable profile: minimal override: true - - name: Cache cargo registry - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/registry - key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo index - uses: actions/cache@v1.1.2 - with: - path: ~/.cargo/git - key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }} - - name: Cache cargo build - uses: actions/cache@v1.1.2 - with: - path: target - key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} - # Install sccache based on https://github.com/denoland/rusty_v8/blob/master/.github/workflows/ci.yml#L69 - - name: Cache sccache - uses: actions/cache@v1.1.2 - with: - path: "/home/runner/.cache/sccache" - key: ${{ runner.os }}-sccache-check-${{ hashFiles('**/Cargo.lock') }} - - name: Install sccache for Linux - shell: pwsh - run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}} - - name: Sccache statistics - run: sccache --show-stats - name: Run cargo check 1/3 uses: actions-rs/cargo@v1 with: @@ -78,10 +48,3 @@ jobs: args: --locked --all --benches --verbose - name: Run validate chainspecs run: ./scripts/actions/validate-chainspecs.sh - - name: Stop sccache - if: always() - run: sccache --stop-server - continue-on-error: true - - name: Prepare build directory for cache - shell: bash - run: bash scripts/actions/clean-target.sh diff --git a/.github/workflows/deploy-docker-nightly.yml b/.github/workflows/deploy-docker-nightly.yml new file mode 100644 index 0000000000..b80691b155 --- /dev/null +++ b/.github/workflows/deploy-docker-nightly.yml @@ -0,0 +1,29 @@ +name: Docker Image Nightly Release + +# Run "nightly" build on each commit to "dev" branch. +on: + push: + branches: + - dev + +jobs: + deploy-docker: + name: Build Release + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@master + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Deploy to docker hub + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openethereum/openethereum + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: scripts/docker/alpine/Dockerfile + tags: "nightly" diff --git a/.github/workflows/deploy-docker-tag.yml b/.github/workflows/deploy-docker-tag.yml new file mode 100644 index 0000000000..84beb5decc --- /dev/null +++ b/.github/workflows/deploy-docker-tag.yml @@ -0,0 +1,30 @@ +name: Docker Image Tag and Latest Release + +on: + push: + tags: + - v* + +jobs: + deploy-docker: + name: Build Release + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@master + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Deploy to docker hub + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openethereum/openethereum + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: scripts/docker/alpine/Dockerfile + tags: "latest,${{ env.RELEASE_VERSION }}" diff --git a/scripts/actions/validate-chainspecs.sh b/scripts/actions/validate-chainspecs.sh index cf5c126f7b..b5501b450e 100755 --- a/scripts/actions/validate-chainspecs.sh +++ b/scripts/actions/validate-chainspecs.sh @@ -16,5 +16,5 @@ for spec in ethcore/res/ethereum/*.json; do if ! ./target/release/chainspec "$spec"; then ERR=1; fi done #show sccache statistics -sccache --stop-server +#sccache --stop-server exit $ERR From 08e6cca3e5b8fa24bd57b7f66982d0399ff36583 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Mon, 21 Dec 2020 10:44:07 +0100 Subject: [PATCH 030/107] Disable windows2019, remove tagged windows artifact --- .github/workflows/build-test.yml | 7 --- .github/workflows/build.yml | 100 ++++++++++++------------------- 2 files changed, 38 insertions(+), 69 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 425ec34e57..6410be554c 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -14,7 +14,6 @@ jobs: platform: - ubuntu-16.04 - macos-latest - - windows2019 # custom runner toolchain: - stable runs-on: ${{ matrix.platform }} @@ -34,9 +33,3 @@ jobs: with: command: test args: --locked --all --release --features "json-tests" --verbose --no-run - - name: Run tests for ${{ matrix.platform }} - if: matrix.platform != 'windows2019' - uses: actions-rs/cargo@v1 - with: - command: test - args: --locked --all --release --features "json-tests" --verbose diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9dda2d4aa8..0279ef7d83 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,7 @@ on: env: AWS_REGION: "us-east-1" AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" + ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: build: @@ -18,7 +19,6 @@ jobs: platform: - ubuntu-16.04 - macos-latest - - windows2019 toolchain: - stable runs-on: ${{ matrix.platform }} @@ -32,33 +32,9 @@ jobs: profile: minimal override: true - # ============================== - # Windows Build - # ============================== - - - name: Install LLVM for Windows - if: matrix.platform == 'windows2019' - run: choco install llvm - - - name: Build OpenEthereum for Windows - if: matrix.platform == 'windows2019' - run: sh scripts/actions/build-windows.sh ${{matrix.platform}} - - - name: Upload Windows build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'windows2019' - with: - name: windows-artifacts - path: artifacts - # ============================== # Linux/Macos Build # ============================== - - - name: Build OpenEthereum for ${{matrix.platform}} - if: matrix.platform != 'windows2019' - run: sh scripts/actions/build-linux.sh ${{matrix.platform}} - - name: Upload Linux build uses: actions/upload-artifact@v2 if: matrix.platform == 'ubuntu-16.04' @@ -85,11 +61,11 @@ jobs: # Create ZIP files # ============================== - - name: Download Windows artifacts - uses: actions/download-artifact@v2 - with: - name: windows-artifacts - path: windows-artifacts + # - name: Download Windows artifacts + # uses: actions/download-artifact@v2 + # with: + # name: windows-artifacts + # path: windows-artifacts - name: Download Linux artifacts uses: actions/download-artifact@v2 @@ -132,18 +108,18 @@ jobs: echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - name: Create zip Windows - id: create_zip_windows - run: | - cd windows-artifacts/ - zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - cd .. - mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + # - name: Create zip Windows + # id: create_zip_windows + # run: | + # cd windows-artifacts/ + # zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + # ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # cd .. + # mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - echo "Setting outputs..." - echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + # echo "Setting outputs..." + # echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') # ======================================================================= # Upload artifacts @@ -162,11 +138,11 @@ jobs: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Upload artifacts + # uses: actions/upload-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip # ======================================================================= # Upload artifacts to S3 @@ -191,8 +167,8 @@ jobs: linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + # windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + # windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} draft-release: name: Draft Release @@ -216,10 +192,10 @@ jobs: with: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Download artifacts + # uses: actions/download-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - name: Display structure of downloaded files run: ls @@ -273,13 +249,13 @@ jobs: asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip asset_content_type: application/zip - - name: Upload Release Asset - Windows - id: upload_release_asset_windows - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip + # - name: Upload Release Asset - Windows + # id: upload_release_asset_windows + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + # asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_content_type: application/zip From a6bd3516e0a4aeb1134724155fecb34e9e43833b Mon Sep 17 00:00:00 2001 From: Justin Beaurone <19704046+jmb-42@users.noreply.github.com> Date: Sat, 12 Dec 2020 00:48:58 -0800 Subject: [PATCH 031/107] OpenEthereum rebranding --- scripts/{parity.service => openethereum.service} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename scripts/{parity.service => openethereum.service} (87%) diff --git a/scripts/parity.service b/scripts/openethereum.service similarity index 87% rename from scripts/parity.service rename to scripts/openethereum.service index 1201d7d708..0987b90409 100644 --- a/scripts/parity.service +++ b/scripts/openethereum.service @@ -6,7 +6,7 @@ After=network.target # run as root, set base_path in config.toml ExecStart=/usr/bin/openethereum --config /etc/openethereum/config.toml # To run as user, comment out above and uncomment below, fill in user and group -# picks up users default config.toml in $HOME/.local/share/io.parity.ethereum/ +# picks up users default config.toml in $HOME/.local/share/openethereum/ # User=username # Group=groupname # ExecStart=/usr/bin/openethereum From f723e288c35acff9cae2389638d897ee568a2b61 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 17 Dec 2020 12:57:34 +0100 Subject: [PATCH 032/107] Cleanup devp2p unused interface fn --- ethcore/sync/src/chain/supplier.rs | 10 ++++------ ethcore/sync/src/sync_io.rs | 14 -------------- ethcore/sync/src/tests/helpers.rs | 10 +--------- util/network-devp2p/src/host.rs | 5 ----- util/network-devp2p/src/lib.rs | 2 ++ util/network/src/lib.rs | 7 ------- 6 files changed, 7 insertions(+), 41 deletions(-) diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index 315adaa99d..c9208e5dd6 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -18,6 +18,7 @@ use bytes::Bytes; use enum_primitive::FromPrimitive; use ethereum_types::H256; use network::{self, PeerId}; +use devp2p::PAYLOAD_SOFT_LIMIT; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; use std::cmp; @@ -187,7 +188,6 @@ impl SyncSupplier { if io.chain().is_processing_fork() { return Err(PacketProcessError::ClientBusy); } - let payload_soft_limit = io.payload_soft_limit(); // Packet layout: // [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] let max_headers: usize = r.val_at(1)?; @@ -246,7 +246,7 @@ impl SyncSupplier { data.append(&mut hdr.into_inner()); count += 1; // Check that the packet won't be oversized - if data.len() > payload_soft_limit { + if data.len() > PAYLOAD_SOFT_LIMIT { break; } } else { @@ -270,7 +270,6 @@ impl SyncSupplier { /// Respond to GetBlockBodies request fn return_block_bodies(io: &dyn SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let payload_soft_limit = io.payload_soft_limit(); let mut count = r.item_count().unwrap_or(0); if count == 0 { debug!(target: "sync", "Empty GetBlockBodies request, ignoring."); @@ -284,7 +283,7 @@ impl SyncSupplier { data.append(&mut body.into_inner()); added += 1; // Check that the packet won't be oversized - if data.len() > payload_soft_limit { + if data.len() > PAYLOAD_SOFT_LIMIT { break; } } @@ -296,7 +295,6 @@ impl SyncSupplier { } fn return_receipts(io: &dyn SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let payload_soft_limit = io.payload_soft_limit(); let mut count = rlp.item_count().unwrap_or(0); trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count); if count == 0 { @@ -311,7 +309,7 @@ impl SyncSupplier { if let Some(receipts) = io.chain().block_receipts(&rlp.val_at::(i)?) { let mut receipts_bytes = ::rlp::encode(&receipts); total_bytes += receipts_bytes.len(); - if total_bytes > payload_soft_limit { + if total_bytes > PAYLOAD_SOFT_LIMIT { break; } data.append(&mut receipts_bytes); diff --git a/ethcore/sync/src/sync_io.rs b/ethcore/sync/src/sync_io.rs index 8527b78105..92c47a635b 100644 --- a/ethcore/sync/src/sync_io.rs +++ b/ethcore/sync/src/sync_io.rs @@ -46,8 +46,6 @@ pub trait SyncIo { } /// Returns information on p2p session fn peer_session_info(&self, peer_id: PeerId) -> Option; - /// Maximum mutually supported ETH protocol version - fn eth_protocol_version(&self, peer_id: PeerId) -> u8; /// Maximum mutually supported version of a gien protocol. fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8; /// Returns if the chain block queue empty @@ -58,8 +56,6 @@ pub trait SyncIo { fn is_expired(&self) -> bool; /// Return sync overlay fn chain_overlay(&self) -> &RwLock>; - /// Returns the size the payload shouldn't exceed - fn payload_soft_limit(&self) -> usize; } /// Wraps `NetworkContext` and the blockchain client @@ -125,12 +121,6 @@ impl<'s> SyncIo for NetSyncIo<'s> { self.network.is_expired() } - fn eth_protocol_version(&self, peer_id: PeerId) -> u8 { - self.network - .protocol_version(self.network.subprotocol_name(), peer_id) - .unwrap_or(0) - } - fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8 { self.network .protocol_version(*protocol, peer_id) @@ -140,8 +130,4 @@ impl<'s> SyncIo for NetSyncIo<'s> { fn peer_version(&self, peer_id: PeerId) -> ClientVersion { self.network.peer_client_version(peer_id) } - - fn payload_soft_limit(&self) -> usize { - self.network.payload_soft_limit() - } } diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 264754f1e0..c536be3209 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -168,25 +168,17 @@ where None } - fn eth_protocol_version(&self, _peer: PeerId) -> u8 { - ETH_PROTOCOL_VERSION_64.0 - } - fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8 { if protocol == &PAR_PROTOCOL { PAR_PROTOCOL_VERSION_2.0 } else { - self.eth_protocol_version(peer_id) + ETH_PROTOCOL_VERSION_64.0 } } fn chain_overlay(&self) -> &RwLock> { &self.overlay } - - fn payload_soft_limit(&self) -> usize { - 100_000 - } } /// Mock for emulution of async run of new blocks diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 4dc6db8a34..e82aa4ceef 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -35,7 +35,6 @@ use std::{ time::Duration, }; -use connection::PAYLOAD_SOFT_LIMIT; use discovery::{Discovery, NodeEntry, TableUpdates, MAX_DATAGRAM_SIZE}; use io::*; use ip_utils::{map_external_address, select_public_address}; @@ -226,10 +225,6 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> { .map(|node| self.reserved_peers.contains(&node)) .unwrap_or(false) } - - fn payload_soft_limit(&self) -> usize { - PAYLOAD_SOFT_LIMIT - } } /// Shared host information diff --git a/util/network-devp2p/src/lib.rs b/util/network-devp2p/src/lib.rs index 52f6caf4bc..47d9018a50 100644 --- a/util/network-devp2p/src/lib.rs +++ b/util/network-devp2p/src/lib.rs @@ -113,6 +113,8 @@ mod session; pub use host::NetworkContext; pub use service::NetworkService; +pub use connection::PAYLOAD_SOFT_LIMIT; + pub use io::TimerToken; pub use node_table::{validate_node_url, NodeId}; diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 76f38581db..ecf30b86d8 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -320,9 +320,6 @@ pub trait NetworkContext { /// Returns whether the given peer ID is a reserved peer. fn is_reserved_peer(&self, peer: PeerId) -> bool; - - /// Returns the size the payload shouldn't exceed - fn payload_soft_limit(&self) -> usize; } impl<'a, T> NetworkContext for &'a T @@ -382,10 +379,6 @@ where fn is_reserved_peer(&self, peer: PeerId) -> bool { (**self).is_reserved_peer(peer) } - - fn payload_soft_limit(&self) -> usize { - (**self).payload_soft_limit() - } } /// Network IO protocol handler. This needs to be implemented for each new subprotocol. From 705bc7159367445b8bfbc1bee76db04cb911ef77 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 17 Dec 2020 16:47:02 +0100 Subject: [PATCH 033/107] Payload limit for test --- util/network-devp2p/src/connection.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/network-devp2p/src/connection.rs b/util/network-devp2p/src/connection.rs index 40dbd04876..548652278b 100644 --- a/util/network-devp2p/src/connection.rs +++ b/util/network-devp2p/src/connection.rs @@ -44,7 +44,10 @@ pub const MAX_PAYLOAD_SIZE: usize = (1 << 24) - 1; /// Network responses should try not to go over this limit. /// This should be lower than MAX_PAYLOAD_SIZE +#[cfg(not(test))] pub const PAYLOAD_SOFT_LIMIT: usize = (1 << 22) - 1; +#[cfg(test)] +pub const PAYLOAD_SOFT_LIMIT: usize = 100_000; pub trait GenericSocket: Read + Write {} From 8d3e0582a8940f210aace14f0cb46affc1f8274e Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 17 Dec 2020 17:24:33 +0100 Subject: [PATCH 034/107] fmt --- ethcore/sync/src/chain/supplier.rs | 2 +- ethcore/sync/src/tests/helpers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index c9208e5dd6..9200275818 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -15,10 +15,10 @@ // along with OpenEthereum. If not, see . use bytes::Bytes; +use devp2p::PAYLOAD_SOFT_LIMIT; use enum_primitive::FromPrimitive; use ethereum_types::H256; use network::{self, PeerId}; -use devp2p::PAYLOAD_SOFT_LIMIT; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; use std::cmp; diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index c536be3209..105e4760d8 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -168,7 +168,7 @@ where None } - fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8 { + fn protocol_version(&self, protocol: &ProtocolId, _peer_id: PeerId) -> u8 { if protocol == &PAR_PROTOCOL { PAR_PROTOCOL_VERSION_2.0 } else { From eab41b49cf43bfe406db58fbb10413e0ec065191 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 17 Dec 2020 20:48:45 +0100 Subject: [PATCH 035/107] test cfg --- ethcore/sync/src/chain/supplier.rs | 5 +++++ util/network-devp2p/src/connection.rs | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index 9200275818..4c6092cd24 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -15,7 +15,12 @@ // along with OpenEthereum. If not, see . use bytes::Bytes; + +#[cfg(not(test))] use devp2p::PAYLOAD_SOFT_LIMIT; +#[cfg(test)] +pub const PAYLOAD_SOFT_LIMIT: usize = 100_000; + use enum_primitive::FromPrimitive; use ethereum_types::H256; use network::{self, PeerId}; diff --git a/util/network-devp2p/src/connection.rs b/util/network-devp2p/src/connection.rs index 548652278b..40dbd04876 100644 --- a/util/network-devp2p/src/connection.rs +++ b/util/network-devp2p/src/connection.rs @@ -44,10 +44,7 @@ pub const MAX_PAYLOAD_SIZE: usize = (1 << 24) - 1; /// Network responses should try not to go over this limit. /// This should be lower than MAX_PAYLOAD_SIZE -#[cfg(not(test))] pub const PAYLOAD_SOFT_LIMIT: usize = (1 << 22) - 1; -#[cfg(test)] -pub const PAYLOAD_SOFT_LIMIT: usize = 100_000; pub trait GenericSocket: Read + Write {} From e2f665e9cf6751e77960dc8619f12d39737ed774 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Wed, 30 Dec 2020 15:07:20 +0100 Subject: [PATCH 036/107] Enable Windows2019 CI on main/dev (#213) * Revert "Disable windows2019, remove tagged windows artifact" This reverts commit 08e6cca3e5b8fa24bd57b7f66982d0399ff36583. * Allow running CI on windows only when pushing to main/dev * Remove unneeded block code --- .github/workflows/build-test-windows.yml | 33 ++++++++ .github/workflows/build.yml | 100 ++++++++++++++--------- 2 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 .github/workflows/build-test-windows.yml diff --git a/.github/workflows/build-test-windows.yml b/.github/workflows/build-test-windows.yml new file mode 100644 index 0000000000..a3983eec3f --- /dev/null +++ b/.github/workflows/build-test-windows.yml @@ -0,0 +1,33 @@ +name: Build and Test Suite on Windows + +on: + push: + branches: + - main + - dev +jobs: + build-tests: + name: Test and Build + strategy: + matrix: + platform: + - windows2019 # custom runner + toolchain: + - stable + runs-on: ${{ matrix.platform }} + steps: + - name: Checkout sources + uses: actions/checkout@main + with: + submodules: true + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + profile: minimal + override: true + - name: Build tests + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked --all --release --features "json-tests" --verbose --no-run diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0279ef7d83..9dda2d4aa8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,6 @@ on: env: AWS_REGION: "us-east-1" AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" - ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: build: @@ -19,6 +18,7 @@ jobs: platform: - ubuntu-16.04 - macos-latest + - windows2019 toolchain: - stable runs-on: ${{ matrix.platform }} @@ -32,9 +32,33 @@ jobs: profile: minimal override: true + # ============================== + # Windows Build + # ============================== + + - name: Install LLVM for Windows + if: matrix.platform == 'windows2019' + run: choco install llvm + + - name: Build OpenEthereum for Windows + if: matrix.platform == 'windows2019' + run: sh scripts/actions/build-windows.sh ${{matrix.platform}} + + - name: Upload Windows build + uses: actions/upload-artifact@v2 + if: matrix.platform == 'windows2019' + with: + name: windows-artifacts + path: artifacts + # ============================== # Linux/Macos Build # ============================== + + - name: Build OpenEthereum for ${{matrix.platform}} + if: matrix.platform != 'windows2019' + run: sh scripts/actions/build-linux.sh ${{matrix.platform}} + - name: Upload Linux build uses: actions/upload-artifact@v2 if: matrix.platform == 'ubuntu-16.04' @@ -61,11 +85,11 @@ jobs: # Create ZIP files # ============================== - # - name: Download Windows artifacts - # uses: actions/download-artifact@v2 - # with: - # name: windows-artifacts - # path: windows-artifacts + - name: Download Windows artifacts + uses: actions/download-artifact@v2 + with: + name: windows-artifacts + path: windows-artifacts - name: Download Linux artifacts uses: actions/download-artifact@v2 @@ -108,18 +132,18 @@ jobs: echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - # - name: Create zip Windows - # id: create_zip_windows - # run: | - # cd windows-artifacts/ - # zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - # ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # cd .. - # mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + - name: Create zip Windows + id: create_zip_windows + run: | + cd windows-artifacts/ + zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + cd .. + mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - # echo "Setting outputs..." - # echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + echo "Setting outputs..." + echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') # ======================================================================= # Upload artifacts @@ -138,11 +162,11 @@ jobs: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - # - name: Upload artifacts - # uses: actions/upload-artifact@v2 - # with: - # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip # ======================================================================= # Upload artifacts to S3 @@ -167,8 +191,8 @@ jobs: linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - # windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - # windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} draft-release: name: Draft Release @@ -192,10 +216,10 @@ jobs: with: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - # - name: Download artifacts - # uses: actions/download-artifact@v2 - # with: - # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - name: Display structure of downloaded files run: ls @@ -249,13 +273,13 @@ jobs: asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip asset_content_type: application/zip - # - name: Upload Release Asset - Windows - # id: upload_release_asset_windows - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # with: - # upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - # asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # asset_content_type: application/zip + - name: Upload Release Asset - Windows + id: upload_release_asset_windows + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip From f286597d109a335639e9cdfbb2ee0ca8748f5f93 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 8 Jan 2021 15:56:53 +0100 Subject: [PATCH 037/107] Update link to issue (#202) --- .cargo/config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config b/.cargo/config index a160c8eab7..c497d8e4ef 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,3 +1,3 @@ [target.x86_64-pc-windows-msvc] -# Link the C runtime statically ; https://github.com/openethereum/openethereum/issues/6643 +# Link the C runtime statically ; https://github.com/openethereum/parity-ethereum/issues/6643 rustflags = ["-Ctarget-feature=+crt-static"] From 0706e5468dbd65babd05a6ebd5d40b0251bfb6f9 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Jan 2021 11:00:27 +0100 Subject: [PATCH 038/107] EIP-1898: Allow default block parameter to be blockHash (#203) * Allow default block parameter to be blockHash Backport to 3.1 of https://github.com/openethereum/openethereum/pull/10932 Co-authored-by: Richard Patel * Request canonical with BlockHash Co-authored-by: Seun LanLege Co-authored-by: Richard Patel --- ethcore/src/client/client.rs | 4 ++ ethcore/src/client/test_client.rs | 4 ++ ethcore/src/client/traits.rs | 3 + rpc/src/v1/helpers/errors.rs | 10 +++ rpc/src/v1/impls/eth.rs | 26 ++++++++ rpc/src/v1/impls/parity.rs | 3 + rpc/src/v1/impls/traces.rs | 4 ++ rpc/src/v1/types/block_number.rs | 107 ++++++++++++++++++++++++++++-- rpc/src/v1/types/filter.rs | 1 + rpc/src/v1/types/trace_filter.rs | 1 + 10 files changed, 156 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index e7ca0fd6f7..c5e8dd7a86 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -2069,6 +2069,10 @@ impl BlockChainClient for Client { self.config.spec_name.clone() } + fn is_canon(&self, hash: &H256) -> bool { + self.chain.read().is_canon(hash) + } + fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); if !self.enabled.load(AtomicOrdering::Relaxed) { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 2de1b62920..6e284e6c2e 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -847,6 +847,10 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } + fn is_canon(&self, _hash: &H256) -> bool { + unimplemented!() + } + fn block_number(&self, id: BlockId) -> Option { match id { BlockId::Number(number) => Some(number), diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 69eca8c777..62ce8ef38d 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -271,6 +271,9 @@ pub trait BlockChainClient: .expect("code will return Some if given BlockId::Latest; qed") } + /// Returns true if the given block is known and in the canon chain. + fn is_canon(&self, hash: &H256) -> bool; + /// Get address code hash at given block's state. /// Get value of the storage at given position at the given block's state. diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index c9d04995f4..9d841bd6e4 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -530,3 +530,13 @@ pub fn require_experimental(allow_experimental_rpcs: bool, eip: &str) -> Result< }) } } + +/// returns an error for when require_canonical was specified in RPC for EIP-1898 +pub fn invalid_input() -> Error { + Error { + // UNSUPPORTED_REQUEST shares the same error code for EIP-1898 + code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), + message: "Invalid input".into(), + data: None, + } +} diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2896edf8d1..928990d4ee 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -243,6 +243,7 @@ where BlockNumberOrId::Number(num) => { let id = match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Latest => BlockId::Latest, BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Num(n) => BlockId::Number(n), @@ -469,6 +470,7 @@ where /// if no state found for the best pending block. fn get_state(&self, number: BlockNumber) -> StateOrBlock { match number { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash).into(), BlockNumber::Num(num) => BlockId::Number(num).into(), BlockNumber::Earliest => BlockId::Earliest.into(), BlockNumber::Latest => BlockId::Latest.into(), @@ -539,6 +541,22 @@ where BlockNumber::Num(n) => BlockId::Number(n), BlockNumber::Latest => BlockId::Latest, BlockNumber::Earliest => BlockId::Earliest, + BlockNumber::Hash { + hash, + require_canonical, + } => { + // block check takes precedence over canon check. + match client.block_status(BlockId::Hash(hash.clone())) { + BlockStatus::InChain => {} + _ => return Err(errors::unknown_block()), + }; + + if require_canonical && !client.is_canon(&hash) { + return Err(errors::invalid_input()); + } + + return Ok(()); + } }; match client.block_status(id) { @@ -688,6 +706,7 @@ where let num = num.unwrap_or_default(); let id = match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(n) => BlockId::Number(n), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -893,6 +912,7 @@ where index: Index, ) -> BoxFuture> { let block_id = match num { + BlockNumber::Hash { hash, .. } => PendingOrBlock::Block(BlockId::Hash(hash)), BlockNumber::Latest => PendingOrBlock::Block(BlockId::Latest), BlockNumber::Earliest => PendingOrBlock::Block(BlockId::Earliest), BlockNumber::Num(num) => PendingOrBlock::Block(BlockId::Number(num)), @@ -942,6 +962,10 @@ where index: Index, ) -> BoxFuture> { let id = match num { + BlockNumber::Hash { hash, .. } => PendingUncleId { + id: PendingOrBlock::Block(BlockId::Hash(hash)), + position: index.value(), + }, BlockNumber::Latest => PendingUncleId { id: PendingOrBlock::Block(BlockId::Latest), position: index.value(), @@ -1092,6 +1116,7 @@ where self.pending_state_and_header_with_fallback() } else { let id = match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -1132,6 +1157,7 @@ where self.pending_state_and_header_with_fallback() } else { let id = match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 893e9a4921..3c1c9c7629 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -368,6 +368,7 @@ where (header.encoded(), None) } else { let id = match number { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -401,6 +402,7 @@ where .ok_or_else(errors::unknown_block)); return Box::new(future::ok(receipts.into_iter().map(Into::into).collect())); } + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -434,6 +436,7 @@ where (state, header) } else { let id = match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index 329e0547ec..bf528e252f 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -111,6 +111,7 @@ where let signed = fake_sign::sign_call(request)?; let id = match block { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -157,6 +158,7 @@ where .collect::>>()?; let id = match block { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -198,6 +200,7 @@ where let signed = SignedTransaction::new(tx).map_err(errors::transaction)?; let id = match block { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, @@ -247,6 +250,7 @@ where flags: TraceOptions, ) -> Result> { let id = match block_number { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index 8e88f49bf8..6ac3afb576 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -15,8 +15,9 @@ // along with OpenEthereum. If not, see . use ethcore::client::BlockId; +use hash::H256; use serde::{ - de::{Error, Visitor}, + de::{Error, MapAccess, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; use std::fmt; @@ -24,6 +25,13 @@ use std::fmt; /// Represents rpc api block number param. #[derive(Debug, PartialEq, Clone, Hash, Eq)] pub enum BlockNumber { + /// Hash + Hash { + /// block hash + hash: H256, + /// only return blocks part of the canon chain + require_canonical: bool, + }, /// Number Num(u64), /// Latest block @@ -65,6 +73,13 @@ impl Serialize for BlockNumber { S: Serializer, { match *self { + BlockNumber::Hash { + hash, + require_canonical, + } => serializer.serialize_str(&format!( + "{{ 'hash': '{}', 'requireCanonical': '{}' }}", + hash, require_canonical + )), BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), BlockNumber::Latest => serializer.serialize_str("latest"), BlockNumber::Earliest => serializer.serialize_str("earliest"), @@ -85,6 +100,59 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { ) } + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'a>, + { + let (mut require_canonical, mut block_number, mut block_hash) = + (false, None::, None::); + + loop { + let key_str: Option = visitor.next_key()?; + + match key_str { + Some(key) => match key.as_str() { + "blockNumber" => { + let value: String = visitor.next_value()?; + if value.starts_with("0x") { + let number = u64::from_str_radix(&value[2..], 16).map_err(|e| { + Error::custom(format!("Invalid block number: {}", e)) + })?; + + block_number = Some(number); + break; + } else { + return Err(Error::custom( + "Invalid block number: missing 0x prefix".to_string(), + )); + } + } + "blockHash" => { + block_hash = Some(visitor.next_value()?); + } + "requireCanonical" => { + require_canonical = visitor.next_value()?; + } + key => return Err(Error::custom(format!("Unknown key: {}", key))), + }, + None => break, + }; + } + + if let Some(number) = block_number { + return Ok(BlockNumber::Num(number)); + } + + if let Some(hash) = block_hash { + return Ok(BlockNumber::Hash { + hash, + require_canonical, + }); + } + + return Err(Error::custom("Invalid input")); + } + fn visit_str(self, value: &str) -> Result where E: Error, @@ -113,10 +181,10 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { /// Converts `BlockNumber` to `BlockId`, panics on `BlockNumber::Pending` pub fn block_number_to_id(number: BlockNumber) -> BlockId { match number { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(num) => BlockId::Number(num), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, - BlockNumber::Pending => panic!("`BlockNumber::Pending` should be handled manually"), } } @@ -126,26 +194,51 @@ mod tests { use super::*; use ethcore::client::BlockId; use serde_json; + use std::str::FromStr; #[test] fn block_number_deserialization() { - let s = r#"["0xa", "latest", "earliest", "pending"]"#; + let s = r#"[ + "0xa", + "latest", + "earliest", + "pending", + {"blockNumber": "0xa"}, + {"blockHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"}, + {"blockHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "requireCanonical": true} + ]"#; let deserialized: Vec = serde_json::from_str(s).unwrap(); + assert_eq!( deserialized, vec![ BlockNumber::Num(10), BlockNumber::Latest, BlockNumber::Earliest, - BlockNumber::Pending + BlockNumber::Pending, + BlockNumber::Num(10), + BlockNumber::Hash { + hash: H256::from_str( + "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + ) + .unwrap(), + require_canonical: false + }, + BlockNumber::Hash { + hash: H256::from_str( + "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + ) + .unwrap(), + require_canonical: true + } ] ) } #[test] - fn should_not_deserialize_decimal() { - let s = r#""10""#; - assert!(serde_json::from_str::(s).is_err()); + fn should_not_deserialize() { + let s = r#"[{}, "10"]"#; + assert!(serde_json::from_str::>(s).is_err()); } #[test] diff --git a/rpc/src/v1/types/filter.rs b/rpc/src/v1/types/filter.rs index 87c08e3c38..07c841c32e 100644 --- a/rpc/src/v1/types/filter.rs +++ b/rpc/src/v1/types/filter.rs @@ -97,6 +97,7 @@ impl Filter { } let num_to_id = |num| match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(n) => BlockId::Number(n), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest | BlockNumber::Pending => BlockId::Latest, diff --git a/rpc/src/v1/types/trace_filter.rs b/rpc/src/v1/types/trace_filter.rs index 693b4b1bc0..50b3ea47f1 100644 --- a/rpc/src/v1/types/trace_filter.rs +++ b/rpc/src/v1/types/trace_filter.rs @@ -42,6 +42,7 @@ pub struct TraceFilter { impl Into for TraceFilter { fn into(self) -> client::TraceFilter { let num_to_id = |num| match num { + BlockNumber::Hash { hash, .. } => BlockId::Hash(hash), BlockNumber::Num(n) => BlockId::Number(n), BlockNumber::Earliest => BlockId::Earliest, BlockNumber::Latest => BlockId::Latest, From b0a1e3da0306658dc96b7d767d24f446d38dba2f Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Mon, 11 Jan 2021 14:14:41 +0100 Subject: [PATCH 039/107] Update ethereum/tests to f55f344 (#220) --- ethcore/res/ethereum/berlin_test.json | 8 +++++--- ethcore/res/ethereum/tests | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ethcore/res/ethereum/berlin_test.json b/ethcore/res/ethereum/berlin_test.json index d08e8e6f67..610684a3e9 100644 --- a/ethcore/res/ethereum/berlin_test.json +++ b/ethcore/res/ethereum/berlin_test.json @@ -43,7 +43,9 @@ "eip1706Transition": "0x0", "eip1884Transition": "0x0", "eip2028Transition": "0x0", - "eip2315Transition": "0x0" + "eip2315Transition": "0x0", + "eip2929Transition": "0x0", + "eip2930Transition": "0x0" }, "genesis": { "seal": { @@ -113,8 +115,8 @@ "name": "modexp", "activate_at": "0x00", "pricing": { - "0": { - "price" : { "modexp2565": { } } + "modexp": { + "divisor": 20 } } } diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index 66a55cd42f..f55f344ad2 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit 66a55cd42f63845e34767504d0a7a62b452a7e7a +Subproject commit f55f344ad25cb97ebf4f3d72eca7a263aabde818 From 0e5d6944b7772e2321955e7e670f2cc5f9a624c1 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Mon, 11 Jan 2021 14:03:53 +0100 Subject: [PATCH 040/107] Add eip2929,eip2930 to ForkId list --- ethcore/src/spec/spec.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index bdc60714fc..6153025116 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -663,6 +663,8 @@ impl Spec { params.eip1884_transition, params.eip2028_transition, params.eip2315_transition, + params.eip2929_transition, + params.eip2930_transition, params.dust_protection_transition, params.wasm_activation_transition, params.wasm_disable_transition, From c46fe330dc4e3b513eff7560868ef6be99936e03 Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Wed, 13 Jan 2021 17:03:12 +0000 Subject: [PATCH 041/107] Big folder refactor --- .gitmodules | 8 +- Cargo.lock | 70 - Cargo.toml | 79 +- {chainspec => bin/chainspec}/Cargo.toml | 2 +- {chainspec => bin/chainspec}/src/main.rs | 0 .../ethkey/cli => bin/ethkey}/Cargo.toml | 4 +- .../ethkey/cli => bin/ethkey}/src/main.rs | 0 .../ethstore/cli => bin/ethstore}/Cargo.toml | 6 +- .../cli => bin/ethstore}/src/crack.rs | 0 .../ethstore/cli => bin/ethstore}/src/main.rs | 0 {evmbin => bin/evmbin}/Cargo.toml | 12 +- {evmbin => bin/evmbin}/README.md | 0 {evmbin => bin/evmbin}/benches/mod.rs | 0 {evmbin => bin/evmbin}/res/testchain.json | 0 {evmbin => bin/evmbin}/src/display/config.rs | 0 {evmbin => bin/evmbin}/src/display/json.rs | 0 {evmbin => bin/evmbin}/src/display/mod.rs | 0 {evmbin => bin/evmbin}/src/display/simple.rs | 0 .../evmbin}/src/display/std_json.rs | 0 {evmbin => bin/evmbin}/src/info.rs | 0 {evmbin => bin/evmbin}/src/main.rs | 0 {parity => bin/oe}/account.rs | 0 {parity => bin/oe}/account_utils.rs | 0 {parity => bin/oe}/blockchain.rs | 0 {parity => bin/oe}/cache.rs | 0 {parity => bin/oe}/cli/mod.rs | 0 .../oe}/cli/presets/config.dev-insecure.toml | 0 .../oe}/cli/presets/config.dev.toml | 0 .../oe}/cli/presets/config.insecure.toml | 0 .../oe}/cli/presets/config.mining.toml | 0 .../presets/config.non-standard-ports.toml | 0 {parity => bin/oe}/cli/presets/mod.rs | 0 {parity => bin/oe}/cli/tests/config.full.toml | 0 .../oe}/cli/tests/config.invalid1.toml | 0 .../oe}/cli/tests/config.invalid2.toml | 0 .../oe}/cli/tests/config.invalid3.toml | 0 .../oe}/cli/tests/config.invalid4.toml | 0 {parity => bin/oe}/cli/tests/config.toml | 0 {parity => bin/oe}/cli/usage.rs | 0 {parity => bin/oe}/cli/usage_header.txt | 0 {parity => bin/oe}/cli/version.txt | 0 {parity => bin/oe}/configuration.rs | 0 {parity => bin/oe}/db/mod.rs | 0 {parity => bin/oe}/db/rocksdb/blooms.rs | 0 {parity => bin/oe}/db/rocksdb/helpers.rs | 0 {parity => bin/oe}/db/rocksdb/migration.rs | 0 {parity => bin/oe}/db/rocksdb/mod.rs | 0 {parity => bin/oe}/helpers.rs | 0 {parity => bin/oe}/informant.rs | 0 {parity => bin/oe}/lib.rs | 1 - {parity => bin/oe}/logger/Cargo.toml | 0 {parity => bin/oe}/logger/src/lib.rs | 0 {parity => bin/oe}/logger/src/rotating.rs | 0 {parity => bin/oe}/main.rs | 0 {parity => bin/oe}/metrics.rs | 0 {parity => bin/oe}/modules.rs | 0 {parity => bin/oe}/params.rs | 0 {parity => bin/oe}/presale.rs | 0 {parity => bin/oe}/rpc.rs | 0 {parity => bin/oe}/rpc_apis.rs | 0 {parity => bin/oe}/run.rs | 0 {parity => bin/oe}/secretstore.rs | 0 {parity => bin/oe}/signer.rs | 0 {parity => bin/oe}/snapshot.rs | 0 {parity => bin/oe}/stratum.rs | 0 {parity => bin/oe}/upgrade.rs | 0 {parity => bin/oe}/user_defaults.rs | 0 {accounts => crates/accounts}/Cargo.toml | 0 .../accounts}/ethkey/.gitignore | 0 .../accounts}/ethkey/.travis.yml | 0 .../accounts}/ethkey/Cargo.toml | 2 +- .../accounts}/ethkey/README.md | 0 .../accounts}/ethkey/src/brain.rs | 0 .../accounts}/ethkey/src/brain_prefix.rs | 0 .../accounts}/ethkey/src/brain_recover.rs | 0 .../accounts}/ethkey/src/crypto.rs | 0 .../accounts}/ethkey/src/error.rs | 0 .../accounts}/ethkey/src/extended.rs | 0 .../accounts}/ethkey/src/keccak.rs | 0 .../accounts}/ethkey/src/keypair.rs | 0 .../accounts}/ethkey/src/lib.rs | 0 .../accounts}/ethkey/src/math.rs | 0 .../accounts}/ethkey/src/password.rs | 0 .../accounts}/ethkey/src/prefix.rs | 0 .../accounts}/ethkey/src/random.rs | 0 .../accounts}/ethkey/src/secret.rs | 0 .../accounts}/ethkey/src/signature.rs | 0 .../accounts}/ethstore/.editorconfig | 0 .../accounts}/ethstore/.gitignore | 0 .../accounts}/ethstore/.travis.yml | 0 .../accounts}/ethstore/Cargo.toml | 0 .../accounts}/ethstore/README.md | 0 .../accounts}/ethstore/src/account/cipher.rs | 0 .../accounts}/ethstore/src/account/crypto.rs | 0 .../accounts}/ethstore/src/account/kdf.rs | 0 .../accounts}/ethstore/src/account/mod.rs | 0 .../ethstore/src/account/safe_account.rs | 0 .../accounts}/ethstore/src/account/version.rs | 0 .../ethstore/src/accounts_dir/disk.rs | 0 .../ethstore/src/accounts_dir/memory.rs | 0 .../ethstore/src/accounts_dir/mod.rs | 0 .../ethstore/src/accounts_dir/vault.rs | 0 .../accounts}/ethstore/src/error.rs | 0 .../accounts}/ethstore/src/ethkey.rs | 0 .../accounts}/ethstore/src/ethstore.rs | 0 .../accounts}/ethstore/src/import.rs | 0 .../accounts}/ethstore/src/json/bytes.rs | 0 .../accounts}/ethstore/src/json/cipher.rs | 0 .../accounts}/ethstore/src/json/crypto.rs | 0 .../accounts}/ethstore/src/json/error.rs | 0 .../accounts}/ethstore/src/json/hash.rs | 0 .../accounts}/ethstore/src/json/id.rs | 0 .../accounts}/ethstore/src/json/kdf.rs | 0 .../accounts}/ethstore/src/json/key_file.rs | 0 .../accounts}/ethstore/src/json/mod.rs | 0 .../accounts}/ethstore/src/json/presale.rs | 0 .../accounts}/ethstore/src/json/vault_file.rs | 0 .../ethstore/src/json/vault_key_file.rs | 0 .../accounts}/ethstore/src/json/version.rs | 0 .../accounts}/ethstore/src/lib.rs | 0 .../accounts}/ethstore/src/presale.rs | 0 .../accounts}/ethstore/src/random.rs | 0 .../accounts}/ethstore/src/secret_store.rs | 0 .../accounts}/ethstore/tests/api.rs | 0 .../ethstore/tests/res/ciphertext/30.json | 0 .../ethstore/tests/res/ciphertext/31.json | 0 ...--3f49624084b67849c7b4e805c5988c21a430f9d9 | 0 ...--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf | 0 ...--63121b431a52f8043c16fcf0d1df9cb7b5f66649 | 0 .../accounts}/ethstore/tests/res/pat/p1.json | 0 .../accounts}/ethstore/tests/res/pat/p2.json | 0 .../accounts}/ethstore/tests/util/mod.rs | 0 .../ethstore/tests/util/transient_dir.rs | 0 .../accounts}/src/account_data.rs | 0 {accounts => crates/accounts}/src/error.rs | 0 {accounts => crates/accounts}/src/lib.rs | 0 {accounts => crates/accounts}/src/stores.rs | 0 .../concensus/ethash}/Cargo.toml | 0 .../concensus/ethash}/benches/basic.rs | 0 .../concensus/ethash}/benches/progpow.rs | 0 .../ethash}/res/progpow_testvectors.json | 0 .../concensus/ethash}/src/cache.rs | 0 .../concensus/ethash}/src/compute.rs | 0 .../concensus/ethash}/src/keccak.rs | 0 .../concensus/ethash}/src/lib.rs | 0 .../concensus/ethash}/src/progpow.rs | 0 .../concensus/ethash}/src/seed_compute.rs | 0 .../concensus/ethash}/src/shared.rs | 0 {miner => crates/concensus/miner}/Cargo.toml | 12 +- .../concensus/miner}/local-store/Cargo.toml | 6 +- .../concensus/miner}/local-store/src/lib.rs | 0 .../concensus/miner}/price-info/Cargo.toml | 6 +- .../concensus/miner}/price-info/src/lib.rs | 0 .../res/contracts/service_transaction.json | 0 .../concensus/miner}/src/external.rs | 0 .../miner}/src/gas_price_calibrator.rs | 0 .../concensus/miner}/src/gas_pricer.rs | 0 {miner => crates/concensus/miner}/src/lib.rs | 0 .../concensus/miner}/src/local_accounts.rs | 0 .../concensus/miner}/src/pool/client.rs | 0 .../concensus/miner}/src/pool/listener.rs | 0 .../miner}/src/pool/local_transactions.rs | 0 .../concensus/miner}/src/pool/mod.rs | 0 .../concensus/miner}/src/pool/queue.rs | 0 .../concensus/miner}/src/pool/ready.rs | 0 .../concensus/miner}/src/pool/replace.rs | 0 .../miner}/src/pool/res/big_transaction.data | 0 .../concensus/miner}/src/pool/scoring.rs | 0 .../concensus/miner}/src/pool/tests/client.rs | 0 .../concensus/miner}/src/pool/tests/mod.rs | 0 .../concensus/miner}/src/pool/tests/tx.rs | 0 .../concensus/miner}/src/pool/verifier.rs | 0 .../miner}/src/service_transaction_checker.rs | 0 .../concensus/miner}/src/work_notify.rs | 0 .../concensus/miner}/stratum/Cargo.toml | 0 .../concensus/miner}/stratum/src/lib.rs | 0 .../concensus/miner}/stratum/src/traits.rs | 0 .../concensus/miner}/using-queue/Cargo.toml | 0 .../concensus/miner}/using-queue/src/lib.rs | 0 {util => crates/db}/bloom/Cargo.toml | 0 {util => crates/db}/bloom/src/lib.rs | 0 {util => crates/db}/blooms-db/Cargo.toml | 0 .../db}/blooms-db/benches/blooms.rs | 0 {util => crates/db}/blooms-db/src/db.rs | 0 {util => crates/db}/blooms-db/src/file.rs | 0 {util => crates/db}/blooms-db/src/lib.rs | 0 {ethcore => crates/db}/db/Cargo.toml | 2 +- .../db}/db/src/cache_manager.rs | 0 {ethcore => crates/db}/db/src/db.rs | 0 {ethcore => crates/db}/db/src/keys.rs | 0 {ethcore => crates/db}/db/src/lib.rs | 0 {util => crates/db}/journaldb/Cargo.toml | 4 +- .../db}/journaldb/src/archivedb.rs | 0 .../db}/journaldb/src/as_hash_db_impls.rs | 0 .../db}/journaldb/src/earlymergedb.rs | 0 {util => crates/db}/journaldb/src/lib.rs | 0 .../db}/journaldb/src/overlaydb.rs | 0 .../db}/journaldb/src/overlayrecentdb.rs | 0 .../db}/journaldb/src/refcounteddb.rs | 0 {util => crates/db}/journaldb/src/traits.rs | 0 {util => crates/db}/journaldb/src/util.rs | 0 .../db}/memory-db/.cargo_vcs_info.json | 0 {util => crates/db}/memory-db/Cargo.toml | 0 {util => crates/db}/memory-db/Cargo.toml.orig | 0 {util => crates/db}/memory-db/README.md | 0 .../db}/memory-db/benches/bench.rs | 0 {util => crates/db}/memory-db/src/lib.rs | 0 .../db}/migration-rocksdb/Cargo.toml | 2 +- .../db}/migration-rocksdb/src/lib.rs | 0 .../db}/migration-rocksdb/tests/tests.rs | 0 .../db}/patricia-trie-ethereum/Cargo.toml | 2 +- .../db}/patricia-trie-ethereum/src/lib.rs | 0 .../src/rlp_node_codec.rs | 0 {ethcore => crates/ethcore}/Cargo.toml | 40 +- .../ethcore}/benches/builtin.rs | 0 .../ethcore}/blockchain/Cargo.toml | 4 +- .../ethcore}/blockchain/src/best_block.rs | 0 .../ethcore}/blockchain/src/block_info.rs | 0 .../ethcore}/blockchain/src/blockchain.rs | 0 .../ethcore}/blockchain/src/cache.rs | 0 .../ethcore}/blockchain/src/config.rs | 0 .../ethcore}/blockchain/src/generator.rs | 0 .../ethcore}/blockchain/src/import_route.rs | 0 .../ethcore}/blockchain/src/lib.rs | 0 .../ethcore}/blockchain/src/update.rs | 0 .../ethcore/res/chainspec}/callisto.json | 0 .../ethcore/res/chainspec}/ellaism.json | 0 .../ethcore/res/chainspec}/ewc.json | 0 .../ethcore/res/chainspec}/foundation.json | 0 .../ethcore/res/chainspec}/goerli.json | 0 .../ethcore/res/chainspec}/instant_seal.json | 0 .../ethcore/res/chainspec}/kovan.json | 0 .../ethcore/res/chainspec}/mix.json | 0 .../ethcore/res/chainspec}/morden.json | 0 .../ethcore/res/chainspec}/musicoin.json | 0 .../ethcore/res/chainspec}/poacore.json | 0 .../ethcore/res/chainspec}/poasokol.json | 0 .../ethcore/res/chainspec}/rinkeby.json | 0 .../ethcore/res/chainspec}/ropsten.json | 0 .../res/chainspec/test}/authority_round.json | 0 ...authority_round_block_reward_contract.json | 0 .../test}/authority_round_empty_steps.json | 0 .../res/chainspec/test}/basic_authority.json | 0 .../res/chainspec/test}/berlin_test.json | 0 .../chainspec/test}/builtin_multi_bench.json | 0 .../test}/builtin_one_activation_bench.json | 0 .../res/chainspec/test}/byzantium_test.json | 0 ...yzantium_to_constantinoplefixat5_test.json | 0 .../chainspec/test}/constantinople_test.json | 0 .../res/chainspec/test}/constructor.json | 0 .../test}/contract_ver_2_genesis.json | 0 .../test}/deprecated_contract_genesis.json | 0 .../res/chainspec/test}/eip150_test.json | 0 .../res/chainspec/test}/eip161_test.json | 0 .../res/chainspec/test}/eip210_test.json | 0 .../chainspec/test}/frontier_like_test.json | 0 .../res/chainspec/test}/frontier_test.json | 0 .../res/chainspec/test}/homestead_test.json | 0 .../res/chainspec/test}/istanbul_test.json | 0 .../res/chainspec/test}/kovan_wasm_test.json | 0 .../res/chainspec/test}/mcip3_test.json | 0 .../ethcore/res/chainspec/test}/null.json | 0 .../res/chainspec/test}/null_morden.json | 0 .../test}/null_morden_with_finality.json | 0 .../test}/null_morden_with_reward.json | 0 .../test}/spec_backward_compability.json | 0 .../res/chainspec/test}/st_peters_test.json | 0 .../res/chainspec/test}/transition_test.json | 0 .../chainspec/test}/validator_contract.json | 0 .../res/chainspec/test}/validator_multi.json | 0 .../test}/validator_safe_contract.json | 0 .../res/chainspec/test}/yolo3_test.json | 0 .../ethcore/res/chainspec}/volta.json | 0 .../ethcore/res/chainspec}/xdai.json | 0 .../ethcore}/res/contracts/block_reward.json | 0 .../ethcore}/res/contracts/registrar.json | 2 +- .../res/contracts/test_validator_set.json | 0 .../ethcore}/res/contracts/tx_acl.json | 0 .../res/contracts/tx_acl_deprecated.json | 0 .../res/contracts/validator_report.json | 0 .../ethcore}/res/contracts/validator_set.json | 0 .../tests => crates/ethcore/res/json_tests | 0 crates/ethcore/res/json_tests.json | 60 + .../ethcore}/service/Cargo.toml | 4 +- .../ethcore}/service/src/error.rs | 0 .../ethcore}/service/src/lib.rs | 0 .../ethcore}/service/src/service.rs | 0 .../ethcore}/service/src/stop_guard.rs | 0 {ethcore => crates/ethcore}/src/account_db.rs | 0 {ethcore => crates/ethcore}/src/block.rs | 0 .../ethcore}/src/client/ancient_import.rs | 0 .../ethcore}/src/client/bad_blocks.rs | 0 .../ethcore}/src/client/chain_notify.rs | 0 .../ethcore}/src/client/client.rs | 0 .../ethcore}/src/client/config.rs | 0 .../ethcore}/src/client/evm_test_client.rs | 0 .../ethcore}/src/client/io_message.rs | 0 {ethcore => crates/ethcore}/src/client/mod.rs | 0 .../ethcore}/src/client/test_client.rs | 0 .../ethcore}/src/client/trace.rs | 0 .../ethcore}/src/client/traits.rs | 0 .../src/engines/authority_round/finality.rs | 0 .../src/engines/authority_round/mod.rs | 0 .../ethcore}/src/engines/basic_authority.rs | 2 +- .../ethcore}/src/engines/block_reward.rs | 0 .../src/engines/clique/block_state.rs | 0 .../ethcore}/src/engines/clique/mod.rs | 0 .../ethcore}/src/engines/clique/params.rs | 0 .../ethcore}/src/engines/clique/tests.rs | 0 .../ethcore}/src/engines/clique/util.rs | 0 .../ethcore}/src/engines/instant_seal.rs | 0 .../ethcore}/src/engines/mod.rs | 0 .../ethcore}/src/engines/null_engine.rs | 0 .../ethcore}/src/engines/signer.rs | 0 .../src/engines/validator_set/contract.rs | 0 .../ethcore}/src/engines/validator_set/mod.rs | 0 .../src/engines/validator_set/multi.rs | 0 .../engines/validator_set/safe_contract.rs | 0 .../src/engines/validator_set/simple_list.rs | 0 .../src/engines/validator_set/test.rs | 0 {ethcore => crates/ethcore}/src/error.rs | 0 .../ethcore}/src/ethereum/denominations.rs | 0 .../ethcore}/src/ethereum/ethash.rs | 0 .../ethcore}/src/ethereum/mod.rs | 78 +- {ethcore => crates/ethcore}/src/executed.rs | 0 {ethcore => crates/ethcore}/src/executive.rs | 0 .../ethcore}/src/externalities.rs | 0 {ethcore => crates/ethcore}/src/factory.rs | 0 .../ethcore}/src/json_tests/chain.rs | 0 .../ethcore}/src/json_tests/difficulty.rs | 0 .../ethcore}/src/json_tests/executive.rs | 0 .../ethcore}/src/json_tests/mod.rs | 0 .../ethcore}/src/json_tests/runner.rs | 2 +- .../ethcore}/src/json_tests/skip.rs | 0 .../ethcore}/src/json_tests/state.rs | 0 .../ethcore}/src/json_tests/test_common.rs | 0 .../ethcore}/src/json_tests/transaction.rs | 0 .../ethcore}/src/json_tests/trie.rs | 0 {ethcore => crates/ethcore}/src/lib.rs | 0 .../ethcore}/src/machine/impls.rs | 0 .../ethcore}/src/machine/mod.rs | 0 .../ethcore}/src/machine/traits.rs | 0 .../ethcore}/src/miner/miner.rs | 0 {ethcore => crates/ethcore}/src/miner/mod.rs | 0 .../ethcore}/src/miner/pool_client.rs | 0 .../ethcore}/src/miner/stratum.rs | 0 .../ethcore}/src/pod_account.rs | 0 {ethcore => crates/ethcore}/src/pod_state.rs | 0 .../ethcore}/src/snapshot/account.rs | 0 .../ethcore}/src/snapshot/block.rs | 0 .../src/snapshot/consensus/authority.rs | 0 .../ethcore}/src/snapshot/consensus/mod.rs | 0 .../ethcore}/src/snapshot/consensus/work.rs | 0 .../ethcore}/src/snapshot/error.rs | 0 .../ethcore}/src/snapshot/io.rs | 0 .../ethcore}/src/snapshot/mod.rs | 0 .../ethcore}/src/snapshot/service.rs | 0 .../ethcore}/src/snapshot/tests/helpers.rs | 0 .../ethcore}/src/snapshot/tests/mod.rs | 0 .../src/snapshot/tests/proof_of_authority.rs | 0 .../src/snapshot/tests/proof_of_work.rs | 0 .../ethcore}/src/snapshot/tests/service.rs | 0 .../ethcore}/src/snapshot/tests/state.rs | 0 .../tests/test_validator_contract.json | 0 .../ethcore}/src/snapshot/traits.rs | 0 .../ethcore}/src/snapshot/watcher.rs | 0 .../ethcore}/src/spec/genesis.rs | 0 {ethcore => crates/ethcore}/src/spec/mod.rs | 0 {ethcore => crates/ethcore}/src/spec/seal.rs | 0 {ethcore => crates/ethcore}/src/spec/spec.rs | 28 +- .../ethcore}/src/state/account.rs | 0 .../ethcore}/src/state/backend.rs | 0 {ethcore => crates/ethcore}/src/state/mod.rs | 0 .../ethcore}/src/state/substate.rs | 0 {ethcore => crates/ethcore}/src/state_db.rs | 0 .../ethcore}/src/test_helpers.rs | 0 .../ethcore}/src/tests/blockchain.rs | 0 .../ethcore}/src/tests/client.rs | 0 {ethcore => crates/ethcore}/src/tests/evm.rs | 0 {ethcore => crates/ethcore}/src/tests/mod.rs | 0 .../ethcore}/src/tests/trace.rs | 0 .../ethcore}/src/trace/config.rs | 0 {ethcore => crates/ethcore}/src/trace/db.rs | 0 .../ethcore}/src/trace/executive_tracer.rs | 0 .../ethcore}/src/trace/import.rs | 0 {ethcore => crates/ethcore}/src/trace/mod.rs | 0 .../ethcore}/src/trace/noop_tracer.rs | 0 .../ethcore}/src/trace/types/error.rs | 0 .../ethcore}/src/trace/types/filter.rs | 0 .../ethcore}/src/trace/types/flat.rs | 0 .../ethcore}/src/trace/types/localized.rs | 0 .../ethcore}/src/trace/types/mod.rs | 0 .../ethcore}/src/trace/types/trace.rs | 0 .../ethcore}/src/transaction_ext.rs | 0 {ethcore => crates/ethcore}/src/tx_filter.rs | 4 +- .../src/verification/canon_verifier.rs | 0 .../ethcore}/src/verification/mod.rs | 0 .../src/verification/noop_verifier.rs | 0 .../ethcore}/src/verification/queue/kind.rs | 0 .../ethcore}/src/verification/queue/mod.rs | 0 .../ethcore}/src/verification/verification.rs | 0 .../ethcore}/src/verification/verifier.rs | 0 {ethcore => crates/ethcore}/sync/Cargo.toml | 8 +- {ethcore => crates/ethcore}/sync/src/api.rs | 0 .../ethcore}/sync/src/block_sync.rs | 0 .../ethcore}/sync/src/blocks.rs | 0 .../ethcore}/sync/src/chain/fork_filter.rs | 0 .../ethcore}/sync/src/chain/handler.rs | 0 .../ethcore}/sync/src/chain/mod.rs | 0 .../ethcore}/sync/src/chain/propagator.rs | 0 .../ethcore}/sync/src/chain/requester.rs | 0 .../ethcore}/sync/src/chain/supplier.rs | 0 .../ethcore}/sync/src/chain/sync_packet.rs | 0 {ethcore => crates/ethcore}/sync/src/lib.rs | 0 .../ethcore}/sync/src/res/private_spec.json | 0 .../ethcore}/sync/src/snapshot.rs | 0 .../ethcore}/sync/src/sync_io.rs | 0 .../ethcore}/sync/src/tests/chain.rs | 0 .../ethcore}/sync/src/tests/consensus.rs | 0 .../ethcore}/sync/src/tests/helpers.rs | 0 .../ethcore}/sync/src/tests/mod.rs | 0 .../ethcore}/sync/src/tests/rpc.rs | 0 .../ethcore}/sync/src/tests/snapshot.rs | 0 .../ethcore}/sync/src/transactions_stats.rs | 0 {ethcore => crates/ethcore}/types/Cargo.toml | 2 +- .../ethcore}/types/src/account_diff.rs | 0 .../ethcore}/types/src/ancestry_action.rs | 0 .../ethcore}/types/src/basic_account.rs | 0 .../ethcore}/types/src/block.rs | 0 .../ethcore}/types/src/block_status.rs | 0 .../ethcore}/types/src/blockchain_info.rs | 0 .../ethcore}/types/src/call_analytics.rs | 0 .../ethcore}/types/src/creation_status.rs | 0 .../ethcore}/types/src/data_format.rs | 0 .../ethcore}/types/src/encoded.rs | 0 .../ethcore}/types/src/engines/epoch.rs | 0 .../ethcore}/types/src/engines/mod.rs | 0 .../ethcore}/types/src/filter.rs | 0 .../ethcore}/types/src/header.rs | 0 {ethcore => crates/ethcore}/types/src/ids.rs | 0 {ethcore => crates/ethcore}/types/src/lib.rs | 0 .../ethcore}/types/src/log_entry.rs | 0 .../ethcore}/types/src/pruning_info.rs | 0 .../ethcore}/types/src/receipt.rs | 0 .../ethcore}/types/src/restoration_status.rs | 0 .../ethcore}/types/src/security_level.rs | 0 .../ethcore}/types/src/snapshot_manifest.rs | 0 .../ethcore}/types/src/state_diff.rs | 0 .../ethcore}/types/src/trace_filter.rs | 0 .../ethcore}/types/src/transaction/error.rs | 0 .../ethcore}/types/src/transaction/mod.rs | 0 .../types/src/transaction/transaction.rs | 0 .../types/src/transaction/transaction_id.rs | 0 .../ethcore}/types/src/tree_route.rs | 0 .../types/src/verification_queue_info.rs | 0 .../ethcore}/types/src/views/block.rs | 0 .../ethcore}/types/src/views/body.rs | 0 .../ethcore}/types/src/views/header.rs | 0 .../ethcore}/types/src/views/mod.rs | 0 .../ethcore}/types/src/views/transaction.rs | 0 .../ethcore}/types/src/views/view_rlp.rs | 0 {json => crates/ethjson}/Cargo.toml | 0 .../ethjson}/src/blockchain/account.rs | 0 .../ethjson}/src/blockchain/block.rs | 0 .../ethjson}/src/blockchain/blockchain.rs | 0 .../ethjson}/src/blockchain/header.rs | 0 .../ethjson}/src/blockchain/mod.rs | 0 .../ethjson}/src/blockchain/state.rs | 1 - .../ethjson}/src/blockchain/test.rs | 0 .../ethjson}/src/blockchain/transaction.rs | 0 {json => crates/ethjson}/src/bytes.rs | 0 {json => crates/ethjson}/src/hash.rs | 0 {json => crates/ethjson}/src/lib.rs | 0 {json => crates/ethjson}/src/maybe.rs | 0 {json => crates/ethjson}/src/spec/account.rs | 0 .../ethjson}/src/spec/authority_round.rs | 0 .../ethjson}/src/spec/basic_authority.rs | 0 {json => crates/ethjson}/src/spec/builtin.rs | 0 {json => crates/ethjson}/src/spec/clique.rs | 0 {json => crates/ethjson}/src/spec/engine.rs | 0 {json => crates/ethjson}/src/spec/ethash.rs | 0 {json => crates/ethjson}/src/spec/genesis.rs | 0 .../ethjson}/src/spec/instant_seal.rs | 0 {json => crates/ethjson}/src/spec/mod.rs | 0 .../ethjson}/src/spec/null_engine.rs | 0 {json => crates/ethjson}/src/spec/params.rs | 0 {json => crates/ethjson}/src/spec/seal.rs | 0 {json => crates/ethjson}/src/spec/spec.rs | 0 {json => crates/ethjson}/src/spec/state.rs | 0 .../ethjson}/src/spec/validator_set.rs | 0 {json => crates/ethjson}/src/state/log.rs | 0 {json => crates/ethjson}/src/state/mod.rs | 0 {json => crates/ethjson}/src/state/state.rs | 0 {json => crates/ethjson}/src/state/test.rs | 0 .../ethjson}/src/state/transaction.rs | 0 {json => crates/ethjson}/src/test/mod.rs | 0 .../ethjson}/src/transaction/mod.rs | 0 .../ethjson}/src/transaction/test.rs | 0 .../ethjson}/src/transaction/transaction.rs | 0 .../ethjson}/src/transaction/txtest.rs | 0 {json => crates/ethjson}/src/trie/input.rs | 0 {json => crates/ethjson}/src/trie/mod.rs | 0 {json => crates/ethjson}/src/trie/test.rs | 0 {json => crates/ethjson}/src/trie/trie.rs | 0 {json => crates/ethjson}/src/uint.rs | 0 {json => crates/ethjson}/src/vm/call.rs | 0 {json => crates/ethjson}/src/vm/env.rs | 0 {json => crates/ethjson}/src/vm/mod.rs | 0 {json => crates/ethjson}/src/vm/test.rs | 0 .../ethjson}/src/vm/transaction.rs | 0 {json => crates/ethjson}/src/vm/vm.rs | 0 {util => crates/net}/fake-fetch/Cargo.toml | 0 {util => crates/net}/fake-fetch/src/lib.rs | 0 {util => crates/net}/fetch/Cargo.toml | 0 {util => crates/net}/fetch/src/client.rs | 0 {util => crates/net}/fetch/src/lib.rs | 0 .../net}/network-devp2p/Cargo.toml | 4 +- .../net}/network-devp2p/src/connection.rs | 0 .../net}/network-devp2p/src/discovery.rs | 0 .../net}/network-devp2p/src/handshake.rs | 0 .../net}/network-devp2p/src/host.rs | 0 .../net}/network-devp2p/src/ip_utils.rs | 0 .../net}/network-devp2p/src/lib.rs | 0 .../net}/network-devp2p/src/node_table.rs | 0 .../net}/network-devp2p/src/service.rs | 0 .../net}/network-devp2p/src/session.rs | 0 .../net}/network-devp2p/tests/tests.rs | 0 {util => crates/net}/network/Cargo.toml | 4 +- .../net}/network/src/client_version.rs | 0 .../net}/network/src/connection_filter.rs | 0 {util => crates/net}/network/src/error.rs | 0 {util => crates/net}/network/src/lib.rs | 0 .../net}/node-filter/Cargo.toml | 12 +- .../net}/node-filter/res/node_filter.json | 0 .../net}/node-filter/res/peer_set.json | 0 .../net}/node-filter/src/lib.rs | 0 {rpc => crates/rpc}/Cargo.toml | 22 +- {rpc => crates/rpc}/src/authcodes.rs | 0 {rpc => crates/rpc}/src/http_common.rs | 0 {rpc => crates/rpc}/src/lib.rs | 0 {rpc => crates/rpc}/src/tests/helpers.rs | 0 {rpc => crates/rpc}/src/tests/http_client.rs | 0 {rpc => crates/rpc}/src/tests/mod.rs | 0 {rpc => crates/rpc}/src/tests/rpc.rs | 0 {rpc => crates/rpc}/src/tests/ws.rs | 0 {rpc => crates/rpc}/src/v1/extractors.rs | 0 .../rpc}/src/v1/helpers/block_import.rs | 0 .../rpc}/src/v1/helpers/deprecated.rs | 0 .../rpc}/src/v1/helpers/dispatch/full.rs | 0 .../rpc}/src/v1/helpers/dispatch/mod.rs | 0 .../v1/helpers/dispatch/prospective_signer.rs | 0 .../rpc}/src/v1/helpers/dispatch/signing.rs | 0 {rpc => crates/rpc}/src/v1/helpers/eip191.rs | 0 .../rpc}/src/v1/helpers/engine_signer.rs | 0 {rpc => crates/rpc}/src/v1/helpers/errors.rs | 0 .../src/v1/helpers/external_signer/mod.rs | 0 .../src/v1/helpers/external_signer/oneshot.rs | 0 .../helpers/external_signer/signing_queue.rs | 0 .../rpc}/src/v1/helpers/fake_sign.rs | 0 {rpc => crates/rpc}/src/v1/helpers/mod.rs | 0 .../rpc}/src/v1/helpers/network_settings.rs | 0 {rpc => crates/rpc}/src/v1/helpers/nonce.rs | 0 .../rpc}/src/v1/helpers/poll_filter.rs | 0 .../rpc}/src/v1/helpers/poll_manager.rs | 0 .../rpc}/src/v1/helpers/requests.rs | 0 .../rpc}/src/v1/helpers/secretstore.rs | 0 .../rpc}/src/v1/helpers/signature.rs | 0 .../rpc}/src/v1/helpers/subscribers.rs | 0 .../src/v1/helpers/subscription_manager.rs | 0 {rpc => crates/rpc}/src/v1/helpers/work.rs | 0 {rpc => crates/rpc}/src/v1/impls/debug.rs | 0 {rpc => crates/rpc}/src/v1/impls/eth.rs | 0 .../rpc}/src/v1/impls/eth_filter.rs | 0 .../rpc}/src/v1/impls/eth_pubsub.rs | 0 {rpc => crates/rpc}/src/v1/impls/mod.rs | 0 {rpc => crates/rpc}/src/v1/impls/net.rs | 0 {rpc => crates/rpc}/src/v1/impls/parity.rs | 0 .../rpc}/src/v1/impls/parity_accounts.rs | 0 .../rpc}/src/v1/impls/parity_set.rs | 0 {rpc => crates/rpc}/src/v1/impls/personal.rs | 0 {rpc => crates/rpc}/src/v1/impls/pubsub.rs | 0 .../rpc}/src/v1/impls/secretstore.rs | 0 {rpc => crates/rpc}/src/v1/impls/signer.rs | 0 {rpc => crates/rpc}/src/v1/impls/signing.rs | 0 .../rpc}/src/v1/impls/signing_unsafe.rs | 0 {rpc => crates/rpc}/src/v1/impls/traces.rs | 0 {rpc => crates/rpc}/src/v1/impls/web3.rs | 0 {rpc => crates/rpc}/src/v1/informant.rs | 0 {rpc => crates/rpc}/src/v1/metadata.rs | 0 {rpc => crates/rpc}/src/v1/mod.rs | 0 {rpc => crates/rpc}/src/v1/tests/eth.rs | 0 .../src/v1/tests/helpers/miner_service.rs | 0 .../rpc}/src/v1/tests/helpers/mod.rs | 0 .../src/v1/tests/helpers/snapshot_service.rs | 0 .../src/v1/tests/helpers/sync_provider.rs | 0 .../rpc}/src/v1/tests/mocked/debug.rs | 0 .../rpc}/src/v1/tests/mocked/eth.rs | 0 .../rpc}/src/v1/tests/mocked/eth_pubsub.rs | 0 .../src/v1/tests/mocked/manage_network.rs | 0 .../rpc}/src/v1/tests/mocked/mod.rs | 0 .../rpc}/src/v1/tests/mocked/net.rs | 0 .../rpc}/src/v1/tests/mocked/parity.rs | 0 .../src/v1/tests/mocked/parity_accounts.rs | 0 .../rpc}/src/v1/tests/mocked/parity_set.rs | 0 .../rpc}/src/v1/tests/mocked/personal.rs | 0 .../rpc}/src/v1/tests/mocked/pubsub.rs | 0 .../rpc}/src/v1/tests/mocked/secretstore.rs | 0 .../rpc}/src/v1/tests/mocked/signer.rs | 0 .../rpc}/src/v1/tests/mocked/signing.rs | 0 .../src/v1/tests/mocked/signing_unsafe.rs | 0 .../rpc}/src/v1/tests/mocked/traces.rs | 0 .../rpc}/src/v1/tests/mocked/web3.rs | 0 {rpc => crates/rpc}/src/v1/tests/mod.rs | 2 +- {rpc => crates/rpc}/src/v1/traits/debug.rs | 0 {rpc => crates/rpc}/src/v1/traits/eth.rs | 0 .../rpc}/src/v1/traits/eth_pubsub.rs | 0 .../rpc}/src/v1/traits/eth_signing.rs | 0 {rpc => crates/rpc}/src/v1/traits/mod.rs | 0 {rpc => crates/rpc}/src/v1/traits/net.rs | 0 {rpc => crates/rpc}/src/v1/traits/parity.rs | 0 .../rpc}/src/v1/traits/parity_accounts.rs | 0 .../rpc}/src/v1/traits/parity_set.rs | 0 .../rpc}/src/v1/traits/parity_signing.rs | 0 {rpc => crates/rpc}/src/v1/traits/personal.rs | 0 {rpc => crates/rpc}/src/v1/traits/pubsub.rs | 0 .../rpc}/src/v1/traits/secretstore.rs | 0 {rpc => crates/rpc}/src/v1/traits/signer.rs | 0 {rpc => crates/rpc}/src/v1/traits/traces.rs | 0 {rpc => crates/rpc}/src/v1/traits/web3.rs | 0 .../rpc}/src/v1/types/account_info.rs | 0 {rpc => crates/rpc}/src/v1/types/block.rs | 0 .../rpc}/src/v1/types/block_number.rs | 0 {rpc => crates/rpc}/src/v1/types/bytes.rs | 0 .../rpc}/src/v1/types/call_request.rs | 0 .../rpc}/src/v1/types/confirmations.rs | 0 .../rpc}/src/v1/types/derivation.rs | 0 {rpc => crates/rpc}/src/v1/types/eip191.rs | 0 {rpc => crates/rpc}/src/v1/types/eth_types.rs | 0 {rpc => crates/rpc}/src/v1/types/filter.rs | 0 {rpc => crates/rpc}/src/v1/types/histogram.rs | 0 {rpc => crates/rpc}/src/v1/types/index.rs | 0 {rpc => crates/rpc}/src/v1/types/log.rs | 0 {rpc => crates/rpc}/src/v1/types/mod.rs | 0 {rpc => crates/rpc}/src/v1/types/node_kind.rs | 0 .../rpc}/src/v1/types/provenance.rs | 0 {rpc => crates/rpc}/src/v1/types/pubsub.rs | 0 {rpc => crates/rpc}/src/v1/types/receipt.rs | 0 .../rpc}/src/v1/types/rpc_settings.rs | 0 .../rpc}/src/v1/types/secretstore.rs | 0 {rpc => crates/rpc}/src/v1/types/sync.rs | 0 {rpc => crates/rpc}/src/v1/types/trace.rs | 0 .../rpc}/src/v1/types/trace_filter.rs | 0 .../rpc}/src/v1/types/transaction.rs | 0 .../src/v1/types/transaction_condition.rs | 0 .../rpc}/src/v1/types/transaction_request.rs | 0 {rpc => crates/rpc}/src/v1/types/work.rs | 0 {util => crates/runtime}/io/Cargo.toml | 0 {util => crates/runtime}/io/src/lib.rs | 0 .../runtime}/io/src/service_mio.rs | 0 .../runtime}/io/src/service_non_mio.rs | 0 {util => crates/runtime}/io/src/worker.rs | 0 {util => crates/runtime}/runtime/Cargo.toml | 0 {util => crates/runtime}/runtime/src/lib.rs | 0 {util => crates/util}/EIP-152/Cargo.toml | 0 {util => crates/util}/EIP-152/src/lib.rs | 0 {util => crates/util}/EIP-712/Cargo.toml | 0 {util => crates/util}/EIP-712/README.md | 0 {util => crates/util}/EIP-712/src/eip712.rs | 0 {util => crates/util}/EIP-712/src/encode.rs | 0 {util => crates/util}/EIP-712/src/error.rs | 0 {util => crates/util}/EIP-712/src/lib.rs | 0 {util => crates/util}/EIP-712/src/parser.rs | 0 .../util/cli-signer}/Cargo.toml | 2 +- .../util/cli-signer}/rpc-client/Cargo.toml | 2 +- .../util/cli-signer}/rpc-client/src/client.rs | 0 .../util/cli-signer}/rpc-client/src/lib.rs | 0 .../rpc-client/src/signer_client.rs | 0 .../util/cli-signer}/src/lib.rs | 0 {util => crates/util}/dir/Cargo.toml | 2 +- {util => crates/util}/dir/src/helpers.rs | 0 {util => crates/util}/dir/src/lib.rs | 0 {util => crates/util}/fastmap/Cargo.toml | 0 {util => crates/util}/fastmap/src/lib.rs | 0 .../util}/keccak-hasher/Cargo.toml | 0 .../util}/keccak-hasher/src/lib.rs | 0 .../util}/len-caching-lock/Cargo.toml | 0 .../util}/len-caching-lock/src/lib.rs | 0 .../util}/len-caching-lock/src/mutex.rs | 0 .../util}/len-caching-lock/src/rwlock.rs | 0 {util => crates/util}/macros/Cargo.toml | 0 {util => crates/util}/macros/src/lib.rs | 0 {util => crates/util}/memory-cache/Cargo.toml | 0 {util => crates/util}/memory-cache/src/lib.rs | 0 {util => crates/util}/memzero/Cargo.toml | 0 {util => crates/util}/memzero/src/lib.rs | 0 {util => crates/util}/panic-hook/Cargo.toml | 0 {util => crates/util}/panic-hook/src/lib.rs | 0 {util => crates/util}/rlp-compress/Cargo.toml | 0 .../util}/rlp-compress/src/common.rs | 0 {util => crates/util}/rlp-compress/src/lib.rs | 0 .../util}/rlp-compress/tests/compress.rs | 0 {util => crates/util}/rlp-derive/Cargo.toml | 0 {util => crates/util}/rlp-derive/src/de.rs | 0 {util => crates/util}/rlp-derive/src/en.rs | 0 {util => crates/util}/rlp-derive/src/lib.rs | 0 {util => crates/util}/rlp-derive/tests/rlp.rs | 0 {util => crates/util}/stats/Cargo.toml | 0 {util => crates/util}/stats/src/lib.rs | 0 {util => crates/util}/time-utils/Cargo.toml | 0 {util => crates/util}/time-utils/src/lib.rs | 0 .../util}/triehash-ethereum/Cargo.toml | 0 .../util}/triehash-ethereum/src/lib.rs | 0 {util => crates/util}/unexpected/Cargo.toml | 0 {util => crates/util}/unexpected/src/lib.rs | 0 {util => crates/util}/version/Cargo.toml | 0 {util => crates/util}/version/build.rs | 0 {util => crates/util}/version/src/lib.rs | 0 {ethcore => crates/vm}/builtin/Cargo.toml | 2 +- {ethcore => crates/vm}/builtin/src/lib.rs | 0 .../vm}/call-contract/Cargo.toml | 2 +- .../vm}/call-contract/src/call_contract.rs | 0 .../vm}/call-contract/src/lib.rs | 0 {ethcore => crates/vm}/evm/Cargo.toml | 0 {ethcore => crates/vm}/evm/benches/basic.rs | 0 {ethcore => crates/vm}/evm/src/evm.rs | 0 {ethcore => crates/vm}/evm/src/factory.rs | 0 .../vm}/evm/src/instructions.rs | 0 .../vm}/evm/src/interpreter/gasometer.rs | 0 .../vm}/evm/src/interpreter/informant.rs | 0 .../vm}/evm/src/interpreter/memory.rs | 0 .../vm}/evm/src/interpreter/mod.rs | 0 .../vm}/evm/src/interpreter/shared_cache.rs | 0 .../vm}/evm/src/interpreter/stack.rs | 0 {ethcore => crates/vm}/evm/src/lib.rs | 0 {ethcore => crates/vm}/evm/src/tests.rs | 0 {ethcore => crates/vm}/evm/src/vmtype.rs | 0 {ethcore => crates/vm}/vm/Cargo.toml | 4 +- {ethcore => crates/vm}/vm/src/access_list.rs | 0 .../vm}/vm/src/action_params.rs | 0 {ethcore => crates/vm}/vm/src/call_type.rs | 0 {ethcore => crates/vm}/vm/src/env_info.rs | 0 {ethcore => crates/vm}/vm/src/error.rs | 0 {ethcore => crates/vm}/vm/src/ext.rs | 0 {ethcore => crates/vm}/vm/src/lib.rs | 0 {ethcore => crates/vm}/vm/src/return_data.rs | 0 {ethcore => crates/vm}/vm/src/schedule.rs | 0 {ethcore => crates/vm}/vm/src/tests.rs | 0 {ethcore => crates/vm}/wasm/Cargo.toml | 0 {ethcore => crates/vm}/wasm/src/env.rs | 0 {ethcore => crates/vm}/wasm/src/lib.rs | 3 - .../vm}/wasm/src/panic_payload.rs | 0 {ethcore => crates/vm}/wasm/src/parser.rs | 0 {ethcore => crates/vm}/wasm/src/runtime.rs | 0 ethcore/res/ethereum/runner/full.json | 60 - .../res/ethereum/tests-issues/currents.json | 4 - ethcore/res/wasm-tests | 1 - ethcore/wasm/run/Cargo.toml | 20 - ethcore/wasm/run/res/sample-fixture.json | 45 - ethcore/wasm/run/res/sample1.wasm | Bin 125 -> 0 bytes ethcore/wasm/run/res/sample2.wasm | Bin 15410 -> 0 bytes ethcore/wasm/run/res/sample3.wasm | Bin 9736 -> 0 bytes ethcore/wasm/run/src/fixture.rs | 88 - ethcore/wasm/run/src/main.rs | 71 - ethcore/wasm/run/src/runner.rs | 345 --- ethcore/wasm/src/tests.rs | 1181 --------- scripts/add_license.sh | 20 - scripts/doc.sh | 5 - scripts/evm_jsontests_bench.sh | 24 +- scripts/hook.sh | 12 - scripts/remove_duplicate_empty_lines.sh | 6 - secret-store/Cargo.toml | 49 - secret-store/res/acl_storage.json | 3 - secret-store/res/key_server_set.json | 24 - secret-store/res/service.json | 33 - secret-store/src/acl_storage.rs | 172 -- secret-store/src/helpers.rs | 30 - secret-store/src/key_server.rs | 809 ------ .../key_version_negotiation_session.rs | 1258 ---------- .../key_server_cluster/admin_sessions/mod.rs | 55 - .../servers_set_change_session.rs | 1832 -------------- .../admin_sessions/sessions_queue.rs | 58 - .../admin_sessions/share_add_session.rs | 1463 ----------- .../admin_sessions/share_change_session.rs | 431 ---- .../client_sessions/decryption_session.rs | 2211 ----------------- .../client_sessions/encryption_session.rs | 415 ---- .../client_sessions/generation_session.rs | 1571 ------------ .../key_server_cluster/client_sessions/mod.rs | 21 - .../client_sessions/signing_session_ecdsa.rs | 1626 ------------ .../signing_session_schnorr.rs | 1478 ----------- .../src/key_server_cluster/cluster.rs | 1805 -------------- .../key_server_cluster/cluster_connections.rs | 180 -- .../cluster_connections_net.rs | 588 ----- .../cluster_message_processor.rs | 429 ---- .../key_server_cluster/cluster_sessions.rs | 937 ------- .../cluster_sessions_creator.rs | 678 ----- .../key_server_cluster/connection_trigger.rs | 519 ---- .../connection_trigger_with_migration.rs | 1123 --------- .../src/key_server_cluster/io/deadline.rs | 91 - .../src/key_server_cluster/io/handshake.rs | 533 ---- .../src/key_server_cluster/io/message.rs | 673 ----- secret-store/src/key_server_cluster/io/mod.rs | 38 - .../src/key_server_cluster/io/read_header.rs | 55 - .../src/key_server_cluster/io/read_message.rs | 98 - .../src/key_server_cluster/io/read_payload.rs | 77 - .../io/shared_tcp_stream.rs | 71 - .../key_server_cluster/io/write_message.rs | 85 - .../jobs/consensus_session.rs | 1395 ----------- .../key_server_cluster/jobs/decryption_job.rs | 265 -- .../src/key_server_cluster/jobs/dummy_job.rs | 68 - .../key_server_cluster/jobs/job_session.rs | 1043 -------- .../key_server_cluster/jobs/key_access_job.rs | 130 - .../src/key_server_cluster/jobs/mod.rs | 25 - .../jobs/servers_set_change_access_job.rs | 206 -- .../jobs/signing_job_ecdsa.rs | 193 -- .../jobs/signing_job_schnorr.rs | 194 -- .../jobs/unknown_sessions_job.rs | 108 - secret-store/src/key_server_cluster/math.rs | 1574 ------------ .../src/key_server_cluster/message.rs | 1675 ------------- secret-store/src/key_server_cluster/mod.rs | 92 - .../net/accept_connection.rs | 69 - .../src/key_server_cluster/net/connect.rs | 95 - .../src/key_server_cluster/net/connection.rs | 31 - .../src/key_server_cluster/net/mod.rs | 25 - secret-store/src/key_server_set.rs | 982 -------- secret-store/src/key_storage.rs | 738 ------ secret-store/src/lib.rs | 250 -- secret-store/src/listener/http_listener.rs | 634 ----- secret-store/src/listener/mod.rs | 172 -- secret-store/src/listener/service_contract.rs | 1365 ---------- .../listener/service_contract_aggregate.rs | 161 -- .../src/listener/service_contract_listener.rs | 1971 --------------- secret-store/src/listener/tasks_queue.rs | 82 - secret-store/src/node_key_pair.rs | 124 - secret-store/src/serialization.rs | 195 -- secret-store/src/traits.rs | 150 -- secret-store/src/trusted_client.rs | 126 - secret-store/src/types/all.rs | 156 -- secret-store/src/types/error.rs | 213 -- secret-store/src/types/mod.rs | 22 - .../key_server_cluster/cluster_connections.rs | 176 -- .../cluster_connections_net.rs | 539 ---- .../cluster_message_processor.rs | 357 --- util/registrar/Cargo.toml | 13 - util/registrar/res/registrar.json | 21 - util/registrar/src/lib.rs | 27 - util/registrar/src/registrar.rs | 78 - 846 files changed, 255 insertions(+), 39400 deletions(-) rename {chainspec => bin/chainspec}/Cargo.toml (80%) rename {chainspec => bin/chainspec}/src/main.rs (100%) rename {accounts/ethkey/cli => bin/ethkey}/Cargo.toml (76%) rename {accounts/ethkey/cli => bin/ethkey}/src/main.rs (100%) rename {accounts/ethstore/cli => bin/ethstore}/Cargo.toml (72%) rename {accounts/ethstore/cli => bin/ethstore}/src/crack.rs (100%) rename {accounts/ethstore/cli => bin/ethstore}/src/main.rs (100%) rename {evmbin => bin/evmbin}/Cargo.toml (57%) rename {evmbin => bin/evmbin}/README.md (100%) rename {evmbin => bin/evmbin}/benches/mod.rs (100%) rename {evmbin => bin/evmbin}/res/testchain.json (100%) rename {evmbin => bin/evmbin}/src/display/config.rs (100%) rename {evmbin => bin/evmbin}/src/display/json.rs (100%) rename {evmbin => bin/evmbin}/src/display/mod.rs (100%) rename {evmbin => bin/evmbin}/src/display/simple.rs (100%) rename {evmbin => bin/evmbin}/src/display/std_json.rs (100%) rename {evmbin => bin/evmbin}/src/info.rs (100%) rename {evmbin => bin/evmbin}/src/main.rs (100%) rename {parity => bin/oe}/account.rs (100%) rename {parity => bin/oe}/account_utils.rs (100%) rename {parity => bin/oe}/blockchain.rs (100%) rename {parity => bin/oe}/cache.rs (100%) rename {parity => bin/oe}/cli/mod.rs (100%) rename {parity => bin/oe}/cli/presets/config.dev-insecure.toml (100%) rename {parity => bin/oe}/cli/presets/config.dev.toml (100%) rename {parity => bin/oe}/cli/presets/config.insecure.toml (100%) rename {parity => bin/oe}/cli/presets/config.mining.toml (100%) rename {parity => bin/oe}/cli/presets/config.non-standard-ports.toml (100%) rename {parity => bin/oe}/cli/presets/mod.rs (100%) rename {parity => bin/oe}/cli/tests/config.full.toml (100%) rename {parity => bin/oe}/cli/tests/config.invalid1.toml (100%) rename {parity => bin/oe}/cli/tests/config.invalid2.toml (100%) rename {parity => bin/oe}/cli/tests/config.invalid3.toml (100%) rename {parity => bin/oe}/cli/tests/config.invalid4.toml (100%) rename {parity => bin/oe}/cli/tests/config.toml (100%) rename {parity => bin/oe}/cli/usage.rs (100%) rename {parity => bin/oe}/cli/usage_header.txt (100%) rename {parity => bin/oe}/cli/version.txt (100%) rename {parity => bin/oe}/configuration.rs (100%) rename {parity => bin/oe}/db/mod.rs (100%) rename {parity => bin/oe}/db/rocksdb/blooms.rs (100%) rename {parity => bin/oe}/db/rocksdb/helpers.rs (100%) rename {parity => bin/oe}/db/rocksdb/migration.rs (100%) rename {parity => bin/oe}/db/rocksdb/mod.rs (100%) rename {parity => bin/oe}/helpers.rs (100%) rename {parity => bin/oe}/informant.rs (100%) rename {parity => bin/oe}/lib.rs (99%) rename {parity => bin/oe}/logger/Cargo.toml (100%) rename {parity => bin/oe}/logger/src/lib.rs (100%) rename {parity => bin/oe}/logger/src/rotating.rs (100%) rename {parity => bin/oe}/main.rs (100%) rename {parity => bin/oe}/metrics.rs (100%) rename {parity => bin/oe}/modules.rs (100%) rename {parity => bin/oe}/params.rs (100%) rename {parity => bin/oe}/presale.rs (100%) rename {parity => bin/oe}/rpc.rs (100%) rename {parity => bin/oe}/rpc_apis.rs (100%) rename {parity => bin/oe}/run.rs (100%) rename {parity => bin/oe}/secretstore.rs (100%) rename {parity => bin/oe}/signer.rs (100%) rename {parity => bin/oe}/snapshot.rs (100%) rename {parity => bin/oe}/stratum.rs (100%) rename {parity => bin/oe}/upgrade.rs (100%) rename {parity => bin/oe}/user_defaults.rs (100%) rename {accounts => crates/accounts}/Cargo.toml (100%) rename {accounts => crates/accounts}/ethkey/.gitignore (100%) rename {accounts => crates/accounts}/ethkey/.travis.yml (100%) rename {accounts => crates/accounts}/ethkey/Cargo.toml (90%) rename {accounts => crates/accounts}/ethkey/README.md (100%) rename {accounts => crates/accounts}/ethkey/src/brain.rs (100%) rename {accounts => crates/accounts}/ethkey/src/brain_prefix.rs (100%) rename {accounts => crates/accounts}/ethkey/src/brain_recover.rs (100%) rename {accounts => crates/accounts}/ethkey/src/crypto.rs (100%) rename {accounts => crates/accounts}/ethkey/src/error.rs (100%) rename {accounts => crates/accounts}/ethkey/src/extended.rs (100%) rename {accounts => crates/accounts}/ethkey/src/keccak.rs (100%) rename {accounts => crates/accounts}/ethkey/src/keypair.rs (100%) rename {accounts => crates/accounts}/ethkey/src/lib.rs (100%) rename {accounts => crates/accounts}/ethkey/src/math.rs (100%) rename {accounts => crates/accounts}/ethkey/src/password.rs (100%) rename {accounts => crates/accounts}/ethkey/src/prefix.rs (100%) rename {accounts => crates/accounts}/ethkey/src/random.rs (100%) rename {accounts => crates/accounts}/ethkey/src/secret.rs (100%) rename {accounts => crates/accounts}/ethkey/src/signature.rs (100%) rename {accounts => crates/accounts}/ethstore/.editorconfig (100%) rename {accounts => crates/accounts}/ethstore/.gitignore (100%) rename {accounts => crates/accounts}/ethstore/.travis.yml (100%) rename {accounts => crates/accounts}/ethstore/Cargo.toml (100%) rename {accounts => crates/accounts}/ethstore/README.md (100%) rename {accounts => crates/accounts}/ethstore/src/account/cipher.rs (100%) rename {accounts => crates/accounts}/ethstore/src/account/crypto.rs (100%) rename {accounts => crates/accounts}/ethstore/src/account/kdf.rs (100%) rename {accounts => crates/accounts}/ethstore/src/account/mod.rs (100%) rename {accounts => crates/accounts}/ethstore/src/account/safe_account.rs (100%) rename {accounts => crates/accounts}/ethstore/src/account/version.rs (100%) rename {accounts => crates/accounts}/ethstore/src/accounts_dir/disk.rs (100%) rename {accounts => crates/accounts}/ethstore/src/accounts_dir/memory.rs (100%) rename {accounts => crates/accounts}/ethstore/src/accounts_dir/mod.rs (100%) rename {accounts => crates/accounts}/ethstore/src/accounts_dir/vault.rs (100%) rename {accounts => crates/accounts}/ethstore/src/error.rs (100%) rename {accounts => crates/accounts}/ethstore/src/ethkey.rs (100%) rename {accounts => crates/accounts}/ethstore/src/ethstore.rs (100%) rename {accounts => crates/accounts}/ethstore/src/import.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/bytes.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/cipher.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/crypto.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/error.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/hash.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/id.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/kdf.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/key_file.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/mod.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/presale.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/vault_file.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/vault_key_file.rs (100%) rename {accounts => crates/accounts}/ethstore/src/json/version.rs (100%) rename {accounts => crates/accounts}/ethstore/src/lib.rs (100%) rename {accounts => crates/accounts}/ethstore/src/presale.rs (100%) rename {accounts => crates/accounts}/ethstore/src/random.rs (100%) rename {accounts => crates/accounts}/ethstore/src/secret_store.rs (100%) rename {accounts => crates/accounts}/ethstore/tests/api.rs (100%) rename {accounts => crates/accounts}/ethstore/tests/res/ciphertext/30.json (100%) rename {accounts => crates/accounts}/ethstore/tests/res/ciphertext/31.json (100%) rename {accounts => crates/accounts}/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 (100%) rename {accounts => crates/accounts}/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf (100%) rename {accounts => crates/accounts}/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 (100%) rename {accounts => crates/accounts}/ethstore/tests/res/pat/p1.json (100%) rename {accounts => crates/accounts}/ethstore/tests/res/pat/p2.json (100%) rename {accounts => crates/accounts}/ethstore/tests/util/mod.rs (100%) rename {accounts => crates/accounts}/ethstore/tests/util/transient_dir.rs (100%) rename {accounts => crates/accounts}/src/account_data.rs (100%) rename {accounts => crates/accounts}/src/error.rs (100%) rename {accounts => crates/accounts}/src/lib.rs (100%) rename {accounts => crates/accounts}/src/stores.rs (100%) rename {ethash => crates/concensus/ethash}/Cargo.toml (100%) rename {ethash => crates/concensus/ethash}/benches/basic.rs (100%) rename {ethash => crates/concensus/ethash}/benches/progpow.rs (100%) rename {ethash => crates/concensus/ethash}/res/progpow_testvectors.json (100%) rename {ethash => crates/concensus/ethash}/src/cache.rs (100%) rename {ethash => crates/concensus/ethash}/src/compute.rs (100%) rename {ethash => crates/concensus/ethash}/src/keccak.rs (100%) rename {ethash => crates/concensus/ethash}/src/lib.rs (100%) rename {ethash => crates/concensus/ethash}/src/progpow.rs (100%) rename {ethash => crates/concensus/ethash}/src/seed_compute.rs (100%) rename {ethash => crates/concensus/ethash}/src/shared.rs (100%) rename {miner => crates/concensus/miner}/Cargo.toml (73%) rename {miner => crates/concensus/miner}/local-store/Cargo.toml (70%) rename {miner => crates/concensus/miner}/local-store/src/lib.rs (100%) rename {miner => crates/concensus/miner}/price-info/Cargo.toml (68%) rename {miner => crates/concensus/miner}/price-info/src/lib.rs (100%) rename {miner => crates/concensus/miner}/res/contracts/service_transaction.json (100%) rename {miner => crates/concensus/miner}/src/external.rs (100%) rename {miner => crates/concensus/miner}/src/gas_price_calibrator.rs (100%) rename {miner => crates/concensus/miner}/src/gas_pricer.rs (100%) rename {miner => crates/concensus/miner}/src/lib.rs (100%) rename {miner => crates/concensus/miner}/src/local_accounts.rs (100%) rename {miner => crates/concensus/miner}/src/pool/client.rs (100%) rename {miner => crates/concensus/miner}/src/pool/listener.rs (100%) rename {miner => crates/concensus/miner}/src/pool/local_transactions.rs (100%) rename {miner => crates/concensus/miner}/src/pool/mod.rs (100%) rename {miner => crates/concensus/miner}/src/pool/queue.rs (100%) rename {miner => crates/concensus/miner}/src/pool/ready.rs (100%) rename {miner => crates/concensus/miner}/src/pool/replace.rs (100%) rename {miner => crates/concensus/miner}/src/pool/res/big_transaction.data (100%) rename {miner => crates/concensus/miner}/src/pool/scoring.rs (100%) rename {miner => crates/concensus/miner}/src/pool/tests/client.rs (100%) rename {miner => crates/concensus/miner}/src/pool/tests/mod.rs (100%) rename {miner => crates/concensus/miner}/src/pool/tests/tx.rs (100%) rename {miner => crates/concensus/miner}/src/pool/verifier.rs (100%) rename {miner => crates/concensus/miner}/src/service_transaction_checker.rs (100%) rename {miner => crates/concensus/miner}/src/work_notify.rs (100%) rename {miner => crates/concensus/miner}/stratum/Cargo.toml (100%) rename {miner => crates/concensus/miner}/stratum/src/lib.rs (100%) rename {miner => crates/concensus/miner}/stratum/src/traits.rs (100%) rename {miner => crates/concensus/miner}/using-queue/Cargo.toml (100%) rename {miner => crates/concensus/miner}/using-queue/src/lib.rs (100%) rename {util => crates/db}/bloom/Cargo.toml (100%) rename {util => crates/db}/bloom/src/lib.rs (100%) rename {util => crates/db}/blooms-db/Cargo.toml (100%) rename {util => crates/db}/blooms-db/benches/blooms.rs (100%) rename {util => crates/db}/blooms-db/src/db.rs (100%) rename {util => crates/db}/blooms-db/src/file.rs (100%) rename {util => crates/db}/blooms-db/src/lib.rs (100%) rename {ethcore => crates/db}/db/Cargo.toml (90%) rename {ethcore => crates/db}/db/src/cache_manager.rs (100%) rename {ethcore => crates/db}/db/src/db.rs (100%) rename {ethcore => crates/db}/db/src/keys.rs (100%) rename {ethcore => crates/db}/db/src/lib.rs (100%) rename {util => crates/db}/journaldb/Cargo.toml (85%) rename {util => crates/db}/journaldb/src/archivedb.rs (100%) rename {util => crates/db}/journaldb/src/as_hash_db_impls.rs (100%) rename {util => crates/db}/journaldb/src/earlymergedb.rs (100%) rename {util => crates/db}/journaldb/src/lib.rs (100%) rename {util => crates/db}/journaldb/src/overlaydb.rs (100%) rename {util => crates/db}/journaldb/src/overlayrecentdb.rs (100%) rename {util => crates/db}/journaldb/src/refcounteddb.rs (100%) rename {util => crates/db}/journaldb/src/traits.rs (100%) rename {util => crates/db}/journaldb/src/util.rs (100%) rename {util => crates/db}/memory-db/.cargo_vcs_info.json (100%) rename {util => crates/db}/memory-db/Cargo.toml (100%) rename {util => crates/db}/memory-db/Cargo.toml.orig (100%) rename {util => crates/db}/memory-db/README.md (100%) rename {util => crates/db}/memory-db/benches/bench.rs (100%) rename {util => crates/db}/memory-db/src/lib.rs (100%) rename {util => crates/db}/migration-rocksdb/Cargo.toml (83%) rename {util => crates/db}/migration-rocksdb/src/lib.rs (100%) rename {util => crates/db}/migration-rocksdb/tests/tests.rs (100%) rename {util => crates/db}/patricia-trie-ethereum/Cargo.toml (86%) rename {util => crates/db}/patricia-trie-ethereum/src/lib.rs (100%) rename {util => crates/db}/patricia-trie-ethereum/src/rlp_node_codec.rs (100%) rename {ethcore => crates/ethcore}/Cargo.toml (78%) rename {ethcore => crates/ethcore}/benches/builtin.rs (100%) rename {ethcore => crates/ethcore}/blockchain/Cargo.toml (92%) rename {ethcore => crates/ethcore}/blockchain/src/best_block.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/block_info.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/blockchain.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/cache.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/config.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/generator.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/import_route.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/lib.rs (100%) rename {ethcore => crates/ethcore}/blockchain/src/update.rs (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/callisto.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/ellaism.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/ewc.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/foundation.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/goerli.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec}/instant_seal.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/kovan.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/mix.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/morden.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/musicoin.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/poacore.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/poasokol.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/rinkeby.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/ropsten.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/authority_round.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/authority_round_block_reward_contract.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/authority_round_empty_steps.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/basic_authority.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/berlin_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/builtin_multi_bench.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/builtin_one_activation_bench.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/byzantium_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/byzantium_to_constantinoplefixat5_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/constantinople_test.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/constructor.json (100%) rename {ethcore/res/tx_permission_tests => crates/ethcore/res/chainspec/test}/contract_ver_2_genesis.json (100%) rename {ethcore/res/tx_permission_tests => crates/ethcore/res/chainspec/test}/deprecated_contract_genesis.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/eip150_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/eip161_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/eip210_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/frontier_like_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/frontier_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/homestead_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/istanbul_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/kovan_wasm_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/mcip3_test.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/null.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/null_morden.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/null_morden_with_finality.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/null_morden_with_reward.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/spec_backward_compability.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/st_peters_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/transition_test.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/validator_contract.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/validator_multi.json (100%) rename {ethcore/res => crates/ethcore/res/chainspec/test}/validator_safe_contract.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec/test}/yolo3_test.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/volta.json (100%) rename {ethcore/res/ethereum => crates/ethcore/res/chainspec}/xdai.json (100%) rename {ethcore => crates/ethcore}/res/contracts/block_reward.json (100%) rename {ethcore => crates/ethcore}/res/contracts/registrar.json (99%) rename {ethcore => crates/ethcore}/res/contracts/test_validator_set.json (100%) rename {ethcore => crates/ethcore}/res/contracts/tx_acl.json (100%) rename {ethcore => crates/ethcore}/res/contracts/tx_acl_deprecated.json (100%) rename {ethcore => crates/ethcore}/res/contracts/validator_report.json (100%) rename {ethcore => crates/ethcore}/res/contracts/validator_set.json (100%) rename ethcore/res/ethereum/tests => crates/ethcore/res/json_tests (100%) create mode 100644 crates/ethcore/res/json_tests.json rename {ethcore => crates/ethcore}/service/Cargo.toml (88%) rename {ethcore => crates/ethcore}/service/src/error.rs (100%) rename {ethcore => crates/ethcore}/service/src/lib.rs (100%) rename {ethcore => crates/ethcore}/service/src/service.rs (100%) rename {ethcore => crates/ethcore}/service/src/stop_guard.rs (100%) rename {ethcore => crates/ethcore}/src/account_db.rs (100%) rename {ethcore => crates/ethcore}/src/block.rs (100%) rename {ethcore => crates/ethcore}/src/client/ancient_import.rs (100%) rename {ethcore => crates/ethcore}/src/client/bad_blocks.rs (100%) rename {ethcore => crates/ethcore}/src/client/chain_notify.rs (100%) rename {ethcore => crates/ethcore}/src/client/client.rs (100%) rename {ethcore => crates/ethcore}/src/client/config.rs (100%) rename {ethcore => crates/ethcore}/src/client/evm_test_client.rs (100%) rename {ethcore => crates/ethcore}/src/client/io_message.rs (100%) rename {ethcore => crates/ethcore}/src/client/mod.rs (100%) rename {ethcore => crates/ethcore}/src/client/test_client.rs (100%) rename {ethcore => crates/ethcore}/src/client/trace.rs (100%) rename {ethcore => crates/ethcore}/src/client/traits.rs (100%) rename {ethcore => crates/ethcore}/src/engines/authority_round/finality.rs (100%) rename {ethcore => crates/ethcore}/src/engines/authority_round/mod.rs (100%) rename {ethcore => crates/ethcore}/src/engines/basic_authority.rs (99%) rename {ethcore => crates/ethcore}/src/engines/block_reward.rs (100%) rename {ethcore => crates/ethcore}/src/engines/clique/block_state.rs (100%) rename {ethcore => crates/ethcore}/src/engines/clique/mod.rs (100%) rename {ethcore => crates/ethcore}/src/engines/clique/params.rs (100%) rename {ethcore => crates/ethcore}/src/engines/clique/tests.rs (100%) rename {ethcore => crates/ethcore}/src/engines/clique/util.rs (100%) rename {ethcore => crates/ethcore}/src/engines/instant_seal.rs (100%) rename {ethcore => crates/ethcore}/src/engines/mod.rs (100%) rename {ethcore => crates/ethcore}/src/engines/null_engine.rs (100%) rename {ethcore => crates/ethcore}/src/engines/signer.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/contract.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/mod.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/multi.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/safe_contract.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/simple_list.rs (100%) rename {ethcore => crates/ethcore}/src/engines/validator_set/test.rs (100%) rename {ethcore => crates/ethcore}/src/error.rs (100%) rename {ethcore => crates/ethcore}/src/ethereum/denominations.rs (100%) rename {ethcore => crates/ethcore}/src/ethereum/ethash.rs (100%) rename {ethcore => crates/ethcore}/src/ethereum/mod.rs (78%) rename {ethcore => crates/ethcore}/src/executed.rs (100%) rename {ethcore => crates/ethcore}/src/executive.rs (100%) rename {ethcore => crates/ethcore}/src/externalities.rs (100%) rename {ethcore => crates/ethcore}/src/factory.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/chain.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/difficulty.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/executive.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/mod.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/runner.rs (99%) rename {ethcore => crates/ethcore}/src/json_tests/skip.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/state.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/test_common.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/transaction.rs (100%) rename {ethcore => crates/ethcore}/src/json_tests/trie.rs (100%) rename {ethcore => crates/ethcore}/src/lib.rs (100%) rename {ethcore => crates/ethcore}/src/machine/impls.rs (100%) rename {ethcore => crates/ethcore}/src/machine/mod.rs (100%) rename {ethcore => crates/ethcore}/src/machine/traits.rs (100%) rename {ethcore => crates/ethcore}/src/miner/miner.rs (100%) rename {ethcore => crates/ethcore}/src/miner/mod.rs (100%) rename {ethcore => crates/ethcore}/src/miner/pool_client.rs (100%) rename {ethcore => crates/ethcore}/src/miner/stratum.rs (100%) rename {ethcore => crates/ethcore}/src/pod_account.rs (100%) rename {ethcore => crates/ethcore}/src/pod_state.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/account.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/block.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/consensus/authority.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/consensus/mod.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/consensus/work.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/error.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/io.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/mod.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/service.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/helpers.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/mod.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/proof_of_authority.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/proof_of_work.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/service.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/state.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/tests/test_validator_contract.json (100%) rename {ethcore => crates/ethcore}/src/snapshot/traits.rs (100%) rename {ethcore => crates/ethcore}/src/snapshot/watcher.rs (100%) rename {ethcore => crates/ethcore}/src/spec/genesis.rs (100%) rename {ethcore => crates/ethcore}/src/spec/mod.rs (100%) rename {ethcore => crates/ethcore}/src/spec/seal.rs (100%) rename {ethcore => crates/ethcore}/src/spec/spec.rs (98%) rename {ethcore => crates/ethcore}/src/state/account.rs (100%) rename {ethcore => crates/ethcore}/src/state/backend.rs (100%) rename {ethcore => crates/ethcore}/src/state/mod.rs (100%) rename {ethcore => crates/ethcore}/src/state/substate.rs (100%) rename {ethcore => crates/ethcore}/src/state_db.rs (100%) rename {ethcore => crates/ethcore}/src/test_helpers.rs (100%) rename {ethcore => crates/ethcore}/src/tests/blockchain.rs (100%) rename {ethcore => crates/ethcore}/src/tests/client.rs (100%) rename {ethcore => crates/ethcore}/src/tests/evm.rs (100%) rename {ethcore => crates/ethcore}/src/tests/mod.rs (100%) rename {ethcore => crates/ethcore}/src/tests/trace.rs (100%) rename {ethcore => crates/ethcore}/src/trace/config.rs (100%) rename {ethcore => crates/ethcore}/src/trace/db.rs (100%) rename {ethcore => crates/ethcore}/src/trace/executive_tracer.rs (100%) rename {ethcore => crates/ethcore}/src/trace/import.rs (100%) rename {ethcore => crates/ethcore}/src/trace/mod.rs (100%) rename {ethcore => crates/ethcore}/src/trace/noop_tracer.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/error.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/filter.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/flat.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/localized.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/mod.rs (100%) rename {ethcore => crates/ethcore}/src/trace/types/trace.rs (100%) rename {ethcore => crates/ethcore}/src/transaction_ext.rs (100%) rename {ethcore => crates/ethcore}/src/tx_filter.rs (98%) rename {ethcore => crates/ethcore}/src/verification/canon_verifier.rs (100%) rename {ethcore => crates/ethcore}/src/verification/mod.rs (100%) rename {ethcore => crates/ethcore}/src/verification/noop_verifier.rs (100%) rename {ethcore => crates/ethcore}/src/verification/queue/kind.rs (100%) rename {ethcore => crates/ethcore}/src/verification/queue/mod.rs (100%) rename {ethcore => crates/ethcore}/src/verification/verification.rs (100%) rename {ethcore => crates/ethcore}/src/verification/verifier.rs (100%) rename {ethcore => crates/ethcore}/sync/Cargo.toml (88%) rename {ethcore => crates/ethcore}/sync/src/api.rs (100%) rename {ethcore => crates/ethcore}/sync/src/block_sync.rs (100%) rename {ethcore => crates/ethcore}/sync/src/blocks.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/fork_filter.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/handler.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/mod.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/propagator.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/requester.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/supplier.rs (100%) rename {ethcore => crates/ethcore}/sync/src/chain/sync_packet.rs (100%) rename {ethcore => crates/ethcore}/sync/src/lib.rs (100%) rename {ethcore => crates/ethcore}/sync/src/res/private_spec.json (100%) rename {ethcore => crates/ethcore}/sync/src/snapshot.rs (100%) rename {ethcore => crates/ethcore}/sync/src/sync_io.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/chain.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/consensus.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/helpers.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/mod.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/rpc.rs (100%) rename {ethcore => crates/ethcore}/sync/src/tests/snapshot.rs (100%) rename {ethcore => crates/ethcore}/sync/src/transactions_stats.rs (100%) rename {ethcore => crates/ethcore}/types/Cargo.toml (93%) rename {ethcore => crates/ethcore}/types/src/account_diff.rs (100%) rename {ethcore => crates/ethcore}/types/src/ancestry_action.rs (100%) rename {ethcore => crates/ethcore}/types/src/basic_account.rs (100%) rename {ethcore => crates/ethcore}/types/src/block.rs (100%) rename {ethcore => crates/ethcore}/types/src/block_status.rs (100%) rename {ethcore => crates/ethcore}/types/src/blockchain_info.rs (100%) rename {ethcore => crates/ethcore}/types/src/call_analytics.rs (100%) rename {ethcore => crates/ethcore}/types/src/creation_status.rs (100%) rename {ethcore => crates/ethcore}/types/src/data_format.rs (100%) rename {ethcore => crates/ethcore}/types/src/encoded.rs (100%) rename {ethcore => crates/ethcore}/types/src/engines/epoch.rs (100%) rename {ethcore => crates/ethcore}/types/src/engines/mod.rs (100%) rename {ethcore => crates/ethcore}/types/src/filter.rs (100%) rename {ethcore => crates/ethcore}/types/src/header.rs (100%) rename {ethcore => crates/ethcore}/types/src/ids.rs (100%) rename {ethcore => crates/ethcore}/types/src/lib.rs (100%) rename {ethcore => crates/ethcore}/types/src/log_entry.rs (100%) rename {ethcore => crates/ethcore}/types/src/pruning_info.rs (100%) rename {ethcore => crates/ethcore}/types/src/receipt.rs (100%) rename {ethcore => crates/ethcore}/types/src/restoration_status.rs (100%) rename {ethcore => crates/ethcore}/types/src/security_level.rs (100%) rename {ethcore => crates/ethcore}/types/src/snapshot_manifest.rs (100%) rename {ethcore => crates/ethcore}/types/src/state_diff.rs (100%) rename {ethcore => crates/ethcore}/types/src/trace_filter.rs (100%) rename {ethcore => crates/ethcore}/types/src/transaction/error.rs (100%) rename {ethcore => crates/ethcore}/types/src/transaction/mod.rs (100%) rename {ethcore => crates/ethcore}/types/src/transaction/transaction.rs (100%) rename {ethcore => crates/ethcore}/types/src/transaction/transaction_id.rs (100%) rename {ethcore => crates/ethcore}/types/src/tree_route.rs (100%) rename {ethcore => crates/ethcore}/types/src/verification_queue_info.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/block.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/body.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/header.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/mod.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/transaction.rs (100%) rename {ethcore => crates/ethcore}/types/src/views/view_rlp.rs (100%) rename {json => crates/ethjson}/Cargo.toml (100%) rename {json => crates/ethjson}/src/blockchain/account.rs (100%) rename {json => crates/ethjson}/src/blockchain/block.rs (100%) rename {json => crates/ethjson}/src/blockchain/blockchain.rs (100%) rename {json => crates/ethjson}/src/blockchain/header.rs (100%) rename {json => crates/ethjson}/src/blockchain/mod.rs (100%) rename {json => crates/ethjson}/src/blockchain/state.rs (99%) rename {json => crates/ethjson}/src/blockchain/test.rs (100%) rename {json => crates/ethjson}/src/blockchain/transaction.rs (100%) rename {json => crates/ethjson}/src/bytes.rs (100%) rename {json => crates/ethjson}/src/hash.rs (100%) rename {json => crates/ethjson}/src/lib.rs (100%) rename {json => crates/ethjson}/src/maybe.rs (100%) rename {json => crates/ethjson}/src/spec/account.rs (100%) rename {json => crates/ethjson}/src/spec/authority_round.rs (100%) rename {json => crates/ethjson}/src/spec/basic_authority.rs (100%) rename {json => crates/ethjson}/src/spec/builtin.rs (100%) rename {json => crates/ethjson}/src/spec/clique.rs (100%) rename {json => crates/ethjson}/src/spec/engine.rs (100%) rename {json => crates/ethjson}/src/spec/ethash.rs (100%) rename {json => crates/ethjson}/src/spec/genesis.rs (100%) rename {json => crates/ethjson}/src/spec/instant_seal.rs (100%) rename {json => crates/ethjson}/src/spec/mod.rs (100%) rename {json => crates/ethjson}/src/spec/null_engine.rs (100%) rename {json => crates/ethjson}/src/spec/params.rs (100%) rename {json => crates/ethjson}/src/spec/seal.rs (100%) rename {json => crates/ethjson}/src/spec/spec.rs (100%) rename {json => crates/ethjson}/src/spec/state.rs (100%) rename {json => crates/ethjson}/src/spec/validator_set.rs (100%) rename {json => crates/ethjson}/src/state/log.rs (100%) rename {json => crates/ethjson}/src/state/mod.rs (100%) rename {json => crates/ethjson}/src/state/state.rs (100%) rename {json => crates/ethjson}/src/state/test.rs (100%) rename {json => crates/ethjson}/src/state/transaction.rs (100%) rename {json => crates/ethjson}/src/test/mod.rs (100%) rename {json => crates/ethjson}/src/transaction/mod.rs (100%) rename {json => crates/ethjson}/src/transaction/test.rs (100%) rename {json => crates/ethjson}/src/transaction/transaction.rs (100%) rename {json => crates/ethjson}/src/transaction/txtest.rs (100%) rename {json => crates/ethjson}/src/trie/input.rs (100%) rename {json => crates/ethjson}/src/trie/mod.rs (100%) rename {json => crates/ethjson}/src/trie/test.rs (100%) rename {json => crates/ethjson}/src/trie/trie.rs (100%) rename {json => crates/ethjson}/src/uint.rs (100%) rename {json => crates/ethjson}/src/vm/call.rs (100%) rename {json => crates/ethjson}/src/vm/env.rs (100%) rename {json => crates/ethjson}/src/vm/mod.rs (100%) rename {json => crates/ethjson}/src/vm/test.rs (100%) rename {json => crates/ethjson}/src/vm/transaction.rs (100%) rename {json => crates/ethjson}/src/vm/vm.rs (100%) rename {util => crates/net}/fake-fetch/Cargo.toml (100%) rename {util => crates/net}/fake-fetch/src/lib.rs (100%) rename {util => crates/net}/fetch/Cargo.toml (100%) rename {util => crates/net}/fetch/src/client.rs (100%) rename {util => crates/net}/fetch/src/lib.rs (100%) rename {util => crates/net}/network-devp2p/Cargo.toml (89%) rename {util => crates/net}/network-devp2p/src/connection.rs (100%) rename {util => crates/net}/network-devp2p/src/discovery.rs (100%) rename {util => crates/net}/network-devp2p/src/handshake.rs (100%) rename {util => crates/net}/network-devp2p/src/host.rs (100%) rename {util => crates/net}/network-devp2p/src/ip_utils.rs (100%) rename {util => crates/net}/network-devp2p/src/lib.rs (100%) rename {util => crates/net}/network-devp2p/src/node_table.rs (100%) rename {util => crates/net}/network-devp2p/src/service.rs (100%) rename {util => crates/net}/network-devp2p/src/session.rs (100%) rename {util => crates/net}/network-devp2p/tests/tests.rs (100%) rename {util => crates/net}/network/Cargo.toml (86%) rename {util => crates/net}/network/src/client_version.rs (100%) rename {util => crates/net}/network/src/connection_filter.rs (100%) rename {util => crates/net}/network/src/error.rs (100%) rename {util => crates/net}/network/src/lib.rs (100%) rename {ethcore => crates/net}/node-filter/Cargo.toml (64%) rename {ethcore => crates/net}/node-filter/res/node_filter.json (100%) rename {ethcore => crates/net}/node-filter/res/peer_set.json (100%) rename {ethcore => crates/net}/node-filter/src/lib.rs (100%) rename {rpc => crates/rpc}/Cargo.toml (75%) rename {rpc => crates/rpc}/src/authcodes.rs (100%) rename {rpc => crates/rpc}/src/http_common.rs (100%) rename {rpc => crates/rpc}/src/lib.rs (100%) rename {rpc => crates/rpc}/src/tests/helpers.rs (100%) rename {rpc => crates/rpc}/src/tests/http_client.rs (100%) rename {rpc => crates/rpc}/src/tests/mod.rs (100%) rename {rpc => crates/rpc}/src/tests/rpc.rs (100%) rename {rpc => crates/rpc}/src/tests/ws.rs (100%) rename {rpc => crates/rpc}/src/v1/extractors.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/block_import.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/deprecated.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/dispatch/full.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/dispatch/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/dispatch/prospective_signer.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/dispatch/signing.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/eip191.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/engine_signer.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/errors.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/external_signer/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/external_signer/oneshot.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/external_signer/signing_queue.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/fake_sign.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/network_settings.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/nonce.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/poll_filter.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/poll_manager.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/requests.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/secretstore.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/signature.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/subscribers.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/subscription_manager.rs (100%) rename {rpc => crates/rpc}/src/v1/helpers/work.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/debug.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/eth.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/eth_filter.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/eth_pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/net.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/parity.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/parity_accounts.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/parity_set.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/personal.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/secretstore.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/signer.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/signing.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/signing_unsafe.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/traces.rs (100%) rename {rpc => crates/rpc}/src/v1/impls/web3.rs (100%) rename {rpc => crates/rpc}/src/v1/informant.rs (100%) rename {rpc => crates/rpc}/src/v1/metadata.rs (100%) rename {rpc => crates/rpc}/src/v1/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/eth.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/helpers/miner_service.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/helpers/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/helpers/snapshot_service.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/helpers/sync_provider.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/debug.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/eth.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/eth_pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/manage_network.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/net.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/parity.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/parity_accounts.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/parity_set.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/personal.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/secretstore.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/signer.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/signing.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/signing_unsafe.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/traces.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mocked/web3.rs (100%) rename {rpc => crates/rpc}/src/v1/tests/mod.rs (93%) rename {rpc => crates/rpc}/src/v1/traits/debug.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/eth.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/eth_pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/eth_signing.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/net.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/parity.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/parity_accounts.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/parity_set.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/parity_signing.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/personal.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/secretstore.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/signer.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/traces.rs (100%) rename {rpc => crates/rpc}/src/v1/traits/web3.rs (100%) rename {rpc => crates/rpc}/src/v1/types/account_info.rs (100%) rename {rpc => crates/rpc}/src/v1/types/block.rs (100%) rename {rpc => crates/rpc}/src/v1/types/block_number.rs (100%) rename {rpc => crates/rpc}/src/v1/types/bytes.rs (100%) rename {rpc => crates/rpc}/src/v1/types/call_request.rs (100%) rename {rpc => crates/rpc}/src/v1/types/confirmations.rs (100%) rename {rpc => crates/rpc}/src/v1/types/derivation.rs (100%) rename {rpc => crates/rpc}/src/v1/types/eip191.rs (100%) rename {rpc => crates/rpc}/src/v1/types/eth_types.rs (100%) rename {rpc => crates/rpc}/src/v1/types/filter.rs (100%) rename {rpc => crates/rpc}/src/v1/types/histogram.rs (100%) rename {rpc => crates/rpc}/src/v1/types/index.rs (100%) rename {rpc => crates/rpc}/src/v1/types/log.rs (100%) rename {rpc => crates/rpc}/src/v1/types/mod.rs (100%) rename {rpc => crates/rpc}/src/v1/types/node_kind.rs (100%) rename {rpc => crates/rpc}/src/v1/types/provenance.rs (100%) rename {rpc => crates/rpc}/src/v1/types/pubsub.rs (100%) rename {rpc => crates/rpc}/src/v1/types/receipt.rs (100%) rename {rpc => crates/rpc}/src/v1/types/rpc_settings.rs (100%) rename {rpc => crates/rpc}/src/v1/types/secretstore.rs (100%) rename {rpc => crates/rpc}/src/v1/types/sync.rs (100%) rename {rpc => crates/rpc}/src/v1/types/trace.rs (100%) rename {rpc => crates/rpc}/src/v1/types/trace_filter.rs (100%) rename {rpc => crates/rpc}/src/v1/types/transaction.rs (100%) rename {rpc => crates/rpc}/src/v1/types/transaction_condition.rs (100%) rename {rpc => crates/rpc}/src/v1/types/transaction_request.rs (100%) rename {rpc => crates/rpc}/src/v1/types/work.rs (100%) rename {util => crates/runtime}/io/Cargo.toml (100%) rename {util => crates/runtime}/io/src/lib.rs (100%) rename {util => crates/runtime}/io/src/service_mio.rs (100%) rename {util => crates/runtime}/io/src/service_non_mio.rs (100%) rename {util => crates/runtime}/io/src/worker.rs (100%) rename {util => crates/runtime}/runtime/Cargo.toml (100%) rename {util => crates/runtime}/runtime/src/lib.rs (100%) rename {util => crates/util}/EIP-152/Cargo.toml (100%) rename {util => crates/util}/EIP-152/src/lib.rs (100%) rename {util => crates/util}/EIP-712/Cargo.toml (100%) rename {util => crates/util}/EIP-712/README.md (100%) rename {util => crates/util}/EIP-712/src/eip712.rs (100%) rename {util => crates/util}/EIP-712/src/encode.rs (100%) rename {util => crates/util}/EIP-712/src/error.rs (100%) rename {util => crates/util}/EIP-712/src/lib.rs (100%) rename {util => crates/util}/EIP-712/src/parser.rs (100%) rename {cli-signer => crates/util/cli-signer}/Cargo.toml (90%) rename {cli-signer => crates/util/cli-signer}/rpc-client/Cargo.toml (91%) rename {cli-signer => crates/util/cli-signer}/rpc-client/src/client.rs (100%) rename {cli-signer => crates/util/cli-signer}/rpc-client/src/lib.rs (100%) rename {cli-signer => crates/util/cli-signer}/rpc-client/src/signer_client.rs (100%) rename {cli-signer => crates/util/cli-signer}/src/lib.rs (100%) rename {util => crates/util}/dir/Cargo.toml (83%) rename {util => crates/util}/dir/src/helpers.rs (100%) rename {util => crates/util}/dir/src/lib.rs (100%) rename {util => crates/util}/fastmap/Cargo.toml (100%) rename {util => crates/util}/fastmap/src/lib.rs (100%) rename {util => crates/util}/keccak-hasher/Cargo.toml (100%) rename {util => crates/util}/keccak-hasher/src/lib.rs (100%) rename {util => crates/util}/len-caching-lock/Cargo.toml (100%) rename {util => crates/util}/len-caching-lock/src/lib.rs (100%) rename {util => crates/util}/len-caching-lock/src/mutex.rs (100%) rename {util => crates/util}/len-caching-lock/src/rwlock.rs (100%) rename {util => crates/util}/macros/Cargo.toml (100%) rename {util => crates/util}/macros/src/lib.rs (100%) rename {util => crates/util}/memory-cache/Cargo.toml (100%) rename {util => crates/util}/memory-cache/src/lib.rs (100%) rename {util => crates/util}/memzero/Cargo.toml (100%) rename {util => crates/util}/memzero/src/lib.rs (100%) rename {util => crates/util}/panic-hook/Cargo.toml (100%) rename {util => crates/util}/panic-hook/src/lib.rs (100%) rename {util => crates/util}/rlp-compress/Cargo.toml (100%) rename {util => crates/util}/rlp-compress/src/common.rs (100%) rename {util => crates/util}/rlp-compress/src/lib.rs (100%) rename {util => crates/util}/rlp-compress/tests/compress.rs (100%) rename {util => crates/util}/rlp-derive/Cargo.toml (100%) rename {util => crates/util}/rlp-derive/src/de.rs (100%) rename {util => crates/util}/rlp-derive/src/en.rs (100%) rename {util => crates/util}/rlp-derive/src/lib.rs (100%) rename {util => crates/util}/rlp-derive/tests/rlp.rs (100%) rename {util => crates/util}/stats/Cargo.toml (100%) rename {util => crates/util}/stats/src/lib.rs (100%) rename {util => crates/util}/time-utils/Cargo.toml (100%) rename {util => crates/util}/time-utils/src/lib.rs (100%) rename {util => crates/util}/triehash-ethereum/Cargo.toml (100%) rename {util => crates/util}/triehash-ethereum/src/lib.rs (100%) rename {util => crates/util}/unexpected/Cargo.toml (100%) rename {util => crates/util}/unexpected/src/lib.rs (100%) rename {util => crates/util}/version/Cargo.toml (100%) rename {util => crates/util}/version/build.rs (100%) rename {util => crates/util}/version/src/lib.rs (100%) rename {ethcore => crates/vm}/builtin/Cargo.toml (95%) rename {ethcore => crates/vm}/builtin/src/lib.rs (100%) rename {ethcore => crates/vm}/call-contract/Cargo.toml (83%) rename {ethcore => crates/vm}/call-contract/src/call_contract.rs (100%) rename {ethcore => crates/vm}/call-contract/src/lib.rs (100%) rename {ethcore => crates/vm}/evm/Cargo.toml (100%) rename {ethcore => crates/vm}/evm/benches/basic.rs (100%) rename {ethcore => crates/vm}/evm/src/evm.rs (100%) rename {ethcore => crates/vm}/evm/src/factory.rs (100%) rename {ethcore => crates/vm}/evm/src/instructions.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/gasometer.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/informant.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/memory.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/mod.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/shared_cache.rs (100%) rename {ethcore => crates/vm}/evm/src/interpreter/stack.rs (100%) rename {ethcore => crates/vm}/evm/src/lib.rs (100%) rename {ethcore => crates/vm}/evm/src/tests.rs (100%) rename {ethcore => crates/vm}/evm/src/vmtype.rs (100%) rename {ethcore => crates/vm}/vm/Cargo.toml (72%) rename {ethcore => crates/vm}/vm/src/access_list.rs (100%) rename {ethcore => crates/vm}/vm/src/action_params.rs (100%) rename {ethcore => crates/vm}/vm/src/call_type.rs (100%) rename {ethcore => crates/vm}/vm/src/env_info.rs (100%) rename {ethcore => crates/vm}/vm/src/error.rs (100%) rename {ethcore => crates/vm}/vm/src/ext.rs (100%) rename {ethcore => crates/vm}/vm/src/lib.rs (100%) rename {ethcore => crates/vm}/vm/src/return_data.rs (100%) rename {ethcore => crates/vm}/vm/src/schedule.rs (100%) rename {ethcore => crates/vm}/vm/src/tests.rs (100%) rename {ethcore => crates/vm}/wasm/Cargo.toml (100%) rename {ethcore => crates/vm}/wasm/src/env.rs (100%) rename {ethcore => crates/vm}/wasm/src/lib.rs (99%) rename {ethcore => crates/vm}/wasm/src/panic_payload.rs (100%) rename {ethcore => crates/vm}/wasm/src/parser.rs (100%) rename {ethcore => crates/vm}/wasm/src/runtime.rs (100%) delete mode 100644 ethcore/res/ethereum/runner/full.json delete mode 100644 ethcore/res/ethereum/tests-issues/currents.json delete mode 160000 ethcore/res/wasm-tests delete mode 100644 ethcore/wasm/run/Cargo.toml delete mode 100644 ethcore/wasm/run/res/sample-fixture.json delete mode 100644 ethcore/wasm/run/res/sample1.wasm delete mode 100644 ethcore/wasm/run/res/sample2.wasm delete mode 100644 ethcore/wasm/run/res/sample3.wasm delete mode 100644 ethcore/wasm/run/src/fixture.rs delete mode 100644 ethcore/wasm/run/src/main.rs delete mode 100644 ethcore/wasm/run/src/runner.rs delete mode 100644 ethcore/wasm/src/tests.rs delete mode 100755 scripts/add_license.sh delete mode 100755 scripts/doc.sh delete mode 100755 scripts/hook.sh delete mode 100755 scripts/remove_duplicate_empty_lines.sh delete mode 100644 secret-store/Cargo.toml delete mode 100644 secret-store/res/acl_storage.json delete mode 100644 secret-store/res/key_server_set.json delete mode 100644 secret-store/res/service.json delete mode 100644 secret-store/src/acl_storage.rs delete mode 100644 secret-store/src/helpers.rs delete mode 100644 secret-store/src/key_server.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/mod.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/sessions_queue.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs delete mode 100644 secret-store/src/key_server_cluster/admin_sessions/share_change_session.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/decryption_session.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/encryption_session.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/generation_session.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/mod.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs delete mode 100644 secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs delete mode 100644 secret-store/src/key_server_cluster/cluster.rs delete mode 100644 secret-store/src/key_server_cluster/cluster_connections.rs delete mode 100644 secret-store/src/key_server_cluster/cluster_connections_net.rs delete mode 100644 secret-store/src/key_server_cluster/cluster_message_processor.rs delete mode 100644 secret-store/src/key_server_cluster/cluster_sessions.rs delete mode 100644 secret-store/src/key_server_cluster/cluster_sessions_creator.rs delete mode 100644 secret-store/src/key_server_cluster/connection_trigger.rs delete mode 100644 secret-store/src/key_server_cluster/connection_trigger_with_migration.rs delete mode 100644 secret-store/src/key_server_cluster/io/deadline.rs delete mode 100644 secret-store/src/key_server_cluster/io/handshake.rs delete mode 100644 secret-store/src/key_server_cluster/io/message.rs delete mode 100644 secret-store/src/key_server_cluster/io/mod.rs delete mode 100644 secret-store/src/key_server_cluster/io/read_header.rs delete mode 100644 secret-store/src/key_server_cluster/io/read_message.rs delete mode 100644 secret-store/src/key_server_cluster/io/read_payload.rs delete mode 100644 secret-store/src/key_server_cluster/io/shared_tcp_stream.rs delete mode 100644 secret-store/src/key_server_cluster/io/write_message.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/consensus_session.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/decryption_job.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/dummy_job.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/job_session.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/key_access_job.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/mod.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/servers_set_change_access_job.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/signing_job_ecdsa.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/signing_job_schnorr.rs delete mode 100644 secret-store/src/key_server_cluster/jobs/unknown_sessions_job.rs delete mode 100644 secret-store/src/key_server_cluster/math.rs delete mode 100644 secret-store/src/key_server_cluster/message.rs delete mode 100644 secret-store/src/key_server_cluster/mod.rs delete mode 100644 secret-store/src/key_server_cluster/net/accept_connection.rs delete mode 100644 secret-store/src/key_server_cluster/net/connect.rs delete mode 100644 secret-store/src/key_server_cluster/net/connection.rs delete mode 100644 secret-store/src/key_server_cluster/net/mod.rs delete mode 100644 secret-store/src/key_server_set.rs delete mode 100644 secret-store/src/key_storage.rs delete mode 100644 secret-store/src/lib.rs delete mode 100644 secret-store/src/listener/http_listener.rs delete mode 100644 secret-store/src/listener/mod.rs delete mode 100644 secret-store/src/listener/service_contract.rs delete mode 100644 secret-store/src/listener/service_contract_aggregate.rs delete mode 100644 secret-store/src/listener/service_contract_listener.rs delete mode 100644 secret-store/src/listener/tasks_queue.rs delete mode 100644 secret-store/src/node_key_pair.rs delete mode 100644 secret-store/src/serialization.rs delete mode 100644 secret-store/src/traits.rs delete mode 100644 secret-store/src/trusted_client.rs delete mode 100644 secret-store/src/types/all.rs delete mode 100644 secret-store/src/types/error.rs delete mode 100644 secret-store/src/types/mod.rs delete mode 100644 secret_store/src/key_server_cluster/cluster_connections.rs delete mode 100644 secret_store/src/key_server_cluster/cluster_connections_net.rs delete mode 100644 secret_store/src/key_server_cluster/cluster_message_processor.rs delete mode 100644 util/registrar/Cargo.toml delete mode 100644 util/registrar/res/registrar.json delete mode 100644 util/registrar/src/lib.rs delete mode 100644 util/registrar/src/registrar.rs diff --git a/.gitmodules b/.gitmodules index b49256b4df..2789e41fb5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "ethcore/res/ethereum/tests"] - path = ethcore/res/ethereum/tests +[submodule "crates/ethcore/res/json_tests"] + path = crates/ethcore/res/json_tests url = https://github.com/ethereum/tests.git - branch = develop -[submodule "ethcore/res/wasm-tests"] - path = ethcore/res/wasm-tests - url = https://github.com/paritytech/wasm-tests diff --git a/Cargo.lock b/Cargo.lock index 4a52e12943..01f122fe1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1249,47 +1249,6 @@ dependencies = [ "tiny-keccak 1.5.0", ] -[[package]] -name = "ethcore-secretstore" -version = "1.0.0" -dependencies = [ - "byteorder", - "common-types", - "env_logger", - "ethabi", - "ethabi-contract", - "ethabi-derive", - "ethcore", - "ethcore-accounts", - "ethcore-call-contract", - "ethcore-sync", - "ethereum-types 0.4.2", - "ethkey", - "futures", - "hyper 0.12.35", - "jsonrpc-server-utils", - "keccak-hash", - "kvdb", - "kvdb-rocksdb", - "lazy_static", - "log", - "parity-bytes", - "parity-crypto 0.3.1", - "parity-runtime", - "parking_lot 0.7.1", - "percent-encoding 2.1.0", - "rustc-hex 1.0.0", - "serde", - "serde_derive", - "serde_json", - "tempdir", - "tiny-keccak 1.5.0", - "tokio", - "tokio-io", - "tokio-service", - "url 2.1.0", -] - [[package]] name = "ethcore-service" version = "0.1.0" @@ -2885,7 +2844,6 @@ dependencies = [ "ethcore-logger", "ethcore-miner", "ethcore-network", - "ethcore-secretstore", "ethcore-service", "ethcore-sync", "ethereum-types 0.4.2", @@ -2920,7 +2878,6 @@ dependencies = [ "pretty_assertions", "prometheus", "regex 1.3.9", - "registrar", "rlp 0.3.0", "rpassword", "rustc-hex 1.0.0", @@ -3604,22 +3561,6 @@ dependencies = [ "getopts", ] -[[package]] -name = "pwasm-run-test" -version = "0.1.0" -dependencies = [ - "clap", - "env_logger", - "ethereum-types 0.4.2", - "ethjson", - "rustc-hex 1.0.0", - "serde", - "serde_derive", - "serde_json", - "vm", - "wasm", -] - [[package]] name = "pwasm-utils" version = "0.6.2" @@ -3961,17 +3902,6 @@ version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" -[[package]] -name = "registrar" -version = "0.0.1" -dependencies = [ - "ethabi", - "ethabi-contract", - "ethabi-derive", - "futures", - "keccak-hash", -] - [[package]] name = "relay" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index c2eccb9792..aed85d0390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ authors = [ ] [dependencies] -blooms-db = { path = "util/blooms-db" } +blooms-db = { path = "crates/db/blooms-db" } log = "0.4" rustc-hex = "1.0" docopt = "1.0" @@ -35,44 +35,42 @@ fdlimit = "0.1" ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } jsonrpc-core = "15.0.0" parity-bytes = "0.1" -common-types = { path = "ethcore/types" } -ethcore = { path = "ethcore", features = ["parity"] } -ethcore-accounts = { path = "accounts", optional = true } -ethcore-blockchain = { path = "ethcore/blockchain" } -ethcore-call-contract = { path = "ethcore/call-contract"} -ethcore-db = { path = "ethcore/db" } -ethcore-io = { path = "util/io" } -ethcore-logger = { path = "parity/logger" } -ethcore-miner = { path = "miner" } -ethcore-network = { path = "util/network" } -ethcore-service = { path = "ethcore/service" } -ethcore-sync = { path = "ethcore/sync" } +common-types = { path = "crates/ethcore/types" } +ethcore = { path = "crates/ethcore", features = ["parity"] } +ethcore-accounts = { path = "crates/accounts", optional = true } +ethcore-blockchain = { path = "crates/ethcore/blockchain" } +ethcore-call-contract = { path = "crates/vm/call-contract"} +ethcore-db = { path = "crates/db/db" } +ethcore-io = { path = "crates/runtime/io" } +ethcore-logger = { path = "bin/oe/logger" } +ethcore-miner = { path = "crates/concensus/miner" } +ethcore-network = { path = "crates/net/network" } +ethcore-service = { path = "crates/ethcore/service" } +ethcore-sync = { path = "crates/ethcore/sync" } ethereum-types = "0.4" -ethkey = { path = "accounts/ethkey" } -ethstore = { path = "accounts/ethstore" } -fetch = { path = "util/fetch" } -node-filter = { path = "ethcore/node-filter" } +ethkey = { path = "crates/accounts/ethkey" } +ethstore = { path = "crates/accounts/ethstore" } +fetch = { path = "crates/net/fetch" } +node-filter = { path = "crates/net/node-filter" } rlp = { version = "0.3.0", features = ["ethereum"] } -cli-signer= { path = "cli-signer" } +cli-signer= { path = "crates/util/cli-signer" } parity-daemonize = "0.3" -parity-local-store = { path = "miner/local-store" } -parity-runtime = { path = "util/runtime" } -parity-rpc = { path = "rpc" } -parity-version = { path = "util/version" } +parity-local-store = { path = "crates/concensus/miner/local-store" } +parity-runtime = { path = "crates/runtime/runtime" } +parity-rpc = { path = "crates/rpc" } +parity-version = { path = "crates/util/version" } parity-path = "0.1" -dir = { path = "util/dir" } -panic_hook = { path = "util/panic-hook" } +dir = { path = "crates/util/dir" } +panic_hook = { path = "crates/util/panic-hook" } keccak-hash = "0.1" -migration-rocksdb = { path = "util/migration-rocksdb" } +migration-rocksdb = { path = "crates/db/migration-rocksdb" } kvdb = "0.1" kvdb-rocksdb = "0.1.3" -journaldb = { path = "util/journaldb" } -stats = { path = "util/stats" } +journaldb = { path = "crates/db/journaldb" } +stats = { path = "crates/util/stats" } prometheus = "0.9.0" -ethcore-secretstore = { path = "secret-store", optional = true } - -registrar = { path = "util/registrar" } +# ethcore-secretstore = { path = "crates/util/secret-store", optional = true } [build-dependencies] rustc_version = "0.2" @@ -81,7 +79,7 @@ rustc_version = "0.2" pretty_assertions = "0.1" ipnetwork = "0.12.6" tempdir = "0.3" -fake-fetch = { path = "util/fake-fetch" } +fake-fetch = { path = "crates/net/fake-fetch" } lazy_static = "1.2.0" [target.'cfg(windows)'.dependencies] @@ -97,7 +95,6 @@ test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] slow-blocks = ["ethcore/slow-blocks"] -secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts"] final = ["parity-version/final"] deadlock_detection = ["parking_lot/deadlock_detection"] # to create a memory profile (requires nightly rust), use e.g. @@ -109,10 +106,10 @@ deadlock_detection = ["parking_lot/deadlock_detection"] memory_profiling = [] [lib] -path = "parity/lib.rs" +path = "bin/oe/lib.rs" [[bin]] -path = "parity/main.rs" +path = "bin/oe/main.rs" name = "openethereum" [profile.test] @@ -128,16 +125,10 @@ lto = true # in the dependency tree in any other way # (i.e. pretty much only standalone CLI tools) members = [ - "accounts/ethkey/cli", - "accounts/ethstore/cli", - "chainspec", - "ethcore/wasm/run", - "evmbin", - "util/triehash-ethereum", - "util/keccak-hasher", - "util/patricia-trie-ethereum", - "util/fastmap", - "util/time-utils" + "bin/ethkey", + "bin/ethstore", + "bin/evmbin", + "bin/chainspec" ] [patch.crates-io] diff --git a/chainspec/Cargo.toml b/bin/chainspec/Cargo.toml similarity index 80% rename from chainspec/Cargo.toml rename to bin/chainspec/Cargo.toml index c0308edd32..f990a81ddd 100644 --- a/chainspec/Cargo.toml +++ b/bin/chainspec/Cargo.toml @@ -5,5 +5,5 @@ version = "0.1.0" authors = ["Marek Kotewicz "] [dependencies] -ethjson = { path = "../json" } +ethjson = { path = "../../crates/ethjson" } serde_json = "1.0" diff --git a/chainspec/src/main.rs b/bin/chainspec/src/main.rs similarity index 100% rename from chainspec/src/main.rs rename to bin/chainspec/src/main.rs diff --git a/accounts/ethkey/cli/Cargo.toml b/bin/ethkey/Cargo.toml similarity index 76% rename from accounts/ethkey/cli/Cargo.toml rename to bin/ethkey/Cargo.toml index c1d44897cc..e649202e0c 100644 --- a/accounts/ethkey/cli/Cargo.toml +++ b/bin/ethkey/Cargo.toml @@ -7,8 +7,8 @@ authors = ["Parity Technologies "] [dependencies] docopt = "1.0" env_logger = "0.5" -ethkey = { path = "../" } -panic_hook = { path = "../../../util/panic-hook" } +ethkey = { path = "../../crates/accounts/ethkey" } +panic_hook = { path = "../../crates/util/panic-hook" } parity-wordlist="1.3" rustc-hex = "1.0" serde = "1.0" diff --git a/accounts/ethkey/cli/src/main.rs b/bin/ethkey/src/main.rs similarity index 100% rename from accounts/ethkey/cli/src/main.rs rename to bin/ethkey/src/main.rs diff --git a/accounts/ethstore/cli/Cargo.toml b/bin/ethstore/Cargo.toml similarity index 72% rename from accounts/ethstore/cli/Cargo.toml rename to bin/ethstore/Cargo.toml index 9578a75377..6ad76cb0ad 100644 --- a/accounts/ethstore/cli/Cargo.toml +++ b/bin/ethstore/Cargo.toml @@ -12,9 +12,9 @@ rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" parking_lot = "0.7" -ethstore = { path = "../" } -dir = { path = '../../../util/dir' } -panic_hook = { path = "../../../util/panic-hook" } +ethstore = { path = "../../crates/accounts/ethstore" } +dir = { path = '../../crates/util/dir' } +panic_hook = { path = "../../crates/util/panic-hook" } [[bin]] name = "ethstore" diff --git a/accounts/ethstore/cli/src/crack.rs b/bin/ethstore/src/crack.rs similarity index 100% rename from accounts/ethstore/cli/src/crack.rs rename to bin/ethstore/src/crack.rs diff --git a/accounts/ethstore/cli/src/main.rs b/bin/ethstore/src/main.rs similarity index 100% rename from accounts/ethstore/cli/src/main.rs rename to bin/ethstore/src/main.rs diff --git a/evmbin/Cargo.toml b/bin/evmbin/Cargo.toml similarity index 57% rename from evmbin/Cargo.toml rename to bin/evmbin/Cargo.toml index 18d0b3e8e0..1e0ac33ad4 100644 --- a/evmbin/Cargo.toml +++ b/bin/evmbin/Cargo.toml @@ -9,20 +9,20 @@ name = "openethereum-evm" path = "./src/main.rs" [dependencies] -common-types = { path = "../ethcore/types", features = ["test-helpers"] } +common-types = { path = "../../crates/ethcore/types", features = ["test-helpers"] } docopt = "1.0" env_logger = "0.5" -ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests", "to-pod-full"] } +ethcore = { path = "../../crates/ethcore", features = ["test-helpers", "json-tests", "to-pod-full"] } ethereum-types = "0.4" -ethjson = { path = "../json" } -evm = { path = "../ethcore/evm" } -panic_hook = { path = "../util/panic-hook" } +ethjson = { path = "../../crates/ethjson" } +evm = { path = "../../crates/vm/evm" } +panic_hook = { path = "../../crates/util/panic-hook" } parity-bytes = "0.1" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -vm = { path = "../ethcore/vm" } +vm = { path = "../../crates/vm/vm" } [dev-dependencies] criterion = "0.3.0" diff --git a/evmbin/README.md b/bin/evmbin/README.md similarity index 100% rename from evmbin/README.md rename to bin/evmbin/README.md diff --git a/evmbin/benches/mod.rs b/bin/evmbin/benches/mod.rs similarity index 100% rename from evmbin/benches/mod.rs rename to bin/evmbin/benches/mod.rs diff --git a/evmbin/res/testchain.json b/bin/evmbin/res/testchain.json similarity index 100% rename from evmbin/res/testchain.json rename to bin/evmbin/res/testchain.json diff --git a/evmbin/src/display/config.rs b/bin/evmbin/src/display/config.rs similarity index 100% rename from evmbin/src/display/config.rs rename to bin/evmbin/src/display/config.rs diff --git a/evmbin/src/display/json.rs b/bin/evmbin/src/display/json.rs similarity index 100% rename from evmbin/src/display/json.rs rename to bin/evmbin/src/display/json.rs diff --git a/evmbin/src/display/mod.rs b/bin/evmbin/src/display/mod.rs similarity index 100% rename from evmbin/src/display/mod.rs rename to bin/evmbin/src/display/mod.rs diff --git a/evmbin/src/display/simple.rs b/bin/evmbin/src/display/simple.rs similarity index 100% rename from evmbin/src/display/simple.rs rename to bin/evmbin/src/display/simple.rs diff --git a/evmbin/src/display/std_json.rs b/bin/evmbin/src/display/std_json.rs similarity index 100% rename from evmbin/src/display/std_json.rs rename to bin/evmbin/src/display/std_json.rs diff --git a/evmbin/src/info.rs b/bin/evmbin/src/info.rs similarity index 100% rename from evmbin/src/info.rs rename to bin/evmbin/src/info.rs diff --git a/evmbin/src/main.rs b/bin/evmbin/src/main.rs similarity index 100% rename from evmbin/src/main.rs rename to bin/evmbin/src/main.rs diff --git a/parity/account.rs b/bin/oe/account.rs similarity index 100% rename from parity/account.rs rename to bin/oe/account.rs diff --git a/parity/account_utils.rs b/bin/oe/account_utils.rs similarity index 100% rename from parity/account_utils.rs rename to bin/oe/account_utils.rs diff --git a/parity/blockchain.rs b/bin/oe/blockchain.rs similarity index 100% rename from parity/blockchain.rs rename to bin/oe/blockchain.rs diff --git a/parity/cache.rs b/bin/oe/cache.rs similarity index 100% rename from parity/cache.rs rename to bin/oe/cache.rs diff --git a/parity/cli/mod.rs b/bin/oe/cli/mod.rs similarity index 100% rename from parity/cli/mod.rs rename to bin/oe/cli/mod.rs diff --git a/parity/cli/presets/config.dev-insecure.toml b/bin/oe/cli/presets/config.dev-insecure.toml similarity index 100% rename from parity/cli/presets/config.dev-insecure.toml rename to bin/oe/cli/presets/config.dev-insecure.toml diff --git a/parity/cli/presets/config.dev.toml b/bin/oe/cli/presets/config.dev.toml similarity index 100% rename from parity/cli/presets/config.dev.toml rename to bin/oe/cli/presets/config.dev.toml diff --git a/parity/cli/presets/config.insecure.toml b/bin/oe/cli/presets/config.insecure.toml similarity index 100% rename from parity/cli/presets/config.insecure.toml rename to bin/oe/cli/presets/config.insecure.toml diff --git a/parity/cli/presets/config.mining.toml b/bin/oe/cli/presets/config.mining.toml similarity index 100% rename from parity/cli/presets/config.mining.toml rename to bin/oe/cli/presets/config.mining.toml diff --git a/parity/cli/presets/config.non-standard-ports.toml b/bin/oe/cli/presets/config.non-standard-ports.toml similarity index 100% rename from parity/cli/presets/config.non-standard-ports.toml rename to bin/oe/cli/presets/config.non-standard-ports.toml diff --git a/parity/cli/presets/mod.rs b/bin/oe/cli/presets/mod.rs similarity index 100% rename from parity/cli/presets/mod.rs rename to bin/oe/cli/presets/mod.rs diff --git a/parity/cli/tests/config.full.toml b/bin/oe/cli/tests/config.full.toml similarity index 100% rename from parity/cli/tests/config.full.toml rename to bin/oe/cli/tests/config.full.toml diff --git a/parity/cli/tests/config.invalid1.toml b/bin/oe/cli/tests/config.invalid1.toml similarity index 100% rename from parity/cli/tests/config.invalid1.toml rename to bin/oe/cli/tests/config.invalid1.toml diff --git a/parity/cli/tests/config.invalid2.toml b/bin/oe/cli/tests/config.invalid2.toml similarity index 100% rename from parity/cli/tests/config.invalid2.toml rename to bin/oe/cli/tests/config.invalid2.toml diff --git a/parity/cli/tests/config.invalid3.toml b/bin/oe/cli/tests/config.invalid3.toml similarity index 100% rename from parity/cli/tests/config.invalid3.toml rename to bin/oe/cli/tests/config.invalid3.toml diff --git a/parity/cli/tests/config.invalid4.toml b/bin/oe/cli/tests/config.invalid4.toml similarity index 100% rename from parity/cli/tests/config.invalid4.toml rename to bin/oe/cli/tests/config.invalid4.toml diff --git a/parity/cli/tests/config.toml b/bin/oe/cli/tests/config.toml similarity index 100% rename from parity/cli/tests/config.toml rename to bin/oe/cli/tests/config.toml diff --git a/parity/cli/usage.rs b/bin/oe/cli/usage.rs similarity index 100% rename from parity/cli/usage.rs rename to bin/oe/cli/usage.rs diff --git a/parity/cli/usage_header.txt b/bin/oe/cli/usage_header.txt similarity index 100% rename from parity/cli/usage_header.txt rename to bin/oe/cli/usage_header.txt diff --git a/parity/cli/version.txt b/bin/oe/cli/version.txt similarity index 100% rename from parity/cli/version.txt rename to bin/oe/cli/version.txt diff --git a/parity/configuration.rs b/bin/oe/configuration.rs similarity index 100% rename from parity/configuration.rs rename to bin/oe/configuration.rs diff --git a/parity/db/mod.rs b/bin/oe/db/mod.rs similarity index 100% rename from parity/db/mod.rs rename to bin/oe/db/mod.rs diff --git a/parity/db/rocksdb/blooms.rs b/bin/oe/db/rocksdb/blooms.rs similarity index 100% rename from parity/db/rocksdb/blooms.rs rename to bin/oe/db/rocksdb/blooms.rs diff --git a/parity/db/rocksdb/helpers.rs b/bin/oe/db/rocksdb/helpers.rs similarity index 100% rename from parity/db/rocksdb/helpers.rs rename to bin/oe/db/rocksdb/helpers.rs diff --git a/parity/db/rocksdb/migration.rs b/bin/oe/db/rocksdb/migration.rs similarity index 100% rename from parity/db/rocksdb/migration.rs rename to bin/oe/db/rocksdb/migration.rs diff --git a/parity/db/rocksdb/mod.rs b/bin/oe/db/rocksdb/mod.rs similarity index 100% rename from parity/db/rocksdb/mod.rs rename to bin/oe/db/rocksdb/mod.rs diff --git a/parity/helpers.rs b/bin/oe/helpers.rs similarity index 100% rename from parity/helpers.rs rename to bin/oe/helpers.rs diff --git a/parity/informant.rs b/bin/oe/informant.rs similarity index 100% rename from parity/informant.rs rename to bin/oe/informant.rs diff --git a/parity/lib.rs b/bin/oe/lib.rs similarity index 99% rename from parity/lib.rs rename to bin/oe/lib.rs index 3f811826d6..09d8ae5d0b 100644 --- a/parity/lib.rs +++ b/bin/oe/lib.rs @@ -67,7 +67,6 @@ extern crate parity_rpc; extern crate parity_runtime; extern crate parity_version; extern crate prometheus; -extern crate registrar; extern crate stats; #[macro_use] diff --git a/parity/logger/Cargo.toml b/bin/oe/logger/Cargo.toml similarity index 100% rename from parity/logger/Cargo.toml rename to bin/oe/logger/Cargo.toml diff --git a/parity/logger/src/lib.rs b/bin/oe/logger/src/lib.rs similarity index 100% rename from parity/logger/src/lib.rs rename to bin/oe/logger/src/lib.rs diff --git a/parity/logger/src/rotating.rs b/bin/oe/logger/src/rotating.rs similarity index 100% rename from parity/logger/src/rotating.rs rename to bin/oe/logger/src/rotating.rs diff --git a/parity/main.rs b/bin/oe/main.rs similarity index 100% rename from parity/main.rs rename to bin/oe/main.rs diff --git a/parity/metrics.rs b/bin/oe/metrics.rs similarity index 100% rename from parity/metrics.rs rename to bin/oe/metrics.rs diff --git a/parity/modules.rs b/bin/oe/modules.rs similarity index 100% rename from parity/modules.rs rename to bin/oe/modules.rs diff --git a/parity/params.rs b/bin/oe/params.rs similarity index 100% rename from parity/params.rs rename to bin/oe/params.rs diff --git a/parity/presale.rs b/bin/oe/presale.rs similarity index 100% rename from parity/presale.rs rename to bin/oe/presale.rs diff --git a/parity/rpc.rs b/bin/oe/rpc.rs similarity index 100% rename from parity/rpc.rs rename to bin/oe/rpc.rs diff --git a/parity/rpc_apis.rs b/bin/oe/rpc_apis.rs similarity index 100% rename from parity/rpc_apis.rs rename to bin/oe/rpc_apis.rs diff --git a/parity/run.rs b/bin/oe/run.rs similarity index 100% rename from parity/run.rs rename to bin/oe/run.rs diff --git a/parity/secretstore.rs b/bin/oe/secretstore.rs similarity index 100% rename from parity/secretstore.rs rename to bin/oe/secretstore.rs diff --git a/parity/signer.rs b/bin/oe/signer.rs similarity index 100% rename from parity/signer.rs rename to bin/oe/signer.rs diff --git a/parity/snapshot.rs b/bin/oe/snapshot.rs similarity index 100% rename from parity/snapshot.rs rename to bin/oe/snapshot.rs diff --git a/parity/stratum.rs b/bin/oe/stratum.rs similarity index 100% rename from parity/stratum.rs rename to bin/oe/stratum.rs diff --git a/parity/upgrade.rs b/bin/oe/upgrade.rs similarity index 100% rename from parity/upgrade.rs rename to bin/oe/upgrade.rs diff --git a/parity/user_defaults.rs b/bin/oe/user_defaults.rs similarity index 100% rename from parity/user_defaults.rs rename to bin/oe/user_defaults.rs diff --git a/accounts/Cargo.toml b/crates/accounts/Cargo.toml similarity index 100% rename from accounts/Cargo.toml rename to crates/accounts/Cargo.toml diff --git a/accounts/ethkey/.gitignore b/crates/accounts/ethkey/.gitignore similarity index 100% rename from accounts/ethkey/.gitignore rename to crates/accounts/ethkey/.gitignore diff --git a/accounts/ethkey/.travis.yml b/crates/accounts/ethkey/.travis.yml similarity index 100% rename from accounts/ethkey/.travis.yml rename to crates/accounts/ethkey/.travis.yml diff --git a/accounts/ethkey/Cargo.toml b/crates/accounts/ethkey/Cargo.toml similarity index 90% rename from accounts/ethkey/Cargo.toml rename to crates/accounts/ethkey/Cargo.toml index e432a11820..6348230d3e 100644 --- a/accounts/ethkey/Cargo.toml +++ b/crates/accounts/ethkey/Cargo.toml @@ -11,7 +11,7 @@ eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "c ethereum-types = "0.4" lazy_static = "1.0" log = "0.4" -memzero = { path = "../../util/memzero" } +memzero = { path = "../../../crates/util/memzero" } parity-wordlist = "1.3" quick-error = "1.2.2" rand = "0.4" diff --git a/accounts/ethkey/README.md b/crates/accounts/ethkey/README.md similarity index 100% rename from accounts/ethkey/README.md rename to crates/accounts/ethkey/README.md diff --git a/accounts/ethkey/src/brain.rs b/crates/accounts/ethkey/src/brain.rs similarity index 100% rename from accounts/ethkey/src/brain.rs rename to crates/accounts/ethkey/src/brain.rs diff --git a/accounts/ethkey/src/brain_prefix.rs b/crates/accounts/ethkey/src/brain_prefix.rs similarity index 100% rename from accounts/ethkey/src/brain_prefix.rs rename to crates/accounts/ethkey/src/brain_prefix.rs diff --git a/accounts/ethkey/src/brain_recover.rs b/crates/accounts/ethkey/src/brain_recover.rs similarity index 100% rename from accounts/ethkey/src/brain_recover.rs rename to crates/accounts/ethkey/src/brain_recover.rs diff --git a/accounts/ethkey/src/crypto.rs b/crates/accounts/ethkey/src/crypto.rs similarity index 100% rename from accounts/ethkey/src/crypto.rs rename to crates/accounts/ethkey/src/crypto.rs diff --git a/accounts/ethkey/src/error.rs b/crates/accounts/ethkey/src/error.rs similarity index 100% rename from accounts/ethkey/src/error.rs rename to crates/accounts/ethkey/src/error.rs diff --git a/accounts/ethkey/src/extended.rs b/crates/accounts/ethkey/src/extended.rs similarity index 100% rename from accounts/ethkey/src/extended.rs rename to crates/accounts/ethkey/src/extended.rs diff --git a/accounts/ethkey/src/keccak.rs b/crates/accounts/ethkey/src/keccak.rs similarity index 100% rename from accounts/ethkey/src/keccak.rs rename to crates/accounts/ethkey/src/keccak.rs diff --git a/accounts/ethkey/src/keypair.rs b/crates/accounts/ethkey/src/keypair.rs similarity index 100% rename from accounts/ethkey/src/keypair.rs rename to crates/accounts/ethkey/src/keypair.rs diff --git a/accounts/ethkey/src/lib.rs b/crates/accounts/ethkey/src/lib.rs similarity index 100% rename from accounts/ethkey/src/lib.rs rename to crates/accounts/ethkey/src/lib.rs diff --git a/accounts/ethkey/src/math.rs b/crates/accounts/ethkey/src/math.rs similarity index 100% rename from accounts/ethkey/src/math.rs rename to crates/accounts/ethkey/src/math.rs diff --git a/accounts/ethkey/src/password.rs b/crates/accounts/ethkey/src/password.rs similarity index 100% rename from accounts/ethkey/src/password.rs rename to crates/accounts/ethkey/src/password.rs diff --git a/accounts/ethkey/src/prefix.rs b/crates/accounts/ethkey/src/prefix.rs similarity index 100% rename from accounts/ethkey/src/prefix.rs rename to crates/accounts/ethkey/src/prefix.rs diff --git a/accounts/ethkey/src/random.rs b/crates/accounts/ethkey/src/random.rs similarity index 100% rename from accounts/ethkey/src/random.rs rename to crates/accounts/ethkey/src/random.rs diff --git a/accounts/ethkey/src/secret.rs b/crates/accounts/ethkey/src/secret.rs similarity index 100% rename from accounts/ethkey/src/secret.rs rename to crates/accounts/ethkey/src/secret.rs diff --git a/accounts/ethkey/src/signature.rs b/crates/accounts/ethkey/src/signature.rs similarity index 100% rename from accounts/ethkey/src/signature.rs rename to crates/accounts/ethkey/src/signature.rs diff --git a/accounts/ethstore/.editorconfig b/crates/accounts/ethstore/.editorconfig similarity index 100% rename from accounts/ethstore/.editorconfig rename to crates/accounts/ethstore/.editorconfig diff --git a/accounts/ethstore/.gitignore b/crates/accounts/ethstore/.gitignore similarity index 100% rename from accounts/ethstore/.gitignore rename to crates/accounts/ethstore/.gitignore diff --git a/accounts/ethstore/.travis.yml b/crates/accounts/ethstore/.travis.yml similarity index 100% rename from accounts/ethstore/.travis.yml rename to crates/accounts/ethstore/.travis.yml diff --git a/accounts/ethstore/Cargo.toml b/crates/accounts/ethstore/Cargo.toml similarity index 100% rename from accounts/ethstore/Cargo.toml rename to crates/accounts/ethstore/Cargo.toml diff --git a/accounts/ethstore/README.md b/crates/accounts/ethstore/README.md similarity index 100% rename from accounts/ethstore/README.md rename to crates/accounts/ethstore/README.md diff --git a/accounts/ethstore/src/account/cipher.rs b/crates/accounts/ethstore/src/account/cipher.rs similarity index 100% rename from accounts/ethstore/src/account/cipher.rs rename to crates/accounts/ethstore/src/account/cipher.rs diff --git a/accounts/ethstore/src/account/crypto.rs b/crates/accounts/ethstore/src/account/crypto.rs similarity index 100% rename from accounts/ethstore/src/account/crypto.rs rename to crates/accounts/ethstore/src/account/crypto.rs diff --git a/accounts/ethstore/src/account/kdf.rs b/crates/accounts/ethstore/src/account/kdf.rs similarity index 100% rename from accounts/ethstore/src/account/kdf.rs rename to crates/accounts/ethstore/src/account/kdf.rs diff --git a/accounts/ethstore/src/account/mod.rs b/crates/accounts/ethstore/src/account/mod.rs similarity index 100% rename from accounts/ethstore/src/account/mod.rs rename to crates/accounts/ethstore/src/account/mod.rs diff --git a/accounts/ethstore/src/account/safe_account.rs b/crates/accounts/ethstore/src/account/safe_account.rs similarity index 100% rename from accounts/ethstore/src/account/safe_account.rs rename to crates/accounts/ethstore/src/account/safe_account.rs diff --git a/accounts/ethstore/src/account/version.rs b/crates/accounts/ethstore/src/account/version.rs similarity index 100% rename from accounts/ethstore/src/account/version.rs rename to crates/accounts/ethstore/src/account/version.rs diff --git a/accounts/ethstore/src/accounts_dir/disk.rs b/crates/accounts/ethstore/src/accounts_dir/disk.rs similarity index 100% rename from accounts/ethstore/src/accounts_dir/disk.rs rename to crates/accounts/ethstore/src/accounts_dir/disk.rs diff --git a/accounts/ethstore/src/accounts_dir/memory.rs b/crates/accounts/ethstore/src/accounts_dir/memory.rs similarity index 100% rename from accounts/ethstore/src/accounts_dir/memory.rs rename to crates/accounts/ethstore/src/accounts_dir/memory.rs diff --git a/accounts/ethstore/src/accounts_dir/mod.rs b/crates/accounts/ethstore/src/accounts_dir/mod.rs similarity index 100% rename from accounts/ethstore/src/accounts_dir/mod.rs rename to crates/accounts/ethstore/src/accounts_dir/mod.rs diff --git a/accounts/ethstore/src/accounts_dir/vault.rs b/crates/accounts/ethstore/src/accounts_dir/vault.rs similarity index 100% rename from accounts/ethstore/src/accounts_dir/vault.rs rename to crates/accounts/ethstore/src/accounts_dir/vault.rs diff --git a/accounts/ethstore/src/error.rs b/crates/accounts/ethstore/src/error.rs similarity index 100% rename from accounts/ethstore/src/error.rs rename to crates/accounts/ethstore/src/error.rs diff --git a/accounts/ethstore/src/ethkey.rs b/crates/accounts/ethstore/src/ethkey.rs similarity index 100% rename from accounts/ethstore/src/ethkey.rs rename to crates/accounts/ethstore/src/ethkey.rs diff --git a/accounts/ethstore/src/ethstore.rs b/crates/accounts/ethstore/src/ethstore.rs similarity index 100% rename from accounts/ethstore/src/ethstore.rs rename to crates/accounts/ethstore/src/ethstore.rs diff --git a/accounts/ethstore/src/import.rs b/crates/accounts/ethstore/src/import.rs similarity index 100% rename from accounts/ethstore/src/import.rs rename to crates/accounts/ethstore/src/import.rs diff --git a/accounts/ethstore/src/json/bytes.rs b/crates/accounts/ethstore/src/json/bytes.rs similarity index 100% rename from accounts/ethstore/src/json/bytes.rs rename to crates/accounts/ethstore/src/json/bytes.rs diff --git a/accounts/ethstore/src/json/cipher.rs b/crates/accounts/ethstore/src/json/cipher.rs similarity index 100% rename from accounts/ethstore/src/json/cipher.rs rename to crates/accounts/ethstore/src/json/cipher.rs diff --git a/accounts/ethstore/src/json/crypto.rs b/crates/accounts/ethstore/src/json/crypto.rs similarity index 100% rename from accounts/ethstore/src/json/crypto.rs rename to crates/accounts/ethstore/src/json/crypto.rs diff --git a/accounts/ethstore/src/json/error.rs b/crates/accounts/ethstore/src/json/error.rs similarity index 100% rename from accounts/ethstore/src/json/error.rs rename to crates/accounts/ethstore/src/json/error.rs diff --git a/accounts/ethstore/src/json/hash.rs b/crates/accounts/ethstore/src/json/hash.rs similarity index 100% rename from accounts/ethstore/src/json/hash.rs rename to crates/accounts/ethstore/src/json/hash.rs diff --git a/accounts/ethstore/src/json/id.rs b/crates/accounts/ethstore/src/json/id.rs similarity index 100% rename from accounts/ethstore/src/json/id.rs rename to crates/accounts/ethstore/src/json/id.rs diff --git a/accounts/ethstore/src/json/kdf.rs b/crates/accounts/ethstore/src/json/kdf.rs similarity index 100% rename from accounts/ethstore/src/json/kdf.rs rename to crates/accounts/ethstore/src/json/kdf.rs diff --git a/accounts/ethstore/src/json/key_file.rs b/crates/accounts/ethstore/src/json/key_file.rs similarity index 100% rename from accounts/ethstore/src/json/key_file.rs rename to crates/accounts/ethstore/src/json/key_file.rs diff --git a/accounts/ethstore/src/json/mod.rs b/crates/accounts/ethstore/src/json/mod.rs similarity index 100% rename from accounts/ethstore/src/json/mod.rs rename to crates/accounts/ethstore/src/json/mod.rs diff --git a/accounts/ethstore/src/json/presale.rs b/crates/accounts/ethstore/src/json/presale.rs similarity index 100% rename from accounts/ethstore/src/json/presale.rs rename to crates/accounts/ethstore/src/json/presale.rs diff --git a/accounts/ethstore/src/json/vault_file.rs b/crates/accounts/ethstore/src/json/vault_file.rs similarity index 100% rename from accounts/ethstore/src/json/vault_file.rs rename to crates/accounts/ethstore/src/json/vault_file.rs diff --git a/accounts/ethstore/src/json/vault_key_file.rs b/crates/accounts/ethstore/src/json/vault_key_file.rs similarity index 100% rename from accounts/ethstore/src/json/vault_key_file.rs rename to crates/accounts/ethstore/src/json/vault_key_file.rs diff --git a/accounts/ethstore/src/json/version.rs b/crates/accounts/ethstore/src/json/version.rs similarity index 100% rename from accounts/ethstore/src/json/version.rs rename to crates/accounts/ethstore/src/json/version.rs diff --git a/accounts/ethstore/src/lib.rs b/crates/accounts/ethstore/src/lib.rs similarity index 100% rename from accounts/ethstore/src/lib.rs rename to crates/accounts/ethstore/src/lib.rs diff --git a/accounts/ethstore/src/presale.rs b/crates/accounts/ethstore/src/presale.rs similarity index 100% rename from accounts/ethstore/src/presale.rs rename to crates/accounts/ethstore/src/presale.rs diff --git a/accounts/ethstore/src/random.rs b/crates/accounts/ethstore/src/random.rs similarity index 100% rename from accounts/ethstore/src/random.rs rename to crates/accounts/ethstore/src/random.rs diff --git a/accounts/ethstore/src/secret_store.rs b/crates/accounts/ethstore/src/secret_store.rs similarity index 100% rename from accounts/ethstore/src/secret_store.rs rename to crates/accounts/ethstore/src/secret_store.rs diff --git a/accounts/ethstore/tests/api.rs b/crates/accounts/ethstore/tests/api.rs similarity index 100% rename from accounts/ethstore/tests/api.rs rename to crates/accounts/ethstore/tests/api.rs diff --git a/accounts/ethstore/tests/res/ciphertext/30.json b/crates/accounts/ethstore/tests/res/ciphertext/30.json similarity index 100% rename from accounts/ethstore/tests/res/ciphertext/30.json rename to crates/accounts/ethstore/tests/res/ciphertext/30.json diff --git a/accounts/ethstore/tests/res/ciphertext/31.json b/crates/accounts/ethstore/tests/res/ciphertext/31.json similarity index 100% rename from accounts/ethstore/tests/res/ciphertext/31.json rename to crates/accounts/ethstore/tests/res/ciphertext/31.json diff --git a/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 b/crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 similarity index 100% rename from accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 rename to crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 diff --git a/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf b/crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf similarity index 100% rename from accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf rename to crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf diff --git a/accounts/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 b/crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 similarity index 100% rename from accounts/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 rename to crates/accounts/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 diff --git a/accounts/ethstore/tests/res/pat/p1.json b/crates/accounts/ethstore/tests/res/pat/p1.json similarity index 100% rename from accounts/ethstore/tests/res/pat/p1.json rename to crates/accounts/ethstore/tests/res/pat/p1.json diff --git a/accounts/ethstore/tests/res/pat/p2.json b/crates/accounts/ethstore/tests/res/pat/p2.json similarity index 100% rename from accounts/ethstore/tests/res/pat/p2.json rename to crates/accounts/ethstore/tests/res/pat/p2.json diff --git a/accounts/ethstore/tests/util/mod.rs b/crates/accounts/ethstore/tests/util/mod.rs similarity index 100% rename from accounts/ethstore/tests/util/mod.rs rename to crates/accounts/ethstore/tests/util/mod.rs diff --git a/accounts/ethstore/tests/util/transient_dir.rs b/crates/accounts/ethstore/tests/util/transient_dir.rs similarity index 100% rename from accounts/ethstore/tests/util/transient_dir.rs rename to crates/accounts/ethstore/tests/util/transient_dir.rs diff --git a/accounts/src/account_data.rs b/crates/accounts/src/account_data.rs similarity index 100% rename from accounts/src/account_data.rs rename to crates/accounts/src/account_data.rs diff --git a/accounts/src/error.rs b/crates/accounts/src/error.rs similarity index 100% rename from accounts/src/error.rs rename to crates/accounts/src/error.rs diff --git a/accounts/src/lib.rs b/crates/accounts/src/lib.rs similarity index 100% rename from accounts/src/lib.rs rename to crates/accounts/src/lib.rs diff --git a/accounts/src/stores.rs b/crates/accounts/src/stores.rs similarity index 100% rename from accounts/src/stores.rs rename to crates/accounts/src/stores.rs diff --git a/ethash/Cargo.toml b/crates/concensus/ethash/Cargo.toml similarity index 100% rename from ethash/Cargo.toml rename to crates/concensus/ethash/Cargo.toml diff --git a/ethash/benches/basic.rs b/crates/concensus/ethash/benches/basic.rs similarity index 100% rename from ethash/benches/basic.rs rename to crates/concensus/ethash/benches/basic.rs diff --git a/ethash/benches/progpow.rs b/crates/concensus/ethash/benches/progpow.rs similarity index 100% rename from ethash/benches/progpow.rs rename to crates/concensus/ethash/benches/progpow.rs diff --git a/ethash/res/progpow_testvectors.json b/crates/concensus/ethash/res/progpow_testvectors.json similarity index 100% rename from ethash/res/progpow_testvectors.json rename to crates/concensus/ethash/res/progpow_testvectors.json diff --git a/ethash/src/cache.rs b/crates/concensus/ethash/src/cache.rs similarity index 100% rename from ethash/src/cache.rs rename to crates/concensus/ethash/src/cache.rs diff --git a/ethash/src/compute.rs b/crates/concensus/ethash/src/compute.rs similarity index 100% rename from ethash/src/compute.rs rename to crates/concensus/ethash/src/compute.rs diff --git a/ethash/src/keccak.rs b/crates/concensus/ethash/src/keccak.rs similarity index 100% rename from ethash/src/keccak.rs rename to crates/concensus/ethash/src/keccak.rs diff --git a/ethash/src/lib.rs b/crates/concensus/ethash/src/lib.rs similarity index 100% rename from ethash/src/lib.rs rename to crates/concensus/ethash/src/lib.rs diff --git a/ethash/src/progpow.rs b/crates/concensus/ethash/src/progpow.rs similarity index 100% rename from ethash/src/progpow.rs rename to crates/concensus/ethash/src/progpow.rs diff --git a/ethash/src/seed_compute.rs b/crates/concensus/ethash/src/seed_compute.rs similarity index 100% rename from ethash/src/seed_compute.rs rename to crates/concensus/ethash/src/seed_compute.rs diff --git a/ethash/src/shared.rs b/crates/concensus/ethash/src/shared.rs similarity index 100% rename from ethash/src/shared.rs rename to crates/concensus/ethash/src/shared.rs diff --git a/miner/Cargo.toml b/crates/concensus/miner/Cargo.toml similarity index 73% rename from miner/Cargo.toml rename to crates/concensus/miner/Cargo.toml index 22e2e7dd84..d7bb02b56f 100644 --- a/miner/Cargo.toml +++ b/crates/concensus/miner/Cargo.toml @@ -8,26 +8,26 @@ authors = ["Parity Technologies "] [dependencies] # Only work_notify, consider a separate crate -ethash = { path = "../ethash", optional = true } -fetch = { path = "../util/fetch", optional = true } +ethash = { path = "../../concensus/ethash", optional = true } +fetch = { path = "../../net/fetch", optional = true } hyper = { version = "0.12", optional = true } url = { version = "2", optional = true } # Miner ansi_term = "0.10" -common-types = { path = "../ethcore/types" } +common-types = { path = "../../ethcore/types" } error-chain = "0.12" ethabi = "6.0" ethabi-derive = "6.0" ethabi-contract = "6.0" -ethcore-call-contract = { path = "../ethcore/call-contract" } +ethcore-call-contract = { path = "../../vm/call-contract" } ethereum-types = "0.4" futures = "0.1" heapsize = "0.4" keccak-hash = "0.1" linked-hash-map = "0.5" log = "0.4" -parity-runtime = { path = "../util/runtime" } +parity-runtime = { path = "../../runtime/runtime" } parking_lot = "0.7" price-info = { path = "./price-info", optional = true } rlp = { version = "0.3.0", features = ["ethereum"] } @@ -36,7 +36,7 @@ transaction-pool = "2.0.1" [dev-dependencies] env_logger = "0.5" -ethkey = { path = "../accounts/ethkey" } +ethkey = { path = "../../accounts/ethkey" } rustc-hex = "1.0" [features] diff --git a/miner/local-store/Cargo.toml b/crates/concensus/miner/local-store/Cargo.toml similarity index 70% rename from miner/local-store/Cargo.toml rename to crates/concensus/miner/local-store/Cargo.toml index d16c644071..db34cd7c7f 100644 --- a/miner/local-store/Cargo.toml +++ b/crates/concensus/miner/local-store/Cargo.toml @@ -5,8 +5,8 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -common-types = { path = "../../ethcore/types" } -ethcore-io = { path = "../../util/io" } +common-types = { path = "../../../ethcore/types" } +ethcore-io = { path = "../../../runtime/io" } kvdb = "0.1" log = "0.4" rlp = { version = "0.3.0", features = ["ethereum"] } @@ -15,5 +15,5 @@ serde_derive = "1.0" serde_json = "1.0" [dev-dependencies] -ethkey = { path = "../../accounts/ethkey" } +ethkey = { path = "../../../accounts/ethkey" } kvdb-memorydb = "0.1" diff --git a/miner/local-store/src/lib.rs b/crates/concensus/miner/local-store/src/lib.rs similarity index 100% rename from miner/local-store/src/lib.rs rename to crates/concensus/miner/local-store/src/lib.rs diff --git a/miner/price-info/Cargo.toml b/crates/concensus/miner/price-info/Cargo.toml similarity index 68% rename from miner/price-info/Cargo.toml rename to crates/concensus/miner/price-info/Cargo.toml index 0426b01b4b..3a884b24db 100644 --- a/miner/price-info/Cargo.toml +++ b/crates/concensus/miner/price-info/Cargo.toml @@ -7,12 +7,12 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] -fetch = { path = "../../util/fetch" } +fetch = { path = "../../../net/fetch" } futures = "0.1" -parity-runtime = { path = "../../util/runtime" } +parity-runtime = { path = "../../../runtime/runtime" } log = "0.4" serde_json = "1.0" [dev-dependencies] parking_lot = "0.7" -fake-fetch = { path = "../../util/fake-fetch" } +fake-fetch = { path = "../../../net/fake-fetch" } diff --git a/miner/price-info/src/lib.rs b/crates/concensus/miner/price-info/src/lib.rs similarity index 100% rename from miner/price-info/src/lib.rs rename to crates/concensus/miner/price-info/src/lib.rs diff --git a/miner/res/contracts/service_transaction.json b/crates/concensus/miner/res/contracts/service_transaction.json similarity index 100% rename from miner/res/contracts/service_transaction.json rename to crates/concensus/miner/res/contracts/service_transaction.json diff --git a/miner/src/external.rs b/crates/concensus/miner/src/external.rs similarity index 100% rename from miner/src/external.rs rename to crates/concensus/miner/src/external.rs diff --git a/miner/src/gas_price_calibrator.rs b/crates/concensus/miner/src/gas_price_calibrator.rs similarity index 100% rename from miner/src/gas_price_calibrator.rs rename to crates/concensus/miner/src/gas_price_calibrator.rs diff --git a/miner/src/gas_pricer.rs b/crates/concensus/miner/src/gas_pricer.rs similarity index 100% rename from miner/src/gas_pricer.rs rename to crates/concensus/miner/src/gas_pricer.rs diff --git a/miner/src/lib.rs b/crates/concensus/miner/src/lib.rs similarity index 100% rename from miner/src/lib.rs rename to crates/concensus/miner/src/lib.rs diff --git a/miner/src/local_accounts.rs b/crates/concensus/miner/src/local_accounts.rs similarity index 100% rename from miner/src/local_accounts.rs rename to crates/concensus/miner/src/local_accounts.rs diff --git a/miner/src/pool/client.rs b/crates/concensus/miner/src/pool/client.rs similarity index 100% rename from miner/src/pool/client.rs rename to crates/concensus/miner/src/pool/client.rs diff --git a/miner/src/pool/listener.rs b/crates/concensus/miner/src/pool/listener.rs similarity index 100% rename from miner/src/pool/listener.rs rename to crates/concensus/miner/src/pool/listener.rs diff --git a/miner/src/pool/local_transactions.rs b/crates/concensus/miner/src/pool/local_transactions.rs similarity index 100% rename from miner/src/pool/local_transactions.rs rename to crates/concensus/miner/src/pool/local_transactions.rs diff --git a/miner/src/pool/mod.rs b/crates/concensus/miner/src/pool/mod.rs similarity index 100% rename from miner/src/pool/mod.rs rename to crates/concensus/miner/src/pool/mod.rs diff --git a/miner/src/pool/queue.rs b/crates/concensus/miner/src/pool/queue.rs similarity index 100% rename from miner/src/pool/queue.rs rename to crates/concensus/miner/src/pool/queue.rs diff --git a/miner/src/pool/ready.rs b/crates/concensus/miner/src/pool/ready.rs similarity index 100% rename from miner/src/pool/ready.rs rename to crates/concensus/miner/src/pool/ready.rs diff --git a/miner/src/pool/replace.rs b/crates/concensus/miner/src/pool/replace.rs similarity index 100% rename from miner/src/pool/replace.rs rename to crates/concensus/miner/src/pool/replace.rs diff --git a/miner/src/pool/res/big_transaction.data b/crates/concensus/miner/src/pool/res/big_transaction.data similarity index 100% rename from miner/src/pool/res/big_transaction.data rename to crates/concensus/miner/src/pool/res/big_transaction.data diff --git a/miner/src/pool/scoring.rs b/crates/concensus/miner/src/pool/scoring.rs similarity index 100% rename from miner/src/pool/scoring.rs rename to crates/concensus/miner/src/pool/scoring.rs diff --git a/miner/src/pool/tests/client.rs b/crates/concensus/miner/src/pool/tests/client.rs similarity index 100% rename from miner/src/pool/tests/client.rs rename to crates/concensus/miner/src/pool/tests/client.rs diff --git a/miner/src/pool/tests/mod.rs b/crates/concensus/miner/src/pool/tests/mod.rs similarity index 100% rename from miner/src/pool/tests/mod.rs rename to crates/concensus/miner/src/pool/tests/mod.rs diff --git a/miner/src/pool/tests/tx.rs b/crates/concensus/miner/src/pool/tests/tx.rs similarity index 100% rename from miner/src/pool/tests/tx.rs rename to crates/concensus/miner/src/pool/tests/tx.rs diff --git a/miner/src/pool/verifier.rs b/crates/concensus/miner/src/pool/verifier.rs similarity index 100% rename from miner/src/pool/verifier.rs rename to crates/concensus/miner/src/pool/verifier.rs diff --git a/miner/src/service_transaction_checker.rs b/crates/concensus/miner/src/service_transaction_checker.rs similarity index 100% rename from miner/src/service_transaction_checker.rs rename to crates/concensus/miner/src/service_transaction_checker.rs diff --git a/miner/src/work_notify.rs b/crates/concensus/miner/src/work_notify.rs similarity index 100% rename from miner/src/work_notify.rs rename to crates/concensus/miner/src/work_notify.rs diff --git a/miner/stratum/Cargo.toml b/crates/concensus/miner/stratum/Cargo.toml similarity index 100% rename from miner/stratum/Cargo.toml rename to crates/concensus/miner/stratum/Cargo.toml diff --git a/miner/stratum/src/lib.rs b/crates/concensus/miner/stratum/src/lib.rs similarity index 100% rename from miner/stratum/src/lib.rs rename to crates/concensus/miner/stratum/src/lib.rs diff --git a/miner/stratum/src/traits.rs b/crates/concensus/miner/stratum/src/traits.rs similarity index 100% rename from miner/stratum/src/traits.rs rename to crates/concensus/miner/stratum/src/traits.rs diff --git a/miner/using-queue/Cargo.toml b/crates/concensus/miner/using-queue/Cargo.toml similarity index 100% rename from miner/using-queue/Cargo.toml rename to crates/concensus/miner/using-queue/Cargo.toml diff --git a/miner/using-queue/src/lib.rs b/crates/concensus/miner/using-queue/src/lib.rs similarity index 100% rename from miner/using-queue/src/lib.rs rename to crates/concensus/miner/using-queue/src/lib.rs diff --git a/util/bloom/Cargo.toml b/crates/db/bloom/Cargo.toml similarity index 100% rename from util/bloom/Cargo.toml rename to crates/db/bloom/Cargo.toml diff --git a/util/bloom/src/lib.rs b/crates/db/bloom/src/lib.rs similarity index 100% rename from util/bloom/src/lib.rs rename to crates/db/bloom/src/lib.rs diff --git a/util/blooms-db/Cargo.toml b/crates/db/blooms-db/Cargo.toml similarity index 100% rename from util/blooms-db/Cargo.toml rename to crates/db/blooms-db/Cargo.toml diff --git a/util/blooms-db/benches/blooms.rs b/crates/db/blooms-db/benches/blooms.rs similarity index 100% rename from util/blooms-db/benches/blooms.rs rename to crates/db/blooms-db/benches/blooms.rs diff --git a/util/blooms-db/src/db.rs b/crates/db/blooms-db/src/db.rs similarity index 100% rename from util/blooms-db/src/db.rs rename to crates/db/blooms-db/src/db.rs diff --git a/util/blooms-db/src/file.rs b/crates/db/blooms-db/src/file.rs similarity index 100% rename from util/blooms-db/src/file.rs rename to crates/db/blooms-db/src/file.rs diff --git a/util/blooms-db/src/lib.rs b/crates/db/blooms-db/src/lib.rs similarity index 100% rename from util/blooms-db/src/lib.rs rename to crates/db/blooms-db/src/lib.rs diff --git a/ethcore/db/Cargo.toml b/crates/db/db/Cargo.toml similarity index 90% rename from ethcore/db/Cargo.toml rename to crates/db/db/Cargo.toml index 2c730a758b..64f175c24a 100644 --- a/ethcore/db/Cargo.toml +++ b/crates/db/db/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -common-types = { path = "../types" } +common-types = { path = "../../ethcore/types" } ethereum-types = "0.4" heapsize = "0.4" kvdb = "0.1" diff --git a/ethcore/db/src/cache_manager.rs b/crates/db/db/src/cache_manager.rs similarity index 100% rename from ethcore/db/src/cache_manager.rs rename to crates/db/db/src/cache_manager.rs diff --git a/ethcore/db/src/db.rs b/crates/db/db/src/db.rs similarity index 100% rename from ethcore/db/src/db.rs rename to crates/db/db/src/db.rs diff --git a/ethcore/db/src/keys.rs b/crates/db/db/src/keys.rs similarity index 100% rename from ethcore/db/src/keys.rs rename to crates/db/db/src/keys.rs diff --git a/ethcore/db/src/lib.rs b/crates/db/db/src/lib.rs similarity index 100% rename from ethcore/db/src/lib.rs rename to crates/db/db/src/lib.rs diff --git a/util/journaldb/Cargo.toml b/crates/db/journaldb/Cargo.toml similarity index 85% rename from util/journaldb/Cargo.toml rename to crates/db/journaldb/Cargo.toml index f3750318ed..5ca9853ab6 100644 --- a/util/journaldb/Cargo.toml +++ b/crates/db/journaldb/Cargo.toml @@ -10,10 +10,10 @@ parity-bytes = "0.1" ethereum-types = "0.4" hash-db = "0.11.0" heapsize = "0.4" -keccak-hasher = { path = "../keccak-hasher" } +keccak-hasher = { path = "../../util/keccak-hasher" } kvdb = "0.1" log = "0.4" -memory-db = { path = "../../util/memory-db" } +memory-db = { path = "../memory-db" } parking_lot = "0.7" fastmap = { path = "../../util/fastmap" } rlp = { version = "0.3.0", features = ["ethereum"] } diff --git a/util/journaldb/src/archivedb.rs b/crates/db/journaldb/src/archivedb.rs similarity index 100% rename from util/journaldb/src/archivedb.rs rename to crates/db/journaldb/src/archivedb.rs diff --git a/util/journaldb/src/as_hash_db_impls.rs b/crates/db/journaldb/src/as_hash_db_impls.rs similarity index 100% rename from util/journaldb/src/as_hash_db_impls.rs rename to crates/db/journaldb/src/as_hash_db_impls.rs diff --git a/util/journaldb/src/earlymergedb.rs b/crates/db/journaldb/src/earlymergedb.rs similarity index 100% rename from util/journaldb/src/earlymergedb.rs rename to crates/db/journaldb/src/earlymergedb.rs diff --git a/util/journaldb/src/lib.rs b/crates/db/journaldb/src/lib.rs similarity index 100% rename from util/journaldb/src/lib.rs rename to crates/db/journaldb/src/lib.rs diff --git a/util/journaldb/src/overlaydb.rs b/crates/db/journaldb/src/overlaydb.rs similarity index 100% rename from util/journaldb/src/overlaydb.rs rename to crates/db/journaldb/src/overlaydb.rs diff --git a/util/journaldb/src/overlayrecentdb.rs b/crates/db/journaldb/src/overlayrecentdb.rs similarity index 100% rename from util/journaldb/src/overlayrecentdb.rs rename to crates/db/journaldb/src/overlayrecentdb.rs diff --git a/util/journaldb/src/refcounteddb.rs b/crates/db/journaldb/src/refcounteddb.rs similarity index 100% rename from util/journaldb/src/refcounteddb.rs rename to crates/db/journaldb/src/refcounteddb.rs diff --git a/util/journaldb/src/traits.rs b/crates/db/journaldb/src/traits.rs similarity index 100% rename from util/journaldb/src/traits.rs rename to crates/db/journaldb/src/traits.rs diff --git a/util/journaldb/src/util.rs b/crates/db/journaldb/src/util.rs similarity index 100% rename from util/journaldb/src/util.rs rename to crates/db/journaldb/src/util.rs diff --git a/util/memory-db/.cargo_vcs_info.json b/crates/db/memory-db/.cargo_vcs_info.json similarity index 100% rename from util/memory-db/.cargo_vcs_info.json rename to crates/db/memory-db/.cargo_vcs_info.json diff --git a/util/memory-db/Cargo.toml b/crates/db/memory-db/Cargo.toml similarity index 100% rename from util/memory-db/Cargo.toml rename to crates/db/memory-db/Cargo.toml diff --git a/util/memory-db/Cargo.toml.orig b/crates/db/memory-db/Cargo.toml.orig similarity index 100% rename from util/memory-db/Cargo.toml.orig rename to crates/db/memory-db/Cargo.toml.orig diff --git a/util/memory-db/README.md b/crates/db/memory-db/README.md similarity index 100% rename from util/memory-db/README.md rename to crates/db/memory-db/README.md diff --git a/util/memory-db/benches/bench.rs b/crates/db/memory-db/benches/bench.rs similarity index 100% rename from util/memory-db/benches/bench.rs rename to crates/db/memory-db/benches/bench.rs diff --git a/util/memory-db/src/lib.rs b/crates/db/memory-db/src/lib.rs similarity index 100% rename from util/memory-db/src/lib.rs rename to crates/db/memory-db/src/lib.rs diff --git a/util/migration-rocksdb/Cargo.toml b/crates/db/migration-rocksdb/Cargo.toml similarity index 83% rename from util/migration-rocksdb/Cargo.toml rename to crates/db/migration-rocksdb/Cargo.toml index 3cbfce09f5..025ed98cc9 100644 --- a/util/migration-rocksdb/Cargo.toml +++ b/crates/db/migration-rocksdb/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] [dependencies] log = "0.4" -macros = { path = "../macros" } +macros = { path = "../../util/macros" } kvdb = "0.1" kvdb-rocksdb = "0.1.3" diff --git a/util/migration-rocksdb/src/lib.rs b/crates/db/migration-rocksdb/src/lib.rs similarity index 100% rename from util/migration-rocksdb/src/lib.rs rename to crates/db/migration-rocksdb/src/lib.rs diff --git a/util/migration-rocksdb/tests/tests.rs b/crates/db/migration-rocksdb/tests/tests.rs similarity index 100% rename from util/migration-rocksdb/tests/tests.rs rename to crates/db/migration-rocksdb/tests/tests.rs diff --git a/util/patricia-trie-ethereum/Cargo.toml b/crates/db/patricia-trie-ethereum/Cargo.toml similarity index 86% rename from util/patricia-trie-ethereum/Cargo.toml rename to crates/db/patricia-trie-ethereum/Cargo.toml index 205201a2db..1a2bdf3446 100644 --- a/util/patricia-trie-ethereum/Cargo.toml +++ b/crates/db/patricia-trie-ethereum/Cargo.toml @@ -7,7 +7,7 @@ license = "GPL-3.0" [dependencies] trie-db = "0.11.0" -keccak-hasher = { version = "0.1.1", path = "../keccak-hasher" } +keccak-hasher = { version = "0.1.1", path = "../../util/keccak-hasher" } hash-db = "0.11.0" rlp = { version = "0.3.0", features = ["ethereum"] } parity-bytes = "0.1" diff --git a/util/patricia-trie-ethereum/src/lib.rs b/crates/db/patricia-trie-ethereum/src/lib.rs similarity index 100% rename from util/patricia-trie-ethereum/src/lib.rs rename to crates/db/patricia-trie-ethereum/src/lib.rs diff --git a/util/patricia-trie-ethereum/src/rlp_node_codec.rs b/crates/db/patricia-trie-ethereum/src/rlp_node_codec.rs similarity index 100% rename from util/patricia-trie-ethereum/src/rlp_node_codec.rs rename to crates/db/patricia-trie-ethereum/src/rlp_node_codec.rs diff --git a/ethcore/Cargo.toml b/crates/ethcore/Cargo.toml similarity index 78% rename from ethcore/Cargo.toml rename to crates/ethcore/Cargo.toml index 62e82d3ff4..57c75a9671 100644 --- a/ethcore/Cargo.toml +++ b/crates/ethcore/Cargo.toml @@ -8,7 +8,7 @@ authors = ["Parity Technologies "] [dependencies] ansi_term = "0.10" -blooms-db = { path = "../util/blooms-db", optional = true } +blooms-db = { path = "../db/blooms-db", optional = true } common-types = { path = "types" } crossbeam-utils = "0.6" eip-152 = { version = "0.1", path = "../util/EIP-152" } @@ -17,24 +17,24 @@ error-chain = { version = "0.12", default-features = false } ethabi = "6.0" ethabi-contract = "6.0" ethabi-derive = "6.0" -ethash = { path = "../ethash" } +ethash = { path = "../concensus/ethash" } ethcore-blockchain = { path = "./blockchain" } -ethcore-bloom-journal = { path = "../util/bloom" } -ethcore-builtin = { path = "./builtin" } -ethcore-call-contract = { path = "./call-contract" } -ethcore-db = { path = "./db" } -ethcore-io = { path = "../util/io" } -ethcore-miner = { path = "../miner" } -ethcore-stratum = { path = "../miner/stratum", optional = true } +ethcore-bloom-journal = { path = "../db/bloom" } +ethcore-builtin = { path = "../vm/builtin" } +ethcore-call-contract = { path = "../vm/call-contract" } +ethcore-db = { path = "../db/db" } +ethcore-io = { path = "../runtime/io" } +ethcore-miner = { path = "../concensus/miner" } +ethcore-stratum = { path = "../concensus/miner/stratum", optional = true } ethereum-types = "0.4" -ethjson = { path = "../json" } +ethjson = { path = "../ethjson" } ethkey = { path = "../accounts/ethkey" } -evm = { path = "evm" } +evm = { path = "../vm/evm" } globset = "0.4" hash-db = "0.11.0" heapsize = "0.4" itertools = "0.5" -journaldb = { path = "../util/journaldb" } +journaldb = { path = "../db/journaldb" } keccak-hash = "0.1" keccak-hasher = { path = "../util/keccak-hasher" } kvdb = "0.1" @@ -47,13 +47,13 @@ lru-cache = "0.1" macros = { path = "../util/macros" } maplit = "1" memory-cache = { path = "../util/memory-cache" } -memory-db = { path = "../util/memory-db" } +memory-db = { path = "../db/memory-db" } num_cpus = "1.2" parity-bytes = "0.1" parity-snappy = "0.1" parking_lot = "0.7" trie-db = "0.11.0" -patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" } +patricia-trie-ethereum = { path = "../db/patricia-trie-ethereum" } rand = "0.4" rayon = "1.1" regex = "1.3.9" @@ -70,20 +70,20 @@ time-utils = { path = "../util/time-utils" } trace-time = "0.1" triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" } unexpected = { path = "../util/unexpected" } -using_queue = { path = "../miner/using-queue" } -vm = { path = "vm" } +using_queue = { path = "../concensus/miner/using-queue" } +vm = { path = "../vm/vm" } walkdir = "2.3" -wasm = { path = "wasm" } +wasm = { path = "../vm/wasm" } [dev-dependencies] -blooms-db = { path = "../util/blooms-db" } +blooms-db = { path = "../db/blooms-db" } criterion = "0.2" env_logger = "0.5" ethcore-accounts = { path = "../accounts" } -fetch = { path = "../util/fetch" } +fetch = { path = "../net/fetch" } hex-literal = "0.2.1" kvdb-rocksdb = "0.1.3" -parity-runtime = { path = "../util/runtime" } +parity-runtime = { path = "../runtime/runtime" } rlp_compress = { path = "../util/rlp-compress" } tempdir = "0.3" trie-standardmap = "0.1" diff --git a/ethcore/benches/builtin.rs b/crates/ethcore/benches/builtin.rs similarity index 100% rename from ethcore/benches/builtin.rs rename to crates/ethcore/benches/builtin.rs diff --git a/ethcore/blockchain/Cargo.toml b/crates/ethcore/blockchain/Cargo.toml similarity index 92% rename from ethcore/blockchain/Cargo.toml rename to crates/ethcore/blockchain/Cargo.toml index d627341de8..d20a238895 100644 --- a/ethcore/blockchain/Cargo.toml +++ b/crates/ethcore/blockchain/Cargo.toml @@ -9,9 +9,9 @@ edition = "2018" [dependencies] ansi_term = "0.11" -blooms-db = { path = "../../util/blooms-db" } +blooms-db = { path = "../../db/blooms-db" } common-types = { path = "../types" } -ethcore-db = { path = "../db" } +ethcore-db = { path = "../../db/db" } ethereum-types = "0.4" heapsize = "0.4" itertools = "0.5" diff --git a/ethcore/blockchain/src/best_block.rs b/crates/ethcore/blockchain/src/best_block.rs similarity index 100% rename from ethcore/blockchain/src/best_block.rs rename to crates/ethcore/blockchain/src/best_block.rs diff --git a/ethcore/blockchain/src/block_info.rs b/crates/ethcore/blockchain/src/block_info.rs similarity index 100% rename from ethcore/blockchain/src/block_info.rs rename to crates/ethcore/blockchain/src/block_info.rs diff --git a/ethcore/blockchain/src/blockchain.rs b/crates/ethcore/blockchain/src/blockchain.rs similarity index 100% rename from ethcore/blockchain/src/blockchain.rs rename to crates/ethcore/blockchain/src/blockchain.rs diff --git a/ethcore/blockchain/src/cache.rs b/crates/ethcore/blockchain/src/cache.rs similarity index 100% rename from ethcore/blockchain/src/cache.rs rename to crates/ethcore/blockchain/src/cache.rs diff --git a/ethcore/blockchain/src/config.rs b/crates/ethcore/blockchain/src/config.rs similarity index 100% rename from ethcore/blockchain/src/config.rs rename to crates/ethcore/blockchain/src/config.rs diff --git a/ethcore/blockchain/src/generator.rs b/crates/ethcore/blockchain/src/generator.rs similarity index 100% rename from ethcore/blockchain/src/generator.rs rename to crates/ethcore/blockchain/src/generator.rs diff --git a/ethcore/blockchain/src/import_route.rs b/crates/ethcore/blockchain/src/import_route.rs similarity index 100% rename from ethcore/blockchain/src/import_route.rs rename to crates/ethcore/blockchain/src/import_route.rs diff --git a/ethcore/blockchain/src/lib.rs b/crates/ethcore/blockchain/src/lib.rs similarity index 100% rename from ethcore/blockchain/src/lib.rs rename to crates/ethcore/blockchain/src/lib.rs diff --git a/ethcore/blockchain/src/update.rs b/crates/ethcore/blockchain/src/update.rs similarity index 100% rename from ethcore/blockchain/src/update.rs rename to crates/ethcore/blockchain/src/update.rs diff --git a/ethcore/res/ethereum/callisto.json b/crates/ethcore/res/chainspec/callisto.json similarity index 100% rename from ethcore/res/ethereum/callisto.json rename to crates/ethcore/res/chainspec/callisto.json diff --git a/ethcore/res/ethereum/ellaism.json b/crates/ethcore/res/chainspec/ellaism.json similarity index 100% rename from ethcore/res/ethereum/ellaism.json rename to crates/ethcore/res/chainspec/ellaism.json diff --git a/ethcore/res/ethereum/ewc.json b/crates/ethcore/res/chainspec/ewc.json similarity index 100% rename from ethcore/res/ethereum/ewc.json rename to crates/ethcore/res/chainspec/ewc.json diff --git a/ethcore/res/ethereum/foundation.json b/crates/ethcore/res/chainspec/foundation.json similarity index 100% rename from ethcore/res/ethereum/foundation.json rename to crates/ethcore/res/chainspec/foundation.json diff --git a/ethcore/res/ethereum/goerli.json b/crates/ethcore/res/chainspec/goerli.json similarity index 100% rename from ethcore/res/ethereum/goerli.json rename to crates/ethcore/res/chainspec/goerli.json diff --git a/ethcore/res/instant_seal.json b/crates/ethcore/res/chainspec/instant_seal.json similarity index 100% rename from ethcore/res/instant_seal.json rename to crates/ethcore/res/chainspec/instant_seal.json diff --git a/ethcore/res/ethereum/kovan.json b/crates/ethcore/res/chainspec/kovan.json similarity index 100% rename from ethcore/res/ethereum/kovan.json rename to crates/ethcore/res/chainspec/kovan.json diff --git a/ethcore/res/ethereum/mix.json b/crates/ethcore/res/chainspec/mix.json similarity index 100% rename from ethcore/res/ethereum/mix.json rename to crates/ethcore/res/chainspec/mix.json diff --git a/ethcore/res/ethereum/morden.json b/crates/ethcore/res/chainspec/morden.json similarity index 100% rename from ethcore/res/ethereum/morden.json rename to crates/ethcore/res/chainspec/morden.json diff --git a/ethcore/res/ethereum/musicoin.json b/crates/ethcore/res/chainspec/musicoin.json similarity index 100% rename from ethcore/res/ethereum/musicoin.json rename to crates/ethcore/res/chainspec/musicoin.json diff --git a/ethcore/res/ethereum/poacore.json b/crates/ethcore/res/chainspec/poacore.json similarity index 100% rename from ethcore/res/ethereum/poacore.json rename to crates/ethcore/res/chainspec/poacore.json diff --git a/ethcore/res/ethereum/poasokol.json b/crates/ethcore/res/chainspec/poasokol.json similarity index 100% rename from ethcore/res/ethereum/poasokol.json rename to crates/ethcore/res/chainspec/poasokol.json diff --git a/ethcore/res/ethereum/rinkeby.json b/crates/ethcore/res/chainspec/rinkeby.json similarity index 100% rename from ethcore/res/ethereum/rinkeby.json rename to crates/ethcore/res/chainspec/rinkeby.json diff --git a/ethcore/res/ethereum/ropsten.json b/crates/ethcore/res/chainspec/ropsten.json similarity index 100% rename from ethcore/res/ethereum/ropsten.json rename to crates/ethcore/res/chainspec/ropsten.json diff --git a/ethcore/res/authority_round.json b/crates/ethcore/res/chainspec/test/authority_round.json similarity index 100% rename from ethcore/res/authority_round.json rename to crates/ethcore/res/chainspec/test/authority_round.json diff --git a/ethcore/res/authority_round_block_reward_contract.json b/crates/ethcore/res/chainspec/test/authority_round_block_reward_contract.json similarity index 100% rename from ethcore/res/authority_round_block_reward_contract.json rename to crates/ethcore/res/chainspec/test/authority_round_block_reward_contract.json diff --git a/ethcore/res/authority_round_empty_steps.json b/crates/ethcore/res/chainspec/test/authority_round_empty_steps.json similarity index 100% rename from ethcore/res/authority_round_empty_steps.json rename to crates/ethcore/res/chainspec/test/authority_round_empty_steps.json diff --git a/ethcore/res/basic_authority.json b/crates/ethcore/res/chainspec/test/basic_authority.json similarity index 100% rename from ethcore/res/basic_authority.json rename to crates/ethcore/res/chainspec/test/basic_authority.json diff --git a/ethcore/res/ethereum/berlin_test.json b/crates/ethcore/res/chainspec/test/berlin_test.json similarity index 100% rename from ethcore/res/ethereum/berlin_test.json rename to crates/ethcore/res/chainspec/test/berlin_test.json diff --git a/ethcore/res/ethereum/builtin_multi_bench.json b/crates/ethcore/res/chainspec/test/builtin_multi_bench.json similarity index 100% rename from ethcore/res/ethereum/builtin_multi_bench.json rename to crates/ethcore/res/chainspec/test/builtin_multi_bench.json diff --git a/ethcore/res/ethereum/builtin_one_activation_bench.json b/crates/ethcore/res/chainspec/test/builtin_one_activation_bench.json similarity index 100% rename from ethcore/res/ethereum/builtin_one_activation_bench.json rename to crates/ethcore/res/chainspec/test/builtin_one_activation_bench.json diff --git a/ethcore/res/ethereum/byzantium_test.json b/crates/ethcore/res/chainspec/test/byzantium_test.json similarity index 100% rename from ethcore/res/ethereum/byzantium_test.json rename to crates/ethcore/res/chainspec/test/byzantium_test.json diff --git a/ethcore/res/ethereum/byzantium_to_constantinoplefixat5_test.json b/crates/ethcore/res/chainspec/test/byzantium_to_constantinoplefixat5_test.json similarity index 100% rename from ethcore/res/ethereum/byzantium_to_constantinoplefixat5_test.json rename to crates/ethcore/res/chainspec/test/byzantium_to_constantinoplefixat5_test.json diff --git a/ethcore/res/ethereum/constantinople_test.json b/crates/ethcore/res/chainspec/test/constantinople_test.json similarity index 100% rename from ethcore/res/ethereum/constantinople_test.json rename to crates/ethcore/res/chainspec/test/constantinople_test.json diff --git a/ethcore/res/constructor.json b/crates/ethcore/res/chainspec/test/constructor.json similarity index 100% rename from ethcore/res/constructor.json rename to crates/ethcore/res/chainspec/test/constructor.json diff --git a/ethcore/res/tx_permission_tests/contract_ver_2_genesis.json b/crates/ethcore/res/chainspec/test/contract_ver_2_genesis.json similarity index 100% rename from ethcore/res/tx_permission_tests/contract_ver_2_genesis.json rename to crates/ethcore/res/chainspec/test/contract_ver_2_genesis.json diff --git a/ethcore/res/tx_permission_tests/deprecated_contract_genesis.json b/crates/ethcore/res/chainspec/test/deprecated_contract_genesis.json similarity index 100% rename from ethcore/res/tx_permission_tests/deprecated_contract_genesis.json rename to crates/ethcore/res/chainspec/test/deprecated_contract_genesis.json diff --git a/ethcore/res/ethereum/eip150_test.json b/crates/ethcore/res/chainspec/test/eip150_test.json similarity index 100% rename from ethcore/res/ethereum/eip150_test.json rename to crates/ethcore/res/chainspec/test/eip150_test.json diff --git a/ethcore/res/ethereum/eip161_test.json b/crates/ethcore/res/chainspec/test/eip161_test.json similarity index 100% rename from ethcore/res/ethereum/eip161_test.json rename to crates/ethcore/res/chainspec/test/eip161_test.json diff --git a/ethcore/res/ethereum/eip210_test.json b/crates/ethcore/res/chainspec/test/eip210_test.json similarity index 100% rename from ethcore/res/ethereum/eip210_test.json rename to crates/ethcore/res/chainspec/test/eip210_test.json diff --git a/ethcore/res/ethereum/frontier_like_test.json b/crates/ethcore/res/chainspec/test/frontier_like_test.json similarity index 100% rename from ethcore/res/ethereum/frontier_like_test.json rename to crates/ethcore/res/chainspec/test/frontier_like_test.json diff --git a/ethcore/res/ethereum/frontier_test.json b/crates/ethcore/res/chainspec/test/frontier_test.json similarity index 100% rename from ethcore/res/ethereum/frontier_test.json rename to crates/ethcore/res/chainspec/test/frontier_test.json diff --git a/ethcore/res/ethereum/homestead_test.json b/crates/ethcore/res/chainspec/test/homestead_test.json similarity index 100% rename from ethcore/res/ethereum/homestead_test.json rename to crates/ethcore/res/chainspec/test/homestead_test.json diff --git a/ethcore/res/ethereum/istanbul_test.json b/crates/ethcore/res/chainspec/test/istanbul_test.json similarity index 100% rename from ethcore/res/ethereum/istanbul_test.json rename to crates/ethcore/res/chainspec/test/istanbul_test.json diff --git a/ethcore/res/ethereum/kovan_wasm_test.json b/crates/ethcore/res/chainspec/test/kovan_wasm_test.json similarity index 100% rename from ethcore/res/ethereum/kovan_wasm_test.json rename to crates/ethcore/res/chainspec/test/kovan_wasm_test.json diff --git a/ethcore/res/ethereum/mcip3_test.json b/crates/ethcore/res/chainspec/test/mcip3_test.json similarity index 100% rename from ethcore/res/ethereum/mcip3_test.json rename to crates/ethcore/res/chainspec/test/mcip3_test.json diff --git a/ethcore/res/null.json b/crates/ethcore/res/chainspec/test/null.json similarity index 100% rename from ethcore/res/null.json rename to crates/ethcore/res/chainspec/test/null.json diff --git a/ethcore/res/null_morden.json b/crates/ethcore/res/chainspec/test/null_morden.json similarity index 100% rename from ethcore/res/null_morden.json rename to crates/ethcore/res/chainspec/test/null_morden.json diff --git a/ethcore/res/null_morden_with_finality.json b/crates/ethcore/res/chainspec/test/null_morden_with_finality.json similarity index 100% rename from ethcore/res/null_morden_with_finality.json rename to crates/ethcore/res/chainspec/test/null_morden_with_finality.json diff --git a/ethcore/res/null_morden_with_reward.json b/crates/ethcore/res/chainspec/test/null_morden_with_reward.json similarity index 100% rename from ethcore/res/null_morden_with_reward.json rename to crates/ethcore/res/chainspec/test/null_morden_with_reward.json diff --git a/ethcore/res/spec_backward_compability.json b/crates/ethcore/res/chainspec/test/spec_backward_compability.json similarity index 100% rename from ethcore/res/spec_backward_compability.json rename to crates/ethcore/res/chainspec/test/spec_backward_compability.json diff --git a/ethcore/res/ethereum/st_peters_test.json b/crates/ethcore/res/chainspec/test/st_peters_test.json similarity index 100% rename from ethcore/res/ethereum/st_peters_test.json rename to crates/ethcore/res/chainspec/test/st_peters_test.json diff --git a/ethcore/res/ethereum/transition_test.json b/crates/ethcore/res/chainspec/test/transition_test.json similarity index 100% rename from ethcore/res/ethereum/transition_test.json rename to crates/ethcore/res/chainspec/test/transition_test.json diff --git a/ethcore/res/validator_contract.json b/crates/ethcore/res/chainspec/test/validator_contract.json similarity index 100% rename from ethcore/res/validator_contract.json rename to crates/ethcore/res/chainspec/test/validator_contract.json diff --git a/ethcore/res/validator_multi.json b/crates/ethcore/res/chainspec/test/validator_multi.json similarity index 100% rename from ethcore/res/validator_multi.json rename to crates/ethcore/res/chainspec/test/validator_multi.json diff --git a/ethcore/res/validator_safe_contract.json b/crates/ethcore/res/chainspec/test/validator_safe_contract.json similarity index 100% rename from ethcore/res/validator_safe_contract.json rename to crates/ethcore/res/chainspec/test/validator_safe_contract.json diff --git a/ethcore/res/ethereum/yolo3_test.json b/crates/ethcore/res/chainspec/test/yolo3_test.json similarity index 100% rename from ethcore/res/ethereum/yolo3_test.json rename to crates/ethcore/res/chainspec/test/yolo3_test.json diff --git a/ethcore/res/ethereum/volta.json b/crates/ethcore/res/chainspec/volta.json similarity index 100% rename from ethcore/res/ethereum/volta.json rename to crates/ethcore/res/chainspec/volta.json diff --git a/ethcore/res/ethereum/xdai.json b/crates/ethcore/res/chainspec/xdai.json similarity index 100% rename from ethcore/res/ethereum/xdai.json rename to crates/ethcore/res/chainspec/xdai.json diff --git a/ethcore/res/contracts/block_reward.json b/crates/ethcore/res/contracts/block_reward.json similarity index 100% rename from ethcore/res/contracts/block_reward.json rename to crates/ethcore/res/contracts/block_reward.json diff --git a/ethcore/res/contracts/registrar.json b/crates/ethcore/res/contracts/registrar.json similarity index 99% rename from ethcore/res/contracts/registrar.json rename to crates/ethcore/res/contracts/registrar.json index 38edcc7877..2f4aab1fdb 100644 --- a/ethcore/res/contracts/registrar.json +++ b/crates/ethcore/res/contracts/registrar.json @@ -18,4 +18,4 @@ {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"type":"function"}, {"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"type":"function"}, {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"key","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"} -] +] \ No newline at end of file diff --git a/ethcore/res/contracts/test_validator_set.json b/crates/ethcore/res/contracts/test_validator_set.json similarity index 100% rename from ethcore/res/contracts/test_validator_set.json rename to crates/ethcore/res/contracts/test_validator_set.json diff --git a/ethcore/res/contracts/tx_acl.json b/crates/ethcore/res/contracts/tx_acl.json similarity index 100% rename from ethcore/res/contracts/tx_acl.json rename to crates/ethcore/res/contracts/tx_acl.json diff --git a/ethcore/res/contracts/tx_acl_deprecated.json b/crates/ethcore/res/contracts/tx_acl_deprecated.json similarity index 100% rename from ethcore/res/contracts/tx_acl_deprecated.json rename to crates/ethcore/res/contracts/tx_acl_deprecated.json diff --git a/ethcore/res/contracts/validator_report.json b/crates/ethcore/res/contracts/validator_report.json similarity index 100% rename from ethcore/res/contracts/validator_report.json rename to crates/ethcore/res/contracts/validator_report.json diff --git a/ethcore/res/contracts/validator_set.json b/crates/ethcore/res/contracts/validator_set.json similarity index 100% rename from ethcore/res/contracts/validator_set.json rename to crates/ethcore/res/contracts/validator_set.json diff --git a/ethcore/res/ethereum/tests b/crates/ethcore/res/json_tests similarity index 100% rename from ethcore/res/ethereum/tests rename to crates/ethcore/res/json_tests diff --git a/crates/ethcore/res/json_tests.json b/crates/ethcore/res/json_tests.json new file mode 100644 index 0000000000..7fa2059846 --- /dev/null +++ b/crates/ethcore/res/json_tests.json @@ -0,0 +1,60 @@ +{ + "chain": [ + { + "path": "res/json_tests/BlockchainTests", + "skip" : [] + }, + { + "path": "res/json_tests/LegacyTests/Constantinople/BlockchainTests", + "skip" : [] + } + ], + "state": [ + { + "path": "res/json_tests/GeneralStateTests", + "skip" : [] + + }, + { + "path": "res/json_tests/LegacyTests/Constantinople/GeneralStateTests", + "skip" : [] + + } + ], + "difficulty": [ + { + "path": [ + "res/json_tests/BasicTests/difficulty.json", + "res/json_tests/BasicTests/difficultyMainNetwork.json" + ], + "chainspec": "Foundation" + } + ], + "executive": [ + { + "path": "res/json_tests/VMTests" + } + ], + "transaction": [ + { + "path": "res/json_tests/TransactionTests" + } + ], + "trie": [ + { + "path": [ + "res/json_tests/TrieTests/trietest.json", + "res/json_tests/TrieTests/trieanyorder.json" + ], + "triespec": "Generic" + }, + { + "path": [ + "res/json_tests/TrieTests/hex_encoded_securetrie_test.json", + "res/json_tests/TrieTests/trietest_secureTrie.json", + "res/json_tests/TrieTests/trieanyorder_secureTrie.json" + ], + "triespec": "Secure" + } + ] +} \ No newline at end of file diff --git a/ethcore/service/Cargo.toml b/crates/ethcore/service/Cargo.toml similarity index 88% rename from ethcore/service/Cargo.toml rename to crates/ethcore/service/Cargo.toml index 68c73b4f90..cd0f9e1122 100644 --- a/ethcore/service/Cargo.toml +++ b/crates/ethcore/service/Cargo.toml @@ -9,7 +9,7 @@ ansi_term = "0.10" error-chain = { version = "0.12", default-features = false } ethcore = { path = ".." } ethcore-blockchain = { path = "../blockchain" } -ethcore-io = { path = "../../util/io" } +ethcore-io = { path = "../../runtime/io" } ethcore-sync = { path = "../sync" } ethereum-types = "0.4" kvdb = "0.1" @@ -17,7 +17,7 @@ log = "0.4" trace-time = "0.1" [dev-dependencies] -ethcore-db = { path = "../db" } +ethcore-db = { path = "../../db/db" } ethcore = { path = "..", features = ["test-helpers"] } tempdir = "0.3" kvdb-rocksdb = "0.1.3" diff --git a/ethcore/service/src/error.rs b/crates/ethcore/service/src/error.rs similarity index 100% rename from ethcore/service/src/error.rs rename to crates/ethcore/service/src/error.rs diff --git a/ethcore/service/src/lib.rs b/crates/ethcore/service/src/lib.rs similarity index 100% rename from ethcore/service/src/lib.rs rename to crates/ethcore/service/src/lib.rs diff --git a/ethcore/service/src/service.rs b/crates/ethcore/service/src/service.rs similarity index 100% rename from ethcore/service/src/service.rs rename to crates/ethcore/service/src/service.rs diff --git a/ethcore/service/src/stop_guard.rs b/crates/ethcore/service/src/stop_guard.rs similarity index 100% rename from ethcore/service/src/stop_guard.rs rename to crates/ethcore/service/src/stop_guard.rs diff --git a/ethcore/src/account_db.rs b/crates/ethcore/src/account_db.rs similarity index 100% rename from ethcore/src/account_db.rs rename to crates/ethcore/src/account_db.rs diff --git a/ethcore/src/block.rs b/crates/ethcore/src/block.rs similarity index 100% rename from ethcore/src/block.rs rename to crates/ethcore/src/block.rs diff --git a/ethcore/src/client/ancient_import.rs b/crates/ethcore/src/client/ancient_import.rs similarity index 100% rename from ethcore/src/client/ancient_import.rs rename to crates/ethcore/src/client/ancient_import.rs diff --git a/ethcore/src/client/bad_blocks.rs b/crates/ethcore/src/client/bad_blocks.rs similarity index 100% rename from ethcore/src/client/bad_blocks.rs rename to crates/ethcore/src/client/bad_blocks.rs diff --git a/ethcore/src/client/chain_notify.rs b/crates/ethcore/src/client/chain_notify.rs similarity index 100% rename from ethcore/src/client/chain_notify.rs rename to crates/ethcore/src/client/chain_notify.rs diff --git a/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs similarity index 100% rename from ethcore/src/client/client.rs rename to crates/ethcore/src/client/client.rs diff --git a/ethcore/src/client/config.rs b/crates/ethcore/src/client/config.rs similarity index 100% rename from ethcore/src/client/config.rs rename to crates/ethcore/src/client/config.rs diff --git a/ethcore/src/client/evm_test_client.rs b/crates/ethcore/src/client/evm_test_client.rs similarity index 100% rename from ethcore/src/client/evm_test_client.rs rename to crates/ethcore/src/client/evm_test_client.rs diff --git a/ethcore/src/client/io_message.rs b/crates/ethcore/src/client/io_message.rs similarity index 100% rename from ethcore/src/client/io_message.rs rename to crates/ethcore/src/client/io_message.rs diff --git a/ethcore/src/client/mod.rs b/crates/ethcore/src/client/mod.rs similarity index 100% rename from ethcore/src/client/mod.rs rename to crates/ethcore/src/client/mod.rs diff --git a/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs similarity index 100% rename from ethcore/src/client/test_client.rs rename to crates/ethcore/src/client/test_client.rs diff --git a/ethcore/src/client/trace.rs b/crates/ethcore/src/client/trace.rs similarity index 100% rename from ethcore/src/client/trace.rs rename to crates/ethcore/src/client/trace.rs diff --git a/ethcore/src/client/traits.rs b/crates/ethcore/src/client/traits.rs similarity index 100% rename from ethcore/src/client/traits.rs rename to crates/ethcore/src/client/traits.rs diff --git a/ethcore/src/engines/authority_round/finality.rs b/crates/ethcore/src/engines/authority_round/finality.rs similarity index 100% rename from ethcore/src/engines/authority_round/finality.rs rename to crates/ethcore/src/engines/authority_round/finality.rs diff --git a/ethcore/src/engines/authority_round/mod.rs b/crates/ethcore/src/engines/authority_round/mod.rs similarity index 100% rename from ethcore/src/engines/authority_round/mod.rs rename to crates/ethcore/src/engines/authority_round/mod.rs diff --git a/ethcore/src/engines/basic_authority.rs b/crates/ethcore/src/engines/basic_authority.rs similarity index 99% rename from ethcore/src/engines/basic_authority.rs rename to crates/ethcore/src/engines/basic_authority.rs index 51f1a2bbe3..8164e65a6b 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/crates/ethcore/src/engines/basic_authority.rs @@ -233,7 +233,7 @@ mod tests { /// Create a new test chain spec with `BasicAuthority` consensus engine. fn new_test_authority() -> Spec { - let bytes: &[u8] = include_bytes!("../../res/basic_authority.json"); + let bytes: &[u8] = include_bytes!("../../res/chainspec/test/basic_authority.json"); let tempdir = TempDir::new("").unwrap(); Spec::load(&tempdir.path(), bytes).expect("invalid chain spec") } diff --git a/ethcore/src/engines/block_reward.rs b/crates/ethcore/src/engines/block_reward.rs similarity index 100% rename from ethcore/src/engines/block_reward.rs rename to crates/ethcore/src/engines/block_reward.rs diff --git a/ethcore/src/engines/clique/block_state.rs b/crates/ethcore/src/engines/clique/block_state.rs similarity index 100% rename from ethcore/src/engines/clique/block_state.rs rename to crates/ethcore/src/engines/clique/block_state.rs diff --git a/ethcore/src/engines/clique/mod.rs b/crates/ethcore/src/engines/clique/mod.rs similarity index 100% rename from ethcore/src/engines/clique/mod.rs rename to crates/ethcore/src/engines/clique/mod.rs diff --git a/ethcore/src/engines/clique/params.rs b/crates/ethcore/src/engines/clique/params.rs similarity index 100% rename from ethcore/src/engines/clique/params.rs rename to crates/ethcore/src/engines/clique/params.rs diff --git a/ethcore/src/engines/clique/tests.rs b/crates/ethcore/src/engines/clique/tests.rs similarity index 100% rename from ethcore/src/engines/clique/tests.rs rename to crates/ethcore/src/engines/clique/tests.rs diff --git a/ethcore/src/engines/clique/util.rs b/crates/ethcore/src/engines/clique/util.rs similarity index 100% rename from ethcore/src/engines/clique/util.rs rename to crates/ethcore/src/engines/clique/util.rs diff --git a/ethcore/src/engines/instant_seal.rs b/crates/ethcore/src/engines/instant_seal.rs similarity index 100% rename from ethcore/src/engines/instant_seal.rs rename to crates/ethcore/src/engines/instant_seal.rs diff --git a/ethcore/src/engines/mod.rs b/crates/ethcore/src/engines/mod.rs similarity index 100% rename from ethcore/src/engines/mod.rs rename to crates/ethcore/src/engines/mod.rs diff --git a/ethcore/src/engines/null_engine.rs b/crates/ethcore/src/engines/null_engine.rs similarity index 100% rename from ethcore/src/engines/null_engine.rs rename to crates/ethcore/src/engines/null_engine.rs diff --git a/ethcore/src/engines/signer.rs b/crates/ethcore/src/engines/signer.rs similarity index 100% rename from ethcore/src/engines/signer.rs rename to crates/ethcore/src/engines/signer.rs diff --git a/ethcore/src/engines/validator_set/contract.rs b/crates/ethcore/src/engines/validator_set/contract.rs similarity index 100% rename from ethcore/src/engines/validator_set/contract.rs rename to crates/ethcore/src/engines/validator_set/contract.rs diff --git a/ethcore/src/engines/validator_set/mod.rs b/crates/ethcore/src/engines/validator_set/mod.rs similarity index 100% rename from ethcore/src/engines/validator_set/mod.rs rename to crates/ethcore/src/engines/validator_set/mod.rs diff --git a/ethcore/src/engines/validator_set/multi.rs b/crates/ethcore/src/engines/validator_set/multi.rs similarity index 100% rename from ethcore/src/engines/validator_set/multi.rs rename to crates/ethcore/src/engines/validator_set/multi.rs diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/crates/ethcore/src/engines/validator_set/safe_contract.rs similarity index 100% rename from ethcore/src/engines/validator_set/safe_contract.rs rename to crates/ethcore/src/engines/validator_set/safe_contract.rs diff --git a/ethcore/src/engines/validator_set/simple_list.rs b/crates/ethcore/src/engines/validator_set/simple_list.rs similarity index 100% rename from ethcore/src/engines/validator_set/simple_list.rs rename to crates/ethcore/src/engines/validator_set/simple_list.rs diff --git a/ethcore/src/engines/validator_set/test.rs b/crates/ethcore/src/engines/validator_set/test.rs similarity index 100% rename from ethcore/src/engines/validator_set/test.rs rename to crates/ethcore/src/engines/validator_set/test.rs diff --git a/ethcore/src/error.rs b/crates/ethcore/src/error.rs similarity index 100% rename from ethcore/src/error.rs rename to crates/ethcore/src/error.rs diff --git a/ethcore/src/ethereum/denominations.rs b/crates/ethcore/src/ethereum/denominations.rs similarity index 100% rename from ethcore/src/ethereum/denominations.rs rename to crates/ethcore/src/ethereum/denominations.rs diff --git a/ethcore/src/ethereum/ethash.rs b/crates/ethcore/src/ethereum/ethash.rs similarity index 100% rename from ethcore/src/ethereum/ethash.rs rename to crates/ethcore/src/ethereum/ethash.rs diff --git a/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs similarity index 78% rename from ethcore/src/ethereum/mod.rs rename to crates/ethcore/src/ethereum/mod.rs index 736d0d5ae5..70ce87455b 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -46,7 +46,7 @@ fn load_machine(b: &[u8]) -> EthereumMachine { pub fn new_foundation<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/foundation.json"), + include_bytes!("../../res/chainspec/foundation.json"), ) } @@ -54,7 +54,7 @@ pub fn new_foundation<'a, T: Into>>(params: T) -> Spec { pub fn new_poanet<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/poacore.json"), + include_bytes!("../../res/chainspec/poacore.json"), ) } @@ -62,7 +62,7 @@ pub fn new_poanet<'a, T: Into>>(params: T) -> Spec { pub fn new_xdai<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/xdai.json"), + include_bytes!("../../res/chainspec/xdai.json"), ) } @@ -70,13 +70,13 @@ pub fn new_xdai<'a, T: Into>>(params: T) -> Spec { pub fn new_volta<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/volta.json"), + include_bytes!("../../res/chainspec/volta.json"), ) } /// Create a new EWC mainnet chain spec. pub fn new_ewc<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/ewc.json")) + load(params.into(), include_bytes!("../../res/chainspec/ewc.json")) } /// Create a new Musicoin mainnet chain spec. @@ -85,7 +85,7 @@ pub fn new_musicoin<'a, T: Into>>(params: T) -> Spec { // https://gist.github.com/andresilva/6f2afaf9486732a0797f4bdeae018ee9 load( params.into(), - include_bytes!("../../res/ethereum/musicoin.json"), + include_bytes!("../../res/chainspec/musicoin.json"), ) } @@ -93,20 +93,20 @@ pub fn new_musicoin<'a, T: Into>>(params: T) -> Spec { pub fn new_ellaism<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/ellaism.json"), + include_bytes!("../../res/chainspec/ellaism.json"), ) } /// Create a new MIX mainnet chain spec. pub fn new_mix<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/ethereum/mix.json")) + load(params.into(), include_bytes!("../../res/chainspec/mix.json")) } /// Create a new Callisto chain spec pub fn new_callisto<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/callisto.json"), + include_bytes!("../../res/chainspec/callisto.json"), ) } @@ -114,7 +114,7 @@ pub fn new_callisto<'a, T: Into>>(params: T) -> Spec { pub fn new_morden<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/morden.json"), + include_bytes!("../../res/chainspec/morden.json"), ) } @@ -122,7 +122,7 @@ pub fn new_morden<'a, T: Into>>(params: T) -> Spec { pub fn new_ropsten<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/ropsten.json"), + include_bytes!("../../res/chainspec/ropsten.json"), ) } @@ -130,7 +130,7 @@ pub fn new_ropsten<'a, T: Into>>(params: T) -> Spec { pub fn new_kovan<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/kovan.json"), + include_bytes!("../../res/chainspec/kovan.json"), ) } @@ -138,7 +138,7 @@ pub fn new_kovan<'a, T: Into>>(params: T) -> Spec { pub fn new_rinkeby<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/rinkeby.json"), + include_bytes!("../../res/chainspec/rinkeby.json"), ) } @@ -146,7 +146,7 @@ pub fn new_rinkeby<'a, T: Into>>(params: T) -> Spec { pub fn new_goerli<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/goerli.json"), + include_bytes!("../../res/chainspec/goerli.json"), ) } @@ -154,7 +154,7 @@ pub fn new_goerli<'a, T: Into>>(params: T) -> Spec { pub fn new_sokol<'a, T: Into>>(params: T) -> Spec { load( params.into(), - include_bytes!("../../res/ethereum/poasokol.json"), + include_bytes!("../../res/chainspec/poasokol.json"), ) } @@ -164,38 +164,38 @@ pub fn new_sokol<'a, T: Into>>(params: T) -> Spec { pub fn new_frontier_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/frontier_test.json"), + include_bytes!("../../res/chainspec/test/frontier_test.json"), ) } /// Create a new Ropsten chain spec. pub fn new_ropsten_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/ropsten.json")) + load(None, include_bytes!("../../res/chainspec/ropsten.json")) } /// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. pub fn new_homestead_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/homestead_test.json"), + include_bytes!("../../res/chainspec/test/homestead_test.json"), ) } /// Create a new Foundation Homestead-EIP150-era chain spec as though it never changed from Homestead/Frontier. pub fn new_eip150_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/eip150_test.json")) + load(None, include_bytes!("../../res/chainspec/test/eip150_test.json")) } /// Create a new Foundation Homestead-EIP161-era chain spec as though it never changed from Homestead/Frontier. pub fn new_eip161_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/eip161_test.json")) + load(None, include_bytes!("../../res/chainspec/test/eip161_test.json")) } /// Create a new Foundation Frontier/Homestead/DAO chain spec with transition points at #5 and #8. pub fn new_transition_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/transition_test.json"), + include_bytes!("../../res/chainspec/test/transition_test.json"), ) } @@ -203,7 +203,7 @@ pub fn new_transition_test() -> Spec { pub fn new_mainnet_like() -> Spec { load( None, - include_bytes!("../../res/ethereum/frontier_like_test.json"), + include_bytes!("../../res/chainspec/test/frontier_like_test.json"), ) } @@ -211,7 +211,7 @@ pub fn new_mainnet_like() -> Spec { pub fn new_byzantium_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/byzantium_test.json"), + include_bytes!("../../res/chainspec/test/byzantium_test.json"), ) } @@ -219,7 +219,7 @@ pub fn new_byzantium_test() -> Spec { pub fn new_constantinople_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/constantinople_test.json"), + include_bytes!("../../res/chainspec/test/constantinople_test.json"), ) } @@ -227,7 +227,7 @@ pub fn new_constantinople_test() -> Spec { pub fn new_constantinople_fix_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/st_peters_test.json"), + include_bytes!("../../res/chainspec/test/st_peters_test.json"), ) } @@ -235,7 +235,7 @@ pub fn new_constantinople_fix_test() -> Spec { pub fn new_istanbul_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/istanbul_test.json"), + include_bytes!("../../res/chainspec/test/istanbul_test.json"), ) } @@ -243,72 +243,72 @@ pub fn new_istanbul_test() -> Spec { pub fn new_byzantium_to_constantinoplefixat5_test() -> Spec { load( None, - include_bytes!("../../res/ethereum/byzantium_to_constantinoplefixat5_test.json"), + include_bytes!("../../res/chainspec/test/byzantium_to_constantinoplefixat5_test.json"), ) } /// Create a new Foundation Berlin era spec. pub fn new_berlin_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/berlin_test.json")) + load(None, include_bytes!("../../res/chainspec/test/berlin_test.json")) } /// Create a new YOLO spec pub fn new_yolo3_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/yolo3_test.json")) + load(None, include_bytes!("../../res/chainspec/test/yolo3_test.json")) } /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { - load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) + load(None, include_bytes!("../../res/chainspec/test/mcip3_test.json")) } // For tests /// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead. pub fn new_frontier_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/frontier_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/frontier_test.json")) } /// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. pub fn new_homestead_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/homestead_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/homestead_test.json")) } /// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier. pub fn new_eip210_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/eip210_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/eip210_test.json")) } /// Create a new Foundation Byzantium era spec. pub fn new_byzantium_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/byzantium_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/byzantium_test.json")) } /// Create a new Foundation Constantinople era spec. pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(include_bytes!( - "../../res/ethereum/constantinople_test.json" + "../../res/chainspec/test/constantinople_test.json" )) } /// Create a new Foundation St. Peter's (Contantinople Fix) era spec. pub fn new_constantinople_fix_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/st_peters_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/st_peters_test.json")) } /// Create a new Foundation Istanbul era spec. pub fn new_istanbul_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/istanbul_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/istanbul_test.json")) } /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/mcip3_test.json")) } /// Create new Kovan spec with wasm activated at certain block pub fn new_kovan_wasm_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/ethereum/kovan_wasm_test.json")) + load_machine(include_bytes!("../../res/chainspec/test/kovan_wasm_test.json")) } #[cfg(test)] diff --git a/ethcore/src/executed.rs b/crates/ethcore/src/executed.rs similarity index 100% rename from ethcore/src/executed.rs rename to crates/ethcore/src/executed.rs diff --git a/ethcore/src/executive.rs b/crates/ethcore/src/executive.rs similarity index 100% rename from ethcore/src/executive.rs rename to crates/ethcore/src/executive.rs diff --git a/ethcore/src/externalities.rs b/crates/ethcore/src/externalities.rs similarity index 100% rename from ethcore/src/externalities.rs rename to crates/ethcore/src/externalities.rs diff --git a/ethcore/src/factory.rs b/crates/ethcore/src/factory.rs similarity index 100% rename from ethcore/src/factory.rs rename to crates/ethcore/src/factory.rs diff --git a/ethcore/src/json_tests/chain.rs b/crates/ethcore/src/json_tests/chain.rs similarity index 100% rename from ethcore/src/json_tests/chain.rs rename to crates/ethcore/src/json_tests/chain.rs diff --git a/ethcore/src/json_tests/difficulty.rs b/crates/ethcore/src/json_tests/difficulty.rs similarity index 100% rename from ethcore/src/json_tests/difficulty.rs rename to crates/ethcore/src/json_tests/difficulty.rs diff --git a/ethcore/src/json_tests/executive.rs b/crates/ethcore/src/json_tests/executive.rs similarity index 100% rename from ethcore/src/json_tests/executive.rs rename to crates/ethcore/src/json_tests/executive.rs diff --git a/ethcore/src/json_tests/mod.rs b/crates/ethcore/src/json_tests/mod.rs similarity index 100% rename from ethcore/src/json_tests/mod.rs rename to crates/ethcore/src/json_tests/mod.rs diff --git a/ethcore/src/json_tests/runner.rs b/crates/ethcore/src/json_tests/runner.rs similarity index 99% rename from ethcore/src/json_tests/runner.rs rename to crates/ethcore/src/json_tests/runner.rs index 4b22146faa..2b8fa1f82f 100644 --- a/ethcore/src/json_tests/runner.rs +++ b/crates/ethcore/src/json_tests/runner.rs @@ -232,7 +232,7 @@ impl TestRunner { #[test] fn ethereum_json_tests() { - let content = std::fs::read("res/ethereum/runner/full.json") + let content = std::fs::read("res/json_tests.json") .expect("cannot open ethereum tests spec file"); let runner = TestRunner::load(content.as_slice()).expect("cannot load ethereum tests spec file"); diff --git a/ethcore/src/json_tests/skip.rs b/crates/ethcore/src/json_tests/skip.rs similarity index 100% rename from ethcore/src/json_tests/skip.rs rename to crates/ethcore/src/json_tests/skip.rs diff --git a/ethcore/src/json_tests/state.rs b/crates/ethcore/src/json_tests/state.rs similarity index 100% rename from ethcore/src/json_tests/state.rs rename to crates/ethcore/src/json_tests/state.rs diff --git a/ethcore/src/json_tests/test_common.rs b/crates/ethcore/src/json_tests/test_common.rs similarity index 100% rename from ethcore/src/json_tests/test_common.rs rename to crates/ethcore/src/json_tests/test_common.rs diff --git a/ethcore/src/json_tests/transaction.rs b/crates/ethcore/src/json_tests/transaction.rs similarity index 100% rename from ethcore/src/json_tests/transaction.rs rename to crates/ethcore/src/json_tests/transaction.rs diff --git a/ethcore/src/json_tests/trie.rs b/crates/ethcore/src/json_tests/trie.rs similarity index 100% rename from ethcore/src/json_tests/trie.rs rename to crates/ethcore/src/json_tests/trie.rs diff --git a/ethcore/src/lib.rs b/crates/ethcore/src/lib.rs similarity index 100% rename from ethcore/src/lib.rs rename to crates/ethcore/src/lib.rs diff --git a/ethcore/src/machine/impls.rs b/crates/ethcore/src/machine/impls.rs similarity index 100% rename from ethcore/src/machine/impls.rs rename to crates/ethcore/src/machine/impls.rs diff --git a/ethcore/src/machine/mod.rs b/crates/ethcore/src/machine/mod.rs similarity index 100% rename from ethcore/src/machine/mod.rs rename to crates/ethcore/src/machine/mod.rs diff --git a/ethcore/src/machine/traits.rs b/crates/ethcore/src/machine/traits.rs similarity index 100% rename from ethcore/src/machine/traits.rs rename to crates/ethcore/src/machine/traits.rs diff --git a/ethcore/src/miner/miner.rs b/crates/ethcore/src/miner/miner.rs similarity index 100% rename from ethcore/src/miner/miner.rs rename to crates/ethcore/src/miner/miner.rs diff --git a/ethcore/src/miner/mod.rs b/crates/ethcore/src/miner/mod.rs similarity index 100% rename from ethcore/src/miner/mod.rs rename to crates/ethcore/src/miner/mod.rs diff --git a/ethcore/src/miner/pool_client.rs b/crates/ethcore/src/miner/pool_client.rs similarity index 100% rename from ethcore/src/miner/pool_client.rs rename to crates/ethcore/src/miner/pool_client.rs diff --git a/ethcore/src/miner/stratum.rs b/crates/ethcore/src/miner/stratum.rs similarity index 100% rename from ethcore/src/miner/stratum.rs rename to crates/ethcore/src/miner/stratum.rs diff --git a/ethcore/src/pod_account.rs b/crates/ethcore/src/pod_account.rs similarity index 100% rename from ethcore/src/pod_account.rs rename to crates/ethcore/src/pod_account.rs diff --git a/ethcore/src/pod_state.rs b/crates/ethcore/src/pod_state.rs similarity index 100% rename from ethcore/src/pod_state.rs rename to crates/ethcore/src/pod_state.rs diff --git a/ethcore/src/snapshot/account.rs b/crates/ethcore/src/snapshot/account.rs similarity index 100% rename from ethcore/src/snapshot/account.rs rename to crates/ethcore/src/snapshot/account.rs diff --git a/ethcore/src/snapshot/block.rs b/crates/ethcore/src/snapshot/block.rs similarity index 100% rename from ethcore/src/snapshot/block.rs rename to crates/ethcore/src/snapshot/block.rs diff --git a/ethcore/src/snapshot/consensus/authority.rs b/crates/ethcore/src/snapshot/consensus/authority.rs similarity index 100% rename from ethcore/src/snapshot/consensus/authority.rs rename to crates/ethcore/src/snapshot/consensus/authority.rs diff --git a/ethcore/src/snapshot/consensus/mod.rs b/crates/ethcore/src/snapshot/consensus/mod.rs similarity index 100% rename from ethcore/src/snapshot/consensus/mod.rs rename to crates/ethcore/src/snapshot/consensus/mod.rs diff --git a/ethcore/src/snapshot/consensus/work.rs b/crates/ethcore/src/snapshot/consensus/work.rs similarity index 100% rename from ethcore/src/snapshot/consensus/work.rs rename to crates/ethcore/src/snapshot/consensus/work.rs diff --git a/ethcore/src/snapshot/error.rs b/crates/ethcore/src/snapshot/error.rs similarity index 100% rename from ethcore/src/snapshot/error.rs rename to crates/ethcore/src/snapshot/error.rs diff --git a/ethcore/src/snapshot/io.rs b/crates/ethcore/src/snapshot/io.rs similarity index 100% rename from ethcore/src/snapshot/io.rs rename to crates/ethcore/src/snapshot/io.rs diff --git a/ethcore/src/snapshot/mod.rs b/crates/ethcore/src/snapshot/mod.rs similarity index 100% rename from ethcore/src/snapshot/mod.rs rename to crates/ethcore/src/snapshot/mod.rs diff --git a/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs similarity index 100% rename from ethcore/src/snapshot/service.rs rename to crates/ethcore/src/snapshot/service.rs diff --git a/ethcore/src/snapshot/tests/helpers.rs b/crates/ethcore/src/snapshot/tests/helpers.rs similarity index 100% rename from ethcore/src/snapshot/tests/helpers.rs rename to crates/ethcore/src/snapshot/tests/helpers.rs diff --git a/ethcore/src/snapshot/tests/mod.rs b/crates/ethcore/src/snapshot/tests/mod.rs similarity index 100% rename from ethcore/src/snapshot/tests/mod.rs rename to crates/ethcore/src/snapshot/tests/mod.rs diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/crates/ethcore/src/snapshot/tests/proof_of_authority.rs similarity index 100% rename from ethcore/src/snapshot/tests/proof_of_authority.rs rename to crates/ethcore/src/snapshot/tests/proof_of_authority.rs diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/crates/ethcore/src/snapshot/tests/proof_of_work.rs similarity index 100% rename from ethcore/src/snapshot/tests/proof_of_work.rs rename to crates/ethcore/src/snapshot/tests/proof_of_work.rs diff --git a/ethcore/src/snapshot/tests/service.rs b/crates/ethcore/src/snapshot/tests/service.rs similarity index 100% rename from ethcore/src/snapshot/tests/service.rs rename to crates/ethcore/src/snapshot/tests/service.rs diff --git a/ethcore/src/snapshot/tests/state.rs b/crates/ethcore/src/snapshot/tests/state.rs similarity index 100% rename from ethcore/src/snapshot/tests/state.rs rename to crates/ethcore/src/snapshot/tests/state.rs diff --git a/ethcore/src/snapshot/tests/test_validator_contract.json b/crates/ethcore/src/snapshot/tests/test_validator_contract.json similarity index 100% rename from ethcore/src/snapshot/tests/test_validator_contract.json rename to crates/ethcore/src/snapshot/tests/test_validator_contract.json diff --git a/ethcore/src/snapshot/traits.rs b/crates/ethcore/src/snapshot/traits.rs similarity index 100% rename from ethcore/src/snapshot/traits.rs rename to crates/ethcore/src/snapshot/traits.rs diff --git a/ethcore/src/snapshot/watcher.rs b/crates/ethcore/src/snapshot/watcher.rs similarity index 100% rename from ethcore/src/snapshot/watcher.rs rename to crates/ethcore/src/snapshot/watcher.rs diff --git a/ethcore/src/spec/genesis.rs b/crates/ethcore/src/spec/genesis.rs similarity index 100% rename from ethcore/src/spec/genesis.rs rename to crates/ethcore/src/spec/genesis.rs diff --git a/ethcore/src/spec/mod.rs b/crates/ethcore/src/spec/mod.rs similarity index 100% rename from ethcore/src/spec/mod.rs rename to crates/ethcore/src/spec/mod.rs diff --git a/ethcore/src/spec/seal.rs b/crates/ethcore/src/spec/seal.rs similarity index 100% rename from ethcore/src/spec/seal.rs rename to crates/ethcore/src/spec/seal.rs diff --git a/ethcore/src/spec/spec.rs b/crates/ethcore/src/spec/spec.rs similarity index 98% rename from ethcore/src/spec/spec.rs rename to crates/ethcore/src/spec/spec.rs index 6153025116..0ae5835b92 100644 --- a/ethcore/src/spec/spec.rs +++ b/crates/ethcore/src/spec/spec.rs @@ -602,7 +602,7 @@ macro_rules! load_bundled { ($e:expr) => { Spec::load( &::std::env::temp_dir(), - include_bytes!(concat!("../../res/", $e, ".json")) as &[u8], + include_bytes!(concat!("../../res/chainspec/", $e, ".json")) as &[u8], ) .expect(concat!("Chain spec ", $e, " is invalid.")) }; @@ -611,7 +611,7 @@ macro_rules! load_bundled { #[cfg(any(test, feature = "test-helpers"))] macro_rules! load_machine_bundled { ($e:expr) => { - Spec::load_machine(include_bytes!(concat!("../../res/", $e, ".json")) as &[u8]) + Spec::load_machine(include_bytes!(concat!("../../res/chainspec/", $e, ".json")) as &[u8]) .expect(concat!("Chain spec ", $e, " is invalid.")) }; } @@ -1027,38 +1027,38 @@ impl Spec { /// NullEngine consensus. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test() -> Spec { - load_bundled!("null_morden") + load_bundled!("test/null_morden") } /// Create the EthereumMachine corresponding to Spec::new_test. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_machine() -> EthereumMachine { - load_machine_bundled!("null_morden") + load_machine_bundled!("test/null_morden") } /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus with applying reward on block close. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_with_reward() -> Spec { - load_bundled!("null_morden_with_reward") + load_bundled!("test/null_morden_with_reward") } /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus with finality. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_with_finality() -> Spec { - load_bundled!("null_morden_with_finality") + load_bundled!("test/null_morden_with_finality") } /// Create a new Spec which is a NullEngine consensus with a premine of address whose /// secret is keccak(''). #[cfg(any(test, feature = "test-helpers"))] pub fn new_null() -> Spec { - load_bundled!("null") + load_bundled!("test/null") } /// Create a new Spec which constructs a contract at address 5 with storage at 0 equal to 1. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_constructor() -> Spec { - load_bundled!("constructor") + load_bundled!("test/constructor") } /// Create a new Spec with AuthorityRound consensus which does internal sealing (not @@ -1066,7 +1066,7 @@ impl Spec { /// Accounts with secrets keccak("0") and keccak("1") are the validators. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_round() -> Self { - load_bundled!("authority_round") + load_bundled!("test/authority_round") } /// Create a new Spec with AuthorityRound consensus which does internal sealing (not @@ -1074,7 +1074,7 @@ impl Spec { /// Accounts with secrets keccak("0") and keccak("1") are the validators. #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_round_empty_steps() -> Self { - load_bundled!("authority_round_empty_steps") + load_bundled!("test/authority_round_empty_steps") } /// Create a new Spec with AuthorityRound consensus (with empty steps) using a block reward @@ -1082,7 +1082,7 @@ impl Spec { /// https://github.com/openethereum/block-reward/blob/daf7d44383b6cdb11cb6b953b018648e2b027cfb/contracts/ExampleBlockReward.sol #[cfg(any(test, feature = "test-helpers"))] pub fn new_test_round_block_reward_contract() -> Self { - load_bundled!("authority_round_block_reward_contract") + load_bundled!("test/authority_round_block_reward_contract") } /// TestList.sol used in both specs: https://github.com/paritytech/contracts/pull/30/files (link not valid) @@ -1095,7 +1095,7 @@ impl Spec { /// "0x4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1". #[cfg(any(test, feature = "test-helpers"))] pub fn new_validator_safe_contract() -> Self { - load_bundled!("validator_safe_contract") + load_bundled!("test/validator_safe_contract") } /// The same as the `safeContract`, but allows reporting and uses AuthorityRound. @@ -1103,7 +1103,7 @@ impl Spec { /// Validator can be removed with `reportMalicious`. #[cfg(any(test, feature = "test-helpers"))] pub fn new_validator_contract() -> Self { - load_bundled!("validator_contract") + load_bundled!("test/validator_contract") } /// Create a new Spec with BasicAuthority which uses multiple validator sets changing with @@ -1112,7 +1112,7 @@ impl Spec { /// onwards. #[cfg(any(test, feature = "test-helpers"))] pub fn new_validator_multi() -> Self { - load_bundled!("validator_multi") + load_bundled!("test/validator_multi") } } diff --git a/ethcore/src/state/account.rs b/crates/ethcore/src/state/account.rs similarity index 100% rename from ethcore/src/state/account.rs rename to crates/ethcore/src/state/account.rs diff --git a/ethcore/src/state/backend.rs b/crates/ethcore/src/state/backend.rs similarity index 100% rename from ethcore/src/state/backend.rs rename to crates/ethcore/src/state/backend.rs diff --git a/ethcore/src/state/mod.rs b/crates/ethcore/src/state/mod.rs similarity index 100% rename from ethcore/src/state/mod.rs rename to crates/ethcore/src/state/mod.rs diff --git a/ethcore/src/state/substate.rs b/crates/ethcore/src/state/substate.rs similarity index 100% rename from ethcore/src/state/substate.rs rename to crates/ethcore/src/state/substate.rs diff --git a/ethcore/src/state_db.rs b/crates/ethcore/src/state_db.rs similarity index 100% rename from ethcore/src/state_db.rs rename to crates/ethcore/src/state_db.rs diff --git a/ethcore/src/test_helpers.rs b/crates/ethcore/src/test_helpers.rs similarity index 100% rename from ethcore/src/test_helpers.rs rename to crates/ethcore/src/test_helpers.rs diff --git a/ethcore/src/tests/blockchain.rs b/crates/ethcore/src/tests/blockchain.rs similarity index 100% rename from ethcore/src/tests/blockchain.rs rename to crates/ethcore/src/tests/blockchain.rs diff --git a/ethcore/src/tests/client.rs b/crates/ethcore/src/tests/client.rs similarity index 100% rename from ethcore/src/tests/client.rs rename to crates/ethcore/src/tests/client.rs diff --git a/ethcore/src/tests/evm.rs b/crates/ethcore/src/tests/evm.rs similarity index 100% rename from ethcore/src/tests/evm.rs rename to crates/ethcore/src/tests/evm.rs diff --git a/ethcore/src/tests/mod.rs b/crates/ethcore/src/tests/mod.rs similarity index 100% rename from ethcore/src/tests/mod.rs rename to crates/ethcore/src/tests/mod.rs diff --git a/ethcore/src/tests/trace.rs b/crates/ethcore/src/tests/trace.rs similarity index 100% rename from ethcore/src/tests/trace.rs rename to crates/ethcore/src/tests/trace.rs diff --git a/ethcore/src/trace/config.rs b/crates/ethcore/src/trace/config.rs similarity index 100% rename from ethcore/src/trace/config.rs rename to crates/ethcore/src/trace/config.rs diff --git a/ethcore/src/trace/db.rs b/crates/ethcore/src/trace/db.rs similarity index 100% rename from ethcore/src/trace/db.rs rename to crates/ethcore/src/trace/db.rs diff --git a/ethcore/src/trace/executive_tracer.rs b/crates/ethcore/src/trace/executive_tracer.rs similarity index 100% rename from ethcore/src/trace/executive_tracer.rs rename to crates/ethcore/src/trace/executive_tracer.rs diff --git a/ethcore/src/trace/import.rs b/crates/ethcore/src/trace/import.rs similarity index 100% rename from ethcore/src/trace/import.rs rename to crates/ethcore/src/trace/import.rs diff --git a/ethcore/src/trace/mod.rs b/crates/ethcore/src/trace/mod.rs similarity index 100% rename from ethcore/src/trace/mod.rs rename to crates/ethcore/src/trace/mod.rs diff --git a/ethcore/src/trace/noop_tracer.rs b/crates/ethcore/src/trace/noop_tracer.rs similarity index 100% rename from ethcore/src/trace/noop_tracer.rs rename to crates/ethcore/src/trace/noop_tracer.rs diff --git a/ethcore/src/trace/types/error.rs b/crates/ethcore/src/trace/types/error.rs similarity index 100% rename from ethcore/src/trace/types/error.rs rename to crates/ethcore/src/trace/types/error.rs diff --git a/ethcore/src/trace/types/filter.rs b/crates/ethcore/src/trace/types/filter.rs similarity index 100% rename from ethcore/src/trace/types/filter.rs rename to crates/ethcore/src/trace/types/filter.rs diff --git a/ethcore/src/trace/types/flat.rs b/crates/ethcore/src/trace/types/flat.rs similarity index 100% rename from ethcore/src/trace/types/flat.rs rename to crates/ethcore/src/trace/types/flat.rs diff --git a/ethcore/src/trace/types/localized.rs b/crates/ethcore/src/trace/types/localized.rs similarity index 100% rename from ethcore/src/trace/types/localized.rs rename to crates/ethcore/src/trace/types/localized.rs diff --git a/ethcore/src/trace/types/mod.rs b/crates/ethcore/src/trace/types/mod.rs similarity index 100% rename from ethcore/src/trace/types/mod.rs rename to crates/ethcore/src/trace/types/mod.rs diff --git a/ethcore/src/trace/types/trace.rs b/crates/ethcore/src/trace/types/trace.rs similarity index 100% rename from ethcore/src/trace/types/trace.rs rename to crates/ethcore/src/trace/types/trace.rs diff --git a/ethcore/src/transaction_ext.rs b/crates/ethcore/src/transaction_ext.rs similarity index 100% rename from ethcore/src/transaction_ext.rs rename to crates/ethcore/src/transaction_ext.rs diff --git a/ethcore/src/tx_filter.rs b/crates/ethcore/src/tx_filter.rs similarity index 98% rename from ethcore/src/tx_filter.rs rename to crates/ethcore/src/tx_filter.rs index 2a7da20e91..573fbbfbf5 100644 --- a/ethcore/src/tx_filter.rs +++ b/crates/ethcore/src/tx_filter.rs @@ -186,7 +186,7 @@ mod test { /// Contract code: https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f #[test] fn transaction_filter() { - let spec_data = include_str!("../res/tx_permission_tests/contract_ver_2_genesis.json"); + let spec_data = include_str!("../res/chainspec/test/contract_ver_2_genesis.json"); let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); @@ -414,7 +414,7 @@ mod test { /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a #[test] fn transaction_filter_deprecated() { - let spec_data = include_str!("../res/tx_permission_tests/deprecated_contract_genesis.json"); + let spec_data = include_str!("../res/chainspec/test/deprecated_contract_genesis.json"); let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); diff --git a/ethcore/src/verification/canon_verifier.rs b/crates/ethcore/src/verification/canon_verifier.rs similarity index 100% rename from ethcore/src/verification/canon_verifier.rs rename to crates/ethcore/src/verification/canon_verifier.rs diff --git a/ethcore/src/verification/mod.rs b/crates/ethcore/src/verification/mod.rs similarity index 100% rename from ethcore/src/verification/mod.rs rename to crates/ethcore/src/verification/mod.rs diff --git a/ethcore/src/verification/noop_verifier.rs b/crates/ethcore/src/verification/noop_verifier.rs similarity index 100% rename from ethcore/src/verification/noop_verifier.rs rename to crates/ethcore/src/verification/noop_verifier.rs diff --git a/ethcore/src/verification/queue/kind.rs b/crates/ethcore/src/verification/queue/kind.rs similarity index 100% rename from ethcore/src/verification/queue/kind.rs rename to crates/ethcore/src/verification/queue/kind.rs diff --git a/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs similarity index 100% rename from ethcore/src/verification/queue/mod.rs rename to crates/ethcore/src/verification/queue/mod.rs diff --git a/ethcore/src/verification/verification.rs b/crates/ethcore/src/verification/verification.rs similarity index 100% rename from ethcore/src/verification/verification.rs rename to crates/ethcore/src/verification/verification.rs diff --git a/ethcore/src/verification/verifier.rs b/crates/ethcore/src/verification/verifier.rs similarity index 100% rename from ethcore/src/verification/verifier.rs rename to crates/ethcore/src/verification/verifier.rs diff --git a/ethcore/sync/Cargo.toml b/crates/ethcore/sync/Cargo.toml similarity index 88% rename from ethcore/sync/Cargo.toml rename to crates/ethcore/sync/Cargo.toml index 4ea7ba1aef..590eab7826 100644 --- a/ethcore/sync/Cargo.toml +++ b/crates/ethcore/sync/Cargo.toml @@ -12,9 +12,9 @@ common-types = { path = "../types" } enum_primitive = "0.1.1" derive_more = "0.99" ethcore = { path = ".." } -ethcore-io = { path = "../../util/io" } -ethcore-network = { path = "../../util/network" } -ethcore-network-devp2p = { path = "../../util/network-devp2p" } +ethcore-io = { path = "../../runtime/io" } +ethcore-network = { path = "../../net/network" } +ethcore-network-devp2p = { path = "../../net/network-devp2p" } ethereum-forkid = "0.2" primitive_types07 = { package = "primitive-types", version = "0.7"} ethereum-types = "0.4" @@ -41,6 +41,6 @@ stats = { path = "../../util/stats" } [dev-dependencies] env_logger = "0.5" ethcore = { path = "..", features = ["test-helpers"] } -ethcore-io = { path = "../../util/io", features = ["mio"] } +ethcore-io = { path = "../../runtime/io", features = ["mio"] } kvdb-memorydb = "0.1" rustc-hex = "1.0" diff --git a/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs similarity index 100% rename from ethcore/sync/src/api.rs rename to crates/ethcore/sync/src/api.rs diff --git a/ethcore/sync/src/block_sync.rs b/crates/ethcore/sync/src/block_sync.rs similarity index 100% rename from ethcore/sync/src/block_sync.rs rename to crates/ethcore/sync/src/block_sync.rs diff --git a/ethcore/sync/src/blocks.rs b/crates/ethcore/sync/src/blocks.rs similarity index 100% rename from ethcore/sync/src/blocks.rs rename to crates/ethcore/sync/src/blocks.rs diff --git a/ethcore/sync/src/chain/fork_filter.rs b/crates/ethcore/sync/src/chain/fork_filter.rs similarity index 100% rename from ethcore/sync/src/chain/fork_filter.rs rename to crates/ethcore/sync/src/chain/fork_filter.rs diff --git a/ethcore/sync/src/chain/handler.rs b/crates/ethcore/sync/src/chain/handler.rs similarity index 100% rename from ethcore/sync/src/chain/handler.rs rename to crates/ethcore/sync/src/chain/handler.rs diff --git a/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs similarity index 100% rename from ethcore/sync/src/chain/mod.rs rename to crates/ethcore/sync/src/chain/mod.rs diff --git a/ethcore/sync/src/chain/propagator.rs b/crates/ethcore/sync/src/chain/propagator.rs similarity index 100% rename from ethcore/sync/src/chain/propagator.rs rename to crates/ethcore/sync/src/chain/propagator.rs diff --git a/ethcore/sync/src/chain/requester.rs b/crates/ethcore/sync/src/chain/requester.rs similarity index 100% rename from ethcore/sync/src/chain/requester.rs rename to crates/ethcore/sync/src/chain/requester.rs diff --git a/ethcore/sync/src/chain/supplier.rs b/crates/ethcore/sync/src/chain/supplier.rs similarity index 100% rename from ethcore/sync/src/chain/supplier.rs rename to crates/ethcore/sync/src/chain/supplier.rs diff --git a/ethcore/sync/src/chain/sync_packet.rs b/crates/ethcore/sync/src/chain/sync_packet.rs similarity index 100% rename from ethcore/sync/src/chain/sync_packet.rs rename to crates/ethcore/sync/src/chain/sync_packet.rs diff --git a/ethcore/sync/src/lib.rs b/crates/ethcore/sync/src/lib.rs similarity index 100% rename from ethcore/sync/src/lib.rs rename to crates/ethcore/sync/src/lib.rs diff --git a/ethcore/sync/src/res/private_spec.json b/crates/ethcore/sync/src/res/private_spec.json similarity index 100% rename from ethcore/sync/src/res/private_spec.json rename to crates/ethcore/sync/src/res/private_spec.json diff --git a/ethcore/sync/src/snapshot.rs b/crates/ethcore/sync/src/snapshot.rs similarity index 100% rename from ethcore/sync/src/snapshot.rs rename to crates/ethcore/sync/src/snapshot.rs diff --git a/ethcore/sync/src/sync_io.rs b/crates/ethcore/sync/src/sync_io.rs similarity index 100% rename from ethcore/sync/src/sync_io.rs rename to crates/ethcore/sync/src/sync_io.rs diff --git a/ethcore/sync/src/tests/chain.rs b/crates/ethcore/sync/src/tests/chain.rs similarity index 100% rename from ethcore/sync/src/tests/chain.rs rename to crates/ethcore/sync/src/tests/chain.rs diff --git a/ethcore/sync/src/tests/consensus.rs b/crates/ethcore/sync/src/tests/consensus.rs similarity index 100% rename from ethcore/sync/src/tests/consensus.rs rename to crates/ethcore/sync/src/tests/consensus.rs diff --git a/ethcore/sync/src/tests/helpers.rs b/crates/ethcore/sync/src/tests/helpers.rs similarity index 100% rename from ethcore/sync/src/tests/helpers.rs rename to crates/ethcore/sync/src/tests/helpers.rs diff --git a/ethcore/sync/src/tests/mod.rs b/crates/ethcore/sync/src/tests/mod.rs similarity index 100% rename from ethcore/sync/src/tests/mod.rs rename to crates/ethcore/sync/src/tests/mod.rs diff --git a/ethcore/sync/src/tests/rpc.rs b/crates/ethcore/sync/src/tests/rpc.rs similarity index 100% rename from ethcore/sync/src/tests/rpc.rs rename to crates/ethcore/sync/src/tests/rpc.rs diff --git a/ethcore/sync/src/tests/snapshot.rs b/crates/ethcore/sync/src/tests/snapshot.rs similarity index 100% rename from ethcore/sync/src/tests/snapshot.rs rename to crates/ethcore/sync/src/tests/snapshot.rs diff --git a/ethcore/sync/src/transactions_stats.rs b/crates/ethcore/sync/src/transactions_stats.rs similarity index 100% rename from ethcore/sync/src/transactions_stats.rs rename to crates/ethcore/sync/src/transactions_stats.rs diff --git a/ethcore/types/Cargo.toml b/crates/ethcore/types/Cargo.toml similarity index 93% rename from ethcore/types/Cargo.toml rename to crates/ethcore/types/Cargo.toml index 5fa288cc9c..d6a18bcd1c 100644 --- a/ethcore/types/Cargo.toml +++ b/crates/ethcore/types/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.4" -ethjson = { path = "../../json" } +ethjson = { path = "../../ethjson" } ethkey = { path = "../../accounts/ethkey" } heapsize = "0.4" keccak-hash = "0.1" diff --git a/ethcore/types/src/account_diff.rs b/crates/ethcore/types/src/account_diff.rs similarity index 100% rename from ethcore/types/src/account_diff.rs rename to crates/ethcore/types/src/account_diff.rs diff --git a/ethcore/types/src/ancestry_action.rs b/crates/ethcore/types/src/ancestry_action.rs similarity index 100% rename from ethcore/types/src/ancestry_action.rs rename to crates/ethcore/types/src/ancestry_action.rs diff --git a/ethcore/types/src/basic_account.rs b/crates/ethcore/types/src/basic_account.rs similarity index 100% rename from ethcore/types/src/basic_account.rs rename to crates/ethcore/types/src/basic_account.rs diff --git a/ethcore/types/src/block.rs b/crates/ethcore/types/src/block.rs similarity index 100% rename from ethcore/types/src/block.rs rename to crates/ethcore/types/src/block.rs diff --git a/ethcore/types/src/block_status.rs b/crates/ethcore/types/src/block_status.rs similarity index 100% rename from ethcore/types/src/block_status.rs rename to crates/ethcore/types/src/block_status.rs diff --git a/ethcore/types/src/blockchain_info.rs b/crates/ethcore/types/src/blockchain_info.rs similarity index 100% rename from ethcore/types/src/blockchain_info.rs rename to crates/ethcore/types/src/blockchain_info.rs diff --git a/ethcore/types/src/call_analytics.rs b/crates/ethcore/types/src/call_analytics.rs similarity index 100% rename from ethcore/types/src/call_analytics.rs rename to crates/ethcore/types/src/call_analytics.rs diff --git a/ethcore/types/src/creation_status.rs b/crates/ethcore/types/src/creation_status.rs similarity index 100% rename from ethcore/types/src/creation_status.rs rename to crates/ethcore/types/src/creation_status.rs diff --git a/ethcore/types/src/data_format.rs b/crates/ethcore/types/src/data_format.rs similarity index 100% rename from ethcore/types/src/data_format.rs rename to crates/ethcore/types/src/data_format.rs diff --git a/ethcore/types/src/encoded.rs b/crates/ethcore/types/src/encoded.rs similarity index 100% rename from ethcore/types/src/encoded.rs rename to crates/ethcore/types/src/encoded.rs diff --git a/ethcore/types/src/engines/epoch.rs b/crates/ethcore/types/src/engines/epoch.rs similarity index 100% rename from ethcore/types/src/engines/epoch.rs rename to crates/ethcore/types/src/engines/epoch.rs diff --git a/ethcore/types/src/engines/mod.rs b/crates/ethcore/types/src/engines/mod.rs similarity index 100% rename from ethcore/types/src/engines/mod.rs rename to crates/ethcore/types/src/engines/mod.rs diff --git a/ethcore/types/src/filter.rs b/crates/ethcore/types/src/filter.rs similarity index 100% rename from ethcore/types/src/filter.rs rename to crates/ethcore/types/src/filter.rs diff --git a/ethcore/types/src/header.rs b/crates/ethcore/types/src/header.rs similarity index 100% rename from ethcore/types/src/header.rs rename to crates/ethcore/types/src/header.rs diff --git a/ethcore/types/src/ids.rs b/crates/ethcore/types/src/ids.rs similarity index 100% rename from ethcore/types/src/ids.rs rename to crates/ethcore/types/src/ids.rs diff --git a/ethcore/types/src/lib.rs b/crates/ethcore/types/src/lib.rs similarity index 100% rename from ethcore/types/src/lib.rs rename to crates/ethcore/types/src/lib.rs diff --git a/ethcore/types/src/log_entry.rs b/crates/ethcore/types/src/log_entry.rs similarity index 100% rename from ethcore/types/src/log_entry.rs rename to crates/ethcore/types/src/log_entry.rs diff --git a/ethcore/types/src/pruning_info.rs b/crates/ethcore/types/src/pruning_info.rs similarity index 100% rename from ethcore/types/src/pruning_info.rs rename to crates/ethcore/types/src/pruning_info.rs diff --git a/ethcore/types/src/receipt.rs b/crates/ethcore/types/src/receipt.rs similarity index 100% rename from ethcore/types/src/receipt.rs rename to crates/ethcore/types/src/receipt.rs diff --git a/ethcore/types/src/restoration_status.rs b/crates/ethcore/types/src/restoration_status.rs similarity index 100% rename from ethcore/types/src/restoration_status.rs rename to crates/ethcore/types/src/restoration_status.rs diff --git a/ethcore/types/src/security_level.rs b/crates/ethcore/types/src/security_level.rs similarity index 100% rename from ethcore/types/src/security_level.rs rename to crates/ethcore/types/src/security_level.rs diff --git a/ethcore/types/src/snapshot_manifest.rs b/crates/ethcore/types/src/snapshot_manifest.rs similarity index 100% rename from ethcore/types/src/snapshot_manifest.rs rename to crates/ethcore/types/src/snapshot_manifest.rs diff --git a/ethcore/types/src/state_diff.rs b/crates/ethcore/types/src/state_diff.rs similarity index 100% rename from ethcore/types/src/state_diff.rs rename to crates/ethcore/types/src/state_diff.rs diff --git a/ethcore/types/src/trace_filter.rs b/crates/ethcore/types/src/trace_filter.rs similarity index 100% rename from ethcore/types/src/trace_filter.rs rename to crates/ethcore/types/src/trace_filter.rs diff --git a/ethcore/types/src/transaction/error.rs b/crates/ethcore/types/src/transaction/error.rs similarity index 100% rename from ethcore/types/src/transaction/error.rs rename to crates/ethcore/types/src/transaction/error.rs diff --git a/ethcore/types/src/transaction/mod.rs b/crates/ethcore/types/src/transaction/mod.rs similarity index 100% rename from ethcore/types/src/transaction/mod.rs rename to crates/ethcore/types/src/transaction/mod.rs diff --git a/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs similarity index 100% rename from ethcore/types/src/transaction/transaction.rs rename to crates/ethcore/types/src/transaction/transaction.rs diff --git a/ethcore/types/src/transaction/transaction_id.rs b/crates/ethcore/types/src/transaction/transaction_id.rs similarity index 100% rename from ethcore/types/src/transaction/transaction_id.rs rename to crates/ethcore/types/src/transaction/transaction_id.rs diff --git a/ethcore/types/src/tree_route.rs b/crates/ethcore/types/src/tree_route.rs similarity index 100% rename from ethcore/types/src/tree_route.rs rename to crates/ethcore/types/src/tree_route.rs diff --git a/ethcore/types/src/verification_queue_info.rs b/crates/ethcore/types/src/verification_queue_info.rs similarity index 100% rename from ethcore/types/src/verification_queue_info.rs rename to crates/ethcore/types/src/verification_queue_info.rs diff --git a/ethcore/types/src/views/block.rs b/crates/ethcore/types/src/views/block.rs similarity index 100% rename from ethcore/types/src/views/block.rs rename to crates/ethcore/types/src/views/block.rs diff --git a/ethcore/types/src/views/body.rs b/crates/ethcore/types/src/views/body.rs similarity index 100% rename from ethcore/types/src/views/body.rs rename to crates/ethcore/types/src/views/body.rs diff --git a/ethcore/types/src/views/header.rs b/crates/ethcore/types/src/views/header.rs similarity index 100% rename from ethcore/types/src/views/header.rs rename to crates/ethcore/types/src/views/header.rs diff --git a/ethcore/types/src/views/mod.rs b/crates/ethcore/types/src/views/mod.rs similarity index 100% rename from ethcore/types/src/views/mod.rs rename to crates/ethcore/types/src/views/mod.rs diff --git a/ethcore/types/src/views/transaction.rs b/crates/ethcore/types/src/views/transaction.rs similarity index 100% rename from ethcore/types/src/views/transaction.rs rename to crates/ethcore/types/src/views/transaction.rs diff --git a/ethcore/types/src/views/view_rlp.rs b/crates/ethcore/types/src/views/view_rlp.rs similarity index 100% rename from ethcore/types/src/views/view_rlp.rs rename to crates/ethcore/types/src/views/view_rlp.rs diff --git a/json/Cargo.toml b/crates/ethjson/Cargo.toml similarity index 100% rename from json/Cargo.toml rename to crates/ethjson/Cargo.toml diff --git a/json/src/blockchain/account.rs b/crates/ethjson/src/blockchain/account.rs similarity index 100% rename from json/src/blockchain/account.rs rename to crates/ethjson/src/blockchain/account.rs diff --git a/json/src/blockchain/block.rs b/crates/ethjson/src/blockchain/block.rs similarity index 100% rename from json/src/blockchain/block.rs rename to crates/ethjson/src/blockchain/block.rs diff --git a/json/src/blockchain/blockchain.rs b/crates/ethjson/src/blockchain/blockchain.rs similarity index 100% rename from json/src/blockchain/blockchain.rs rename to crates/ethjson/src/blockchain/blockchain.rs diff --git a/json/src/blockchain/header.rs b/crates/ethjson/src/blockchain/header.rs similarity index 100% rename from json/src/blockchain/header.rs rename to crates/ethjson/src/blockchain/header.rs diff --git a/json/src/blockchain/mod.rs b/crates/ethjson/src/blockchain/mod.rs similarity index 100% rename from json/src/blockchain/mod.rs rename to crates/ethjson/src/blockchain/mod.rs diff --git a/json/src/blockchain/state.rs b/crates/ethjson/src/blockchain/state.rs similarity index 99% rename from json/src/blockchain/state.rs rename to crates/ethjson/src/blockchain/state.rs index f2ebb04b33..4447f9988b 100644 --- a/json/src/blockchain/state.rs +++ b/crates/ethjson/src/blockchain/state.rs @@ -21,7 +21,6 @@ use crate::{ hash::{Address, H256}, spec::{Account, Builtin}, }; -use serde::Deserialize; use std::collections::BTreeMap; #[derive(Clone, Debug, PartialEq, Deserialize)] diff --git a/json/src/blockchain/test.rs b/crates/ethjson/src/blockchain/test.rs similarity index 100% rename from json/src/blockchain/test.rs rename to crates/ethjson/src/blockchain/test.rs diff --git a/json/src/blockchain/transaction.rs b/crates/ethjson/src/blockchain/transaction.rs similarity index 100% rename from json/src/blockchain/transaction.rs rename to crates/ethjson/src/blockchain/transaction.rs diff --git a/json/src/bytes.rs b/crates/ethjson/src/bytes.rs similarity index 100% rename from json/src/bytes.rs rename to crates/ethjson/src/bytes.rs diff --git a/json/src/hash.rs b/crates/ethjson/src/hash.rs similarity index 100% rename from json/src/hash.rs rename to crates/ethjson/src/hash.rs diff --git a/json/src/lib.rs b/crates/ethjson/src/lib.rs similarity index 100% rename from json/src/lib.rs rename to crates/ethjson/src/lib.rs diff --git a/json/src/maybe.rs b/crates/ethjson/src/maybe.rs similarity index 100% rename from json/src/maybe.rs rename to crates/ethjson/src/maybe.rs diff --git a/json/src/spec/account.rs b/crates/ethjson/src/spec/account.rs similarity index 100% rename from json/src/spec/account.rs rename to crates/ethjson/src/spec/account.rs diff --git a/json/src/spec/authority_round.rs b/crates/ethjson/src/spec/authority_round.rs similarity index 100% rename from json/src/spec/authority_round.rs rename to crates/ethjson/src/spec/authority_round.rs diff --git a/json/src/spec/basic_authority.rs b/crates/ethjson/src/spec/basic_authority.rs similarity index 100% rename from json/src/spec/basic_authority.rs rename to crates/ethjson/src/spec/basic_authority.rs diff --git a/json/src/spec/builtin.rs b/crates/ethjson/src/spec/builtin.rs similarity index 100% rename from json/src/spec/builtin.rs rename to crates/ethjson/src/spec/builtin.rs diff --git a/json/src/spec/clique.rs b/crates/ethjson/src/spec/clique.rs similarity index 100% rename from json/src/spec/clique.rs rename to crates/ethjson/src/spec/clique.rs diff --git a/json/src/spec/engine.rs b/crates/ethjson/src/spec/engine.rs similarity index 100% rename from json/src/spec/engine.rs rename to crates/ethjson/src/spec/engine.rs diff --git a/json/src/spec/ethash.rs b/crates/ethjson/src/spec/ethash.rs similarity index 100% rename from json/src/spec/ethash.rs rename to crates/ethjson/src/spec/ethash.rs diff --git a/json/src/spec/genesis.rs b/crates/ethjson/src/spec/genesis.rs similarity index 100% rename from json/src/spec/genesis.rs rename to crates/ethjson/src/spec/genesis.rs diff --git a/json/src/spec/instant_seal.rs b/crates/ethjson/src/spec/instant_seal.rs similarity index 100% rename from json/src/spec/instant_seal.rs rename to crates/ethjson/src/spec/instant_seal.rs diff --git a/json/src/spec/mod.rs b/crates/ethjson/src/spec/mod.rs similarity index 100% rename from json/src/spec/mod.rs rename to crates/ethjson/src/spec/mod.rs diff --git a/json/src/spec/null_engine.rs b/crates/ethjson/src/spec/null_engine.rs similarity index 100% rename from json/src/spec/null_engine.rs rename to crates/ethjson/src/spec/null_engine.rs diff --git a/json/src/spec/params.rs b/crates/ethjson/src/spec/params.rs similarity index 100% rename from json/src/spec/params.rs rename to crates/ethjson/src/spec/params.rs diff --git a/json/src/spec/seal.rs b/crates/ethjson/src/spec/seal.rs similarity index 100% rename from json/src/spec/seal.rs rename to crates/ethjson/src/spec/seal.rs diff --git a/json/src/spec/spec.rs b/crates/ethjson/src/spec/spec.rs similarity index 100% rename from json/src/spec/spec.rs rename to crates/ethjson/src/spec/spec.rs diff --git a/json/src/spec/state.rs b/crates/ethjson/src/spec/state.rs similarity index 100% rename from json/src/spec/state.rs rename to crates/ethjson/src/spec/state.rs diff --git a/json/src/spec/validator_set.rs b/crates/ethjson/src/spec/validator_set.rs similarity index 100% rename from json/src/spec/validator_set.rs rename to crates/ethjson/src/spec/validator_set.rs diff --git a/json/src/state/log.rs b/crates/ethjson/src/state/log.rs similarity index 100% rename from json/src/state/log.rs rename to crates/ethjson/src/state/log.rs diff --git a/json/src/state/mod.rs b/crates/ethjson/src/state/mod.rs similarity index 100% rename from json/src/state/mod.rs rename to crates/ethjson/src/state/mod.rs diff --git a/json/src/state/state.rs b/crates/ethjson/src/state/state.rs similarity index 100% rename from json/src/state/state.rs rename to crates/ethjson/src/state/state.rs diff --git a/json/src/state/test.rs b/crates/ethjson/src/state/test.rs similarity index 100% rename from json/src/state/test.rs rename to crates/ethjson/src/state/test.rs diff --git a/json/src/state/transaction.rs b/crates/ethjson/src/state/transaction.rs similarity index 100% rename from json/src/state/transaction.rs rename to crates/ethjson/src/state/transaction.rs diff --git a/json/src/test/mod.rs b/crates/ethjson/src/test/mod.rs similarity index 100% rename from json/src/test/mod.rs rename to crates/ethjson/src/test/mod.rs diff --git a/json/src/transaction/mod.rs b/crates/ethjson/src/transaction/mod.rs similarity index 100% rename from json/src/transaction/mod.rs rename to crates/ethjson/src/transaction/mod.rs diff --git a/json/src/transaction/test.rs b/crates/ethjson/src/transaction/test.rs similarity index 100% rename from json/src/transaction/test.rs rename to crates/ethjson/src/transaction/test.rs diff --git a/json/src/transaction/transaction.rs b/crates/ethjson/src/transaction/transaction.rs similarity index 100% rename from json/src/transaction/transaction.rs rename to crates/ethjson/src/transaction/transaction.rs diff --git a/json/src/transaction/txtest.rs b/crates/ethjson/src/transaction/txtest.rs similarity index 100% rename from json/src/transaction/txtest.rs rename to crates/ethjson/src/transaction/txtest.rs diff --git a/json/src/trie/input.rs b/crates/ethjson/src/trie/input.rs similarity index 100% rename from json/src/trie/input.rs rename to crates/ethjson/src/trie/input.rs diff --git a/json/src/trie/mod.rs b/crates/ethjson/src/trie/mod.rs similarity index 100% rename from json/src/trie/mod.rs rename to crates/ethjson/src/trie/mod.rs diff --git a/json/src/trie/test.rs b/crates/ethjson/src/trie/test.rs similarity index 100% rename from json/src/trie/test.rs rename to crates/ethjson/src/trie/test.rs diff --git a/json/src/trie/trie.rs b/crates/ethjson/src/trie/trie.rs similarity index 100% rename from json/src/trie/trie.rs rename to crates/ethjson/src/trie/trie.rs diff --git a/json/src/uint.rs b/crates/ethjson/src/uint.rs similarity index 100% rename from json/src/uint.rs rename to crates/ethjson/src/uint.rs diff --git a/json/src/vm/call.rs b/crates/ethjson/src/vm/call.rs similarity index 100% rename from json/src/vm/call.rs rename to crates/ethjson/src/vm/call.rs diff --git a/json/src/vm/env.rs b/crates/ethjson/src/vm/env.rs similarity index 100% rename from json/src/vm/env.rs rename to crates/ethjson/src/vm/env.rs diff --git a/json/src/vm/mod.rs b/crates/ethjson/src/vm/mod.rs similarity index 100% rename from json/src/vm/mod.rs rename to crates/ethjson/src/vm/mod.rs diff --git a/json/src/vm/test.rs b/crates/ethjson/src/vm/test.rs similarity index 100% rename from json/src/vm/test.rs rename to crates/ethjson/src/vm/test.rs diff --git a/json/src/vm/transaction.rs b/crates/ethjson/src/vm/transaction.rs similarity index 100% rename from json/src/vm/transaction.rs rename to crates/ethjson/src/vm/transaction.rs diff --git a/json/src/vm/vm.rs b/crates/ethjson/src/vm/vm.rs similarity index 100% rename from json/src/vm/vm.rs rename to crates/ethjson/src/vm/vm.rs diff --git a/util/fake-fetch/Cargo.toml b/crates/net/fake-fetch/Cargo.toml similarity index 100% rename from util/fake-fetch/Cargo.toml rename to crates/net/fake-fetch/Cargo.toml diff --git a/util/fake-fetch/src/lib.rs b/crates/net/fake-fetch/src/lib.rs similarity index 100% rename from util/fake-fetch/src/lib.rs rename to crates/net/fake-fetch/src/lib.rs diff --git a/util/fetch/Cargo.toml b/crates/net/fetch/Cargo.toml similarity index 100% rename from util/fetch/Cargo.toml rename to crates/net/fetch/Cargo.toml diff --git a/util/fetch/src/client.rs b/crates/net/fetch/src/client.rs similarity index 100% rename from util/fetch/src/client.rs rename to crates/net/fetch/src/client.rs diff --git a/util/fetch/src/lib.rs b/crates/net/fetch/src/lib.rs similarity index 100% rename from util/fetch/src/lib.rs rename to crates/net/fetch/src/lib.rs diff --git a/util/network-devp2p/Cargo.toml b/crates/net/network-devp2p/Cargo.toml similarity index 89% rename from util/network-devp2p/Cargo.toml rename to crates/net/network-devp2p/Cargo.toml index 5c1fecdeac..2b3873945a 100644 --- a/util/network-devp2p/Cargo.toml +++ b/crates/net/network-devp2p/Cargo.toml @@ -19,12 +19,12 @@ libc = "0.2.7" parking_lot = "0.7" ansi_term = "0.10" rustc-hex = "1.0" -ethcore-io = { path = "../io", features = ["mio"] } +ethcore-io = { path = "../../runtime/io", features = ["mio"] } parity-bytes = "0.1" parity-crypto = "0.3.0" ethcore-network = { path = "../network" } ethereum-types = "0.4" -ethkey = { path = "../../accounts/ethkey" } +ethkey = { path = "../../../crates/accounts/ethkey" } rlp = { version = "0.3.0", features = ["ethereum"] } parity-path = "0.1" ipnetwork = "0.12.6" diff --git a/util/network-devp2p/src/connection.rs b/crates/net/network-devp2p/src/connection.rs similarity index 100% rename from util/network-devp2p/src/connection.rs rename to crates/net/network-devp2p/src/connection.rs diff --git a/util/network-devp2p/src/discovery.rs b/crates/net/network-devp2p/src/discovery.rs similarity index 100% rename from util/network-devp2p/src/discovery.rs rename to crates/net/network-devp2p/src/discovery.rs diff --git a/util/network-devp2p/src/handshake.rs b/crates/net/network-devp2p/src/handshake.rs similarity index 100% rename from util/network-devp2p/src/handshake.rs rename to crates/net/network-devp2p/src/handshake.rs diff --git a/util/network-devp2p/src/host.rs b/crates/net/network-devp2p/src/host.rs similarity index 100% rename from util/network-devp2p/src/host.rs rename to crates/net/network-devp2p/src/host.rs diff --git a/util/network-devp2p/src/ip_utils.rs b/crates/net/network-devp2p/src/ip_utils.rs similarity index 100% rename from util/network-devp2p/src/ip_utils.rs rename to crates/net/network-devp2p/src/ip_utils.rs diff --git a/util/network-devp2p/src/lib.rs b/crates/net/network-devp2p/src/lib.rs similarity index 100% rename from util/network-devp2p/src/lib.rs rename to crates/net/network-devp2p/src/lib.rs diff --git a/util/network-devp2p/src/node_table.rs b/crates/net/network-devp2p/src/node_table.rs similarity index 100% rename from util/network-devp2p/src/node_table.rs rename to crates/net/network-devp2p/src/node_table.rs diff --git a/util/network-devp2p/src/service.rs b/crates/net/network-devp2p/src/service.rs similarity index 100% rename from util/network-devp2p/src/service.rs rename to crates/net/network-devp2p/src/service.rs diff --git a/util/network-devp2p/src/session.rs b/crates/net/network-devp2p/src/session.rs similarity index 100% rename from util/network-devp2p/src/session.rs rename to crates/net/network-devp2p/src/session.rs diff --git a/util/network-devp2p/tests/tests.rs b/crates/net/network-devp2p/tests/tests.rs similarity index 100% rename from util/network-devp2p/tests/tests.rs rename to crates/net/network-devp2p/tests/tests.rs diff --git a/util/network/Cargo.toml b/crates/net/network/Cargo.toml similarity index 86% rename from util/network/Cargo.toml rename to crates/net/network/Cargo.toml index 42d0040949..30827dee8d 100644 --- a/util/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -9,9 +9,9 @@ authors = ["Parity Technologies "] [dependencies] error-chain = { version = "0.12", default-features = false } parity-crypto = "0.3.0" -ethcore-io = { path = "../io" } +ethcore-io = { path = "../../runtime/io" } ethereum-types = "0.4" -ethkey = { path = "../../accounts/ethkey" } +ethkey = { path = "../../../crates/accounts/ethkey" } ipnetwork = "0.12.6" lazy_static = "1.0" rlp = { version = "0.3.0", features = ["ethereum"] } diff --git a/util/network/src/client_version.rs b/crates/net/network/src/client_version.rs similarity index 100% rename from util/network/src/client_version.rs rename to crates/net/network/src/client_version.rs diff --git a/util/network/src/connection_filter.rs b/crates/net/network/src/connection_filter.rs similarity index 100% rename from util/network/src/connection_filter.rs rename to crates/net/network/src/connection_filter.rs diff --git a/util/network/src/error.rs b/crates/net/network/src/error.rs similarity index 100% rename from util/network/src/error.rs rename to crates/net/network/src/error.rs diff --git a/util/network/src/lib.rs b/crates/net/network/src/lib.rs similarity index 100% rename from util/network/src/lib.rs rename to crates/net/network/src/lib.rs diff --git a/ethcore/node-filter/Cargo.toml b/crates/net/node-filter/Cargo.toml similarity index 64% rename from ethcore/node-filter/Cargo.toml rename to crates/net/node-filter/Cargo.toml index 26b343af61..ca812ca19a 100644 --- a/ethcore/node-filter/Cargo.toml +++ b/crates/net/node-filter/Cargo.toml @@ -7,9 +7,9 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] -ethcore = { path = ".."} -ethcore-network = { path = "../../util/network" } -ethcore-network-devp2p = { path = "../../util/network-devp2p" } +ethcore = { path = "../../ethcore"} +ethcore-network = { path = "../network" } +ethcore-network-devp2p = { path = "../network-devp2p" } ethereum-types = "0.4" log = "0.4" parking_lot = "0.7" @@ -19,7 +19,7 @@ ethabi-contract = "6.0" lru-cache = "0.1" [dev-dependencies] -ethcore = { path = "..", features = ["test-helpers"] } +ethcore = { path = "../../ethcore", features = ["test-helpers"] } kvdb-memorydb = "0.1" -ethcore-io = { path = "../../util/io" } -tempdir = "0.3" +ethcore-io = { path = "../../runtime/io" } +tempdir = "0.3" \ No newline at end of file diff --git a/ethcore/node-filter/res/node_filter.json b/crates/net/node-filter/res/node_filter.json similarity index 100% rename from ethcore/node-filter/res/node_filter.json rename to crates/net/node-filter/res/node_filter.json diff --git a/ethcore/node-filter/res/peer_set.json b/crates/net/node-filter/res/peer_set.json similarity index 100% rename from ethcore/node-filter/res/peer_set.json rename to crates/net/node-filter/res/peer_set.json diff --git a/ethcore/node-filter/src/lib.rs b/crates/net/node-filter/src/lib.rs similarity index 100% rename from ethcore/node-filter/src/lib.rs rename to crates/net/node-filter/src/lib.rs diff --git a/rpc/Cargo.toml b/crates/rpc/Cargo.toml similarity index 75% rename from rpc/Cargo.toml rename to crates/rpc/Cargo.toml index ae4215f01a..4b2d9bdef3 100644 --- a/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -32,35 +32,35 @@ jsonrpc-ipc-server = "15.0.0" jsonrpc-pubsub = "15.0.0" common-types = { path = "../ethcore/types" } -ethash = { path = "../ethash" } +ethash = { path = "../concensus/ethash" } ethcore = { path = "../ethcore" } ethcore-accounts = { path = "../accounts", optional = true } -ethcore-logger = { path = "../parity/logger" } -ethcore-miner = { path = "../miner" } -ethcore-network = { path = "../util/network" } +ethcore-logger = { path = "../../bin/oe/logger" } +ethcore-miner = { path = "../concensus/miner" } +ethcore-network = { path = "../net/network" } ethcore-sync = { path = "../ethcore/sync" } ethereum-types = "0.4" parity-bytes = "0.1" parity-crypto = "0.3.0" eip-712 = { path = "../util/EIP-712" } -ethjson = { path = "../json" } +ethjson = { path = "../ethjson" } ethkey = { path = "../accounts/ethkey" } ethstore = { path = "../accounts/ethstore" } -fetch = { path = "../util/fetch" } +fetch = { path = "../net/fetch" } keccak-hash = "0.1.2" -parity-runtime = { path = "../util/runtime" } +parity-runtime = { path = "../runtime/runtime" } parity-version = { path = "../util/version" } rlp = { version = "0.3.0", features = ["ethereum"] } stats = { path = "../util/stats" } -vm = { path = "../ethcore/vm" } +vm = { path = "../vm/vm" } [dev-dependencies] ethcore = { path = "../ethcore", features = ["test-helpers"] } ethcore-accounts = { path = "../accounts" } -ethcore-io = { path = "../util/io" } -ethcore-network = { path = "../util/network" } -fake-fetch = { path = "../util/fake-fetch" } +ethcore-io = { path = "../runtime/io" } +ethcore-network = { path = "../net/network" } +fake-fetch = { path = "../net/fake-fetch" } macros = { path = "../util/macros" } pretty_assertions = "0.1" transaction-pool = "2.0.1" diff --git a/rpc/src/authcodes.rs b/crates/rpc/src/authcodes.rs similarity index 100% rename from rpc/src/authcodes.rs rename to crates/rpc/src/authcodes.rs diff --git a/rpc/src/http_common.rs b/crates/rpc/src/http_common.rs similarity index 100% rename from rpc/src/http_common.rs rename to crates/rpc/src/http_common.rs diff --git a/rpc/src/lib.rs b/crates/rpc/src/lib.rs similarity index 100% rename from rpc/src/lib.rs rename to crates/rpc/src/lib.rs diff --git a/rpc/src/tests/helpers.rs b/crates/rpc/src/tests/helpers.rs similarity index 100% rename from rpc/src/tests/helpers.rs rename to crates/rpc/src/tests/helpers.rs diff --git a/rpc/src/tests/http_client.rs b/crates/rpc/src/tests/http_client.rs similarity index 100% rename from rpc/src/tests/http_client.rs rename to crates/rpc/src/tests/http_client.rs diff --git a/rpc/src/tests/mod.rs b/crates/rpc/src/tests/mod.rs similarity index 100% rename from rpc/src/tests/mod.rs rename to crates/rpc/src/tests/mod.rs diff --git a/rpc/src/tests/rpc.rs b/crates/rpc/src/tests/rpc.rs similarity index 100% rename from rpc/src/tests/rpc.rs rename to crates/rpc/src/tests/rpc.rs diff --git a/rpc/src/tests/ws.rs b/crates/rpc/src/tests/ws.rs similarity index 100% rename from rpc/src/tests/ws.rs rename to crates/rpc/src/tests/ws.rs diff --git a/rpc/src/v1/extractors.rs b/crates/rpc/src/v1/extractors.rs similarity index 100% rename from rpc/src/v1/extractors.rs rename to crates/rpc/src/v1/extractors.rs diff --git a/rpc/src/v1/helpers/block_import.rs b/crates/rpc/src/v1/helpers/block_import.rs similarity index 100% rename from rpc/src/v1/helpers/block_import.rs rename to crates/rpc/src/v1/helpers/block_import.rs diff --git a/rpc/src/v1/helpers/deprecated.rs b/crates/rpc/src/v1/helpers/deprecated.rs similarity index 100% rename from rpc/src/v1/helpers/deprecated.rs rename to crates/rpc/src/v1/helpers/deprecated.rs diff --git a/rpc/src/v1/helpers/dispatch/full.rs b/crates/rpc/src/v1/helpers/dispatch/full.rs similarity index 100% rename from rpc/src/v1/helpers/dispatch/full.rs rename to crates/rpc/src/v1/helpers/dispatch/full.rs diff --git a/rpc/src/v1/helpers/dispatch/mod.rs b/crates/rpc/src/v1/helpers/dispatch/mod.rs similarity index 100% rename from rpc/src/v1/helpers/dispatch/mod.rs rename to crates/rpc/src/v1/helpers/dispatch/mod.rs diff --git a/rpc/src/v1/helpers/dispatch/prospective_signer.rs b/crates/rpc/src/v1/helpers/dispatch/prospective_signer.rs similarity index 100% rename from rpc/src/v1/helpers/dispatch/prospective_signer.rs rename to crates/rpc/src/v1/helpers/dispatch/prospective_signer.rs diff --git a/rpc/src/v1/helpers/dispatch/signing.rs b/crates/rpc/src/v1/helpers/dispatch/signing.rs similarity index 100% rename from rpc/src/v1/helpers/dispatch/signing.rs rename to crates/rpc/src/v1/helpers/dispatch/signing.rs diff --git a/rpc/src/v1/helpers/eip191.rs b/crates/rpc/src/v1/helpers/eip191.rs similarity index 100% rename from rpc/src/v1/helpers/eip191.rs rename to crates/rpc/src/v1/helpers/eip191.rs diff --git a/rpc/src/v1/helpers/engine_signer.rs b/crates/rpc/src/v1/helpers/engine_signer.rs similarity index 100% rename from rpc/src/v1/helpers/engine_signer.rs rename to crates/rpc/src/v1/helpers/engine_signer.rs diff --git a/rpc/src/v1/helpers/errors.rs b/crates/rpc/src/v1/helpers/errors.rs similarity index 100% rename from rpc/src/v1/helpers/errors.rs rename to crates/rpc/src/v1/helpers/errors.rs diff --git a/rpc/src/v1/helpers/external_signer/mod.rs b/crates/rpc/src/v1/helpers/external_signer/mod.rs similarity index 100% rename from rpc/src/v1/helpers/external_signer/mod.rs rename to crates/rpc/src/v1/helpers/external_signer/mod.rs diff --git a/rpc/src/v1/helpers/external_signer/oneshot.rs b/crates/rpc/src/v1/helpers/external_signer/oneshot.rs similarity index 100% rename from rpc/src/v1/helpers/external_signer/oneshot.rs rename to crates/rpc/src/v1/helpers/external_signer/oneshot.rs diff --git a/rpc/src/v1/helpers/external_signer/signing_queue.rs b/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs similarity index 100% rename from rpc/src/v1/helpers/external_signer/signing_queue.rs rename to crates/rpc/src/v1/helpers/external_signer/signing_queue.rs diff --git a/rpc/src/v1/helpers/fake_sign.rs b/crates/rpc/src/v1/helpers/fake_sign.rs similarity index 100% rename from rpc/src/v1/helpers/fake_sign.rs rename to crates/rpc/src/v1/helpers/fake_sign.rs diff --git a/rpc/src/v1/helpers/mod.rs b/crates/rpc/src/v1/helpers/mod.rs similarity index 100% rename from rpc/src/v1/helpers/mod.rs rename to crates/rpc/src/v1/helpers/mod.rs diff --git a/rpc/src/v1/helpers/network_settings.rs b/crates/rpc/src/v1/helpers/network_settings.rs similarity index 100% rename from rpc/src/v1/helpers/network_settings.rs rename to crates/rpc/src/v1/helpers/network_settings.rs diff --git a/rpc/src/v1/helpers/nonce.rs b/crates/rpc/src/v1/helpers/nonce.rs similarity index 100% rename from rpc/src/v1/helpers/nonce.rs rename to crates/rpc/src/v1/helpers/nonce.rs diff --git a/rpc/src/v1/helpers/poll_filter.rs b/crates/rpc/src/v1/helpers/poll_filter.rs similarity index 100% rename from rpc/src/v1/helpers/poll_filter.rs rename to crates/rpc/src/v1/helpers/poll_filter.rs diff --git a/rpc/src/v1/helpers/poll_manager.rs b/crates/rpc/src/v1/helpers/poll_manager.rs similarity index 100% rename from rpc/src/v1/helpers/poll_manager.rs rename to crates/rpc/src/v1/helpers/poll_manager.rs diff --git a/rpc/src/v1/helpers/requests.rs b/crates/rpc/src/v1/helpers/requests.rs similarity index 100% rename from rpc/src/v1/helpers/requests.rs rename to crates/rpc/src/v1/helpers/requests.rs diff --git a/rpc/src/v1/helpers/secretstore.rs b/crates/rpc/src/v1/helpers/secretstore.rs similarity index 100% rename from rpc/src/v1/helpers/secretstore.rs rename to crates/rpc/src/v1/helpers/secretstore.rs diff --git a/rpc/src/v1/helpers/signature.rs b/crates/rpc/src/v1/helpers/signature.rs similarity index 100% rename from rpc/src/v1/helpers/signature.rs rename to crates/rpc/src/v1/helpers/signature.rs diff --git a/rpc/src/v1/helpers/subscribers.rs b/crates/rpc/src/v1/helpers/subscribers.rs similarity index 100% rename from rpc/src/v1/helpers/subscribers.rs rename to crates/rpc/src/v1/helpers/subscribers.rs diff --git a/rpc/src/v1/helpers/subscription_manager.rs b/crates/rpc/src/v1/helpers/subscription_manager.rs similarity index 100% rename from rpc/src/v1/helpers/subscription_manager.rs rename to crates/rpc/src/v1/helpers/subscription_manager.rs diff --git a/rpc/src/v1/helpers/work.rs b/crates/rpc/src/v1/helpers/work.rs similarity index 100% rename from rpc/src/v1/helpers/work.rs rename to crates/rpc/src/v1/helpers/work.rs diff --git a/rpc/src/v1/impls/debug.rs b/crates/rpc/src/v1/impls/debug.rs similarity index 100% rename from rpc/src/v1/impls/debug.rs rename to crates/rpc/src/v1/impls/debug.rs diff --git a/rpc/src/v1/impls/eth.rs b/crates/rpc/src/v1/impls/eth.rs similarity index 100% rename from rpc/src/v1/impls/eth.rs rename to crates/rpc/src/v1/impls/eth.rs diff --git a/rpc/src/v1/impls/eth_filter.rs b/crates/rpc/src/v1/impls/eth_filter.rs similarity index 100% rename from rpc/src/v1/impls/eth_filter.rs rename to crates/rpc/src/v1/impls/eth_filter.rs diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/crates/rpc/src/v1/impls/eth_pubsub.rs similarity index 100% rename from rpc/src/v1/impls/eth_pubsub.rs rename to crates/rpc/src/v1/impls/eth_pubsub.rs diff --git a/rpc/src/v1/impls/mod.rs b/crates/rpc/src/v1/impls/mod.rs similarity index 100% rename from rpc/src/v1/impls/mod.rs rename to crates/rpc/src/v1/impls/mod.rs diff --git a/rpc/src/v1/impls/net.rs b/crates/rpc/src/v1/impls/net.rs similarity index 100% rename from rpc/src/v1/impls/net.rs rename to crates/rpc/src/v1/impls/net.rs diff --git a/rpc/src/v1/impls/parity.rs b/crates/rpc/src/v1/impls/parity.rs similarity index 100% rename from rpc/src/v1/impls/parity.rs rename to crates/rpc/src/v1/impls/parity.rs diff --git a/rpc/src/v1/impls/parity_accounts.rs b/crates/rpc/src/v1/impls/parity_accounts.rs similarity index 100% rename from rpc/src/v1/impls/parity_accounts.rs rename to crates/rpc/src/v1/impls/parity_accounts.rs diff --git a/rpc/src/v1/impls/parity_set.rs b/crates/rpc/src/v1/impls/parity_set.rs similarity index 100% rename from rpc/src/v1/impls/parity_set.rs rename to crates/rpc/src/v1/impls/parity_set.rs diff --git a/rpc/src/v1/impls/personal.rs b/crates/rpc/src/v1/impls/personal.rs similarity index 100% rename from rpc/src/v1/impls/personal.rs rename to crates/rpc/src/v1/impls/personal.rs diff --git a/rpc/src/v1/impls/pubsub.rs b/crates/rpc/src/v1/impls/pubsub.rs similarity index 100% rename from rpc/src/v1/impls/pubsub.rs rename to crates/rpc/src/v1/impls/pubsub.rs diff --git a/rpc/src/v1/impls/secretstore.rs b/crates/rpc/src/v1/impls/secretstore.rs similarity index 100% rename from rpc/src/v1/impls/secretstore.rs rename to crates/rpc/src/v1/impls/secretstore.rs diff --git a/rpc/src/v1/impls/signer.rs b/crates/rpc/src/v1/impls/signer.rs similarity index 100% rename from rpc/src/v1/impls/signer.rs rename to crates/rpc/src/v1/impls/signer.rs diff --git a/rpc/src/v1/impls/signing.rs b/crates/rpc/src/v1/impls/signing.rs similarity index 100% rename from rpc/src/v1/impls/signing.rs rename to crates/rpc/src/v1/impls/signing.rs diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/crates/rpc/src/v1/impls/signing_unsafe.rs similarity index 100% rename from rpc/src/v1/impls/signing_unsafe.rs rename to crates/rpc/src/v1/impls/signing_unsafe.rs diff --git a/rpc/src/v1/impls/traces.rs b/crates/rpc/src/v1/impls/traces.rs similarity index 100% rename from rpc/src/v1/impls/traces.rs rename to crates/rpc/src/v1/impls/traces.rs diff --git a/rpc/src/v1/impls/web3.rs b/crates/rpc/src/v1/impls/web3.rs similarity index 100% rename from rpc/src/v1/impls/web3.rs rename to crates/rpc/src/v1/impls/web3.rs diff --git a/rpc/src/v1/informant.rs b/crates/rpc/src/v1/informant.rs similarity index 100% rename from rpc/src/v1/informant.rs rename to crates/rpc/src/v1/informant.rs diff --git a/rpc/src/v1/metadata.rs b/crates/rpc/src/v1/metadata.rs similarity index 100% rename from rpc/src/v1/metadata.rs rename to crates/rpc/src/v1/metadata.rs diff --git a/rpc/src/v1/mod.rs b/crates/rpc/src/v1/mod.rs similarity index 100% rename from rpc/src/v1/mod.rs rename to crates/rpc/src/v1/mod.rs diff --git a/rpc/src/v1/tests/eth.rs b/crates/rpc/src/v1/tests/eth.rs similarity index 100% rename from rpc/src/v1/tests/eth.rs rename to crates/rpc/src/v1/tests/eth.rs diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/crates/rpc/src/v1/tests/helpers/miner_service.rs similarity index 100% rename from rpc/src/v1/tests/helpers/miner_service.rs rename to crates/rpc/src/v1/tests/helpers/miner_service.rs diff --git a/rpc/src/v1/tests/helpers/mod.rs b/crates/rpc/src/v1/tests/helpers/mod.rs similarity index 100% rename from rpc/src/v1/tests/helpers/mod.rs rename to crates/rpc/src/v1/tests/helpers/mod.rs diff --git a/rpc/src/v1/tests/helpers/snapshot_service.rs b/crates/rpc/src/v1/tests/helpers/snapshot_service.rs similarity index 100% rename from rpc/src/v1/tests/helpers/snapshot_service.rs rename to crates/rpc/src/v1/tests/helpers/snapshot_service.rs diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/crates/rpc/src/v1/tests/helpers/sync_provider.rs similarity index 100% rename from rpc/src/v1/tests/helpers/sync_provider.rs rename to crates/rpc/src/v1/tests/helpers/sync_provider.rs diff --git a/rpc/src/v1/tests/mocked/debug.rs b/crates/rpc/src/v1/tests/mocked/debug.rs similarity index 100% rename from rpc/src/v1/tests/mocked/debug.rs rename to crates/rpc/src/v1/tests/mocked/debug.rs diff --git a/rpc/src/v1/tests/mocked/eth.rs b/crates/rpc/src/v1/tests/mocked/eth.rs similarity index 100% rename from rpc/src/v1/tests/mocked/eth.rs rename to crates/rpc/src/v1/tests/mocked/eth.rs diff --git a/rpc/src/v1/tests/mocked/eth_pubsub.rs b/crates/rpc/src/v1/tests/mocked/eth_pubsub.rs similarity index 100% rename from rpc/src/v1/tests/mocked/eth_pubsub.rs rename to crates/rpc/src/v1/tests/mocked/eth_pubsub.rs diff --git a/rpc/src/v1/tests/mocked/manage_network.rs b/crates/rpc/src/v1/tests/mocked/manage_network.rs similarity index 100% rename from rpc/src/v1/tests/mocked/manage_network.rs rename to crates/rpc/src/v1/tests/mocked/manage_network.rs diff --git a/rpc/src/v1/tests/mocked/mod.rs b/crates/rpc/src/v1/tests/mocked/mod.rs similarity index 100% rename from rpc/src/v1/tests/mocked/mod.rs rename to crates/rpc/src/v1/tests/mocked/mod.rs diff --git a/rpc/src/v1/tests/mocked/net.rs b/crates/rpc/src/v1/tests/mocked/net.rs similarity index 100% rename from rpc/src/v1/tests/mocked/net.rs rename to crates/rpc/src/v1/tests/mocked/net.rs diff --git a/rpc/src/v1/tests/mocked/parity.rs b/crates/rpc/src/v1/tests/mocked/parity.rs similarity index 100% rename from rpc/src/v1/tests/mocked/parity.rs rename to crates/rpc/src/v1/tests/mocked/parity.rs diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/crates/rpc/src/v1/tests/mocked/parity_accounts.rs similarity index 100% rename from rpc/src/v1/tests/mocked/parity_accounts.rs rename to crates/rpc/src/v1/tests/mocked/parity_accounts.rs diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/crates/rpc/src/v1/tests/mocked/parity_set.rs similarity index 100% rename from rpc/src/v1/tests/mocked/parity_set.rs rename to crates/rpc/src/v1/tests/mocked/parity_set.rs diff --git a/rpc/src/v1/tests/mocked/personal.rs b/crates/rpc/src/v1/tests/mocked/personal.rs similarity index 100% rename from rpc/src/v1/tests/mocked/personal.rs rename to crates/rpc/src/v1/tests/mocked/personal.rs diff --git a/rpc/src/v1/tests/mocked/pubsub.rs b/crates/rpc/src/v1/tests/mocked/pubsub.rs similarity index 100% rename from rpc/src/v1/tests/mocked/pubsub.rs rename to crates/rpc/src/v1/tests/mocked/pubsub.rs diff --git a/rpc/src/v1/tests/mocked/secretstore.rs b/crates/rpc/src/v1/tests/mocked/secretstore.rs similarity index 100% rename from rpc/src/v1/tests/mocked/secretstore.rs rename to crates/rpc/src/v1/tests/mocked/secretstore.rs diff --git a/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs similarity index 100% rename from rpc/src/v1/tests/mocked/signer.rs rename to crates/rpc/src/v1/tests/mocked/signer.rs diff --git a/rpc/src/v1/tests/mocked/signing.rs b/crates/rpc/src/v1/tests/mocked/signing.rs similarity index 100% rename from rpc/src/v1/tests/mocked/signing.rs rename to crates/rpc/src/v1/tests/mocked/signing.rs diff --git a/rpc/src/v1/tests/mocked/signing_unsafe.rs b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs similarity index 100% rename from rpc/src/v1/tests/mocked/signing_unsafe.rs rename to crates/rpc/src/v1/tests/mocked/signing_unsafe.rs diff --git a/rpc/src/v1/tests/mocked/traces.rs b/crates/rpc/src/v1/tests/mocked/traces.rs similarity index 100% rename from rpc/src/v1/tests/mocked/traces.rs rename to crates/rpc/src/v1/tests/mocked/traces.rs diff --git a/rpc/src/v1/tests/mocked/web3.rs b/crates/rpc/src/v1/tests/mocked/web3.rs similarity index 100% rename from rpc/src/v1/tests/mocked/web3.rs rename to crates/rpc/src/v1/tests/mocked/web3.rs diff --git a/rpc/src/v1/tests/mod.rs b/crates/rpc/src/v1/tests/mod.rs similarity index 93% rename from rpc/src/v1/tests/mod.rs rename to crates/rpc/src/v1/tests/mod.rs index e695bc4cc5..794bbce8a2 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/crates/rpc/src/v1/tests/mod.rs @@ -31,7 +31,7 @@ pub mod helpers; macro_rules! extract_chain { (iter $file:expr) => {{ const RAW_DATA: &'static [u8] = - include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/LegacyTests/Constantinople/", $file, ".json")); + include_bytes!(concat!("../../../../ethcore/res/json_tests/LegacyTests/Constantinople/", $file, ".json")); ::ethjson::blockchain::Test::load(RAW_DATA).unwrap().into_iter() }}; diff --git a/rpc/src/v1/traits/debug.rs b/crates/rpc/src/v1/traits/debug.rs similarity index 100% rename from rpc/src/v1/traits/debug.rs rename to crates/rpc/src/v1/traits/debug.rs diff --git a/rpc/src/v1/traits/eth.rs b/crates/rpc/src/v1/traits/eth.rs similarity index 100% rename from rpc/src/v1/traits/eth.rs rename to crates/rpc/src/v1/traits/eth.rs diff --git a/rpc/src/v1/traits/eth_pubsub.rs b/crates/rpc/src/v1/traits/eth_pubsub.rs similarity index 100% rename from rpc/src/v1/traits/eth_pubsub.rs rename to crates/rpc/src/v1/traits/eth_pubsub.rs diff --git a/rpc/src/v1/traits/eth_signing.rs b/crates/rpc/src/v1/traits/eth_signing.rs similarity index 100% rename from rpc/src/v1/traits/eth_signing.rs rename to crates/rpc/src/v1/traits/eth_signing.rs diff --git a/rpc/src/v1/traits/mod.rs b/crates/rpc/src/v1/traits/mod.rs similarity index 100% rename from rpc/src/v1/traits/mod.rs rename to crates/rpc/src/v1/traits/mod.rs diff --git a/rpc/src/v1/traits/net.rs b/crates/rpc/src/v1/traits/net.rs similarity index 100% rename from rpc/src/v1/traits/net.rs rename to crates/rpc/src/v1/traits/net.rs diff --git a/rpc/src/v1/traits/parity.rs b/crates/rpc/src/v1/traits/parity.rs similarity index 100% rename from rpc/src/v1/traits/parity.rs rename to crates/rpc/src/v1/traits/parity.rs diff --git a/rpc/src/v1/traits/parity_accounts.rs b/crates/rpc/src/v1/traits/parity_accounts.rs similarity index 100% rename from rpc/src/v1/traits/parity_accounts.rs rename to crates/rpc/src/v1/traits/parity_accounts.rs diff --git a/rpc/src/v1/traits/parity_set.rs b/crates/rpc/src/v1/traits/parity_set.rs similarity index 100% rename from rpc/src/v1/traits/parity_set.rs rename to crates/rpc/src/v1/traits/parity_set.rs diff --git a/rpc/src/v1/traits/parity_signing.rs b/crates/rpc/src/v1/traits/parity_signing.rs similarity index 100% rename from rpc/src/v1/traits/parity_signing.rs rename to crates/rpc/src/v1/traits/parity_signing.rs diff --git a/rpc/src/v1/traits/personal.rs b/crates/rpc/src/v1/traits/personal.rs similarity index 100% rename from rpc/src/v1/traits/personal.rs rename to crates/rpc/src/v1/traits/personal.rs diff --git a/rpc/src/v1/traits/pubsub.rs b/crates/rpc/src/v1/traits/pubsub.rs similarity index 100% rename from rpc/src/v1/traits/pubsub.rs rename to crates/rpc/src/v1/traits/pubsub.rs diff --git a/rpc/src/v1/traits/secretstore.rs b/crates/rpc/src/v1/traits/secretstore.rs similarity index 100% rename from rpc/src/v1/traits/secretstore.rs rename to crates/rpc/src/v1/traits/secretstore.rs diff --git a/rpc/src/v1/traits/signer.rs b/crates/rpc/src/v1/traits/signer.rs similarity index 100% rename from rpc/src/v1/traits/signer.rs rename to crates/rpc/src/v1/traits/signer.rs diff --git a/rpc/src/v1/traits/traces.rs b/crates/rpc/src/v1/traits/traces.rs similarity index 100% rename from rpc/src/v1/traits/traces.rs rename to crates/rpc/src/v1/traits/traces.rs diff --git a/rpc/src/v1/traits/web3.rs b/crates/rpc/src/v1/traits/web3.rs similarity index 100% rename from rpc/src/v1/traits/web3.rs rename to crates/rpc/src/v1/traits/web3.rs diff --git a/rpc/src/v1/types/account_info.rs b/crates/rpc/src/v1/types/account_info.rs similarity index 100% rename from rpc/src/v1/types/account_info.rs rename to crates/rpc/src/v1/types/account_info.rs diff --git a/rpc/src/v1/types/block.rs b/crates/rpc/src/v1/types/block.rs similarity index 100% rename from rpc/src/v1/types/block.rs rename to crates/rpc/src/v1/types/block.rs diff --git a/rpc/src/v1/types/block_number.rs b/crates/rpc/src/v1/types/block_number.rs similarity index 100% rename from rpc/src/v1/types/block_number.rs rename to crates/rpc/src/v1/types/block_number.rs diff --git a/rpc/src/v1/types/bytes.rs b/crates/rpc/src/v1/types/bytes.rs similarity index 100% rename from rpc/src/v1/types/bytes.rs rename to crates/rpc/src/v1/types/bytes.rs diff --git a/rpc/src/v1/types/call_request.rs b/crates/rpc/src/v1/types/call_request.rs similarity index 100% rename from rpc/src/v1/types/call_request.rs rename to crates/rpc/src/v1/types/call_request.rs diff --git a/rpc/src/v1/types/confirmations.rs b/crates/rpc/src/v1/types/confirmations.rs similarity index 100% rename from rpc/src/v1/types/confirmations.rs rename to crates/rpc/src/v1/types/confirmations.rs diff --git a/rpc/src/v1/types/derivation.rs b/crates/rpc/src/v1/types/derivation.rs similarity index 100% rename from rpc/src/v1/types/derivation.rs rename to crates/rpc/src/v1/types/derivation.rs diff --git a/rpc/src/v1/types/eip191.rs b/crates/rpc/src/v1/types/eip191.rs similarity index 100% rename from rpc/src/v1/types/eip191.rs rename to crates/rpc/src/v1/types/eip191.rs diff --git a/rpc/src/v1/types/eth_types.rs b/crates/rpc/src/v1/types/eth_types.rs similarity index 100% rename from rpc/src/v1/types/eth_types.rs rename to crates/rpc/src/v1/types/eth_types.rs diff --git a/rpc/src/v1/types/filter.rs b/crates/rpc/src/v1/types/filter.rs similarity index 100% rename from rpc/src/v1/types/filter.rs rename to crates/rpc/src/v1/types/filter.rs diff --git a/rpc/src/v1/types/histogram.rs b/crates/rpc/src/v1/types/histogram.rs similarity index 100% rename from rpc/src/v1/types/histogram.rs rename to crates/rpc/src/v1/types/histogram.rs diff --git a/rpc/src/v1/types/index.rs b/crates/rpc/src/v1/types/index.rs similarity index 100% rename from rpc/src/v1/types/index.rs rename to crates/rpc/src/v1/types/index.rs diff --git a/rpc/src/v1/types/log.rs b/crates/rpc/src/v1/types/log.rs similarity index 100% rename from rpc/src/v1/types/log.rs rename to crates/rpc/src/v1/types/log.rs diff --git a/rpc/src/v1/types/mod.rs b/crates/rpc/src/v1/types/mod.rs similarity index 100% rename from rpc/src/v1/types/mod.rs rename to crates/rpc/src/v1/types/mod.rs diff --git a/rpc/src/v1/types/node_kind.rs b/crates/rpc/src/v1/types/node_kind.rs similarity index 100% rename from rpc/src/v1/types/node_kind.rs rename to crates/rpc/src/v1/types/node_kind.rs diff --git a/rpc/src/v1/types/provenance.rs b/crates/rpc/src/v1/types/provenance.rs similarity index 100% rename from rpc/src/v1/types/provenance.rs rename to crates/rpc/src/v1/types/provenance.rs diff --git a/rpc/src/v1/types/pubsub.rs b/crates/rpc/src/v1/types/pubsub.rs similarity index 100% rename from rpc/src/v1/types/pubsub.rs rename to crates/rpc/src/v1/types/pubsub.rs diff --git a/rpc/src/v1/types/receipt.rs b/crates/rpc/src/v1/types/receipt.rs similarity index 100% rename from rpc/src/v1/types/receipt.rs rename to crates/rpc/src/v1/types/receipt.rs diff --git a/rpc/src/v1/types/rpc_settings.rs b/crates/rpc/src/v1/types/rpc_settings.rs similarity index 100% rename from rpc/src/v1/types/rpc_settings.rs rename to crates/rpc/src/v1/types/rpc_settings.rs diff --git a/rpc/src/v1/types/secretstore.rs b/crates/rpc/src/v1/types/secretstore.rs similarity index 100% rename from rpc/src/v1/types/secretstore.rs rename to crates/rpc/src/v1/types/secretstore.rs diff --git a/rpc/src/v1/types/sync.rs b/crates/rpc/src/v1/types/sync.rs similarity index 100% rename from rpc/src/v1/types/sync.rs rename to crates/rpc/src/v1/types/sync.rs diff --git a/rpc/src/v1/types/trace.rs b/crates/rpc/src/v1/types/trace.rs similarity index 100% rename from rpc/src/v1/types/trace.rs rename to crates/rpc/src/v1/types/trace.rs diff --git a/rpc/src/v1/types/trace_filter.rs b/crates/rpc/src/v1/types/trace_filter.rs similarity index 100% rename from rpc/src/v1/types/trace_filter.rs rename to crates/rpc/src/v1/types/trace_filter.rs diff --git a/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs similarity index 100% rename from rpc/src/v1/types/transaction.rs rename to crates/rpc/src/v1/types/transaction.rs diff --git a/rpc/src/v1/types/transaction_condition.rs b/crates/rpc/src/v1/types/transaction_condition.rs similarity index 100% rename from rpc/src/v1/types/transaction_condition.rs rename to crates/rpc/src/v1/types/transaction_condition.rs diff --git a/rpc/src/v1/types/transaction_request.rs b/crates/rpc/src/v1/types/transaction_request.rs similarity index 100% rename from rpc/src/v1/types/transaction_request.rs rename to crates/rpc/src/v1/types/transaction_request.rs diff --git a/rpc/src/v1/types/work.rs b/crates/rpc/src/v1/types/work.rs similarity index 100% rename from rpc/src/v1/types/work.rs rename to crates/rpc/src/v1/types/work.rs diff --git a/util/io/Cargo.toml b/crates/runtime/io/Cargo.toml similarity index 100% rename from util/io/Cargo.toml rename to crates/runtime/io/Cargo.toml diff --git a/util/io/src/lib.rs b/crates/runtime/io/src/lib.rs similarity index 100% rename from util/io/src/lib.rs rename to crates/runtime/io/src/lib.rs diff --git a/util/io/src/service_mio.rs b/crates/runtime/io/src/service_mio.rs similarity index 100% rename from util/io/src/service_mio.rs rename to crates/runtime/io/src/service_mio.rs diff --git a/util/io/src/service_non_mio.rs b/crates/runtime/io/src/service_non_mio.rs similarity index 100% rename from util/io/src/service_non_mio.rs rename to crates/runtime/io/src/service_non_mio.rs diff --git a/util/io/src/worker.rs b/crates/runtime/io/src/worker.rs similarity index 100% rename from util/io/src/worker.rs rename to crates/runtime/io/src/worker.rs diff --git a/util/runtime/Cargo.toml b/crates/runtime/runtime/Cargo.toml similarity index 100% rename from util/runtime/Cargo.toml rename to crates/runtime/runtime/Cargo.toml diff --git a/util/runtime/src/lib.rs b/crates/runtime/runtime/src/lib.rs similarity index 100% rename from util/runtime/src/lib.rs rename to crates/runtime/runtime/src/lib.rs diff --git a/util/EIP-152/Cargo.toml b/crates/util/EIP-152/Cargo.toml similarity index 100% rename from util/EIP-152/Cargo.toml rename to crates/util/EIP-152/Cargo.toml diff --git a/util/EIP-152/src/lib.rs b/crates/util/EIP-152/src/lib.rs similarity index 100% rename from util/EIP-152/src/lib.rs rename to crates/util/EIP-152/src/lib.rs diff --git a/util/EIP-712/Cargo.toml b/crates/util/EIP-712/Cargo.toml similarity index 100% rename from util/EIP-712/Cargo.toml rename to crates/util/EIP-712/Cargo.toml diff --git a/util/EIP-712/README.md b/crates/util/EIP-712/README.md similarity index 100% rename from util/EIP-712/README.md rename to crates/util/EIP-712/README.md diff --git a/util/EIP-712/src/eip712.rs b/crates/util/EIP-712/src/eip712.rs similarity index 100% rename from util/EIP-712/src/eip712.rs rename to crates/util/EIP-712/src/eip712.rs diff --git a/util/EIP-712/src/encode.rs b/crates/util/EIP-712/src/encode.rs similarity index 100% rename from util/EIP-712/src/encode.rs rename to crates/util/EIP-712/src/encode.rs diff --git a/util/EIP-712/src/error.rs b/crates/util/EIP-712/src/error.rs similarity index 100% rename from util/EIP-712/src/error.rs rename to crates/util/EIP-712/src/error.rs diff --git a/util/EIP-712/src/lib.rs b/crates/util/EIP-712/src/lib.rs similarity index 100% rename from util/EIP-712/src/lib.rs rename to crates/util/EIP-712/src/lib.rs diff --git a/util/EIP-712/src/parser.rs b/crates/util/EIP-712/src/parser.rs similarity index 100% rename from util/EIP-712/src/parser.rs rename to crates/util/EIP-712/src/parser.rs diff --git a/cli-signer/Cargo.toml b/crates/util/cli-signer/Cargo.toml similarity index 90% rename from cli-signer/Cargo.toml rename to crates/util/cli-signer/Cargo.toml index bc833fca40..afc3352cac 100644 --- a/cli-signer/Cargo.toml +++ b/crates/util/cli-signer/Cargo.toml @@ -10,5 +10,5 @@ authors = ["Parity "] ethereum-types = "0.4" futures = "0.1" rpassword = "1.0" -parity-rpc = { path = "../rpc" } +parity-rpc = { path = "../../rpc" } parity-rpc-client = { path = "rpc-client" } diff --git a/cli-signer/rpc-client/Cargo.toml b/crates/util/cli-signer/rpc-client/Cargo.toml similarity index 91% rename from cli-signer/rpc-client/Cargo.toml rename to crates/util/cli-signer/rpc-client/Cargo.toml index 90b8d73b69..19d2c61a8a 100644 --- a/cli-signer/rpc-client/Cargo.toml +++ b/crates/util/cli-signer/rpc-client/Cargo.toml @@ -17,5 +17,5 @@ matches = "0.1" parking_lot = "0.9" jsonrpc-core = "15.0.0" jsonrpc-ws-server = "15.0.0" -parity-rpc = { path = "../../rpc" } +parity-rpc = { path = "../../../rpc" } keccak-hash = "0.1" diff --git a/cli-signer/rpc-client/src/client.rs b/crates/util/cli-signer/rpc-client/src/client.rs similarity index 100% rename from cli-signer/rpc-client/src/client.rs rename to crates/util/cli-signer/rpc-client/src/client.rs diff --git a/cli-signer/rpc-client/src/lib.rs b/crates/util/cli-signer/rpc-client/src/lib.rs similarity index 100% rename from cli-signer/rpc-client/src/lib.rs rename to crates/util/cli-signer/rpc-client/src/lib.rs diff --git a/cli-signer/rpc-client/src/signer_client.rs b/crates/util/cli-signer/rpc-client/src/signer_client.rs similarity index 100% rename from cli-signer/rpc-client/src/signer_client.rs rename to crates/util/cli-signer/rpc-client/src/signer_client.rs diff --git a/cli-signer/src/lib.rs b/crates/util/cli-signer/src/lib.rs similarity index 100% rename from cli-signer/src/lib.rs rename to crates/util/cli-signer/src/lib.rs diff --git a/util/dir/Cargo.toml b/crates/util/dir/Cargo.toml similarity index 83% rename from util/dir/Cargo.toml rename to crates/util/dir/Cargo.toml index 04fa526343..449805c38d 100644 --- a/util/dir/Cargo.toml +++ b/crates/util/dir/Cargo.toml @@ -6,6 +6,6 @@ license = "GPL3" [dependencies] ethereum-types = "0.4" -journaldb = { path = "../journaldb" } +journaldb = { path = "../../db/journaldb" } app_dirs = { git = "https://github.com/openethereum/app-dirs-rs" } home = "0.3" diff --git a/util/dir/src/helpers.rs b/crates/util/dir/src/helpers.rs similarity index 100% rename from util/dir/src/helpers.rs rename to crates/util/dir/src/helpers.rs diff --git a/util/dir/src/lib.rs b/crates/util/dir/src/lib.rs similarity index 100% rename from util/dir/src/lib.rs rename to crates/util/dir/src/lib.rs diff --git a/util/fastmap/Cargo.toml b/crates/util/fastmap/Cargo.toml similarity index 100% rename from util/fastmap/Cargo.toml rename to crates/util/fastmap/Cargo.toml diff --git a/util/fastmap/src/lib.rs b/crates/util/fastmap/src/lib.rs similarity index 100% rename from util/fastmap/src/lib.rs rename to crates/util/fastmap/src/lib.rs diff --git a/util/keccak-hasher/Cargo.toml b/crates/util/keccak-hasher/Cargo.toml similarity index 100% rename from util/keccak-hasher/Cargo.toml rename to crates/util/keccak-hasher/Cargo.toml diff --git a/util/keccak-hasher/src/lib.rs b/crates/util/keccak-hasher/src/lib.rs similarity index 100% rename from util/keccak-hasher/src/lib.rs rename to crates/util/keccak-hasher/src/lib.rs diff --git a/util/len-caching-lock/Cargo.toml b/crates/util/len-caching-lock/Cargo.toml similarity index 100% rename from util/len-caching-lock/Cargo.toml rename to crates/util/len-caching-lock/Cargo.toml diff --git a/util/len-caching-lock/src/lib.rs b/crates/util/len-caching-lock/src/lib.rs similarity index 100% rename from util/len-caching-lock/src/lib.rs rename to crates/util/len-caching-lock/src/lib.rs diff --git a/util/len-caching-lock/src/mutex.rs b/crates/util/len-caching-lock/src/mutex.rs similarity index 100% rename from util/len-caching-lock/src/mutex.rs rename to crates/util/len-caching-lock/src/mutex.rs diff --git a/util/len-caching-lock/src/rwlock.rs b/crates/util/len-caching-lock/src/rwlock.rs similarity index 100% rename from util/len-caching-lock/src/rwlock.rs rename to crates/util/len-caching-lock/src/rwlock.rs diff --git a/util/macros/Cargo.toml b/crates/util/macros/Cargo.toml similarity index 100% rename from util/macros/Cargo.toml rename to crates/util/macros/Cargo.toml diff --git a/util/macros/src/lib.rs b/crates/util/macros/src/lib.rs similarity index 100% rename from util/macros/src/lib.rs rename to crates/util/macros/src/lib.rs diff --git a/util/memory-cache/Cargo.toml b/crates/util/memory-cache/Cargo.toml similarity index 100% rename from util/memory-cache/Cargo.toml rename to crates/util/memory-cache/Cargo.toml diff --git a/util/memory-cache/src/lib.rs b/crates/util/memory-cache/src/lib.rs similarity index 100% rename from util/memory-cache/src/lib.rs rename to crates/util/memory-cache/src/lib.rs diff --git a/util/memzero/Cargo.toml b/crates/util/memzero/Cargo.toml similarity index 100% rename from util/memzero/Cargo.toml rename to crates/util/memzero/Cargo.toml diff --git a/util/memzero/src/lib.rs b/crates/util/memzero/src/lib.rs similarity index 100% rename from util/memzero/src/lib.rs rename to crates/util/memzero/src/lib.rs diff --git a/util/panic-hook/Cargo.toml b/crates/util/panic-hook/Cargo.toml similarity index 100% rename from util/panic-hook/Cargo.toml rename to crates/util/panic-hook/Cargo.toml diff --git a/util/panic-hook/src/lib.rs b/crates/util/panic-hook/src/lib.rs similarity index 100% rename from util/panic-hook/src/lib.rs rename to crates/util/panic-hook/src/lib.rs diff --git a/util/rlp-compress/Cargo.toml b/crates/util/rlp-compress/Cargo.toml similarity index 100% rename from util/rlp-compress/Cargo.toml rename to crates/util/rlp-compress/Cargo.toml diff --git a/util/rlp-compress/src/common.rs b/crates/util/rlp-compress/src/common.rs similarity index 100% rename from util/rlp-compress/src/common.rs rename to crates/util/rlp-compress/src/common.rs diff --git a/util/rlp-compress/src/lib.rs b/crates/util/rlp-compress/src/lib.rs similarity index 100% rename from util/rlp-compress/src/lib.rs rename to crates/util/rlp-compress/src/lib.rs diff --git a/util/rlp-compress/tests/compress.rs b/crates/util/rlp-compress/tests/compress.rs similarity index 100% rename from util/rlp-compress/tests/compress.rs rename to crates/util/rlp-compress/tests/compress.rs diff --git a/util/rlp-derive/Cargo.toml b/crates/util/rlp-derive/Cargo.toml similarity index 100% rename from util/rlp-derive/Cargo.toml rename to crates/util/rlp-derive/Cargo.toml diff --git a/util/rlp-derive/src/de.rs b/crates/util/rlp-derive/src/de.rs similarity index 100% rename from util/rlp-derive/src/de.rs rename to crates/util/rlp-derive/src/de.rs diff --git a/util/rlp-derive/src/en.rs b/crates/util/rlp-derive/src/en.rs similarity index 100% rename from util/rlp-derive/src/en.rs rename to crates/util/rlp-derive/src/en.rs diff --git a/util/rlp-derive/src/lib.rs b/crates/util/rlp-derive/src/lib.rs similarity index 100% rename from util/rlp-derive/src/lib.rs rename to crates/util/rlp-derive/src/lib.rs diff --git a/util/rlp-derive/tests/rlp.rs b/crates/util/rlp-derive/tests/rlp.rs similarity index 100% rename from util/rlp-derive/tests/rlp.rs rename to crates/util/rlp-derive/tests/rlp.rs diff --git a/util/stats/Cargo.toml b/crates/util/stats/Cargo.toml similarity index 100% rename from util/stats/Cargo.toml rename to crates/util/stats/Cargo.toml diff --git a/util/stats/src/lib.rs b/crates/util/stats/src/lib.rs similarity index 100% rename from util/stats/src/lib.rs rename to crates/util/stats/src/lib.rs diff --git a/util/time-utils/Cargo.toml b/crates/util/time-utils/Cargo.toml similarity index 100% rename from util/time-utils/Cargo.toml rename to crates/util/time-utils/Cargo.toml diff --git a/util/time-utils/src/lib.rs b/crates/util/time-utils/src/lib.rs similarity index 100% rename from util/time-utils/src/lib.rs rename to crates/util/time-utils/src/lib.rs diff --git a/util/triehash-ethereum/Cargo.toml b/crates/util/triehash-ethereum/Cargo.toml similarity index 100% rename from util/triehash-ethereum/Cargo.toml rename to crates/util/triehash-ethereum/Cargo.toml diff --git a/util/triehash-ethereum/src/lib.rs b/crates/util/triehash-ethereum/src/lib.rs similarity index 100% rename from util/triehash-ethereum/src/lib.rs rename to crates/util/triehash-ethereum/src/lib.rs diff --git a/util/unexpected/Cargo.toml b/crates/util/unexpected/Cargo.toml similarity index 100% rename from util/unexpected/Cargo.toml rename to crates/util/unexpected/Cargo.toml diff --git a/util/unexpected/src/lib.rs b/crates/util/unexpected/src/lib.rs similarity index 100% rename from util/unexpected/src/lib.rs rename to crates/util/unexpected/src/lib.rs diff --git a/util/version/Cargo.toml b/crates/util/version/Cargo.toml similarity index 100% rename from util/version/Cargo.toml rename to crates/util/version/Cargo.toml diff --git a/util/version/build.rs b/crates/util/version/build.rs similarity index 100% rename from util/version/build.rs rename to crates/util/version/build.rs diff --git a/util/version/src/lib.rs b/crates/util/version/src/lib.rs similarity index 100% rename from util/version/src/lib.rs rename to crates/util/version/src/lib.rs diff --git a/ethcore/builtin/Cargo.toml b/crates/vm/builtin/Cargo.toml similarity index 95% rename from ethcore/builtin/Cargo.toml rename to crates/vm/builtin/Cargo.toml index 4a204f46fd..540d179b09 100644 --- a/ethcore/builtin/Cargo.toml +++ b/crates/vm/builtin/Cargo.toml @@ -10,7 +10,7 @@ bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.3.2" eip-152 = { path = "../../util/EIP-152" } ethereum-types = "0.4" -ethjson = { path = "../../json" } +ethjson = { path = "../../ethjson" } ethkey = { path = "../../accounts/ethkey" } keccak-hash = "0.1.0" log = "0.4" diff --git a/ethcore/builtin/src/lib.rs b/crates/vm/builtin/src/lib.rs similarity index 100% rename from ethcore/builtin/src/lib.rs rename to crates/vm/builtin/src/lib.rs diff --git a/ethcore/call-contract/Cargo.toml b/crates/vm/call-contract/Cargo.toml similarity index 83% rename from ethcore/call-contract/Cargo.toml rename to crates/vm/call-contract/Cargo.toml index 7ee9bb7e65..08066e9888 100644 --- a/ethcore/call-contract/Cargo.toml +++ b/crates/vm/call-contract/Cargo.toml @@ -7,6 +7,6 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -types = { path = "../types", package = "common-types" } +types = { path = "../../ethcore/types", package = "common-types" } ethereum-types = "0.4" bytes = { version = "0.1", package = "parity-bytes" } diff --git a/ethcore/call-contract/src/call_contract.rs b/crates/vm/call-contract/src/call_contract.rs similarity index 100% rename from ethcore/call-contract/src/call_contract.rs rename to crates/vm/call-contract/src/call_contract.rs diff --git a/ethcore/call-contract/src/lib.rs b/crates/vm/call-contract/src/lib.rs similarity index 100% rename from ethcore/call-contract/src/lib.rs rename to crates/vm/call-contract/src/lib.rs diff --git a/ethcore/evm/Cargo.toml b/crates/vm/evm/Cargo.toml similarity index 100% rename from ethcore/evm/Cargo.toml rename to crates/vm/evm/Cargo.toml diff --git a/ethcore/evm/benches/basic.rs b/crates/vm/evm/benches/basic.rs similarity index 100% rename from ethcore/evm/benches/basic.rs rename to crates/vm/evm/benches/basic.rs diff --git a/ethcore/evm/src/evm.rs b/crates/vm/evm/src/evm.rs similarity index 100% rename from ethcore/evm/src/evm.rs rename to crates/vm/evm/src/evm.rs diff --git a/ethcore/evm/src/factory.rs b/crates/vm/evm/src/factory.rs similarity index 100% rename from ethcore/evm/src/factory.rs rename to crates/vm/evm/src/factory.rs diff --git a/ethcore/evm/src/instructions.rs b/crates/vm/evm/src/instructions.rs similarity index 100% rename from ethcore/evm/src/instructions.rs rename to crates/vm/evm/src/instructions.rs diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/crates/vm/evm/src/interpreter/gasometer.rs similarity index 100% rename from ethcore/evm/src/interpreter/gasometer.rs rename to crates/vm/evm/src/interpreter/gasometer.rs diff --git a/ethcore/evm/src/interpreter/informant.rs b/crates/vm/evm/src/interpreter/informant.rs similarity index 100% rename from ethcore/evm/src/interpreter/informant.rs rename to crates/vm/evm/src/interpreter/informant.rs diff --git a/ethcore/evm/src/interpreter/memory.rs b/crates/vm/evm/src/interpreter/memory.rs similarity index 100% rename from ethcore/evm/src/interpreter/memory.rs rename to crates/vm/evm/src/interpreter/memory.rs diff --git a/ethcore/evm/src/interpreter/mod.rs b/crates/vm/evm/src/interpreter/mod.rs similarity index 100% rename from ethcore/evm/src/interpreter/mod.rs rename to crates/vm/evm/src/interpreter/mod.rs diff --git a/ethcore/evm/src/interpreter/shared_cache.rs b/crates/vm/evm/src/interpreter/shared_cache.rs similarity index 100% rename from ethcore/evm/src/interpreter/shared_cache.rs rename to crates/vm/evm/src/interpreter/shared_cache.rs diff --git a/ethcore/evm/src/interpreter/stack.rs b/crates/vm/evm/src/interpreter/stack.rs similarity index 100% rename from ethcore/evm/src/interpreter/stack.rs rename to crates/vm/evm/src/interpreter/stack.rs diff --git a/ethcore/evm/src/lib.rs b/crates/vm/evm/src/lib.rs similarity index 100% rename from ethcore/evm/src/lib.rs rename to crates/vm/evm/src/lib.rs diff --git a/ethcore/evm/src/tests.rs b/crates/vm/evm/src/tests.rs similarity index 100% rename from ethcore/evm/src/tests.rs rename to crates/vm/evm/src/tests.rs diff --git a/ethcore/evm/src/vmtype.rs b/crates/vm/evm/src/vmtype.rs similarity index 100% rename from ethcore/evm/src/vmtype.rs rename to crates/vm/evm/src/vmtype.rs diff --git a/ethcore/vm/Cargo.toml b/crates/vm/vm/Cargo.toml similarity index 72% rename from ethcore/vm/Cargo.toml rename to crates/vm/vm/Cargo.toml index 34b086bce0..70a7056b35 100644 --- a/ethcore/vm/Cargo.toml +++ b/crates/vm/vm/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies "] [dependencies] parity-bytes = "0.1" ethereum-types = "0.4" -patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" } -ethjson = { path = "../../json" } +patricia-trie-ethereum = { path = "../../db/patricia-trie-ethereum" } +ethjson = { path = "../../ethjson" } rlp = { version = "0.3.0", features = ["ethereum"] } keccak-hash = "0.1" diff --git a/ethcore/vm/src/access_list.rs b/crates/vm/vm/src/access_list.rs similarity index 100% rename from ethcore/vm/src/access_list.rs rename to crates/vm/vm/src/access_list.rs diff --git a/ethcore/vm/src/action_params.rs b/crates/vm/vm/src/action_params.rs similarity index 100% rename from ethcore/vm/src/action_params.rs rename to crates/vm/vm/src/action_params.rs diff --git a/ethcore/vm/src/call_type.rs b/crates/vm/vm/src/call_type.rs similarity index 100% rename from ethcore/vm/src/call_type.rs rename to crates/vm/vm/src/call_type.rs diff --git a/ethcore/vm/src/env_info.rs b/crates/vm/vm/src/env_info.rs similarity index 100% rename from ethcore/vm/src/env_info.rs rename to crates/vm/vm/src/env_info.rs diff --git a/ethcore/vm/src/error.rs b/crates/vm/vm/src/error.rs similarity index 100% rename from ethcore/vm/src/error.rs rename to crates/vm/vm/src/error.rs diff --git a/ethcore/vm/src/ext.rs b/crates/vm/vm/src/ext.rs similarity index 100% rename from ethcore/vm/src/ext.rs rename to crates/vm/vm/src/ext.rs diff --git a/ethcore/vm/src/lib.rs b/crates/vm/vm/src/lib.rs similarity index 100% rename from ethcore/vm/src/lib.rs rename to crates/vm/vm/src/lib.rs diff --git a/ethcore/vm/src/return_data.rs b/crates/vm/vm/src/return_data.rs similarity index 100% rename from ethcore/vm/src/return_data.rs rename to crates/vm/vm/src/return_data.rs diff --git a/ethcore/vm/src/schedule.rs b/crates/vm/vm/src/schedule.rs similarity index 100% rename from ethcore/vm/src/schedule.rs rename to crates/vm/vm/src/schedule.rs diff --git a/ethcore/vm/src/tests.rs b/crates/vm/vm/src/tests.rs similarity index 100% rename from ethcore/vm/src/tests.rs rename to crates/vm/vm/src/tests.rs diff --git a/ethcore/wasm/Cargo.toml b/crates/vm/wasm/Cargo.toml similarity index 100% rename from ethcore/wasm/Cargo.toml rename to crates/vm/wasm/Cargo.toml diff --git a/ethcore/wasm/src/env.rs b/crates/vm/wasm/src/env.rs similarity index 100% rename from ethcore/wasm/src/env.rs rename to crates/vm/wasm/src/env.rs diff --git a/ethcore/wasm/src/lib.rs b/crates/vm/wasm/src/lib.rs similarity index 99% rename from ethcore/wasm/src/lib.rs rename to crates/vm/wasm/src/lib.rs index 5ebaaadb45..9601d53cdd 100644 --- a/ethcore/wasm/src/lib.rs +++ b/crates/vm/wasm/src/lib.rs @@ -34,9 +34,6 @@ mod panic_payload; mod parser; mod runtime; -#[cfg(test)] -mod tests; - use vm::{ActionParams, GasLeft, ReturnData}; use wasmi::{Error as InterpreterError, Trap}; diff --git a/ethcore/wasm/src/panic_payload.rs b/crates/vm/wasm/src/panic_payload.rs similarity index 100% rename from ethcore/wasm/src/panic_payload.rs rename to crates/vm/wasm/src/panic_payload.rs diff --git a/ethcore/wasm/src/parser.rs b/crates/vm/wasm/src/parser.rs similarity index 100% rename from ethcore/wasm/src/parser.rs rename to crates/vm/wasm/src/parser.rs diff --git a/ethcore/wasm/src/runtime.rs b/crates/vm/wasm/src/runtime.rs similarity index 100% rename from ethcore/wasm/src/runtime.rs rename to crates/vm/wasm/src/runtime.rs diff --git a/ethcore/res/ethereum/runner/full.json b/ethcore/res/ethereum/runner/full.json deleted file mode 100644 index 58c25e6583..0000000000 --- a/ethcore/res/ethereum/runner/full.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "chain": [ - { - "path": "res/ethereum/tests/BlockchainTests", - "skip" : [] - }, - { - "path": "res/ethereum/tests/LegacyTests/Constantinople/BlockchainTests", - "skip" : [] - } - ], - "state": [ - { - "path": "res/ethereum/tests/GeneralStateTests", - "skip" : [] - - }, - { - "path": "res/ethereum/tests//LegacyTests/Constantinople/GeneralStateTests", - "skip" : [] - - } - ], - "difficulty": [ - { - "path": [ - "res/ethereum/tests/BasicTests/difficulty.json", - "res/ethereum/tests/BasicTests/difficultyMainNetwork.json" - ], - "chainspec": "Foundation" - } - ], - "executive": [ - { - "path": "res/ethereum/tests/VMTests" - } - ], - "transaction": [ - { - "path": "res/ethereum/tests/TransactionTests" - } - ], - "trie": [ - { - "path": [ - "res/ethereum/tests/TrieTests/trietest.json", - "res/ethereum/tests/TrieTests/trieanyorder.json" - ], - "triespec": "Generic" - }, - { - "path": [ - "res/ethereum/tests/TrieTests/hex_encoded_securetrie_test.json", - "res/ethereum/tests/TrieTests/trietest_secureTrie.json", - "res/ethereum/tests/TrieTests/trieanyorder_secureTrie.json" - ], - "triespec": "Secure" - } - ] -} \ No newline at end of file diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json deleted file mode 100644 index d4d3f5e3aa..0000000000 --- a/ethcore/res/ethereum/tests-issues/currents.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "block": [], - "state": [] -} diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests deleted file mode 160000 index 0edbf860ff..0000000000 --- a/ethcore/res/wasm-tests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd diff --git a/ethcore/wasm/run/Cargo.toml b/ethcore/wasm/run/Cargo.toml deleted file mode 100644 index eee0d5fa32..0000000000 --- a/ethcore/wasm/run/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -description = "Parity WASM Test Run" -name = "pwasm-run-test" -version = "0.1.0" -authors = ["Parity Technologies "] - -[dependencies] -serde = "1" -serde_json = "1" -serde_derive = "1" -ethereum-types = "0.4" -ethjson = { path = "../../../json" } -vm = { path = "../../vm" } -wasm = { path = "../" } -clap = "2.24" -env_logger = "0.5" -rustc-hex = "1" - -[features] -default = ["ethereum-types/std"] diff --git a/ethcore/wasm/run/res/sample-fixture.json b/ethcore/wasm/run/res/sample-fixture.json deleted file mode 100644 index 7be3e04be0..0000000000 --- a/ethcore/wasm/run/res/sample-fixture.json +++ /dev/null @@ -1,45 +0,0 @@ -[ - { - "caption": "Sample test", - "source": "./res/sample1.wasm", - "address": "0x1000000000000000000000000000000000000001", - "sender": "0x1000000000000000000000000000000000000002", - "value": "0x0000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": 100000, - "payload": "0x", - "asserts": [ - { "Return": "0x01" }, - { "UsedGas": 17 }, - { "HasCall": { "codeAddress": "0x1000000000000000000000000000000000000002" }}, - { "HasStorage": - { - "key": "0x0000000000000000000000000000000000000000000000000000000000000001", - "value": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - } - ] - }, - { - "caption": "Keccak test", - "source": "./res/sample2.wasm", - "payload": "0x736f6d657468696e67", - "gasLimit": 100000, - "asserts": [ - { "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" } - ] - }, - { - "caption": "Token total supply", - "source": { - "constructor": "./res/sample3.wasm", - "sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f", - "at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "arguments": "0x0000000000000000000000000000000000000000000000000000000010000000" - }, - "payload": "0x18160ddd", - "gasLimit": 100000, - "asserts": [ - { "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" } - ] - } -] \ No newline at end of file diff --git a/ethcore/wasm/run/res/sample1.wasm b/ethcore/wasm/run/res/sample1.wasm deleted file mode 100644 index 6ea0c58cc77bec3f6ccec1a8d3616e28d48df29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmW-YK@Ng26b0Y=4QOdX+_?7y-hqYZfKnSbEfA{nL-{7x0(pYN9dJ=*qckFEHlHgH8L0 NOWJR4p3-Vv`T}Mx8bkm9 diff --git a/ethcore/wasm/run/res/sample2.wasm b/ethcore/wasm/run/res/sample2.wasm deleted file mode 100644 index baf9d17aa98fd185167448c58cc0388993dfab0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15410 zcmd6O3v^u7dG6WgHD~6`jEnM@Hm|#)@B!pne@&F#$l06zb zxNXqLcpURI+(+Y;+z@ha8Xkp)WVK03XrOBq0%-!Ks}!21ft5>c)3xper%Bs1O>n<& zpBX)jA?;mvt=j?3-v8eF-+TX${r~^|_gI^pJ0LVo6We1G#{B%en4i$qx0u%^L8!iEGq>b- zADG;~e|AbUmbGLK%w_VL8gK7DI61R#N;BCVRR}lcGMR9K*zW!Nj~v*Y&rKfGtQGiE z2alHU4`dF^=8o#3pcmAlR(^8N{){*%YHHM!3LKrB%W#8hQo3!Lx-d;k*M!hbTbL2u z)Eps%7S-{k3)==C)@W`dDy-d8*t`~rHVAEvaBJ38uJ_ujs^e={wZ&UnrEJG1_VRV9 zFGobv{2JX)tkHwBMz&3tiQu%J^=+B(qo~Vl$_l*zPFQ$hQLm3ktz9=$!c-N_uK@0InAej6bL~L0@GE77UnM=? z3^YFpIAWm^MV&6L#s|!Ksaw);Q>!tr zyIx~lxH85qVtJNctpzHoL0$vMYXokMjQLHj ztd=#qFs2%$H-Pj;-;^~Vy~&TnO;^^)YOm3C$%RV%Rh3w#*aJ9%tyalo){jY3Mr5T- zPNxKEk6<-7WuRvHkeRQ8cJPX{gMwwW>!cmh79iIk?a~CjSkIM_ED5$#0*k&XJi9^K z?fP>9I`EvpmV=Wq2o99hxzeVBq=@N9q%Bb|EoN_mZYVZKf_b!-P=6j>LR}gi6z0`X z+jF5ToGqoK4E8vFT_F8c7QRT1xu^z?G_!srkkXuntUv{o0i;khu$7b{^^~Rd4vC_B z8kCygK*|i{2Nb!1gtQhLpTK-N5PvE}Y#zHaaq=lH19hN6PqdUdEd|ayzqC|j zI%QGKVF5Hqz=jMgrCyLmHl;yS6jBAW5A7*X1alBPS?R4&atTB}1(j1rTBLM0&@M&y z>rt=4mB!Mnkl-bNbnrNe6CrSFA%4nI_aQc%S}+2_5}qlezHq@YPoR`y%p3tTZP#Dby8!o9!+O7aE`!c06zy{64(mh0h|hpKs$hLFp2d} z)WNU_>s_e73JhwJ-vOWij3|K=fQJCY2wVhU2=aPPmL0}DllfXz4 z=mGFJfC>UF0G`G$kH7{1_1RP<>%FM|7#&pv`T*PulxhNv0KN{OhCmyD=P<06KtBMP zP1UhJfcjZvJYGx<%JoHmo9vR!vb!kP6lG6QwiHv6LnMdDbr>Nx7vY z^|uuL5!on*i>b!Z+7q&IbmPh6saCm04zXn;TWZk~jLsKt0~u+yZenW{V;AC;) zia3mdUS0(CG>_|Hu9~1F9k5ExFh)K&(*moq3A@^W#U<8g^_$=cX%L$j&gpVJ3qx*Z zVag5`mTYDbkzFio*~!9@K8vVKv53hQ7IE3l!j+p?B;*7;oz4nusZKv@Fj&>;O?2s8qM}$6#vMB|;Uf^LnqmCR z32Vj@5E3SOJcfW?V+d!!$zlN`IEPPUCqjQC@ODVB%^W)f|0tvUa(n}^5}Yz(E)79B zd@MsIBlO5iEHdDOE#-K@1o&dhcNw{W)FnhtBVC3Tx{NVS0XYnI;$`|KZt%84 zchcxmH7~7uG9Ek~mA2;x=foj6?+OdL8YzuO4N~S*3~t=t4x=Rv(T(COqssfM)w)5S zijU~S5F4r}CqS@+pam{VB0xb@7MKjZl$(Yd!$zT90mdS(3eEy#bOsPZ7+`rJRDbv6#Rn`w zdBRdL+Eb(=WL^w$B@dS#+5&Z_Q-=mfi|SKWH`S)p&7itzp6`Q?z}DPTLPScICA_HM zbOa`&dsLRik|x!MoCXu~sTJo$2@_GZ)M=L0i7A;8-e1_{<61&9LUmA4D=u@88M?4D z5)17?q3#5~wM3xOa-GpB>>Y>c!6v0wVI2WqIiwG8Q&7qtYC0eszToTOp$wHANdcwg zkgMtqm0UqkwBR`xO8%SS+D7?=8C)Clay^4T38}Tp-_oQ-{m?df$fc4F0Ef8AZkUuqJM!n1m~^h089RjfiNE;a;N#;;w9P zAgmjV77l?`##hbDaou3OG^U|BaolN@xK&|-5im2jE0Lkfmm~t%%6X;Aiz(MTDX!3pslz+Ag`kz0UoxXkLWN9u&jX?r-5kK<4`c2mtz<19P;*7bHm7t zps$`AW~B+^FhQlJ@s^zk9PR;D6?dDUTkVavA-EDA_46mf{J7U+W%ZwoA%OuZ4Xhu4 z-KHBDhmxiybYXx{p8{~Wis3V3;)JeA9AO8@3{Z2(X2p^y?WV3QDJ>c;4d+CQvVZ!L z{fh?7Kb7sDvY5&U>MM+(LMR!*C`QLt7(tyzkkTw$L4{m4X#&f_+%96nWiGRV;Bu7A zK|n?IEF{5Y0*%BT3Z_xs+v$ z+x`j}BQEh{p^T%THnu2Z1}veBV~a9|`kBaH(pyr-R!PQaQ8KocWDKSDq3SpVIBMvJ zR}4{B$XFqiq~u_90x|}MIzpKKd>LCrE{hA&SSDi!mQMMvA$f!D~}uFJ2e4C{*DRg-?XxFLFBPz zB7e_iOR7~8xkc?VU3?=LTzT4|g%>m%t_!0Sr`LrWMG4gZstbo!pB@Jp7xV#DqxXcs zc^F`&V8T$u8Pmf5XeH;aYATjgwX$h7L^#ZVfh$l&|+i7kU5yH9w9l3COAGA zN-k`wLjnbmraB}(GRSCC$HZKDOlaJYuT%ZuF=2IiJg5+s9g`@O9T@7EaO?_GSVAsq zJPgQr$0UklLTq(RaK+>?v1Bxhfn_9(**&^QcZJe}W}Es_fk+Z&MWcqZfr>;fgvDHFt}4KQ8!c#&aLhauFg6z!zN_#ht4Uyh}zFe%GVz{ev( zCB`EcSN`}l!62K!Peqn3r-*gL*-({aQs_~<8h_NXvXew%**Ehhu3OTdee-c zOzGgsLzy2=iecbF++>X6!GH0U$sEIIeH?V*a?S%MbtcI{dVqPnW@s&LHJ~YYYM#4P zgO+-^WF@y+;;0IGFT_#!Lux9t5RW>bBr=wA6fcoQ5IzRF-`*Dm&sRH zrZAg;xNusUr7S)r_^#{8|BKlXAY*noD19XSPihPVj4%+;z_#-Ofh71@!9YOwlc1o2 zfdDpq1dnIjH)}ZNc4*!}zlp#x30@DN2X{f=t&4pfCIR%&&It4ROPQjEF^dSnWffoH-VIT*?rS0He zU?OuyFwXdaV->`)zl_7CV{Mghz^mAbMH1m6>SnH%TwFvgSsyOhglX==Q0QBL$+_gC z3R8j0mP99)d@{);BYdm!6VxSGc2Yl{V;ozSqoR%?|8il%t_)6mRG;mUj3czZp0B|Av!9dCW;^v_eTBUvl9oRB* zQ@Ft((u0i;zLR8@n5{fyMtEb52FiR#>2Q3SGVC1Eg&PY1slnI++PT#BLoPx;j7;H> zAOnZ1v7OKPaF5IVRe1)3GthfsEqcEtbX@R(2bGEi@n!gB|7GXVQH4i>!ddN5uCygi zwsI3#nB0mWWx*$ArPUhksIo$c4}F?|&`JgdUYr@M3ot?lVmXzI)J=F{M-!8sCOnU%O(~uX6|W7-^hPpNJasIfhd2q;b)~Y4x(mHMuX0}o&34jb(Mtz=I8vaK|sv)LFj$Atw zM5mJ<(sa|rPjcS*G1#QO-r4uwEr#ii;xZHbO!GycLx&ag_aS72(3>HohY)XdAmiLQ z1Nw!Ek_T*AP^b?&fYsZE_0QF_`hy>$nq=*5#h?4n#>N3W z{FTGmpo7hSb{}f)jvPOMm_z2iv>C=v=oh)00;HQFbB~P{@HwL$XD%5kMeZAmQXqsa zm+}H&R~-4aFpyD6h415r90<5LT{)|=@PK5G%99Tw8J)C|G%`%fcH>bu_!Y*Zi!UFi zCT{a>HJ!8{MCw4#2Tg~V>PAWe*}3_k+X`M$Y77($oTGbr49MK?!P~IkIO2xIxm2^K zTAA|rmlX@CPRULrvi{+nUESM%l5vI0)7#yK2?GY=Y6otG;bl{Us2FgHMCQ#+cFyiW3U z3T)uXR|OJ~c#Nwks}*~k6l@*{LNy+=?Pva!SpY=;>hTRf&q7KZzjQNk!}IMjri!Bw za*ZbtO3RAzM3fg;@S*etONiRa@Qp80Z3vUWT+GjxQzkpO!7AQyr6OBpKG3$bkdEC! zUdztRD1VNogl9mDR1F3`Nh*z92}^pa2K@%Hh@Jx%E=%FS(S&W>riBAs4ei0ZAoNiE z@W+q|ba1rl!fAkVIM5s<1y@dlVaulA9LkAjU|fl1R^ZxfMTc; z8?}}AD_mCs#}o-&m34dFlW^-^9c{^C9eGv8DqwSP7H=vzd37$LY1Eu?-Vvyd=C4;r z{0b7A!VZ*Zmpe~91C&&h(uY*I7b=OGTKw9n8K^H_PIz0utpSSmRRgI%%uHVwI7g7d z!l}b!3SPLO<2rb$TsM-du$smQ+TcTZ5XELq;Fp`IBTW?4=Y#sgDk+o_yuxD|hF6zD z;o^uy5q0=Dm`Il*?8E~cd}I(&336VL_@WdIAy_0nZ^g2H63i1a$;nj86F)%Ptl{Sl zj0!bB8dLxQ_w5*p@b=G@z@+j*yq1U{q7nr%;x*DcM+sp;_3P1~LQREa7M-Pyi@&nz z&<=1n5ZG_X6<o2o-9GIjje*x&&9iQis|<_b8)yj>oGn*HZB?<(3WI%VH)CzvC;r z7bI1o!OVSuo61b^V#6kt1udXo18o=1!QxuO{24m==Kg3UV!RK8OY!H7>a7=tqaNWZ ziYAc6A2hyaHkik0*-LMOM$G!)jx_+#uv=`jw4mU)FAJfC zpJRovydx|N8voO@!kruYS|L`dl<*7X^$MkN<$XBeyan#xEd8<0KUl5TqwdF^bTkdmdfInU`Y6AxYZ|KB zWl^Xc%I$`xB~iYK#_LgD1YC4!`|(A*PoP|m_xFG$+K*sdH6qfOTeQ!j4by5bp=?EY z2j=8<`mukB@%9v?b{%WqW=L(iPFU!;K(9;4)e6* zXTO#1C#$#wKT>^Pc!@GQv%uqarX~+gPVLJdm9s}Oxf}P-e!Oey=FHUe?BRUZTyCms z|GquyAH#IzCO^LWNM@=tH`jIbTn66YSR)-89>k%iOeYE}uK9&~Dn7 zzxnW<&Z*f0n|m@-Q-i(3!+ZA(XQqaF`?~V`W{z&2M(gDC=AO>J&Yto@ocsL6r)G1R zuDSjDrZQazX7^&mzkk1z^2XWRfyq49y-DI9=IqPMeFqNi&m73iYz>Np;rCnaQe>oldX7*-okzli&y;1I&Jv_4) z)8=o^$o-iaxo=L&J?J7F4n#|LcXv;BZ+BmJfA>K5V0XHEsC&4lyQin8x2LbCzh|Il zuqWL!)HB@M-P_aK+uPUM-#gGd*qiPh>K*Ru?(6C6?d$97?;GeF>`V6z^$quT_xJSo z_V@Mo_Yd?B_NV)Y`iBR)2YLp22l@v32L=WP2hsyW1H*&egFS=2gMEYjg9C$ugXzJc z!Qpgwx+mS6?o0Ql2hxM-bb2T~Jk&kZGt@iOH`G5gFf=%n9vT`N9>x}jvHUQm9tPSl znnHrgq~|7QZpu(XQgMge00(Z$-&}&j(R2C9Tz*bY=0m<@z%2q3AMNby{MfrNJD)2F zW6#linT_P^%xqpx%BhLkKJz)(M(i!jP1A<@ZI-4jN#8b|JoZrI*Zn^9eXo{ zh2vj&@|#b+{L0y%+*Uks`<-{4e&7pVeCXjvpZMle&wT5J7r*z{m!AIP?>_s&i#x8^ zb?rxP*nRswr@s8vuRZlA&wlHb%DPn_z5XBn>Fslc#DPOUcr97cIy2kUy!#Wk{{EMK zQMan4b^MYmc76D|>u&?1{5zj|zH9fo&aMZ)^tGqH_2Mh9 zeR||mr@OjOwVwOZ+vi?5cg3#jJ{oZ>dYa)82HgTo-K4Y^X%u2f=zQt@_o3JmJ2h8l+ z!gJQK$BhR2*sqL_L~7kt(VBQoJZs172K&R#Mr%B_$&8!A=y5lh4Yq3(9z|DcaJjkJ z$U7Gq6~;wr$Jt;XJ6BonbX9IP@Q=eP3U`^uKDFAd{p58<-D=Y-{LJdIwnp@1eYEh% zU_M^>%Z9jBIA;~UYPH2b^K9(TH`X4%+ek+juCFP4-6?#1`+ymtXjVm)TK_;)guW|dW4RioGH4MvmIY_^H4F|9wTzoh>~{N?Ch>aXbE6R%r8*58z8 z&7X*W7V-64FTP^esr&E$oE?b{ZoBxJpPqTitf{}|+CLt6;livk!d!e|+J=haP+4$v;KXuC{s0 z_OTCs@xkwW_kqajhSb_;o;Br~wd>mZhPGUK+2vPWb@esWt%<43jni|td}98NFFf+4 z$Dcmawf%}0(Noc6wnba4jn@0kJM)EYGkCcixb?)QJ_octdK;joFFnAtyH2V8Bo; zOk5Qg3)-d5Rn5Z-k?~lwamkLfk#u6mzIfZGZ#?W4{`8I~k9VDV>DVQo|D$8WkqxFk zu`V_qYqzRzJ2>Wcd6gr2%cuTN^|7D+ZepSJg9~@vZcbYXBO3Ak^F-kvV{^{Ts`0`T z*G8)f_bgmu6h|v+i&t*^!u7h-|TecjY z`8fU^Y5w148J>|& Tf_{90=6Z$qRJMAI-uqtxfELf` diff --git a/ethcore/wasm/run/res/sample3.wasm b/ethcore/wasm/run/res/sample3.wasm deleted file mode 100644 index 1811215b40f3e84c572712a6fbcec5a2830cdf4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9736 zcmeHMOKe=%c|P|wuRB9tQm+w3N&mf)ZPB7gNtQ{8vTR++vMf>*^`K;L3VJk}$Q<#Z z3`cTQNTyIESvUybO&T_p$*BtAG;=Pr8dhR@+b;|uMD<=WEHYTal`-@;mZwN<;>Sa_$k*lrk? z#c~U`Yb%R&`;cE)YpmR8w2a5BqFVS|tI@E}{R>M=cb6Bguf0>dy|6fO#P}>#vZ?J> z?Y0SeUffu&-@a!YeaCWRd9`)VbsoA8^`$|(c73Vg+{TxB#e(PMT-WpRxg5TDj|uZd zCs?SX;ikXz*X2Uqqz?;GCH!XI&8_?I?s4K^kCQ%hntL5F`&>V9&-f=(FDir*q#u}O z>;R88V-HYm#yJUMp9M{9#7*U#EgXn*%1nC3Lcv00p(?OEYIaW5?6Su8DU-9TI%V?Wq=jbUGGiN!D%(n<%C^v`vduKAY!i(t8>CTX z12n2EvPPrKXn)seU)N}*YqZ=o8g`AAx<-p#qXlcUni57jIJK>qPR$?#-%5RAvF^&h9U9PEl3`}c!!j9RHexBj-VRMNq*9+ra!{lA`B!3o+F!@;|4`iG!YqT*i7)M5u=&P z3X{kO+h?K)6A6Yp%T=bi%A!e|yU$c7OqJ!v%kTW6nT!Q{}$(tP9T%yZzaK; zf6|5p2R-LYfJV?N>Ke&Q5aoyZLrsU{`ivUiEFucQ|Gd;`C(fL|E-t)1al_QSj_eN# zQC}$DhETRx@HPEoxu@~UALF%x1-EPJ(qSsi{ z&^ghl6h0H-gU~y9#UNt&9DmW(+N+Tpo^|{u+f|MczTm+K&VbDb%nnJxcD;QQhnJq~ zPq=0DO(on4i%}6n`QPOUI%N9Zu?bTS!{40nxio}7cE95rv)dT+o@WfG`8j@e0{;zo z75FPA;@`c%m_guIfMwtz{4whrc&>g(`uCAOfb>Ve82Ik5T5IFA8_SC;<74$&>*gwI-dtR3x9+LAo2Y!}`dEE+ z`M{w@y*_dH*s&Yek2UH?55F*eeevevO8dZ(vBP5rweTH0;*G9>BZrP>(%+WC-#X`3 z?$(wTZ%FO>qAaf5UA@&{JKMk&6z=4rg>SFkkhR5|E4B8WR-<0KU8^s)?`<^o$J=rAf`PJL(Vl;?zD}3*m>8P*$g~!yF4-p3K_2DAS{U@hF zmGip=Sg_DoTD@td){|mP6<4LJ&{~b!4Xe630!<5a1)55)9)YIMPYE>DW4!_`_lX3W z@8>U>C1;Rjn*IjYScZq-cOBIMl^cg?P@fi8tprU2q6OgZV(3iRD-Hb zE2keg6mI48hd>WVAr}B4lEAi8R{?-SNoC}C$ ze)_jx{HrhJ5tm*4j|9!T)#n%|EIVQPNE_490+a*@Is_{MO(qwx?2N+s5$H#agQfsn zYM4>uQEiMGpHgPjP>ld`aUUU%SPv+~{e)s%A(Ud69yMV+Kq$w9gi5@L&=+qe^v7EW z5d-6>8Hl$M2IFmnO)+%osM#EECv1taaEzL*@eabac$iQ{zXG<$I|)PaF2as@H(@vy z!p=A*?1~evz?sPPB%#FfB&NReL@4e&fdKXaP`?2H(l-Zy$jghT3yDAjQ_MmDQ^`X8 zQpQ61Qo};`Qous*QoTa#Qo2GlvNCk5FHpUZ2Lj2yR*#fakR(k_hBHNmY=^HO!>KHLSeX=?}Zp zQ0L{7(=gxJmz41GZ2ZMd2Oz~qtRO`PXHpSt%tXgIPgxc{HYoVQtei5Hlwesou&f-` zc6J;9ma~tvGT5~;7~MT($|z9bE+Cf~Ri;M4GNWLb(U0*V!3aRg_rKQnM9xBy*`&+DB>hTNVhTxt@hT@(_hUA_{ z4b8NS@4<_@A==+aW60`xMDO%IGIaOk!g%i^LwQdwLwe7nhW3pYWg-5tBLA;1*CULc z_WkK!o^?6~G}}EZ)7`T&-90Pg?iukl$N1`uIA+pe>%a<=4%ZT}Xwuwix6; zg`<(j)}-#y2z;UY7BD>;L0Wb+0+t<(fOU>W?0Tl307vChN6PgsLl9CY-`Y$j$&Z3>YbM9Yr@-Me$H_78((TRU zCGr#CL(Sx6@>jrjG?SC$Dfn>rWCmc#yGIcPcTACxi6VSkKblJ?Qy5u@hE`DqXDIMrVB$U zWT8Nrh61o`jRgC{bYUp!ixp8f91!)uO`^`XMbz)MiMrf&QE%HJ>S#MfeQcMgdx@xL zC8AEXSJa=L6?LV3qF(g8r~{3P`pyASw;31pm_wq@@`9+JyeR4-lcL^nOw=)si~7V% zqVDjrs3)8hb%Il(^Z!-Rss9?LerML7lh-&XXXRDG897BbEhh=7yi9mSULu^3;{;cZ z5vF94a8zC-Ovnp_BXWpvSjGtlV@3wK5i^oaE!|7KY4=j|QsiE0R!W3R zPoC*>L9(IPtGd{mBQ8iZ0QKa@u6xq{_fCp?rqYo#sXtfYv8l3Ko*9 z53o0!maFrKf#**-53of9%*Pe%gHY<4ZWxm{=5f3*jgl3dTjLZWt=@@U?Ap@*bv}kYXb7o$UzEP8fkioQ2 z-*_^8Uk@^Ja!uZNkX+-^AIf<`QLYe5a+xqMSMQ@?^ZdH$Q_g+#&Ge~vui>QOO?l&f zGB0oP!_dp!kCK^qdgH@pW$u1*A^WiV$&6fJ(`GlCrUhn@vhhim%-TH*o5Mk1g9%nob)6U^1NlNp=;}q1GQCIw%cLY$e|QZoDEp|3Bq-az zU{ndx77v1g^dGR^xWMnN^E4+&^>#H#uk$n~NMGk^PLO^JnYg1#{{w{!Kt$Cd;0H*? zT9y7gl6f0^->zARq!m1U6}f%D?*jXQUjs%!tnLGVZ{u+g`1vWb3GlD5u^EWCy#??$ z$lVIWGQ16dAWId0XUc2`{03!*fWHRru*t&!$bg-IzeCksz||?U8vqfGvCjHNnf8q` zU6z$)%km>`9qmA1F7QxESK{-q^J`{xm*S6|1@>?Y?%kPIu!w%sC+sx%#DlGiorA5p z&cW8z&cW6j_FyYW8KDIie{O`k%(y?maT#um5O~Az_c%hsC-6<2)x!jKjLU<)-GY_x z@iVhea;?}Wm~6aE0`y!f_Q@x_R_y!quN8|Qa;=DqMhyB#UMnIZ{-M{3MP4iBQvx_@ie;wMxV3WctW`h43JjEai$LJ{n)*(z*p4vd64B_$s|3(3zeB<. - -use ethjson::{ - bytes::Bytes, - hash::{Address, H256}, - uint::Uint, -}; -use std::borrow::Cow; - -#[derive(Deserialize)] -#[serde(untagged)] -pub enum Source { - Raw(Cow<'static, String>), - Constructor { - #[serde(rename = "constructor")] - source: Cow<'static, String>, - arguments: Bytes, - sender: Address, - at: Address, - }, -} - -impl Source { - pub fn as_ref(&self) -> &str { - match *self { - Source::Raw(ref r) => r.as_ref(), - Source::Constructor { ref source, .. } => source.as_ref(), - } - } -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Fixture { - pub caption: Cow<'static, String>, - pub source: Source, - pub address: Option
, - pub sender: Option
, - pub value: Option, - pub gas_limit: Option, - pub payload: Option, - pub storage: Option>, - pub asserts: Vec, -} - -#[derive(Deserialize, Debug)] -pub struct StorageEntry { - pub key: Uint, - pub value: Uint, -} - -#[derive(Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct CallLocator { - pub sender: Option
, - pub receiver: Option
, - pub value: Option, - pub data: Option, - pub code_address: Option
, -} - -#[derive(Deserialize, Debug)] -pub struct StorageAssert { - pub key: H256, - pub value: H256, -} - -#[derive(Deserialize, Debug)] -pub enum Assert { - HasCall(CallLocator), - HasStorage(StorageAssert), - UsedGas(u64), - Return(Bytes), -} diff --git a/ethcore/wasm/run/src/main.rs b/ethcore/wasm/run/src/main.rs deleted file mode 100644 index 63e2de00ba..0000000000 --- a/ethcore/wasm/run/src/main.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -extern crate serde; -extern crate serde_json; -#[macro_use] -extern crate serde_derive; -extern crate clap; -extern crate env_logger; -extern crate ethereum_types; -extern crate ethjson; -extern crate rustc_hex; -extern crate vm; -extern crate wasm; - -mod fixture; -mod runner; - -use clap::{App, Arg}; -use fixture::Fixture; -use std::fs; - -fn main() { - ::env_logger::init(); - - let matches = App::new("pwasm-run-test") - .arg( - Arg::with_name("target") - .index(1) - .required(true) - .multiple(true) - .help("JSON fixture"), - ) - .get_matches(); - - let mut exit_code = 0; - - for target in matches.values_of("target").expect("No target parameter") { - let mut f = fs::File::open(target).expect("Failed to open file"); - let fixtures: Vec = - serde_json::from_reader(&mut f).expect("Failed to deserialize json"); - - for fixture in fixtures.into_iter() { - let fails = runner::run_fixture(&fixture); - for fail in fails.iter() { - exit_code = 1; - println!( - "Failed assert in test \"{}\" ('{}'): {}", - fixture.caption.as_ref(), - target, - fail - ); - } - } - } - - std::process::exit(exit_code); -} diff --git a/ethcore/wasm/run/src/runner.rs b/ethcore/wasm/run/src/runner.rs deleted file mode 100644 index a348c44e2d..0000000000 --- a/ethcore/wasm/run/src/runner.rs +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{H160, H256, U256}; -use fixture::{Assert, CallLocator, Fixture, Source}; -use rustc_hex::ToHex; -use std::{ - fmt, fs, - io::{self, Read}, - path, - sync::Arc, -}; -use vm::{self, tests::FakeExt, ActionParams, ActionValue, Exec, GasLeft, ParamsType}; -use wasm::WasmInterpreter; - -fn load_code>(p: P) -> io::Result> { - let mut result = Vec::new(); - let mut f = fs::File::open(p)?; - f.read_to_end(&mut result)?; - Ok(result) -} - -fn wasm_interpreter(params: ActionParams) -> Box { - Box::new(WasmInterpreter::new(params)) -} - -#[derive(Debug)] -pub enum SpecNonconformity { - Address, -} - -#[derive(Debug)] -pub enum Fail { - Return { - expected: Vec, - actual: Vec, - }, - UsedGas { - expected: u64, - actual: u64, - }, - Runtime(String), - Load(io::Error), - NoCall(CallLocator), - StorageMismatch { - key: H256, - expected: H256, - actual: Option, - }, - Nonconformity(SpecNonconformity), -} - -impl Fail { - fn runtime(err: vm::Error) -> Vec { - vec![Fail::Runtime(format!("{}", err))] - } - - fn load(err: io::Error) -> Vec { - vec![Fail::Load(err)] - } - - fn nononformity(kind: SpecNonconformity) -> Vec { - vec![Fail::Nonconformity(kind)] - } -} - -impl fmt::Display for Fail { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::Fail::*; - match *self { - Return { - ref expected, - ref actual, - } => write!( - f, - "Expected to return result: 0x{} ({} bytes), but got 0x{} ({} bytes)", - expected.to_hex(), - expected.len(), - actual.to_hex(), - actual.len() - ), - - UsedGas { expected, actual } => write!( - f, - "Expected to use gas: {}, but got actual gas used: {}", - expected, actual - ), - - Runtime(ref s) => write!(f, "WASM Runtime error: {}", s), - - Load(ref e) => write!(f, "Load i/o error: {}", e), - - NoCall(ref call) => write!(f, "Call not found: {:?}", call), - - StorageMismatch { - ref key, - ref expected, - actual: Some(ref actual), - } => write!( - f, - "Storage key {} value mismatch, expected {}, got: {}", - key.to_vec().to_hex(), - expected.to_vec().to_hex(), - actual.to_vec().to_hex(), - ), - - StorageMismatch { - ref key, - ref expected, - actual: None, - } => write!( - f, - "No expected storage value for key {} found, expected {}", - key.to_vec().to_hex(), - expected.to_vec().to_hex(), - ), - - Nonconformity(SpecNonconformity::Address) => { - write!(f, "Cannot use address when constructor is specified!") - } - } - } -} - -pub fn construct( - ext: &mut dyn vm::Ext, - source: Vec, - arguments: Vec, - sender: H160, - at: H160, -) -> Result, vm::Error> { - let mut params = ActionParams::default(); - params.sender = sender; - params.address = at; - params.gas = U256::from(100_000_000); - params.data = Some(arguments); - params.code = Some(Arc::new(source)); - params.params_type = ParamsType::Separate; - - Ok( - match wasm_interpreter(params) - .exec(ext) - .ok() - .expect("Wasm interpreter always calls with trap=false; trap never happens; qed")? - { - GasLeft::Known(_) => Vec::new(), - GasLeft::NeedsReturn { data, .. } => data.to_vec(), - }, - ) -} - -pub fn run_fixture(fixture: &Fixture) -> Vec { - let mut params = ActionParams::default(); - - let source = match load_code(fixture.source.as_ref()) { - Ok(code) => code, - Err(e) => { - return Fail::load(e); - } - }; - - let mut ext = FakeExt::new().with_wasm(); - params.code = Some(Arc::new( - if let Source::Constructor { - ref arguments, - ref sender, - ref at, - .. - } = fixture.source - { - match construct( - &mut ext, - source, - arguments.clone().into(), - sender.clone().into(), - at.clone().into(), - ) { - Ok(code) => code, - Err(e) => { - return Fail::runtime(e); - } - } - } else { - source - }, - )); - - if let Some(ref sender) = fixture.sender { - params.sender = sender.clone().into(); - } - - if let Some(ref address) = fixture.address { - if let Source::Constructor { .. } = fixture.source { - return Fail::nononformity(SpecNonconformity::Address); - } - - params.address = address.clone().into(); - } else if let Source::Constructor { ref at, .. } = fixture.source { - params.address = at.clone().into(); - } - - if let Some(gas_limit) = fixture.gas_limit { - params.gas = U256::from(gas_limit); - } - - if let Some(ref data) = fixture.payload { - params.data = Some(data.clone().into()) - } - - if let Some(value) = fixture.value { - params.value = ActionValue::Transfer(value.clone().into()) - } - - if let Some(ref storage) = fixture.storage { - for storage_entry in storage.iter() { - let key: U256 = storage_entry.key.into(); - let val: U256 = storage_entry.value.into(); - ext.store.insert(key.into(), val.into()); - } - } - - let interpreter = wasm_interpreter(params); - - let interpreter_return = match interpreter - .exec(&mut ext) - .ok() - .expect("Wasm interpreter always calls with trap=false; trap never happens; qed") - { - Ok(ret) => ret, - Err(e) => { - return Fail::runtime(e); - } - }; - let (gas_left, result) = match interpreter_return { - GasLeft::Known(gas) => (gas, Vec::new()), - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - }; - - let mut fails = Vec::new(); - - for assert in fixture.asserts.iter() { - match *assert { - Assert::Return(ref data) => { - if &data[..] != &result[..] { - fails.push(Fail::Return { - expected: (&data[..]).to_vec(), - actual: (&result[..]).to_vec(), - }) - } - } - Assert::UsedGas(gas) => { - let used_gas = fixture.gas_limit.unwrap_or(0) - gas_left.low_u64(); - if gas != used_gas { - fails.push(Fail::UsedGas { - expected: gas, - actual: used_gas, - }); - } - } - Assert::HasCall(ref locator) => { - let mut found = false; - - for fake_call in ext.calls.iter() { - let mut match_ = true; - if let Some(ref data) = locator.data { - if data.as_ref() != &fake_call.data[..] { - match_ = false; - } - } - - if let Some(ref code_addr) = locator.code_address { - if fake_call.code_address.unwrap_or(H160::zero()) - != code_addr.clone().into() - { - match_ = false - } - } - - if let Some(ref sender) = locator.sender { - if fake_call.sender_address.unwrap_or(H160::zero()) != sender.clone().into() - { - match_ = false - } - } - - if let Some(ref receiver) = locator.receiver { - if fake_call.receive_address.unwrap_or(H160::zero()) - != receiver.clone().into() - { - match_ = false - } - } - - if match_ { - found = true; - break; - } - } - - if !found { - fails.push(Fail::NoCall(locator.clone())) - } - } - Assert::HasStorage(ref storage_entry) => { - let expected_storage_key: H256 = storage_entry.key.clone().into(); - let expected_storage_value: H256 = storage_entry.value.clone().into(); - let val = ext.store.get(&expected_storage_key); - - if let Some(val) = val { - if val != &expected_storage_value { - fails.push(Fail::StorageMismatch { - key: expected_storage_key, - expected: expected_storage_value, - actual: Some(val.clone()), - }) - } - } else { - fails.push(Fail::StorageMismatch { - key: expected_storage_key, - expected: expected_storage_value, - actual: None, - }) - } - } - } - } - fails -} diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs deleted file mode 100644 index 00cf534191..0000000000 --- a/ethcore/wasm/src/tests.rs +++ /dev/null @@ -1,1181 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use byteorder::{ByteOrder, LittleEndian}; -use ethereum_types::{Address, H256, U256}; -use std::{collections::HashMap, sync::Arc}; - -use super::WasmInterpreter; -use vm::{ - self, - tests::{FakeCall, FakeCallType, FakeExt}, - ActionParams, ActionValue, CreateContractAddress, Exec, GasLeft, -}; - -macro_rules! load_sample { - ($name: expr) => { - include_bytes!(concat!("../../res/wasm-tests/compiled/", $name)).to_vec() - }; -} - -macro_rules! reqrep_test { - ($name: expr, $input: expr) => { - reqrep_test!($name, $input, vm::EnvInfo::default(), HashMap::new()) - }; - ($name: expr, $input: expr, $info: expr, $block_hashes: expr) => {{ - let _ = ::env_logger::try_init(); - let code = load_sample!($name); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some($input); - - let mut fake_ext = FakeExt::new().with_wasm(); - fake_ext.info = $info; - fake_ext.blockhashes = $block_hashes; - - let interpreter = wasm_interpreter(params); - interpreter - .exec(&mut fake_ext) - .ok() - .unwrap() - .map(|result| match result { - GasLeft::Known(_) => { - panic!("Test is expected to return payload to check"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - }) - }}; -} - -fn test_finalize(res: Result) -> Result { - match res { - Ok(GasLeft::Known(gas)) => Ok(gas), - Ok(GasLeft::NeedsReturn { .. }) => unimplemented!(), // since ret is unimplemented. - Err(e) => Err(e), - } -} - -fn wasm_interpreter(params: ActionParams) -> Box { - Box::new(WasmInterpreter::new(params)) -} - -/// Empty contract does almost nothing except producing 1 (one) local node debug log message -#[test] -fn empty() { - let code = load_sample!("empty.wasm"); - let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - - let mut params = ActionParams::default(); - params.address = address.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new().with_wasm(); - - let gas_left = { - let interpreter = wasm_interpreter(params); - test_finalize(interpreter.exec(&mut ext).ok().unwrap()).unwrap() - }; - - assert_eq!(gas_left, U256::from(96_926)); -} - -// This test checks if the contract deserializes payload header properly. -// Contract is provided with receiver(address), sender, origin and transaction value -// logger.wasm writes all these provided fixed header fields to some arbitrary storage keys. -#[test] -fn logger() { - let _ = ::env_logger::try_init(); - - let code = load_sample!("logger.wasm"); - let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - let sender: Address = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d".parse().unwrap(); - let origin: Address = "0102030405060708090a0b0c0d0e0f1011121314".parse().unwrap(); - - let mut params = ActionParams::default(); - params.address = address.clone(); - params.sender = sender.clone(); - params.origin = origin.clone(); - params.gas = U256::from(100_000); - params.value = ActionValue::transfer(1_000_000_000); - params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new().with_wasm(); - - let gas_left = { - let interpreter = wasm_interpreter(params); - test_finalize(interpreter.exec(&mut ext).ok().unwrap()).unwrap() - }; - - let address_val: H256 = address.into(); - assert_eq!( - ext.store - .get( - &"0100000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ) - .expect("storage key to exist"), - &address_val, - "Logger sets 0x01 key to the provided address" - ); - let sender_val: H256 = sender.into(); - assert_eq!( - ext.store - .get( - &"0200000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ) - .expect("storage key to exist"), - &sender_val, - "Logger sets 0x02 key to the provided sender" - ); - let origin_val: H256 = origin.into(); - assert_eq!( - ext.store - .get( - &"0300000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ) - .expect("storage key to exist"), - &origin_val, - "Logger sets 0x03 key to the provided origin" - ); - assert_eq!( - U256::from( - ext.store - .get( - &"0400000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ) - .expect("storage key to exist") - ), - U256::from(1_000_000_000), - "Logger sets 0x04 key to the trasferred value" - ); - assert_eq!(gas_left, U256::from(17_716)); -} - -// This test checks if the contract can allocate memory and pass pointer to the result stream properly. -// 1. Contract is being provided with the call descriptor ptr -// 2. Descriptor ptr is 16 byte length -// 3. The last 8 bytes of call descriptor is the space for the contract to fill [result_ptr[4], result_len[4]] -// if it has any result. -#[test] -fn identity() { - let _ = ::env_logger::try_init(); - - let code = load_sample!("identity.wasm"); - let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - - let mut params = ActionParams::default(); - params.sender = sender.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Identity contract should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!( - Address::from_slice(&result), - sender, - "Idenity test contract does not return the sender passed" - ); - assert_eq!(gas_left, U256::from(98_419)); -} - -// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with -// their modulo 19 dopant. -// The result is always twice as long as the input. -// This also tests byte-perfect memory allocation and in/out ptr lifecycle. -#[test] -fn dispersion() { - let _ = ::env_logger::try_init(); - - let code = load_sample!("dispersion.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some(vec![0u8, 125, 197, 255, 19]); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Dispersion routine should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!(result, vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]); - assert_eq!(gas_left, U256::from(92_377)); -} - -#[test] -fn suicide_not() { - let code = load_sample!("suicidal.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some(vec![0u8]); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!( - "Suicidal contract should return payload when had not actualy killed himself" - ); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!(result, vec![0u8]); - assert_eq!(gas_left, U256::from(93_378)); -} - -#[test] -fn suicide() { - let _ = ::env_logger::try_init(); - - let code = load_sample!("suicidal.wasm"); - - let refund: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - - let mut args = vec![127u8]; - args.extend(refund.to_vec()); - params.data = Some(args); - - let mut ext = FakeExt::new().with_wasm(); - - let gas_left = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(gas) => gas, - GasLeft::NeedsReturn { .. } => { - panic!("Suicidal contract should not return anything when had killed itself"); - } - } - }; - - assert!(ext.suicides.contains(&refund)); - assert_eq!(gas_left, U256::from(93_346)); -} - -#[test] -fn create() { - let _ = ::env_logger::try_init(); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("creator.wasm"))); - params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]); - params.value = ActionValue::transfer(1_000_000_000); - - let mut ext = FakeExt::new().with_wasm(); - ext.schedule.wasm.as_mut().unwrap().have_create2 = true; - - let gas_left = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero."); - } - GasLeft::NeedsReturn { - gas_left, - data, - apply_state, - } => { - assert!(apply_state); - assert_eq!(data.as_ref(), [0u8; 40].as_ref()); // FakeExt never succeeds in create. - gas_left - } - } - }; - - trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Create, - create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash), - gas: U256::from(49_674), - sender_address: None, - receive_address: None, - value: Some((1_000_000_000 / 2).into()), - data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], - code_address: None, - })); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Create, - create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash( - H256::from([5u8].as_ref()) - )), - gas: U256::from(6039), - sender_address: None, - receive_address: None, - value: Some((1_000_000_000 / 2).into()), - data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], - code_address: None, - })); - assert_eq!(gas_left, U256::from(5974)); -} - -#[test] -fn call_msg() { - let _ = ::env_logger::try_init(); - - let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap(); - - let mut params = ActionParams::default(); - params.sender = sender.clone(); - params.address = receiver.clone(); - params.code_address = contract_address.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("call.wasm"))); - params.data = Some(Vec::new()); - - let mut ext = FakeExt::new().with_wasm(); - ext.balances - .insert(receiver.clone(), U256::from(10000000000u64)); - - let gas_left = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(gas_left) => gas_left, - GasLeft::NeedsReturn { .. } => { - panic!("Call test should not return payload"); - } - } - }; - - trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Call, - create_scheme: None, - gas: U256::from(33_000), - sender_address: Some(receiver), - receive_address: Some(Address::from([ - 99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0 - ])), - value: Some(1000000000.into()), - data: vec![129u8, 123, 113, 107, 101, 97], - code_address: Some(Address::from([ - 99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0 - ])), - })); - - assert_eq!(gas_left, U256::from(91_672)); -} - -// The same as `call_msg`, but send a `pwasm_ethereum::gasleft` -// value as `gas` argument to the inner pwasm_ethereum::call -#[test] -fn call_msg_gasleft() { - let _ = ::env_logger::try_init(); - - let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap(); - - let mut params = ActionParams::default(); - params.sender = sender.clone(); - params.address = receiver.clone(); - params.code_address = contract_address.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("call_gasleft.wasm"))); - params.data = Some(Vec::new()); - - let mut ext = FakeExt::new().with_wasm(); - ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; - ext.balances - .insert(receiver.clone(), U256::from(10000000000u64)); - - let gas_left = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(gas_left) => gas_left, - GasLeft::NeedsReturn { .. } => { - panic!("Call test should not return payload"); - } - } - }; - - trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Call, - create_scheme: None, - gas: U256::from(91_165), - sender_address: Some(receiver), - receive_address: Some(Address::from([ - 99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0 - ])), - value: Some(1000000000.into()), - data: vec![129u8, 123, 113, 107, 101, 97], - code_address: Some(Address::from([ - 99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0 - ])), - })); - - assert_eq!(gas_left, U256::from(91_671)); -} - -#[test] -fn call_code() { - let _ = ::env_logger::try_init(); - - let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - - let mut params = ActionParams::default(); - params.sender = sender.clone(); - params.address = receiver.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("call_code.wasm"))); - params.data = Some(Vec::new()); - params.value = ActionValue::transfer(1_000_000_000); - - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Call test should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Call, - create_scheme: None, - gas: U256::from(20_000), - sender_address: Some(sender), - receive_address: Some(receiver), - value: None, - data: vec![1u8, 2, 3, 5, 7, 11], - code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()), - })); - - // siphash result - let res = LittleEndian::read_u32(&result[..]); - assert_eq!(res, 4198595614); - assert_eq!(gas_left, U256::from(90_037)); -} - -#[test] -fn call_static() { - let _ = ::env_logger::try_init(); - - let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); - let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap(); - - let mut params = ActionParams::default(); - params.sender = sender.clone(); - params.address = receiver.clone(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("call_static.wasm"))); - params.data = Some(Vec::new()); - params.value = ActionValue::transfer(1_000_000_000); - params.code_address = contract_address.clone(); - - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Static call test should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); - assert!(ext.calls.contains(&FakeCall { - call_type: FakeCallType::Call, - create_scheme: None, - gas: U256::from(20_000), - sender_address: Some(receiver), - receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), - value: None, - data: vec![1u8, 2, 3, 5, 7, 11], - code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), - })); - - // siphash result - let res = LittleEndian::read_u32(&result[..]); - assert_eq!(res, 317632590); - - assert_eq!(gas_left, U256::from(90_042)); -} - -// Realloc test -#[test] -fn realloc() { - let code = load_sample!("realloc.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some(vec![0u8]); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("Realloc should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - assert_eq!(result, vec![0u8; 2]); - assert_eq!(gas_left, U256::from(92_848)); -} - -#[test] -fn alloc() { - let code = load_sample!("alloc.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(10_000_000); - params.code = Some(Arc::new(code)); - params.data = Some(vec![0u8]); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("alloc test should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - assert_eq!(result, vec![5u8; 1024 * 400]); - assert_eq!(gas_left, U256::from(6_893_881)); -} - -// Tests that contract's ability to read from a storage -// Test prepopulates address into storage, than executes a contract which read that address from storage and write this address into result -#[test] -fn storage_read() { - let _ = ::env_logger::try_init(); - - let code = load_sample!("storage_read.wasm"); - let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new().with_wasm(); - ext.store.insert( - "0100000000000000000000000000000000000000000000000000000000000000".into(), - address.into(), - ); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("storage_read should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!(Address::from(&result[12..32]), address); - assert_eq!(gas_left, U256::from(98_369)); -} - -// Tests keccak calculation -// keccak.wasm runs wasm-std::keccak function on data param and returns hash -#[test] -fn keccak() { - let _ = ::env_logger::try_init(); - let code = load_sample!("keccak.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some(b"something".to_vec()); - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("keccak should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!( - H256::from_slice(&result), - H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87") - ); - assert_eq!(gas_left, U256::from(85_949)); -} - -// math_* tests check the ability of wasm contract to perform big integer operations -// - addition -// - multiplication -// - substraction -// - division - -// addition -#[test] -fn math_add() { - let (gas_left, result) = reqrep_test!("math.wasm", { - let mut args = [0u8; 65]; - let arg_a = U256::from_dec_str("999999999999999999999999999999").unwrap(); - let arg_b = U256::from_dec_str("888888888888888888888888888888").unwrap(); - arg_a.to_big_endian(&mut args[1..33]); - arg_b.to_big_endian(&mut args[33..65]); - args.to_vec() - }) - .expect("Interpreter to execute without any errors"); - - assert_eq!( - U256::from_dec_str("1888888888888888888888888888887").unwrap(), - (&result[..]).into() - ); - assert_eq!(gas_left, U256::from(92_072)); -} - -// multiplication -#[test] -fn math_mul() { - let (gas_left, result) = reqrep_test!("math.wasm", { - let mut args = [1u8; 65]; - let arg_a = U256::from_dec_str("888888888888888888888888888888").unwrap(); - let arg_b = U256::from_dec_str("999999999999999999999999999999").unwrap(); - arg_a.to_big_endian(&mut args[1..33]); - arg_b.to_big_endian(&mut args[33..65]); - args.to_vec() - }) - .expect("Interpreter to execute without any errors"); - - assert_eq!( - U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), - (&result[..]).into() - ); - assert_eq!(gas_left, U256::from(91_400)); -} - -// subtraction -#[test] -fn math_sub() { - let (gas_left, result) = reqrep_test!("math.wasm", { - let mut args = [2u8; 65]; - let arg_a = U256::from_dec_str("999999999999999999999999999999").unwrap(); - let arg_b = U256::from_dec_str("888888888888888888888888888888").unwrap(); - arg_a.to_big_endian(&mut args[1..33]); - arg_b.to_big_endian(&mut args[33..65]); - args.to_vec() - }) - .expect("Interpreter to execute without any errors"); - - assert_eq!( - U256::from_dec_str("111111111111111111111111111111").unwrap(), - (&result[..]).into() - ); - assert_eq!(gas_left, U256::from(92_072)); -} - -// subtraction with overflow -#[test] -fn math_sub_with_overflow() { - let result = reqrep_test!("math.wasm", { - let mut args = [2u8; 65]; - let arg_a = U256::from_dec_str("888888888888888888888888888888").unwrap(); - let arg_b = U256::from_dec_str("999999999999999999999999999999").unwrap(); - arg_a.to_big_endian(&mut args[1..33]); - arg_b.to_big_endian(&mut args[33..65]); - args.to_vec() - }); - - match result { - Err(vm::Error::Wasm(_)) => {} - _ => panic!("Unexpected result {:?}", result), - } -} - -#[test] -fn math_div() { - let (gas_left, result) = reqrep_test!("math.wasm", { - let mut args = [3u8; 65]; - let arg_a = U256::from_dec_str("999999999999999999999999999999").unwrap(); - let arg_b = U256::from_dec_str("888888888888888888888888").unwrap(); - arg_a.to_big_endian(&mut args[1..33]); - arg_b.to_big_endian(&mut args[33..65]); - args.to_vec() - }) - .expect("Interpreter to execute without any errors"); - - assert_eq!(U256::from_dec_str("1125000").unwrap(), (&result[..]).into()); - assert_eq!(gas_left, U256::from(85_700)); -} - -#[test] -fn storage_metering() { - let _ = ::env_logger::try_init(); - - // #1 - let mut ext = FakeExt::new().with_wasm(); - - let code = Arc::new(load_sample!("setter.wasm")); - let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); - - let mut params = ActionParams::default(); - params.address = address.clone(); - params.gas = U256::from(100_000); - params.code = Some(code.clone()); - params.data = Some(vec![ - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, - ]); - - let gas_left = { - let interpreter = wasm_interpreter(params); - test_finalize(interpreter.exec(&mut ext).ok().unwrap()).unwrap() - }; - - // 0 -> not 0 - assert_eq!(gas_left, U256::from(72_164)); - - // #2 - - let mut params = ActionParams::default(); - params.address = address.clone(); - params.gas = U256::from(100_000); - params.code = Some(code.clone()); - params.data = Some(vec![ - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x6b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, - ]); - - let gas_left = { - let interpreter = wasm_interpreter(params); - test_finalize(interpreter.exec(&mut ext).ok().unwrap()).unwrap() - }; - - // not 0 -> not 0 - assert_eq!(gas_left, U256::from(87_164)); -} - -// This test checks the ability of wasm contract to invoke -// varios blockchain runtime methods -#[test] -fn externs() { - let (gas_left, result) = reqrep_test!( - "externs.wasm", - Vec::new(), - vm::EnvInfo { - number: 0x9999999999u64.into(), - author: "efefefefefefefefefefefefefefefefefefefef".parse().unwrap(), - timestamp: 0x8888888888u64.into(), - difficulty: H256::from( - "0f1f2f3f4f5f6f7f8f9fafbfcfdfefff0d1d2d3d4d5d6d7d8d9dadbdcdddedfd" - ) - .into(), - gas_limit: 0x777777777777u64.into(), - last_hashes: Default::default(), - gas_used: 0.into(), - }, - { - let mut hashes = HashMap::new(); - hashes.insert( - U256::from(0), - H256::from("9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d"), - ); - hashes.insert( - U256::from(1), - H256::from("7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b"), - ); - hashes - } - ) - .expect("Interpreter to execute without any errors"); - - assert_eq!( - &result[0..64].to_vec(), - &vec![ - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, - 0x9d, 0x9d, 0x9d, 0x9d, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, - ], - "Block hashes requested and returned do not match" - ); - - assert_eq!( - &result[64..84].to_vec(), - &vec![ - 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, - 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, - ], - "Coinbase requested and returned does not match" - ); - - assert_eq!( - &result[84..92].to_vec(), - &vec![0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00], - "Timestamp requested and returned does not match" - ); - - assert_eq!( - &result[92..100].to_vec(), - &vec![0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00], - "Block number requested and returned does not match" - ); - - assert_eq!( - &result[100..132].to_vec(), - &vec![ - 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, - 0xef, 0xff, 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, 0x8d, 0x9d, 0xad, 0xbd, - 0xcd, 0xdd, 0xed, 0xfd, - ], - "Difficulty requested and returned does not match" - ); - - assert_eq!( - &result[132..164].to_vec(), - &vec![ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, - 0x77, 0x77, 0x77, 0x77, - ], - "Gas limit requested and returned does not match" - ); - - assert_eq!(gas_left, U256::from(90_428)); -} - -// This test checks the ability of wasm contract to invoke gasleft -#[test] -fn gasleft() { - let _ = ::env_logger::try_init(); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); - - let mut ext = FakeExt::new().with_wasm(); - ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; - - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => {} - GasLeft::NeedsReturn { gas_left, data, .. } => { - let gas = LittleEndian::read_u64(data.as_ref()); - assert_eq!(gas, 93_423); - assert_eq!(gas_left, U256::from(93_349)); - } - } -} - -// This test should fail because -// ext.schedule.wasm.as_mut().unwrap().have_gasleft = false; -#[test] -fn gasleft_fail() { - let _ = ::env_logger::try_init(); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); - let mut ext = FakeExt::new().with_wasm(); - let interpreter = wasm_interpreter(params); - match interpreter.exec(&mut ext).ok().unwrap() { - Err(_) => {} - Ok(_) => { - panic!("interpreter.exec should return Err if ext.schedule.wasm.have_gasleft = false") - } - } -} - -#[test] -fn embedded_keccak() { - let _ = ::env_logger::try_init(); - let mut code = load_sample!("keccak.wasm"); - code.extend_from_slice(b"something"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.params_type = vm::ParamsType::Embedded; - - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("keccak should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!( - H256::from_slice(&result), - H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87") - ); - assert_eq!(gas_left, U256::from(85_949)); -} - -/// This test checks the correctness of log extern -/// Target test puts one event with two topic [keccak(input), reverse(keccak(input))] -/// and reversed input as a data -#[test] -fn events() { - let _ = ::env_logger::try_init(); - let code = load_sample!("events.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some(b"something".to_vec()); - - let mut ext = FakeExt::new().with_wasm(); - - let (gas_left, result) = { - let interpreter = wasm_interpreter(params); - let result = interpreter - .exec(&mut ext) - .ok() - .unwrap() - .expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { - panic!("events should return payload"); - } - GasLeft::NeedsReturn { - gas_left: gas, - data: result, - apply_state: _apply, - } => (gas, result.to_vec()), - } - }; - - assert_eq!(ext.logs.len(), 1); - let log_entry = &ext.logs[0]; - assert_eq!(log_entry.topics.len(), 2); - assert_eq!( - &log_entry.topics[0], - &H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87") - ); - assert_eq!( - &log_entry.topics[1], - &H256::from("871d5ea37430753faab7dff7a7187783517d83bd822c02e28a164c887e1d3768") - ); - assert_eq!(&log_entry.data, b"gnihtemos"); - - assert_eq!(&result, b"gnihtemos"); - assert_eq!(gas_left, U256::from(83_161)); -} - -#[test] -fn recursive() { - let _ = ::env_logger::try_init(); - let code = load_sample!("recursive.wasm"); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000_000); - params.code = Some(Arc::new(code)); - params.data = Some({ - // `recursive` expects only one 32-bit word in LE that - // represents an iteration count. - // - // We pick a relative big number to definitely hit stack overflow. - use byteorder::WriteBytesExt; - let mut data = vec![]; - data.write_u32::(100000).unwrap(); - data - }); - - let mut ext = FakeExt::new().with_wasm(); - - let interpreter = wasm_interpreter(params); - let result = interpreter.exec(&mut ext).ok().unwrap(); - - // We expect that stack overflow will occur and it should be generated by - // deterministic stack metering. Exceeding deterministic stack height limit - // always ends with a trap generated by `unreachable` instruction. - match result { - Err(trap) => { - let err_description = trap.to_string(); - assert!( - err_description.contains("Unreachable"), - "err_description: {} should contain 'Unreachable'", - err_description - ); - } - _ => panic!("this test should trap"), - } -} diff --git a/scripts/add_license.sh b/scripts/add_license.sh deleted file mode 100755 index 2b283590b0..0000000000 --- a/scripts/add_license.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env sh - -PAT_GPL="^// Copyright.*If not, see \.$" -PAT_OTHER="^// Copyright" - -for f in $(find . -type f | egrep '\.(c|cpp|rs)$'); do - HEADER=$(head -16 $f) - if [[ $HEADER =~ $PAT_GPL ]]; then - BODY=$(tail -n +17 $f) - cat license_header > temp - echo "$BODY" >> temp - mv temp $f - elif [[ $HEADER =~ $PAT_OTHER ]]; then - echo "Other license was found do nothing" - else - echo "$f was missing header" - cat license_header $f > temp - mv temp $f - fi -done diff --git a/scripts/doc.sh b/scripts/doc.sh deleted file mode 100755 index e005217cf4..0000000000 --- a/scripts/doc.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env sh -# generate documentation only for openethereum and ethcore libraries - -cargo doc --no-deps --verbose --all && - echo '' > target/doc/index.html diff --git a/scripts/evm_jsontests_bench.sh b/scripts/evm_jsontests_bench.sh index e13ff9ef4a..69736cea5e 100755 --- a/scripts/evm_jsontests_bench.sh +++ b/scripts/evm_jsontests_bench.sh @@ -2,15 +2,15 @@ cargo build --release -p evmbin -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmArithmeticTest -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmBitwiseLogicOperation -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmBlockInfoTest -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmEnvironmentalInfo -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmIOandFlowOperations -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmLogTest -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmPerformance -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmPushDupSwapTest -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmRandomTest -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmSha3Test -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmSystemOperations -./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/ethereum/tests/VMTests/vmTests +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmArithmeticTest +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmBitwiseLogicOperation +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmBlockInfoTest +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmEnvironmentalInfo +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmIOandFlowOperations +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmLogTest +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmPerformance +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmPushDupSwapTest +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmRandomTest +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmSha3Test +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmSystemOperations +./target/release/openethereum-evm stats-jsontests-vm ./ethcore/res/json_tests/VMTests/vmTests diff --git a/scripts/hook.sh b/scripts/hook.sh deleted file mode 100755 index 739b11e7fb..0000000000 --- a/scripts/hook.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env sh -FILE=./.git/hooks/pre-push - -echo "#!/bin/sh\n" > $FILE -# Exit on any error -echo "set -e" >> $FILE -# Run release build -echo "cargo build --features dev" >> $FILE -# Build tests -echo "cargo test --no-run --features dev --all" >> $FILE -echo "" >> $FILE -chmod +x $FILE diff --git a/scripts/remove_duplicate_empty_lines.sh b/scripts/remove_duplicate_empty_lines.sh deleted file mode 100755 index 0df265ab9f..0000000000 --- a/scripts/remove_duplicate_empty_lines.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env sh - -for f in $(find . -name '*.rs'); do - cat -s $f > $f.temp - mv $f.temp $f -done diff --git a/secret-store/Cargo.toml b/secret-store/Cargo.toml deleted file mode 100644 index 65bc0026d9..0000000000 --- a/secret-store/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -description = "Parity Ethereum (EthCore) Secret Store" -name = "ethcore-secretstore" -version = "1.0.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] - -[dependencies] -byteorder = "1.0" -common-types = { path = "../ethcore/types" } -ethabi = "6.0" -ethabi-contract = "6.0" -ethabi-derive = "6.0" -ethcore = { path = "../ethcore" } -ethcore-accounts = { path = "../accounts", optional = true} -ethcore-call-contract = { path = "../ethcore/call-contract" } -ethcore-sync = { path = "../ethcore/sync" } -ethereum-types = "0.4" -ethkey = { path = "../accounts/ethkey" } -futures = "0.1" -hyper = { version = "0.12", default-features = false } -keccak-hash = "0.1" -kvdb = "0.1" -lazy_static = "1.0" -log = "0.4" -parity-bytes = "0.1" -parity-crypto = "0.3" -parity-runtime = { path = "../util/runtime" } -parking_lot = "0.7" -rustc-hex = "1.0" -serde = "1.0" -serde_derive = "1.0" -serde_json = "1.0" -tiny-keccak = "1.4" -tokio = "0.1.22" -tokio-io = "0.1" -tokio-service = "0.1" -url = "2" -percent-encoding = "2" -jsonrpc-server-utils = "15.0.0" - -[dev-dependencies] -env_logger = "0.5" -ethcore = { path = "../ethcore", features = ["test-helpers"] } -tempdir = "0.3" -kvdb-rocksdb = "0.1.3" - -[features] -accounts = ["ethcore-accounts"] diff --git a/secret-store/res/acl_storage.json b/secret-store/res/acl_storage.json deleted file mode 100644 index cfdefd9c73..0000000000 --- a/secret-store/res/acl_storage.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - {"constant":true,"inputs":[{"name":"user","type":"address"},{"name":"document","type":"bytes32"}],"name":"checkPermissions","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"} -] diff --git a/secret-store/res/key_server_set.json b/secret-store/res/key_server_set.json deleted file mode 100644 index 28530e3532..0000000000 --- a/secret-store/res/key_server_set.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - {"constant":true,"inputs":[],"name":"getMigrationMaster","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getMigrationKeyServerPublic","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"id","type":"bytes32"}],"name":"startMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getCurrentKeyServerIndex","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getMigrationKeyServerAddress","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[],"name":"getMigrationId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[],"name":"getNewKeyServers","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"id","type":"bytes32"}],"name":"confirmMigration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[],"name":"getMigrationKeyServers","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"isMigrationConfirmed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[],"name":"getCurrentKeyServersCount","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[],"name":"getCurrentKeyServers","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[],"name":"getCurrentLastChange","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getCurrentKeyServerPublic","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getNewKeyServerAddress","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getCurrentKeyServerAddress","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getNewKeyServerPublic","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"index","type":"uint8"}],"name":"getCurrentKeyServer","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"keyServer","type":"address"}],"name":"KeyServerAdded","type":"event"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"keyServer","type":"address"}],"name":"KeyServerRemoved","type":"event"}, - {"anonymous":false,"inputs":[],"name":"MigrationStarted","type":"event"}, - {"anonymous":false,"inputs":[],"name":"MigrationCompleted","type":"event"} -] \ No newline at end of file diff --git a/secret-store/res/service.json b/secret-store/res/service.json deleted file mode 100644 index d79c38e7aa..0000000000 --- a/secret-store/res/service.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - {"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"requireKeyServer","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"}, - - {"constant":true,"inputs":[],"name":"serverKeyGenerationRequestsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"}],"name":"serverKeyGenerationError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getServerKeyGenerationRequest","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"serverKeyPublic","type":"bytes"}],"name":"serverKeyGenerated","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"keyServer","type":"address"}],"name":"isServerKeyGenerationResponseRequired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"serverKeyId","type":"bytes32"},{"indexed":false,"name":"author","type":"address"},{"indexed":false,"name":"threshold","type":"uint8"}],"name":"ServerKeyGenerationRequested","type":"event"}, - - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"}],"name":"serverKeyRetrievalError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[],"name":"serverKeyRetrievalRequestsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"keyServer","type":"address"}],"name":"isServerKeyRetrievalResponseRequired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getServerKeyRetrievalRequest","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"serverKeyPublic","type":"bytes"},{"name":"threshold","type":"uint8"}],"name":"serverKeyRetrieved","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"serverKeyId","type":"bytes32"}],"name":"ServerKeyRetrievalRequested","type":"event"}, - - {"constant":true,"inputs":[],"name":"documentKeyStoreRequestsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"}],"name":"documentKeyStoreError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"}],"name":"documentKeyStored","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"keyServer","type":"address"}],"name":"isDocumentKeyStoreResponseRequired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getDocumentKeyStoreRequest","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"},{"name":"","type":"bytes"},{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"serverKeyId","type":"bytes32"},{"indexed":false,"name":"author","type":"address"},{"indexed":false,"name":"commonPoint","type":"bytes"},{"indexed":false,"name":"encryptedPoint","type":"bytes"}],"name":"DocumentKeyStoreRequested","type":"event"}, - - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"requester","type":"address"},{"name":"commonPoint","type":"bytes"},{"name":"threshold","type":"uint8"}],"name":"documentKeyCommonRetrieved","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"keyServer","type":"address"},{"name":"requester","type":"address"}],"name":"isDocumentKeyShadowRetrievalResponseRequired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"requester","type":"address"},{"name":"participants","type":"uint256"},{"name":"decryptedSecret","type":"bytes"},{"name":"shadow","type":"bytes"}],"name":"documentKeyPersonalRetrieved","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":false,"inputs":[{"name":"serverKeyId","type":"bytes32"},{"name":"requester","type":"address"}],"name":"documentKeyShadowRetrievalError","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, - {"constant":true,"inputs":[],"name":"documentKeyShadowRetrievalRequestsCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, - {"constant":true,"inputs":[{"name":"index","type":"uint256"}],"name":"getDocumentKeyShadowRetrievalRequest","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"serverKeyId","type":"bytes32"},{"indexed":false,"name":"requester","type":"address"}],"name":"DocumentKeyCommonRetrievalRequested","type":"event"}, - {"anonymous":false,"inputs":[{"indexed":false,"name":"serverKeyId","type":"bytes32"},{"indexed":false,"name":"requesterPublic","type":"bytes"}],"name":"DocumentKeyPersonalRetrievalRequested","type":"event"} -] \ No newline at end of file diff --git a/secret-store/src/acl_storage.rs b/secret-store/src/acl_storage.rs deleted file mode 100644 index 47a826800d..0000000000 --- a/secret-store/src/acl_storage.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use call_contract::CallContract; -use ethabi::FunctionOutputDecoder; -use ethcore::client::{BlockId, ChainNotify, NewBlocks}; -use ethereum_types::Address; -use parking_lot::{Mutex, RwLock}; -use std::{ - collections::{HashMap, HashSet}, - sync::Arc, -}; -use trusted_client::TrustedClient; -use types::{ContractAddress, Error, ServerKeyId}; - -use_contract!(acl_storage, "res/acl_storage.json"); - -const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker"; - -/// ACL storage of Secret Store -pub trait AclStorage: Send + Sync { - /// Check if requestor can access document with hash `document` - fn check(&self, requester: Address, document: &ServerKeyId) -> Result; -} - -/// On-chain ACL storage implementation. -pub struct OnChainAclStorage { - /// Cached on-chain contract. - contract: Mutex, -} - -/// Cached on-chain ACL storage contract. -struct CachedContract { - /// Blockchain client. - client: TrustedClient, - /// Contract address source. - address_source: ContractAddress, - /// Current contract address. - contract_address: Option
, -} - -/// Dummy ACL storage implementation (check always passed). -#[derive(Default, Debug)] -pub struct DummyAclStorage { - prohibited: RwLock>>, -} - -impl OnChainAclStorage { - pub fn new( - trusted_client: TrustedClient, - address_source: ContractAddress, - ) -> Result, Error> { - let client = trusted_client.get_untrusted(); - let acl_storage = Arc::new(OnChainAclStorage { - contract: Mutex::new(CachedContract::new(trusted_client, address_source)), - }); - client - .ok_or_else(|| { - Error::Internal("Constructing OnChainAclStorage without active Client".into()) - })? - .add_notify(acl_storage.clone()); - Ok(acl_storage) - } -} - -impl AclStorage for OnChainAclStorage { - fn check(&self, requester: Address, document: &ServerKeyId) -> Result { - self.contract.lock().check(requester, document) - } -} - -impl ChainNotify for OnChainAclStorage { - // t_nb 11.5 SecretStore OnChainAclStorage. - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { - return; - } - if !new_blocks.route.enacted().is_empty() || !new_blocks.route.retracted().is_empty() { - self.contract.lock().update_contract_address() - } - } -} - -impl CachedContract { - pub fn new(client: TrustedClient, address_source: ContractAddress) -> Self { - let mut contract = CachedContract { - client, - address_source, - contract_address: None, - }; - contract.update_contract_address(); - contract - } - - pub fn update_contract_address(&mut self) { - let contract_address = self.client.read_contract_address( - ACL_CHECKER_CONTRACT_REGISTRY_NAME.into(), - &self.address_source, - ); - if contract_address != self.contract_address { - trace!(target: "secretstore", "Configuring for ACL checker contract from address {:?}", - contract_address); - - self.contract_address = contract_address; - } - } - - pub fn check(&mut self, requester: Address, document: &ServerKeyId) -> Result { - if let Some(client) = self.client.get() { - // call contract to check accesss - match self.contract_address { - Some(contract_address) => { - let (encoded, decoder) = acl_storage::functions::check_permissions::call( - requester, - document.clone(), - ); - let d = client - .call_contract(BlockId::Latest, contract_address, encoded) - .map_err(|e| { - Error::Internal(format!("ACL checker call error: {}", e.to_string())) - })?; - decoder.decode(&d).map_err(|e| { - Error::Internal(format!("ACL checker call error: {}", e.to_string())) - }) - } - None => Err(Error::Internal( - "ACL checker contract is not configured".to_owned(), - )), - } - } else { - Err(Error::Internal( - "Calling ACL contract without trusted blockchain client".into(), - )) - } - } -} - -impl DummyAclStorage { - /// Prohibit given requestor access to given documents - #[cfg(test)] - pub fn prohibit(&self, requester: Address, document: ServerKeyId) { - self.prohibited - .write() - .entry(requester) - .or_insert_with(Default::default) - .insert(document); - } -} - -impl AclStorage for DummyAclStorage { - fn check(&self, requester: Address, document: &ServerKeyId) -> Result { - Ok(self - .prohibited - .read() - .get(&requester) - .map(|docs| !docs.contains(document)) - .unwrap_or(true)) - } -} diff --git a/secret-store/src/helpers.rs b/secret-store/src/helpers.rs deleted file mode 100644 index 95fcdbbdf6..0000000000 --- a/secret-store/src/helpers.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethcore::client::{BlockChainClient, BlockId, Client}; -use ethereum_types::H256; - -// TODO: Instead of a constant, make this based on consensus finality. -/// Number of confirmations required before request can be processed. -pub const REQUEST_CONFIRMATIONS_REQUIRED: u64 = 3; - -/// Get hash of the last block with at least n confirmations. -pub fn get_confirmed_block_hash(client: &Client, confirmations: u64) -> Option { - client - .block_number(BlockId::Latest) - .map(|b| b.saturating_sub(confirmations)) - .and_then(|b| client.block_hash(BlockId::Number(b))) -} diff --git a/secret-store/src/key_server.rs b/secret-store/src/key_server.rs deleted file mode 100644 index 64c4d4ebeb..0000000000 --- a/secret-store/src/key_server.rs +++ /dev/null @@ -1,809 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::{acl_storage::AclStorage, key_server_set::KeyServerSet, key_storage::KeyStorage}; -use crypto::DEFAULT_MAC; -use ethkey::crypto; -use key_server_cluster::{ - math, new_network_cluster, ClusterClient, ClusterConfiguration as NetClusterConfiguration, - NetConnectionsManagerConfig, -}; -use parity_runtime::Executor; -use parking_lot::Mutex; -use std::{collections::BTreeSet, sync::Arc}; -use traits::{ - AdminSessionsServer, DocumentKeyServer, KeyServer, MessageSigner, NodeKeyPair, - ServerKeyGenerator, -}; -use types::{ - ClusterConfiguration, EncryptedDocumentKey, EncryptedDocumentKeyShadow, - EncryptedMessageSignature, Error, MessageHash, NodeId, Public, RequestSignature, Requester, - ServerKeyId, -}; - -/// Secret store key server implementation -pub struct KeyServerImpl { - data: Arc>, -} - -/// Secret store key server data. -pub struct KeyServerCore { - cluster: Arc, -} - -impl KeyServerImpl { - /// Create new key server instance - pub fn new( - config: &ClusterConfiguration, - key_server_set: Arc, - self_key_pair: Arc, - acl_storage: Arc, - key_storage: Arc, - executor: Executor, - ) -> Result { - Ok(KeyServerImpl { - data: Arc::new(Mutex::new(KeyServerCore::new( - config, - key_server_set, - self_key_pair, - acl_storage, - key_storage, - executor, - )?)), - }) - } - - /// Get cluster client reference. - pub fn cluster(&self) -> Arc { - self.data.lock().cluster.clone() - } -} - -impl KeyServer for KeyServerImpl {} - -impl AdminSessionsServer for KeyServerImpl { - fn change_servers_set( - &self, - old_set_signature: RequestSignature, - new_set_signature: RequestSignature, - new_servers_set: BTreeSet, - ) -> Result<(), Error> { - let servers_set_change_session = self.data.lock().cluster.new_servers_set_change_session( - None, - None, - new_servers_set, - old_set_signature, - new_set_signature, - )?; - servers_set_change_session - .as_servers_set_change() - .expect("new_servers_set_change_session creates servers_set_change_session; qed") - .wait() - .map_err(Into::into) - } -} - -impl ServerKeyGenerator for KeyServerImpl { - fn generate_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result { - // recover requestor' public key from signature - let address = author - .address(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // generate server key - let generation_session = self.data.lock().cluster.new_generation_session( - key_id.clone(), - None, - address, - threshold, - )?; - generation_session - .wait(None) - .expect("when wait is called without timeout it always returns Some; qed") - .map_err(Into::into) - } - - fn restore_key_public( - &self, - key_id: &ServerKeyId, - author: &Requester, - ) -> Result { - // recover requestor' public key from signature - let address = author - .address(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // negotiate key version && retrieve common key data - let negotiation_session = self - .data - .lock() - .cluster - .new_key_version_negotiation_session(*key_id)?; - negotiation_session - .wait() - .and_then(|_| negotiation_session.common_key_data()) - .and_then(|key_share| { - if key_share.author == address { - Ok(key_share.public) - } else { - Err(Error::AccessDenied) - } - }) - .map_err(Into::into) - } -} - -impl DocumentKeyServer for KeyServerImpl { - fn store_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - common_point: Public, - encrypted_document_key: Public, - ) -> Result<(), Error> { - // store encrypted key - let encryption_session = self.data.lock().cluster.new_encryption_session( - key_id.clone(), - author.clone(), - common_point, - encrypted_document_key, - )?; - encryption_session.wait(None).map_err(Into::into) - } - - fn generate_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result { - // recover requestor' public key from signature - let public = author - .public(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // generate server key - let server_key = self.generate_key(key_id, author, threshold)?; - - // generate random document key - let document_key = math::generate_random_point()?; - let encrypted_document_key = math::encrypt_secret(&document_key, &server_key)?; - - // store document key in the storage - self.store_document_key( - key_id, - author, - encrypted_document_key.common_point, - encrypted_document_key.encrypted_point, - )?; - - // encrypt document key with requestor public key - let document_key = crypto::ecies::encrypt(&public, &DEFAULT_MAC, &document_key) - .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; - Ok(document_key) - } - - fn restore_document_key( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result { - // recover requestor' public key from signature - let public = requester - .public(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // decrypt document key - let decryption_session = self.data.lock().cluster.new_decryption_session( - key_id.clone(), - None, - requester.clone(), - None, - false, - false, - )?; - let document_key = decryption_session - .wait(None) - .expect("when wait is called without timeout it always returns Some; qed")? - .decrypted_secret; - - // encrypt document key with requestor public key - let document_key = crypto::ecies::encrypt(&public, &DEFAULT_MAC, &document_key) - .map_err(|err| Error::Internal(format!("Error encrypting document key: {}", err)))?; - Ok(document_key) - } - - fn restore_document_key_shadow( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result { - let decryption_session = self.data.lock().cluster.new_decryption_session( - key_id.clone(), - None, - requester.clone(), - None, - true, - false, - )?; - decryption_session - .wait(None) - .expect("when wait is called without timeout it always returns Some; qed") - .map_err(Into::into) - } -} - -impl MessageSigner for KeyServerImpl { - fn sign_message_schnorr( - &self, - key_id: &ServerKeyId, - requester: &Requester, - message: MessageHash, - ) -> Result { - // recover requestor' public key from signature - let public = requester - .public(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // sign message - let signing_session = self.data.lock().cluster.new_schnorr_signing_session( - key_id.clone(), - requester.clone().into(), - None, - message, - )?; - let message_signature = signing_session.wait()?; - - // compose two message signature components into single one - let mut combined_signature = [0; 64]; - combined_signature[..32].clone_from_slice(&**message_signature.0); - combined_signature[32..].clone_from_slice(&**message_signature.1); - - // encrypt combined signature with requestor public key - let message_signature = crypto::ecies::encrypt(&public, &DEFAULT_MAC, &combined_signature) - .map_err(|err| { - Error::Internal(format!("Error encrypting message signature: {}", err)) - })?; - Ok(message_signature) - } - - fn sign_message_ecdsa( - &self, - key_id: &ServerKeyId, - requester: &Requester, - message: MessageHash, - ) -> Result { - // recover requestor' public key from signature - let public = requester - .public(key_id) - .map_err(Error::InsufficientRequesterData)?; - - // sign message - let signing_session = self.data.lock().cluster.new_ecdsa_signing_session( - key_id.clone(), - requester.clone().into(), - None, - message, - )?; - let message_signature = signing_session.wait()?; - - // encrypt combined signature with requestor public key - let message_signature = crypto::ecies::encrypt(&public, &DEFAULT_MAC, &*message_signature) - .map_err(|err| { - Error::Internal(format!("Error encrypting message signature: {}", err)) - })?; - Ok(message_signature) - } -} - -impl KeyServerCore { - pub fn new( - config: &ClusterConfiguration, - key_server_set: Arc, - self_key_pair: Arc, - acl_storage: Arc, - key_storage: Arc, - executor: Executor, - ) -> Result { - let cconfig = NetClusterConfiguration { - self_key_pair: self_key_pair.clone(), - key_server_set: key_server_set, - acl_storage: acl_storage, - key_storage: key_storage, - admin_public: config.admin_public, - preserve_sessions: false, - }; - let net_config = NetConnectionsManagerConfig { - listen_address: ( - config.listener_address.address.clone(), - config.listener_address.port, - ), - allow_connecting_to_higher_nodes: config.allow_connecting_to_higher_nodes, - auto_migrate_enabled: config.auto_migrate_enabled, - }; - - let core = new_network_cluster(executor, cconfig, net_config)?; - let cluster = core.client(); - core.run()?; - - Ok(KeyServerCore { cluster }) - } -} - -#[cfg(test)] -pub mod tests { - use super::KeyServerImpl; - use acl_storage::DummyAclStorage; - use crypto::DEFAULT_MAC; - use ethereum_types::{H256, H520}; - use ethkey::{self, crypto, verify_public, Generator, Random, Secret}; - use key_server_cluster::math; - use key_server_set::tests::MapKeyServerSet; - use key_storage::{tests::DummyKeyStorage, KeyStorage}; - use node_key_pair::PlainNodeKeyPair; - use parity_runtime::Runtime; - use std::{ - collections::{BTreeMap, BTreeSet}, - net::SocketAddr, - sync::Arc, - time, - }; - use traits::{ - AdminSessionsServer, DocumentKeyServer, KeyServer, MessageSigner, ServerKeyGenerator, - }; - use types::{ - ClusterConfiguration, EncryptedDocumentKey, EncryptedDocumentKeyShadow, - EncryptedMessageSignature, Error, MessageHash, NodeAddress, NodeId, Public, - RequestSignature, Requester, ServerKeyId, - }; - - #[derive(Default)] - pub struct DummyKeyServer; - - impl KeyServer for DummyKeyServer {} - - impl AdminSessionsServer for DummyKeyServer { - fn change_servers_set( - &self, - _old_set_signature: RequestSignature, - _new_set_signature: RequestSignature, - _new_servers_set: BTreeSet, - ) -> Result<(), Error> { - unimplemented!("test-only") - } - } - - impl ServerKeyGenerator for DummyKeyServer { - fn generate_key( - &self, - _key_id: &ServerKeyId, - _author: &Requester, - _threshold: usize, - ) -> Result { - unimplemented!("test-only") - } - - fn restore_key_public( - &self, - _key_id: &ServerKeyId, - _author: &Requester, - ) -> Result { - unimplemented!("test-only") - } - } - - impl DocumentKeyServer for DummyKeyServer { - fn store_document_key( - &self, - _key_id: &ServerKeyId, - _author: &Requester, - _common_point: Public, - _encrypted_document_key: Public, - ) -> Result<(), Error> { - unimplemented!("test-only") - } - - fn generate_document_key( - &self, - _key_id: &ServerKeyId, - _author: &Requester, - _threshold: usize, - ) -> Result { - unimplemented!("test-only") - } - - fn restore_document_key( - &self, - _key_id: &ServerKeyId, - _requester: &Requester, - ) -> Result { - unimplemented!("test-only") - } - - fn restore_document_key_shadow( - &self, - _key_id: &ServerKeyId, - _requester: &Requester, - ) -> Result { - unimplemented!("test-only") - } - } - - impl MessageSigner for DummyKeyServer { - fn sign_message_schnorr( - &self, - _key_id: &ServerKeyId, - _requester: &Requester, - _message: MessageHash, - ) -> Result { - unimplemented!("test-only") - } - - fn sign_message_ecdsa( - &self, - _key_id: &ServerKeyId, - _requester: &Requester, - _message: MessageHash, - ) -> Result { - unimplemented!("test-only") - } - } - - fn make_key_servers( - start_port: u16, - num_nodes: usize, - ) -> (Vec, Vec>, Runtime) { - let key_pairs: Vec<_> = (0..num_nodes).map(|_| Random.generate().unwrap()).collect(); - let configs: Vec<_> = (0..num_nodes) - .map(|i| ClusterConfiguration { - listener_address: NodeAddress { - address: "127.0.0.1".into(), - port: start_port + (i as u16), - }, - nodes: key_pairs - .iter() - .enumerate() - .map(|(j, kp)| { - ( - kp.public().clone(), - NodeAddress { - address: "127.0.0.1".into(), - port: start_port + (j as u16), - }, - ) - }) - .collect(), - key_server_set_contract_address: None, - allow_connecting_to_higher_nodes: false, - admin_public: None, - auto_migrate_enabled: false, - }) - .collect(); - let key_servers_set: BTreeMap = configs[0] - .nodes - .iter() - .map(|(k, a)| { - ( - k.clone(), - format!("{}:{}", a.address, a.port).parse().unwrap(), - ) - }) - .collect(); - let key_storages = (0..num_nodes) - .map(|_| Arc::new(DummyKeyStorage::default())) - .collect::>(); - let runtime = Runtime::with_thread_count(4); - let key_servers: Vec<_> = configs - .into_iter() - .enumerate() - .map(|(i, cfg)| { - KeyServerImpl::new( - &cfg, - Arc::new(MapKeyServerSet::new(false, key_servers_set.clone())), - Arc::new(PlainNodeKeyPair::new(key_pairs[i].clone())), - Arc::new(DummyAclStorage::default()), - key_storages[i].clone(), - runtime.executor(), - ) - .unwrap() - }) - .collect(); - - // wait until connections are established. It is fast => do not bother with events here - let start = time::Instant::now(); - let mut tried_reconnections = false; - loop { - if key_servers - .iter() - .all(|ks| ks.cluster().is_fully_connected()) - { - break; - } - - let old_tried_reconnections = tried_reconnections; - let mut fully_connected = true; - for key_server in &key_servers { - if !key_server.cluster().is_fully_connected() { - fully_connected = false; - if !old_tried_reconnections { - tried_reconnections = true; - key_server.cluster().connect(); - } - } - } - if fully_connected { - break; - } - if time::Instant::now() - start > time::Duration::from_millis(3000) { - panic!("connections are not established in 3000ms"); - } - } - - (key_servers, key_storages, runtime) - } - - #[test] - fn document_key_generation_and_retrievement_works_over_network_with_single_node() { - let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6070, 1); - - // generate document key - let threshold = 0; - let document = Random.generate().unwrap().secret().clone(); - let secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&secret, &document).unwrap(); - let generated_key = key_servers[0] - .generate_document_key(&document, &signature.clone().into(), threshold) - .unwrap(); - let generated_key = crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &generated_key).unwrap(); - - // now let's try to retrieve key back - for key_server in key_servers.iter() { - let retrieved_key = key_server - .restore_document_key(&document, &signature.clone().into()) - .unwrap(); - let retrieved_key = - crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &retrieved_key).unwrap(); - assert_eq!(retrieved_key, generated_key); - } - drop(runtime); - } - - #[test] - fn document_key_generation_and_retrievement_works_over_network_with_3_nodes() { - let _ = ::env_logger::try_init(); - let (key_servers, key_storages, runtime) = make_key_servers(6080, 3); - - let test_cases = [0, 1, 2]; - for threshold in &test_cases { - // generate document key - let document = Random.generate().unwrap().secret().clone(); - let secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&secret, &document).unwrap(); - let generated_key = key_servers[0] - .generate_document_key(&document, &signature.clone().into(), *threshold) - .unwrap(); - let generated_key = - crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &generated_key).unwrap(); - - // now let's try to retrieve key back - for (i, key_server) in key_servers.iter().enumerate() { - let retrieved_key = key_server - .restore_document_key(&document, &signature.clone().into()) - .unwrap(); - let retrieved_key = - crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &retrieved_key).unwrap(); - assert_eq!(retrieved_key, generated_key); - - let key_share = key_storages[i].get(&document).unwrap().unwrap(); - assert!(key_share.common_point.is_some()); - assert!(key_share.encrypted_point.is_some()); - } - } - drop(runtime); - } - - #[test] - fn server_key_generation_and_storing_document_key_works_over_network_with_3_nodes() { - let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6090, 3); - - let test_cases = [0, 1, 2]; - for threshold in &test_cases { - // generate server key - let server_key_id = Random.generate().unwrap().secret().clone(); - let requestor_secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&requestor_secret, &server_key_id).unwrap(); - let server_public = key_servers[0] - .generate_key(&server_key_id, &signature.clone().into(), *threshold) - .unwrap(); - - // generate document key (this is done by KS client so that document key is unknown to any KS) - let generated_key = Random.generate().unwrap().public().clone(); - let encrypted_document_key = - math::encrypt_secret(&generated_key, &server_public).unwrap(); - - // store document key - key_servers[0] - .store_document_key( - &server_key_id, - &signature.clone().into(), - encrypted_document_key.common_point, - encrypted_document_key.encrypted_point, - ) - .unwrap(); - - // now let's try to retrieve key back - for key_server in key_servers.iter() { - let retrieved_key = key_server - .restore_document_key(&server_key_id, &signature.clone().into()) - .unwrap(); - let retrieved_key = - crypto::ecies::decrypt(&requestor_secret, &DEFAULT_MAC, &retrieved_key) - .unwrap(); - let retrieved_key = Public::from_slice(&retrieved_key); - assert_eq!(retrieved_key, generated_key); - } - } - drop(runtime); - } - - #[test] - fn server_key_generation_and_message_signing_works_over_network_with_3_nodes() { - let _ = ::env_logger::try_init(); - let (key_servers, _, runtime) = make_key_servers(6100, 3); - - let test_cases = [0, 1, 2]; - for threshold in &test_cases { - // generate server key - let server_key_id = Random.generate().unwrap().secret().clone(); - let requestor_secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&requestor_secret, &server_key_id).unwrap(); - let server_public = key_servers[0] - .generate_key(&server_key_id, &signature.clone().into(), *threshold) - .unwrap(); - - // sign message - let message_hash = H256::from(42); - let combined_signature = key_servers[0] - .sign_message_schnorr(&server_key_id, &signature.into(), message_hash.clone()) - .unwrap(); - let combined_signature = - crypto::ecies::decrypt(&requestor_secret, &DEFAULT_MAC, &combined_signature) - .unwrap(); - let signature_c = Secret::from_slice(&combined_signature[..32]).unwrap(); - let signature_s = Secret::from_slice(&combined_signature[32..]).unwrap(); - - // check signature - assert_eq!( - math::verify_schnorr_signature( - &server_public, - &(signature_c, signature_s), - &message_hash - ), - Ok(true) - ); - } - drop(runtime); - } - - #[test] - fn decryption_session_is_delegated_when_node_does_not_have_key_share() { - let _ = ::env_logger::try_init(); - let (key_servers, key_storages, runtime) = make_key_servers(6110, 3); - - // generate document key - let threshold = 0; - let document = Random.generate().unwrap().secret().clone(); - let secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&secret, &document).unwrap(); - let generated_key = key_servers[0] - .generate_document_key(&document, &signature.clone().into(), threshold) - .unwrap(); - let generated_key = crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &generated_key).unwrap(); - - // remove key from node0 - key_storages[0].remove(&document).unwrap(); - - // now let's try to retrieve key back by requesting it from node0, so that session must be delegated - let retrieved_key = key_servers[0] - .restore_document_key(&document, &signature.into()) - .unwrap(); - let retrieved_key = crypto::ecies::decrypt(&secret, &DEFAULT_MAC, &retrieved_key).unwrap(); - assert_eq!(retrieved_key, generated_key); - drop(runtime); - } - - #[test] - fn schnorr_signing_session_is_delegated_when_node_does_not_have_key_share() { - let _ = ::env_logger::try_init(); - let (key_servers, key_storages, runtime) = make_key_servers(6114, 3); - let threshold = 1; - - // generate server key - let server_key_id = Random.generate().unwrap().secret().clone(); - let requestor_secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&requestor_secret, &server_key_id).unwrap(); - let server_public = key_servers[0] - .generate_key(&server_key_id, &signature.clone().into(), threshold) - .unwrap(); - - // remove key from node0 - key_storages[0].remove(&server_key_id).unwrap(); - - // sign message - let message_hash = H256::from(42); - let combined_signature = key_servers[0] - .sign_message_schnorr(&server_key_id, &signature.into(), message_hash.clone()) - .unwrap(); - let combined_signature = - crypto::ecies::decrypt(&requestor_secret, &DEFAULT_MAC, &combined_signature).unwrap(); - let signature_c = Secret::from_slice(&combined_signature[..32]).unwrap(); - let signature_s = Secret::from_slice(&combined_signature[32..]).unwrap(); - - // check signature - assert_eq!( - math::verify_schnorr_signature( - &server_public, - &(signature_c, signature_s), - &message_hash - ), - Ok(true) - ); - drop(runtime); - } - - #[test] - fn ecdsa_signing_session_is_delegated_when_node_does_not_have_key_share() { - let _ = ::env_logger::try_init(); - let (key_servers, key_storages, runtime) = make_key_servers(6117, 4); - let threshold = 1; - - // generate server key - let server_key_id = Random.generate().unwrap().secret().clone(); - let requestor_secret = Random.generate().unwrap().secret().clone(); - let signature = ethkey::sign(&requestor_secret, &server_key_id).unwrap(); - let server_public = key_servers[0] - .generate_key(&server_key_id, &signature.clone().into(), threshold) - .unwrap(); - - // remove key from node0 - key_storages[0].remove(&server_key_id).unwrap(); - - // sign message - let message_hash = H256::random(); - let signature = key_servers[0] - .sign_message_ecdsa(&server_key_id, &signature.into(), message_hash.clone()) - .unwrap(); - let signature = - crypto::ecies::decrypt(&requestor_secret, &DEFAULT_MAC, &signature).unwrap(); - let signature: H520 = signature[0..65].into(); - - // check signature - assert!(verify_public(&server_public, &signature.into(), &message_hash).unwrap()); - drop(runtime); - } - - #[test] - fn servers_set_change_session_works_over_network() { - // TODO [Test] - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs b/secret-store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs deleted file mode 100644 index 442600a065..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs +++ /dev/null @@ -1,1258 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::Secret; -use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::Cluster, - cluster_sessions::{ClusterSession, SessionIdWithSubSession}, - decryption_session::SessionImpl as DecryptionSession, - message::{ - CommonKeyData, FailedKeyVersionContinueAction, KeyVersionNegotiationMessage, KeyVersions, - KeyVersionsError, Message, RequestKeyVersions, - }, - signing_session_ecdsa::SessionImpl as EcdsaSigningSession, - signing_session_schnorr::SessionImpl as SchnorrSigningSession, - DocumentKeyShare, Error, NodeId, SessionId, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -// TODO [Opt]: change sessions so that versions are sent by chunks. -/// Number of versions sent in single message. -const VERSIONS_PER_MESSAGE: usize = 32; - -/// Key version negotiation transport. -pub trait SessionTransport { - /// Broadcast message to all nodes. - fn broadcast(&self, message: KeyVersionNegotiationMessage) -> Result<(), Error>; - /// Send message to given node. - fn send(&self, node: &NodeId, message: KeyVersionNegotiationMessage) -> Result<(), Error>; -} - -/// Key version negotiation result computer. -pub trait SessionResultComputer: Send + Sync { - /// Compute result of session, if possible. - fn compute_result( - &self, - threshold: Option, - confirmations: &BTreeSet, - versions: &BTreeMap>, - ) -> Option>; -} - -/// Key discovery session API. -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex, -} - -/// Action after key version is negotiated. -#[derive(Clone)] -pub enum ContinueAction { - /// Decryption session + origin + is_shadow_decryption + is_broadcast_decryption. - Decrypt(Arc, Option
, bool, bool), - /// Schnorr signing session + message hash. - SchnorrSign(Arc, H256), - /// ECDSA signing session + message hash. - EcdsaSign(Arc, H256), -} - -/// Failed action after key version is negotiated. -#[derive(Clone, Debug, PartialEq)] -pub enum FailedContinueAction { - /// Decryption origin + requester. - Decrypt(Option
, Address), -} - -/// Immutable session data. -struct SessionCore { - /// Session meta. - pub meta: ShareChangeSessionMeta, - /// Sub-session id. - pub sub_session: Secret, - /// Key share. - pub key_share: Option, - /// Session result computer. - pub result_computer: Arc, - /// Session transport. - pub transport: T, - /// Session nonce. - pub nonce: u64, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Mutable session data. -struct SessionData { - /// Session state. - pub state: SessionState, - /// Initialization confirmations. - pub confirmations: Option>, - /// Common key data that nodes have agreed upon. - pub key_share: Option, - /// { Version => Nodes } - pub versions: Option>>, - /// Session result. - pub result: Option, Error>>, - /// Continue action. - pub continue_with: Option, - /// Failed continue action (reported in error message by master node). - pub failed_continue_with: Option, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// Session meta. - pub meta: ShareChangeSessionMeta, - /// Sub-session id. - pub sub_session: Secret, - /// Key share. - pub key_share: Option, - /// Session result computer. - pub result_computer: Arc, - /// Session transport to communicate to other cluster nodes. - pub transport: T, - /// Session nonce. - pub nonce: u64, -} - -/// Signing session state. -#[derive(Debug, PartialEq)] -enum SessionState { - /// Waiting for initialization. - WaitingForInitialization, - /// Waiting for responses. - WaitingForResponses, - /// Session is completed. - Finished, -} - -/// Isolated session transport. -pub struct IsolatedSessionTransport { - /// Cluster. - pub cluster: Arc, - /// Key id. - pub key_id: SessionId, - /// Sub session id. - pub sub_session: Secret, - /// Session-level nonce. - pub nonce: u64, -} - -/// Fastest session result computer. Computes first possible version that can be recovered on this node. -/// If there's no such version, selects version with the most support. -pub struct FastestResultComputer { - /// This node id. - self_node_id: NodeId, - /// Threshold (if known). - threshold: Option, - /// Count of all configured key server nodes. - configured_nodes_count: usize, - /// Count of all connected key server nodes. - connected_nodes_count: usize, -} - -/// Selects version with most support, waiting for responses from all nodes. -pub struct LargestSupportResultComputer; - -impl SessionImpl -where - T: SessionTransport, -{ - /// Create new session. - pub fn new(params: SessionParams) -> Self { - SessionImpl { - core: SessionCore { - meta: params.meta, - sub_session: params.sub_session, - key_share: params.key_share.clone(), - result_computer: params.result_computer, - transport: params.transport, - nonce: params.nonce, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - state: SessionState::WaitingForInitialization, - confirmations: None, - key_share: params.key_share.map(|key_share| DocumentKeyShare { - threshold: key_share.threshold, - author: key_share.author, - public: key_share.public, - ..Default::default() - }), - versions: None, - result: None, - continue_with: None, - failed_continue_with: None, - }), - } - } - - /// Return session meta. - pub fn meta(&self) -> &ShareChangeSessionMeta { - &self.core.meta - } - - /// Return result computer reference. - pub fn version_holders(&self, version: &H256) -> Result, Error> { - Ok(self - .data - .lock() - .versions - .as_ref() - .ok_or(Error::InvalidStateForRequest)? - .get(version) - .ok_or(Error::ServerKeyIsNotFound)? - .clone()) - } - - /// Set continue action. - pub fn set_continue_action(&self, action: ContinueAction) { - self.data.lock().continue_with = Some(action); - } - - /// Take continue action. - pub fn take_continue_action(&self) -> Option { - self.data.lock().continue_with.take() - } - - /// Take failed continue action. - pub fn take_failed_continue_action(&self) -> Option { - self.data.lock().failed_continue_with.take() - } - - /// Wait for session completion. - pub fn wait(&self) -> Result, Error> { - Self::wait_session(&self.core.completed, &self.data, None, |data| { - data.result.clone() - }) - .expect("wait_session returns Some if called without timeout; qed") - } - - /// Retrieve common key data (author, threshold, public), if available. - pub fn common_key_data(&self) -> Result { - self.data - .lock() - .key_share - .clone() - .ok_or(Error::InvalidStateForRequest) - } - - /// Initialize session. - pub fn initialize(&self, connected_nodes: BTreeSet) -> Result<(), Error> { - // check state - let mut data = self.data.lock(); - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // update state - let mut confirmations = connected_nodes; - let mut versions: BTreeMap> = BTreeMap::new(); - let received_own_confirmation = confirmations.remove(&self.core.meta.self_node_id); - if received_own_confirmation { - if let Some(key_share) = self.core.key_share.as_ref() { - for version in &key_share.versions { - versions - .entry(version.hash.clone()) - .or_insert_with(Default::default) - .insert(self.core.meta.self_node_id.clone()); - } - } - } - - // update state - let no_confirmations_required = confirmations.is_empty(); - data.state = SessionState::WaitingForResponses; - data.confirmations = Some(confirmations); - data.versions = Some(versions); - - // try to complete session - Self::try_complete(&self.core, &mut *data); - if no_confirmations_required && data.state != SessionState::Finished { - return Err(Error::ServerKeyIsNotFound); - } else if data.state == SessionState::Finished { - return Ok(()); - } - - // send requests - let confirmations = data - .confirmations - .as_ref() - .expect("dilled couple of lines above; qed"); - for connected_node in confirmations { - self.core.transport.send( - connected_node, - KeyVersionNegotiationMessage::RequestKeyVersions(RequestKeyVersions { - session: self.core.meta.id.clone().into(), - sub_session: self.core.sub_session.clone().into(), - session_nonce: self.core.nonce, - }), - )?; - } - - Ok(()) - } - - /// Process single message. - pub fn process_message( - &self, - sender: &NodeId, - message: &KeyVersionNegotiationMessage, - ) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &KeyVersionNegotiationMessage::RequestKeyVersions(ref message) => { - self.on_key_versions_request(sender, message) - } - &KeyVersionNegotiationMessage::KeyVersions(ref message) => { - self.on_key_versions(sender, message) - } - &KeyVersionNegotiationMessage::KeyVersionsError(ref message) => { - // remember failed continue action - if let Some(FailedKeyVersionContinueAction::Decrypt( - Some(ref origin), - ref requester, - )) = message.continue_with - { - self.data.lock().failed_continue_with = Some(FailedContinueAction::Decrypt( - Some(origin.clone().into()), - requester.clone().into(), - )); - } - - self.on_session_error(sender, message.error.clone()); - Ok(()) - } - } - } - - /// Process key versions request. - pub fn on_key_versions_request( - &self, - sender: &NodeId, - _message: &RequestKeyVersions, - ) -> Result<(), Error> { - debug_assert!(sender != &self.core.meta.self_node_id); - - // check message - if *sender != self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // send response - self.core.transport.send( - sender, - KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: self.core.meta.id.clone().into(), - sub_session: self.core.sub_session.clone().into(), - session_nonce: self.core.nonce, - key_common: self.core.key_share.as_ref().map(|key_share| CommonKeyData { - threshold: key_share.threshold, - author: key_share.author.into(), - public: key_share.public.into(), - }), - versions: self - .core - .key_share - .as_ref() - .map(|key_share| { - key_share - .versions - .iter() - .rev() - .filter(|v| v.id_numbers.contains_key(sender)) - .chain( - key_share - .versions - .iter() - .rev() - .filter(|v| !v.id_numbers.contains_key(sender)), - ) - .map(|v| v.hash.clone().into()) - .take(VERSIONS_PER_MESSAGE) - .collect() - }) - .unwrap_or_else(|| Default::default()), - }), - )?; - - // update state - data.state = SessionState::Finished; - data.result = Some(Ok(None)); - self.core.completed.notify_all(); - - Ok(()) - } - - /// Process key versions response. - pub fn on_key_versions(&self, sender: &NodeId, message: &KeyVersions) -> Result<(), Error> { - debug_assert!(sender != &self.core.meta.self_node_id); - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::WaitingForResponses && data.state != SessionState::Finished { - return Err(Error::InvalidStateForRequest); - } - let reason = "this field is filled on master node when initializing; this is initialized master node; qed"; - if !data.confirmations.as_mut().expect(reason).remove(sender) { - return Err(Error::InvalidMessage); - } - - // remember versions that sender have - { - match message.key_common.as_ref() { - Some(key_common) if data.key_share.is_none() => { - data.key_share = Some(DocumentKeyShare { - threshold: key_common.threshold, - author: key_common.author.clone().into(), - public: key_common.public.clone().into(), - ..Default::default() - }); - } - Some(key_common) => { - let prev_key_share = data - .key_share - .as_ref() - .expect("data.key_share.is_none() is matched by previous branch; qed"); - if prev_key_share.threshold != key_common.threshold - || prev_key_share.author[..] != key_common.author[..] - || prev_key_share.public[..] != key_common.public[..] - { - return Err(Error::InvalidMessage); - } - } - None if message.versions.is_empty() => (), - None => return Err(Error::InvalidMessage), - } - - let versions = data.versions.as_mut().expect(reason); - for version in &message.versions { - versions - .entry(version.clone().into()) - .or_insert_with(Default::default) - .insert(sender.clone()); - } - } - - // try to compute result - if data.state != SessionState::Finished { - Self::try_complete(&self.core, &mut *data); - } - - Ok(()) - } - - /// Try to complete result && finish session. - fn try_complete(core: &SessionCore, data: &mut SessionData) { - let reason = "this field is filled on master node when initializing; try_complete is only called on initialized master node; qed"; - let confirmations = data.confirmations.as_ref().expect(reason); - let versions = data.versions.as_ref().expect(reason); - let threshold = data.key_share.as_ref().map(|key_share| key_share.threshold); - if let Some(result) = - core.result_computer - .compute_result(threshold, confirmations, versions) - { - // when the master node processing decryption service request, it starts with a key version negotiation session - // if the negotiation fails, only master node knows about it - // => if the error is fatal, only the master will know about it and report it to the contract && the request will never be rejected - // => let's broadcast fatal error so that every other node know about it, and, if it trusts to master node - // will report error to the contract - if let (Some(continue_with), Err(error)) = - (data.continue_with.as_ref(), result.as_ref()) - { - let origin = match *continue_with { - ContinueAction::Decrypt(_, origin, _, _) => origin.clone(), - _ => None, - }; - - let requester = match *continue_with { - ContinueAction::Decrypt(ref session, _, _, _) => session - .requester() - .and_then(|r| r.address(&core.meta.id).ok()), - _ => None, - }; - - if origin.is_some() && requester.is_some() && !error.is_non_fatal() { - let requester = requester.expect("checked in above condition; qed"); - data.failed_continue_with = Some(FailedContinueAction::Decrypt( - origin.clone(), - requester.clone(), - )); - - let send_result = - core.transport - .broadcast(KeyVersionNegotiationMessage::KeyVersionsError( - KeyVersionsError { - session: core.meta.id.clone().into(), - sub_session: core.sub_session.clone().into(), - session_nonce: core.nonce, - error: error.clone(), - continue_with: Some(FailedKeyVersionContinueAction::Decrypt( - origin.map(Into::into), - requester.into(), - )), - }, - )); - - if let Err(send_error) = send_result { - warn!(target: "secretstore_net", "{}: failed to broadcast key version negotiation error {}: {}", - core.meta.self_node_id, error, send_error); - } - } - } - - data.state = SessionState::Finished; - data.result = Some(result.map(Some)); - core.completed.notify_all(); - } - } -} - -impl ClusterSession for SessionImpl -where - T: SessionTransport, -{ - type Id = SessionIdWithSubSession; - - fn type_name() -> &'static str { - "version negotiation" - } - - fn id(&self) -> SessionIdWithSubSession { - SessionIdWithSubSession::new(self.core.meta.id.clone(), self.core.sub_session.clone()) - } - - fn is_finished(&self) -> bool { - self.data.lock().state == SessionState::Finished - } - - fn on_session_timeout(&self) { - let mut data = self.data.lock(); - - if data.confirmations.is_some() { - data.confirmations - .as_mut() - .expect("checked a line above; qed") - .clear(); - Self::try_complete(&self.core, &mut *data); - if data.state != SessionState::Finished { - warn!(target: "secretstore_net", "{}: key version negotiation session failed with timeout", self.core.meta.self_node_id); - - data.result = Some(Err(Error::ConsensusTemporaryUnreachable)); - self.core.completed.notify_all(); - } - } - } - - fn on_node_timeout(&self, node: &NodeId) { - self.on_session_error(node, Error::NodeDisconnected) - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - let mut data = self.data.lock(); - - if data.confirmations.is_some() { - let is_waiting_for_confirmation = data - .confirmations - .as_mut() - .expect("checked a line above; qed") - .remove(node); - if !is_waiting_for_confirmation { - return; - } - - Self::try_complete(&self.core, &mut *data); - if data.state == SessionState::Finished { - return; - } - } - - warn!(target: "secretstore_net", "{}: key version negotiation session failed because of {} from {}", - self.core.meta.self_node_id, error, node); - - data.state = SessionState::Finished; - data.result = Some(Err(error)); - self.core.completed.notify_all(); - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::KeyVersionNegotiation(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl SessionTransport for IsolatedSessionTransport { - fn broadcast(&self, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster - .broadcast(Message::KeyVersionNegotiation(message)) - } - - fn send(&self, node: &NodeId, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster - .send(node, Message::KeyVersionNegotiation(message)) - } -} - -impl FastestResultComputer { - pub fn new( - self_node_id: NodeId, - key_share: Option<&DocumentKeyShare>, - configured_nodes_count: usize, - connected_nodes_count: usize, - ) -> Self { - let threshold = key_share.map(|ks| ks.threshold); - FastestResultComputer { - self_node_id, - threshold, - configured_nodes_count, - connected_nodes_count, - } - } -} - -impl SessionResultComputer for FastestResultComputer { - fn compute_result( - &self, - threshold: Option, - confirmations: &BTreeSet, - versions: &BTreeMap>, - ) -> Option> { - match self.threshold.or(threshold) { - // if there's no versions at all && we're not waiting for confirmations anymore - _ if confirmations.is_empty() && versions.is_empty() => { - Some(Err(Error::ServerKeyIsNotFound)) - } - // if we have key share on this node - Some(threshold) => { - // select version this node have, with enough participants - let has_key_share = self.threshold.is_some(); - let version = versions.iter().find(|&(_, ref n)| { - !has_key_share || n.contains(&self.self_node_id) && n.len() >= threshold + 1 - }); - // if there's no such version, wait for more confirmations - match version { - Some((version, nodes)) => Some(Ok(( - version.clone(), - if has_key_share { - self.self_node_id.clone() - } else { - nodes.iter().cloned().nth(0).expect( - "version is only inserted when there's at least one owner; qed", - ) - }, - ))), - None if !confirmations.is_empty() => None, - // otherwise - try to find any version - None => Some( - versions - .iter() - .find(|&(_, ref n)| n.len() >= threshold + 1) - .map(|(version, nodes)| { - Ok((version.clone(), nodes.iter().cloned().nth(0) - .expect("version is only inserted when there's at least one owner; qed"))) - }) - // if there's no version consensus among all connected nodes - // AND we're connected to ALL configured nodes - // OR there are less than required nodes for key restore - // => this means that we can't restore key with CURRENT configuration => respond with fatal error - // otherwise we could try later, after all nodes are connected - .unwrap_or_else(|| { - Err( - if self.configured_nodes_count == self.connected_nodes_count - || self.configured_nodes_count < threshold + 1 - { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - }, - ) - }), - ), - } - } - // if we do not have share, then wait for all confirmations - None if !confirmations.is_empty() => None, - // ...and select version with largest support - None => Some( - versions - .iter() - .max_by_key(|&(_, ref n)| n.len()) - .map(|(version, nodes)| { - Ok(( - version.clone(), - nodes.iter().cloned().nth(0).expect( - "version is only inserted when there's at least one owner; qed", - ), - )) - }) - .unwrap_or_else(|| { - Err( - if self.configured_nodes_count == self.connected_nodes_count { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - }, - ) - }), - ), - } - } -} - -impl SessionResultComputer for LargestSupportResultComputer { - fn compute_result( - &self, - _threshold: Option, - confirmations: &BTreeSet, - versions: &BTreeMap>, - ) -> Option> { - if !confirmations.is_empty() { - return None; - } - if versions.is_empty() { - return Some(Err(Error::ServerKeyIsNotFound)); - } - - versions - .iter() - .max_by_key(|&(_, ref n)| n.len()) - .map(|(version, nodes)| { - Ok(( - version.clone(), - nodes - .iter() - .cloned() - .nth(0) - .expect("version is only inserted when there's at least one owner; qed"), - )) - }) - } -} - -#[cfg(test)] -mod tests { - use super::{ - ContinueAction, FailedContinueAction, FastestResultComputer, LargestSupportResultComputer, - SessionImpl, SessionParams, SessionResultComputer, SessionState, SessionTransport, - }; - use ethereum_types::{H160, H512}; - use ethkey::public_to_address; - use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::{tests::DummyCluster, Cluster}, - cluster_sessions::ClusterSession, - decryption_session::create_default_decryption_session, - math, - message::{ - CommonKeyData, KeyVersionNegotiationMessage, KeyVersions, Message, RequestKeyVersions, - }, - DocumentKeyShare, DocumentKeyShareVersion, DummyKeyStorage, Error, KeyStorage, NodeId, - SessionId, - }; - use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, - sync::Arc, - }; - - struct DummyTransport { - cluster: Arc, - } - - impl SessionTransport for DummyTransport { - fn broadcast(&self, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster - .broadcast(Message::KeyVersionNegotiation(message)) - } - - fn send(&self, node: &NodeId, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster - .send(node, Message::KeyVersionNegotiation(message)) - } - } - - struct Node { - pub cluster: Arc, - pub key_storage: Arc, - pub session: SessionImpl, - } - - struct MessageLoop { - pub session_id: SessionId, - pub nodes: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - } - - impl MessageLoop { - pub fn prepare_nodes(nodes_num: usize) -> BTreeMap> { - (0..nodes_num) - .map(|_| { - ( - math::generate_random_point().unwrap(), - Arc::new(DummyKeyStorage::default()), - ) - }) - .collect() - } - - pub fn empty(nodes_num: usize) -> Self { - Self::new(Self::prepare_nodes(nodes_num)) - } - - pub fn new(nodes: BTreeMap>) -> Self { - let master_node_id = nodes.keys().cloned().nth(0).unwrap(); - let sub_sesion = math::generate_random_scalar().unwrap(); - let all_nodes_ids: BTreeSet<_> = nodes.keys().cloned().collect(); - MessageLoop { - session_id: Default::default(), - nodes: nodes - .iter() - .map(|(node_id, key_storage)| { - let cluster = Arc::new(DummyCluster::new(node_id.clone())); - cluster.add_nodes(all_nodes_ids.iter().cloned()); - ( - node_id.clone(), - Node { - cluster: cluster.clone(), - key_storage: key_storage.clone(), - session: SessionImpl::new(SessionParams { - meta: ShareChangeSessionMeta { - id: Default::default(), - self_node_id: node_id.clone(), - master_node_id: master_node_id.clone(), - configured_nodes_count: nodes.len(), - connected_nodes_count: nodes.len(), - }, - sub_session: sub_sesion.clone(), - key_share: key_storage.get(&Default::default()).unwrap(), - result_computer: Arc::new(FastestResultComputer::new( - node_id.clone(), - key_storage.get(&Default::default()).unwrap().as_ref(), - nodes.len(), - nodes.len(), - )), - transport: DummyTransport { cluster: cluster }, - nonce: 0, - }), - }, - ) - }) - .collect(), - queue: VecDeque::new(), - } - } - - pub fn node_id(&self, idx: usize) -> &NodeId { - self.nodes.keys().nth(idx).unwrap() - } - - pub fn session(&self, idx: usize) -> &SessionImpl { - &self.nodes.values().nth(idx).unwrap().session - } - - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.nodes - .values() - .filter_map(|n| { - n.cluster - .take_message() - .map(|m| (n.session.meta().self_node_id.clone(), m.0, m.1)) - }) - .nth(0) - .or_else(|| self.queue.pop_front()) - } - - pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - match msg.2 { - Message::KeyVersionNegotiation(message) => { - self.nodes[&msg.1].session.process_message(&msg.0, &message) - } - _ => panic!("unexpected"), - } - } - - pub fn run(&mut self) { - while let Some((from, to, message)) = self.take_message() { - self.process_message((from, to, message)).unwrap(); - } - } - } - - #[test] - fn negotiation_fails_if_initialized_twice() { - let ml = MessageLoop::empty(1); - assert_eq!(ml.session(0).initialize(BTreeSet::new()), Ok(())); - assert_eq!( - ml.session(0).initialize(BTreeSet::new()), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn negotiation_fails_if_message_contains_wrong_nonce() { - let ml = MessageLoop::empty(2); - assert_eq!( - ml.session(1).process_message( - ml.node_id(0), - &KeyVersionNegotiationMessage::RequestKeyVersions(RequestKeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 100, - }) - ), - Err(Error::ReplayProtection) - ); - } - - #[test] - fn negotiation_fails_if_versions_request_received_from_non_master() { - let ml = MessageLoop::empty(3); - assert_eq!( - ml.session(2).process_message( - ml.node_id(1), - &KeyVersionNegotiationMessage::RequestKeyVersions(RequestKeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - }) - ), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn negotiation_fails_if_versions_request_received_twice() { - let ml = MessageLoop::empty(2); - assert_eq!( - ml.session(1).process_message( - ml.node_id(0), - &KeyVersionNegotiationMessage::RequestKeyVersions(RequestKeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - }) - ), - Ok(()) - ); - assert_eq!( - ml.session(1).process_message( - ml.node_id(0), - &KeyVersionNegotiationMessage::RequestKeyVersions(RequestKeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - }) - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn negotiation_fails_if_versions_received_before_initialization() { - let ml = MessageLoop::empty(2); - assert_eq!( - ml.session(1).process_message( - ml.node_id(0), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: Some(CommonKeyData { - threshold: 10, - author: Default::default(), - public: Default::default(), - }), - versions: Vec::new(), - }) - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn negotiation_does_not_fails_if_versions_received_after_completion() { - let ml = MessageLoop::empty(3); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - assert_eq!( - ml.session(0).data.lock().state, - SessionState::WaitingForResponses - ); - - let version_id = (*math::generate_random_scalar().unwrap()).clone(); - assert_eq!( - ml.session(0).process_message( - ml.node_id(1), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: Some(CommonKeyData { - threshold: 0, - author: Default::default(), - public: Default::default(), - }), - - versions: vec![version_id.clone().into()] - }) - ), - Ok(()) - ); - assert_eq!(ml.session(0).data.lock().state, SessionState::Finished); - - assert_eq!( - ml.session(0).process_message( - ml.node_id(2), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: Some(CommonKeyData { - threshold: 0, - author: Default::default(), - public: Default::default(), - }), - - versions: vec![version_id.clone().into()] - }) - ), - Ok(()) - ); - assert_eq!(ml.session(0).data.lock().state, SessionState::Finished); - } - - #[test] - fn negotiation_fails_if_wrong_common_data_sent() { - fn run_test(key_common: CommonKeyData) { - let ml = MessageLoop::empty(3); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - - let version_id = (*math::generate_random_scalar().unwrap()).clone(); - assert_eq!( - ml.session(0).process_message( - ml.node_id(1), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: Some(CommonKeyData { - threshold: 1, - author: Default::default(), - public: Default::default(), - }), - versions: vec![version_id.clone().into()] - }) - ), - Ok(()) - ); - assert_eq!( - ml.session(0).process_message( - ml.node_id(2), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: Some(key_common), - versions: vec![version_id.clone().into()] - }) - ), - Err(Error::InvalidMessage) - ); - } - - run_test(CommonKeyData { - threshold: 2, - author: Default::default(), - public: Default::default(), - }); - - run_test(CommonKeyData { - threshold: 1, - author: H160::from(1).into(), - public: Default::default(), - }); - - run_test(CommonKeyData { - threshold: 1, - author: H160::from(2).into(), - public: Default::default(), - }); - } - - #[test] - fn negotiation_fails_if_threshold_empty_when_versions_are_not_empty() { - let ml = MessageLoop::empty(2); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - - let version_id = (*math::generate_random_scalar().unwrap()).clone(); - assert_eq!( - ml.session(0).process_message( - ml.node_id(1), - &KeyVersionNegotiationMessage::KeyVersions(KeyVersions { - session: Default::default(), - sub_session: math::generate_random_scalar().unwrap().into(), - session_nonce: 0, - key_common: None, - versions: vec![version_id.clone().into()] - }) - ), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn fast_negotiation_does_not_completes_instantly_when_enough_share_owners_are_connected() { - let nodes = MessageLoop::prepare_nodes(2); - let version_id = (*math::generate_random_scalar().unwrap()).clone(); - nodes - .values() - .nth(0) - .unwrap() - .insert( - Default::default(), - DocumentKeyShare { - author: H160::from(2), - threshold: 1, - public: H512::from(3), - common_point: None, - encrypted_point: None, - versions: vec![DocumentKeyShareVersion { - hash: version_id, - id_numbers: vec![( - nodes.keys().cloned().nth(0).unwrap(), - math::generate_random_scalar().unwrap(), - )] - .into_iter() - .collect(), - secret_share: math::generate_random_scalar().unwrap(), - }], - }, - ) - .unwrap(); - let ml = MessageLoop::new(nodes); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - // we can't be sure that node has given key version because previous ShareAdd session could fail - assert!(ml.session(0).data.lock().state != SessionState::Finished); - - // check that upon completion, commmon key data is known - assert_eq!( - ml.session(0).common_key_data(), - Ok(DocumentKeyShare { - author: H160::from(2), - threshold: 1, - public: H512::from(3), - ..Default::default() - }) - ); - } - - #[test] - fn fastest_computer_returns_missing_share_if_no_versions_returned() { - let computer = FastestResultComputer { - self_node_id: Default::default(), - threshold: None, - configured_nodes_count: 1, - connected_nodes_count: 1, - }; - assert_eq!( - computer.compute_result(Some(10), &Default::default(), &Default::default()), - Some(Err(Error::ServerKeyIsNotFound)) - ); - } - - #[test] - fn largest_computer_returns_missing_share_if_no_versions_returned() { - let computer = LargestSupportResultComputer; - assert_eq!( - computer.compute_result(Some(10), &Default::default(), &Default::default()), - Some(Err(Error::ServerKeyIsNotFound)) - ); - } - - #[test] - fn fatal_error_is_not_broadcasted_if_started_without_origin() { - let mut ml = MessageLoop::empty(3); - ml.session(0).set_continue_action(ContinueAction::Decrypt( - create_default_decryption_session(), - None, - false, - false, - )); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - ml.run(); - - assert!(ml - .nodes - .values() - .all(|n| n.session.is_finished() && n.session.take_failed_continue_action().is_none())); - } - - #[test] - fn fatal_error_is_broadcasted_if_started_with_origin() { - let mut ml = MessageLoop::empty(3); - ml.session(0).set_continue_action(ContinueAction::Decrypt( - create_default_decryption_session(), - Some(1.into()), - true, - true, - )); - ml.session(0) - .initialize(ml.nodes.keys().cloned().collect()) - .unwrap(); - ml.run(); - - // on all nodes session is completed - assert!(ml.nodes.values().all(|n| n.session.is_finished())); - - // slave nodes have non-empty failed continue action - assert!(ml - .nodes - .values() - .skip(1) - .all(|n| n.session.take_failed_continue_action() - == Some(FailedContinueAction::Decrypt( - Some(1.into()), - public_to_address(&2.into()) - )))); - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/mod.rs b/secret-store/src/key_server_cluster/admin_sessions/mod.rs deleted file mode 100644 index a7daa73a60..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/mod.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -pub mod key_version_negotiation_session; -pub mod servers_set_change_session; -pub mod share_add_session; -pub mod share_change_session; - -mod sessions_queue; - -use key_server_cluster::{Error, NodeId, SessionId, SessionMeta}; - -/// Share change session metadata. -#[derive(Debug, Clone)] -pub struct ShareChangeSessionMeta { - /// Key id. - pub id: SessionId, - /// Id of node, which has started this session. - pub master_node_id: NodeId, - /// Id of node, on which this session is running. - pub self_node_id: NodeId, - /// Count of all configured key server nodes. - pub configured_nodes_count: usize, - /// Count of all connected key server nodes. - pub connected_nodes_count: usize, -} - -impl ShareChangeSessionMeta { - /// Convert to consensus session meta. `all_nodes_set` is the union of `old_nodes_set` && `new_nodes_set`. - pub fn into_consensus_meta(self, all_nodes_set_len: usize) -> Result { - Ok(SessionMeta { - id: self.id, - master_node_id: self.master_node_id, - self_node_id: self.self_node_id, - threshold: all_nodes_set_len - .checked_sub(1) - .ok_or(Error::ConsensusUnreachable)?, - configured_nodes_count: self.configured_nodes_count, - connected_nodes_count: self.connected_nodes_count, - }) - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs deleted file mode 100644 index 26b689e925..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ /dev/null @@ -1,1832 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{Public, Signature}; -use key_server_cluster::{ - admin_sessions::{sessions_queue::SessionsQueue, ShareChangeSessionMeta}, - cluster::Cluster, - cluster_sessions::ClusterSession, - jobs::{ - consensus_session::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}, - job_session::JobTransport, - servers_set_change_access_job::{ServersSetChangeAccessJob, ServersSetChangeAccessRequest}, - unknown_sessions_job::UnknownSessionsJob, - }, - key_version_negotiation_session::{ - LargestSupportResultComputer, SessionImpl as KeyVersionNegotiationSessionImpl, - SessionParams as KeyVersionNegotiationSessionParams, - SessionTransport as KeyVersionNegotiationTransport, - }, - math, - message::{ - ConfirmConsensusInitialization, ConfirmShareChangeSessionInitialization, - ConsensusMessageWithServersSet, InitializeConsensusSessionWithServersSet, - InitializeShareChangeSession, KeyVersionNegotiationMessage, Message, - ServersSetChangeCompleted, ServersSetChangeConsensusMessage, ServersSetChangeDelegate, - ServersSetChangeDelegateResponse, ServersSetChangeError, ServersSetChangeMessage, - ServersSetChangeShareAddMessage, ShareChangeKeyVersionNegotiation, UnknownSessions, - UnknownSessionsRequest, - }, - share_change_session::{ - prepare_share_change_session_plan, ShareChangeSession, ShareChangeSessionParams, - ShareChangeSessionPlan, - }, - Error, KeyStorage, NodeId, SessionId, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{btree_map::Entry, BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Maximal number of active share change sessions. -const MAX_ACTIVE_KEY_SESSIONS: usize = 64; - -/// Servers set change session. -/// Brief overview: -/// 1) consensus establishing -/// 2) master node requests all other nodes for sessions he is not participating (aka unknown sessions) -/// 3) every slave node responds with sessions id => we are able to collect Map of unknown sessions on master -/// 4) for every known session (i.e. session that master participates in): -/// 4.1) share change plan is created = nodes to add shares for, nodes to move shares from/to, nodes to remove shares from -/// 4.2) share change session is started. Share change session = sequential execution of ShareAdd, then ShareMove && then ShareRemove sessions (order matters here) for single key -/// 5) for every unknown session: -/// 5.1) sub_master is selected from sessions participants -/// 5.2) share change session is delegated from master to this sub_master -/// 5.3) share change session is executed by this sub_master -/// 5.4) share change confirm is sent from sub_master to master -/// 6) upon completing all known share change sessions && receiving confirmations for all unknown share change sessions, session completion signal is sent to all slave nodes && session is completed -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex, -} - -/// Session state. -#[derive(Debug, PartialEq)] -enum SessionState { - /// Establishing consensus. - EstablishingConsensus, - /// Running share change sessions. - RunningShareChangeSessions, - /// Session is completed. - Finished, -} - -/// Immutable session data. -struct SessionCore { - /// Servers set change session meta (id is computed from new_nodes_set). - pub meta: ShareChangeSessionMeta, - /// Cluster which allows this node to send messages to other nodes in the cluster. - pub cluster: Arc, - /// Keys storage. - pub key_storage: Arc, - /// Session-level nonce. - pub nonce: u64, - /// All known nodes. - pub all_nodes_set: BTreeSet, - /// Administrator public key. - pub admin_public: Public, - /// Migration id (if this session is a part of auto-migration process). - pub migration_id: Option, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Servers set change consensus session type. -type ServersSetChangeConsensusSession = ConsensusSession< - ServersSetChangeAccessJob, - ServersSetChangeConsensusTransport, - UnknownSessionsJob, - UnknownSessionsJobTransport, ->; - -/// Mutable session data. -struct SessionData { - /// Session state. - pub state: SessionState, - /// Consensus-based servers set change session. - pub consensus_session: Option, - /// New nodes set. - pub new_nodes_set: Option>, - /// Share change sessions queue (valid on master nodes only). - pub sessions_queue: Option, - /// Share change sessions key version negotiation. - pub negotiation_sessions: BTreeMap< - SessionId, - KeyVersionNegotiationSessionImpl, - >, - /// Share change sessions initialization state (valid on master nodes only). - pub sessions_initialization_state: BTreeMap, - /// Sessions delegated to other nodes (valid on master node only). - pub delegated_key_sessions: BTreeMap, - /// Active share change sessions. - pub active_key_sessions: BTreeMap, - /// Servers set change result. - pub result: Option>, -} - -/// Session initialization data. -struct SessionInitializationData { - /// Master node id. - pub master: NodeId, - /// Nodes that have confirmed session initialization request. - pub confirmations: BTreeSet, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// Session meta (artificial). - pub meta: ShareChangeSessionMeta, - /// Cluster. - pub cluster: Arc, - /// Keys storage. - pub key_storage: Arc, - /// Session nonce. - pub nonce: u64, - /// All known nodes. - pub all_nodes_set: BTreeSet, - /// Administrator public key. - pub admin_public: Public, - /// Migration id (if this session is a part of auto-migration process). - pub migration_id: Option, -} - -/// Servers set change consensus transport. -struct ServersSetChangeConsensusTransport { - /// Session id. - id: SessionId, - /// Session-level nonce. - nonce: u64, - /// Migration id (if part of auto-migration process). - migration_id: Option, - /// Cluster. - cluster: Arc, -} - -/// Unknown sessions job transport. -struct UnknownSessionsJobTransport { - /// Session id. - id: SessionId, - /// Session-level nonce. - nonce: u64, - /// Cluster. - cluster: Arc, -} - -/// Key version negotiation transport. -struct ServersSetChangeKeyVersionNegotiationTransport { - /// Session id. - id: SessionId, - /// Session-level nonce. - nonce: u64, - /// Cluster. - cluster: Arc, -} - -impl SessionImpl { - /// Create new servers set change session. - pub fn new(params: SessionParams) -> Result { - Ok(SessionImpl { - core: SessionCore { - meta: params.meta, - cluster: params.cluster, - key_storage: params.key_storage, - nonce: params.nonce, - all_nodes_set: params.all_nodes_set, - admin_public: params.admin_public, - migration_id: params.migration_id, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - state: SessionState::EstablishingConsensus, - consensus_session: None, - new_nodes_set: None, - sessions_queue: None, - negotiation_sessions: BTreeMap::new(), - sessions_initialization_state: BTreeMap::new(), - delegated_key_sessions: BTreeMap::new(), - active_key_sessions: BTreeMap::new(), - result: None, - }), - }) - } - - /// Get session id. - pub fn id(&self) -> &SessionId { - &self.core.meta.id - } - - /// Get migration id. - pub fn migration_id(&self) -> Option<&H256> { - self.core.migration_id.as_ref() - } - - /// Wait for session completion. - pub fn wait(&self) -> Result<(), Error> { - Self::wait_session(&self.core.completed, &self.data, None, |data| { - data.result.clone() - }) - .expect("wait_session returns Some if called without timeout; qed") - } - - /// Initialize servers set change session on master node. - pub fn initialize( - &self, - new_nodes_set: BTreeSet, - all_set_signature: Signature, - new_set_signature: Signature, - ) -> Result<(), Error> { - check_nodes_set(&self.core.all_nodes_set, &new_nodes_set)?; - - let mut data = self.data.lock(); - if data.state != SessionState::EstablishingConsensus || data.consensus_session.is_some() { - return Err(Error::InvalidStateForRequest); - } - - let mut consensus_session = ConsensusSession::new(ConsensusSessionParams { - meta: self - .core - .meta - .clone() - .into_consensus_meta(self.core.all_nodes_set.len())?, - consensus_executor: ServersSetChangeAccessJob::new_on_master( - self.core.admin_public.clone(), - self.core.all_nodes_set.clone(), - new_nodes_set.clone(), - all_set_signature, - new_set_signature, - ), - consensus_transport: ServersSetChangeConsensusTransport { - id: self.core.meta.id.clone(), - nonce: self.core.nonce, - migration_id: self.core.migration_id.clone(), - cluster: self.core.cluster.clone(), - }, - })?; - - consensus_session.initialize(self.core.all_nodes_set.clone())?; - - let is_finished = consensus_session.state() == ConsensusSessionState::ConsensusEstablished; - data.consensus_session = Some(consensus_session); - data.new_nodes_set = Some(new_nodes_set); - - // this is the case when all other nodes are isolated - if is_finished { - Self::complete_session(&self.core, &mut *data)?; - } - - Ok(()) - } - - /// Process servers set change message. - pub fn process_message( - &self, - sender: &NodeId, - message: &ServersSetChangeMessage, - ) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref message) => { - self.on_consensus_message(sender, message) - } - &ServersSetChangeMessage::UnknownSessionsRequest(ref message) => { - self.on_unknown_sessions_requested(sender, message) - } - &ServersSetChangeMessage::UnknownSessions(ref message) => { - self.on_unknown_sessions(sender, message) - } - &ServersSetChangeMessage::ShareChangeKeyVersionNegotiation(ref message) => { - self.on_key_version_negotiation(sender, message) - } - &ServersSetChangeMessage::InitializeShareChangeSession(ref message) => { - self.on_initialize_share_change_session(sender, message) - } - &ServersSetChangeMessage::ConfirmShareChangeSessionInitialization(ref message) => { - self.on_share_change_session_confirmation(sender, message) - } - &ServersSetChangeMessage::ServersSetChangeDelegate(ref message) => { - self.on_sessions_delegation(sender, message) - } - &ServersSetChangeMessage::ServersSetChangeDelegateResponse(ref message) => { - self.on_delegated_session_completed(sender, message) - } - &ServersSetChangeMessage::ServersSetChangeShareAddMessage(ref message) => { - self.on_share_add_message(sender, message) - } - &ServersSetChangeMessage::ServersSetChangeError(ref message) => { - self.on_session_error(sender, message.error.clone()); - Ok(()) - } - &ServersSetChangeMessage::ServersSetChangeCompleted(ref message) => { - self.on_session_completed(sender, message) - } - } - } - - /// When consensus-related message is received. - pub fn on_consensus_message( - &self, - sender: &NodeId, - message: &ServersSetChangeConsensusMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::EstablishingConsensus { - return Err(Error::InvalidStateForRequest); - } - - // start slave consensus session if needed - if self.core.meta.self_node_id != self.core.meta.master_node_id { - if data.consensus_session.is_none() { - match &message.message { - &ConsensusMessageWithServersSet::InitializeConsensusSession(_) => { - data.consensus_session = - Some(ConsensusSession::new(ConsensusSessionParams { - meta: self - .core - .meta - .clone() - .into_consensus_meta(self.core.all_nodes_set.len())?, - consensus_executor: ServersSetChangeAccessJob::new_on_slave( - self.core.admin_public.clone(), - ), - consensus_transport: ServersSetChangeConsensusTransport { - id: self.core.meta.id.clone(), - nonce: self.core.nonce, - migration_id: self.core.migration_id.clone(), - cluster: self.core.cluster.clone(), - }, - })?); - } - _ => return Err(Error::InvalidStateForRequest), - } - } - } - - // process consensus message - let consensus_session = data - .consensus_session - .as_mut() - .ok_or(Error::InvalidMessage)?; - let is_establishing_consensus = - consensus_session.state() == ConsensusSessionState::EstablishingConsensus; - match &message.message { - &ConsensusMessageWithServersSet::InitializeConsensusSession(ref message) => { - consensus_session.on_consensus_partial_request( - sender, - ServersSetChangeAccessRequest::from(message), - )? - } - &ConsensusMessageWithServersSet::ConfirmConsensusInitialization(ref message) => { - consensus_session.on_consensus_partial_response(sender, message.is_confirmed)? - } - } - - // when consensus is established => request unknown sessions - let is_consensus_established = - consensus_session.state() == ConsensusSessionState::ConsensusEstablished; - if self.core.meta.self_node_id != self.core.meta.master_node_id - || !is_establishing_consensus - || !is_consensus_established - { - return Ok(()); - } - - let unknown_sessions_job = UnknownSessionsJob::new_on_master( - self.core.key_storage.clone(), - self.core.meta.self_node_id.clone(), - ); - consensus_session - .disseminate_jobs( - unknown_sessions_job, - self.unknown_sessions_transport(), - false, - ) - .map(|_| ()) - } - - /// When unknown sessions are requested. - pub fn on_unknown_sessions_requested( - &self, - sender: &NodeId, - message: &UnknownSessionsRequest, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - let new_nodes_set = { - let consensus_session = data - .consensus_session - .as_mut() - .ok_or(Error::InvalidMessage)?; - let unknown_sessions_job = - UnknownSessionsJob::new_on_slave(self.core.key_storage.clone()); - let unknown_sessions_transport = self.unknown_sessions_transport(); - - // and respond with unknown sessions - consensus_session.on_job_request( - &sender, - sender.clone(), - unknown_sessions_job, - unknown_sessions_transport, - )?; - - consensus_session.consensus_job().executor() - .new_servers_set() - .expect("consensus session is now completed; new_servers_set is intermediate result of consensus session; qed") - .clone() - }; - - // update state - data.state = SessionState::RunningShareChangeSessions; - data.new_nodes_set = Some(new_nodes_set); - - Ok(()) - } - - /// When unknown sessions are received. - pub fn on_unknown_sessions( - &self, - sender: &NodeId, - message: &UnknownSessions, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::EstablishingConsensus { - return Err(Error::InvalidStateForRequest); - } - - // process message - let unknown_sessions = { - let consensus_session = data - .consensus_session - .as_mut() - .ok_or(Error::InvalidMessage)?; - consensus_session.on_job_response( - sender, - message - .unknown_sessions - .iter() - .cloned() - .map(Into::into) - .collect(), - )?; - if consensus_session.state() != ConsensusSessionState::Finished { - return Ok(()); - } - - // all nodes have reported their unknown sessions - // => we are ready to start adding/moving/removing shares - consensus_session.result()? - }; - - // initialize sessions queue - data.state = SessionState::RunningShareChangeSessions; - data.sessions_queue = Some(SessionsQueue::new( - &self.core.key_storage, - unknown_sessions.keys().cloned().collect(), - )); - - // and disseminate session initialization requests - Self::disseminate_session_initialization_requests(&self.core, &mut *data) - } - - /// When key version negotiation message is received. - pub fn on_key_version_negotiation( - &self, - sender: &NodeId, - message: &ShareChangeKeyVersionNegotiation, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // process message - match &message.message { - &KeyVersionNegotiationMessage::RequestKeyVersions(ref message) - if sender == &self.core.meta.master_node_id => - { - let key_id = message.session.clone().into(); - let key_share = self.core.key_storage.get(&key_id)?; - let negotiation_session = - KeyVersionNegotiationSessionImpl::new(KeyVersionNegotiationSessionParams { - meta: ShareChangeSessionMeta { - id: key_id.clone(), - self_node_id: self.core.meta.self_node_id.clone(), - master_node_id: sender.clone(), - configured_nodes_count: self.core.meta.configured_nodes_count, - connected_nodes_count: self.core.meta.connected_nodes_count, - }, - sub_session: message.sub_session.clone().into(), - key_share: key_share, - result_computer: Arc::new(LargestSupportResultComputer {}), - transport: ServersSetChangeKeyVersionNegotiationTransport { - id: self.core.meta.id.clone(), - nonce: self.core.nonce, - cluster: self.core.cluster.clone(), - }, - nonce: message.session_nonce, - }); - negotiation_session.on_key_versions_request(sender, message)?; - debug_assert!(negotiation_session.is_finished()); - Ok(()) - } - &KeyVersionNegotiationMessage::KeyVersions(ref message) - if self.core.meta.self_node_id == self.core.meta.master_node_id => - { - let key_id = message.session.clone().into(); - { - let negotiation_session = data - .negotiation_sessions - .get(&key_id) - .ok_or(Error::InvalidMessage)?; - negotiation_session.on_key_versions(sender, message)?; - if !negotiation_session.is_finished() { - return Ok(()); - } - } - - // else prepare plan && start share change session - if !Self::initialize_share_change_session(&self.core, &mut *data, key_id)? { - Self::disseminate_session_initialization_requests(&self.core, &mut *data)?; - } - - Ok(()) - } - _ => Err(Error::InvalidMessage), - } - } - - /// When share change session initialization is requested. - pub fn on_initialize_share_change_session( - &self, - sender: &NodeId, - message: &InitializeShareChangeSession, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // we only accept delegation requests from master node - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // insert new session - let key_id = message.key_id.clone().into(); - match data.active_key_sessions.contains_key(&key_id) { - true => return Err(Error::InvalidMessage), - false => { - let master_plan = ShareChangeSessionPlan { - key_version: message.version.clone().into(), - version_holders: message - .version_holders - .iter() - .cloned() - .map(Into::into) - .collect(), - consensus_group: message - .consensus_group - .iter() - .cloned() - .map(Into::into) - .collect(), - new_nodes_map: message - .new_nodes_map - .iter() - .map(|(k, v)| (k.clone().into(), v.clone().map(Into::into))) - .collect(), - }; - - // if master plan is empty, it is cheating - if master_plan.is_empty() { - return Err(Error::InvalidMessage); - } - - // on nodes, holding selected key share version, we could check if master node plan is correct - let master_node_id = message.master_node_id.clone().into(); - if let Some(key_share) = self.core.key_storage.get(&key_id)? { - let version = message.version.clone().into(); - let key_share_owners = message - .version_holders - .iter() - .cloned() - .map(Into::into) - .collect(); - let new_nodes_set = data.new_nodes_set.as_ref() - .expect("new_nodes_set is filled during consensus establishing; change sessions are running after this; qed"); - let local_plan = prepare_share_change_session_plan( - &self.core.all_nodes_set, - key_share.threshold, - &key_id, - version, - &master_node_id, - &key_share_owners, - new_nodes_set, - )?; - - if local_plan.new_nodes_map.keys().collect::>() - != master_plan.new_nodes_map.keys().collect::>() - { - return Err(Error::InvalidMessage); - } - } - - let session = Self::create_share_change_session( - &self.core, - key_id, - master_node_id, - master_plan, - )?; - if !session.is_finished() { - data.active_key_sessions.insert(key_id.clone(), session); - } - } - }; - - // send confirmation - self.core.cluster.send( - sender, - Message::ServersSetChange( - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization( - ConfirmShareChangeSessionInitialization { - session: message.session.clone(), - session_nonce: message.session_nonce.clone(), - key_id: message.key_id.clone(), - }, - ), - ), - ) - } - - /// When share change session initialization is confirmed. - pub fn on_share_change_session_confirmation( - &self, - sender: &NodeId, - message: &ConfirmShareChangeSessionInitialization, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // we only accept delegation requests from master node - if self.core.meta.self_node_id != self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // add confirmation - let key_id = message.key_id.clone().into(); - let session_master = { - let session_init_data = data - .sessions_initialization_state - .get_mut(&key_id) - .ok_or(Error::InvalidMessage)?; - if !session_init_data.confirmations.remove(sender) { - return Err(Error::InvalidMessage); - } - - if !session_init_data.confirmations.is_empty() { - return Ok(()); - } - - session_init_data.master.clone() - }; - - // and start/delegate session if required - data.sessions_initialization_state.remove(&key_id); - if self.core.meta.self_node_id != session_master { - data.delegated_key_sessions - .insert(key_id, session_master.clone()); - return self.core.cluster.send( - &session_master, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegate( - ServersSetChangeDelegate { - session: self.core.meta.id.clone().into(), - session_nonce: self.core.nonce, - key_id: key_id.into(), - }, - )), - ); - } - - // initialize share change session - { - let key_session = data - .active_key_sessions - .get_mut(&key_id) - .ok_or(Error::InvalidMessage)?; - key_session.initialize()?; - if !key_session.is_finished() { - return Ok(()); - } - } - - // complete key session - Self::complete_key_session(&self.core, &mut *data, true, key_id) - } - - /// When sessions execution is delegated to this node. - pub fn on_sessions_delegation( - &self, - sender: &NodeId, - message: &ServersSetChangeDelegate, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // we only accept delegation requests from master node - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // start session - let key_session = data - .active_key_sessions - .get_mut(&message.key_id.clone().into()) - .ok_or(Error::InvalidMessage)?; - key_session.initialize() - } - - /// When delegated session execution is completed. - pub fn on_delegated_session_completed( - &self, - sender: &NodeId, - message: &ServersSetChangeDelegateResponse, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // we only accept delegation requests on master node - if self.core.meta.self_node_id != self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // forget delegated session - let key_id = message.key_id.clone().into(); - match data.delegated_key_sessions.entry(key_id) { - Entry::Occupied(entry) => { - if entry.get() == sender { - entry.remove() - } else { - return Err(Error::InvalidMessage); - } - } - _ => return Err(Error::InvalidMessage), - }; - - // check if we need to complete the whole change session - Self::disseminate_session_initialization_requests(&self.core, &mut *data) - } - - /// When share add message is received. - pub fn on_share_add_message( - &self, - sender: &NodeId, - message: &ServersSetChangeShareAddMessage, - ) -> Result<(), Error> { - self.on_share_change_message(message.message.session_id().clone().into(), |session| { - session.on_share_add_message(sender, &message.message) - }) - } - - /// When session completion message is received. - pub fn on_session_completed( - &self, - sender: &NodeId, - message: &ServersSetChangeCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - let mut data = self.data.lock(); - data.result = Some(Ok(())); - if data.active_key_sessions.len() != 0 { - return Err(Error::TooEarlyForRequest); - } - - // if we are on the set of nodes that are being removed from the cluster, let's clear database - if !data.new_nodes_set.as_ref() - .expect("new_nodes_set is filled during initialization; session is completed after initialization; qed") - .contains(&self.core.meta.self_node_id) { - self.core.key_storage.clear()?; - } - - data.state = SessionState::Finished; - self.core.completed.notify_all(); - - Ok(()) - } - - /// Create unknown sessions transport. - fn unknown_sessions_transport(&self) -> UnknownSessionsJobTransport { - UnknownSessionsJobTransport { - id: self.core.meta.id.clone(), - nonce: self.core.nonce, - cluster: self.core.cluster.clone(), - } - } - - /// When share change message is received. - fn on_share_change_message Result<(), Error>>( - &self, - session_id: SessionId, - message_processor: F, - ) -> Result<(), Error> { - // check state - let mut data = self.data.lock(); - if data.state != SessionState::RunningShareChangeSessions { - return Err(Error::InvalidStateForRequest); - } - - // process message - let (is_finished, is_master) = { - let key_session = data - .active_key_sessions - .get_mut(&session_id) - .ok_or(Error::InvalidMessage)?; - message_processor(key_session)?; - (key_session.is_finished(), key_session.is_master()) - }; - - if is_finished { - Self::complete_key_session(&self.core, &mut *data, is_master, session_id)?; - } - - Ok(()) - } - - /// Create share change session. - fn create_share_change_session( - core: &SessionCore, - key_id: SessionId, - master_node_id: NodeId, - session_plan: ShareChangeSessionPlan, - ) -> Result { - ShareChangeSession::new(ShareChangeSessionParams { - session_id: core.meta.id.clone(), - nonce: core.nonce, - meta: ShareChangeSessionMeta { - id: key_id, - self_node_id: core.meta.self_node_id.clone(), - master_node_id: master_node_id, - configured_nodes_count: core.meta.configured_nodes_count, - connected_nodes_count: core.meta.connected_nodes_count, - }, - cluster: core.cluster.clone(), - key_storage: core.key_storage.clone(), - plan: session_plan, - }) - } - - /// Disseminate session initialization requests. - fn disseminate_session_initialization_requests( - core: &SessionCore, - data: &mut SessionData, - ) -> Result<(), Error> { - debug_assert_eq!(core.meta.self_node_id, core.meta.master_node_id); - if data.sessions_queue.is_some() { - let number_of_sessions_active = data.active_key_sessions.len() - + data.delegated_key_sessions.len() - + data.negotiation_sessions.len(); - let mut number_of_sessions_to_start = - MAX_ACTIVE_KEY_SESSIONS.saturating_sub(number_of_sessions_active); - while number_of_sessions_to_start > 0 { - let key_id = match data - .sessions_queue - .as_mut() - .expect("checked before beginning of the loop; qed") - .next() - { - None => break, // complete session - Some(Err(e)) => return Err(e), - Some(Ok(key_id)) => key_id, - }; - - let key_share = core.key_storage.get(&key_id)?; - let negotiation_session = - KeyVersionNegotiationSessionImpl::new(KeyVersionNegotiationSessionParams { - meta: ShareChangeSessionMeta { - id: key_id, - self_node_id: core.meta.self_node_id.clone(), - master_node_id: core.meta.self_node_id.clone(), - configured_nodes_count: core.meta.configured_nodes_count, - connected_nodes_count: core.meta.connected_nodes_count, - }, - sub_session: math::generate_random_scalar()?, - key_share: key_share, - result_computer: Arc::new(LargestSupportResultComputer {}), // TODO [Opt]: could use modified Fast version - transport: ServersSetChangeKeyVersionNegotiationTransport { - id: core.meta.id.clone(), - nonce: core.nonce, - cluster: core.cluster.clone(), - }, - nonce: 0, - }); - negotiation_session.initialize(core.cluster.nodes())?; - if !negotiation_session.is_finished() { - data.negotiation_sessions - .insert(key_id, negotiation_session); - continue; - } - - if !Self::initialize_share_change_session(core, data, key_id)? { - continue; - } - - number_of_sessions_to_start = number_of_sessions_to_start - 1; - } - - // if iteration is not yet finished => return - if number_of_sessions_to_start == 0 { - return Ok(()); - } - } - - // iteration is finished => complete session - if data.state != SessionState::Finished { - data.sessions_queue = None; - if data.active_key_sessions.len() == 0 - && data.delegated_key_sessions.len() == 0 - && data.negotiation_sessions.len() == 0 - { - Self::complete_session(core, data)?; - } - } - - Ok(()) - } - - /// Initialize share change session. - fn initialize_share_change_session( - core: &SessionCore, - data: &mut SessionData, - key_id: SessionId, - ) -> Result { - // get selected version && old nodes set from key negotiation session - let negotiation_session = data - .negotiation_sessions - .remove(&key_id) - .expect("share change session is only initialized when negotiation is completed; qed"); - let (selected_version, selected_master) = negotiation_session - .wait()? - .expect("initialize_share_change_session is only called on share change master; negotiation session completes with some on master; qed"); - let selected_version_holders = negotiation_session.version_holders(&selected_version)?; - let selected_version_threshold = negotiation_session.common_key_data()?.threshold; - - // prepare session change plan && check if something needs to be changed - let old_nodes_set = selected_version_holders; - let new_nodes_set = data.new_nodes_set.as_ref() - .expect("this method is called after consensus estabished; new_nodes_set is a result of consensus session; qed"); - let session_plan = prepare_share_change_session_plan( - &core.all_nodes_set, - selected_version_threshold, - &key_id, - selected_version.clone(), - &selected_master, - &old_nodes_set, - new_nodes_set, - )?; - if session_plan.is_empty() { - return Ok(false); - } - - // send key session initialization requests - let mut confirmations: BTreeSet<_> = session_plan.new_nodes_map.keys().cloned().collect(); - let need_create_session = confirmations.remove(&core.meta.self_node_id); - let initialization_message = Message::ServersSetChange( - ServersSetChangeMessage::InitializeShareChangeSession(InitializeShareChangeSession { - session: core.meta.id.clone().into(), - session_nonce: core.nonce, - key_id: key_id.clone().into(), - version: selected_version.into(), - version_holders: old_nodes_set.iter().cloned().map(Into::into).collect(), - master_node_id: selected_master.clone().into(), - consensus_group: session_plan - .consensus_group - .iter() - .cloned() - .map(Into::into) - .collect(), - new_nodes_map: session_plan - .new_nodes_map - .iter() - .map(|(n, nid)| (n.clone().into(), nid.clone().map(Into::into))) - .collect(), - }), - ); - for node in &confirmations { - core.cluster.send(&node, initialization_message.clone())?; - } - - // create session on this node if required - if need_create_session { - data.active_key_sessions.insert( - key_id.clone(), - Self::create_share_change_session( - core, - key_id, - selected_master.clone(), - session_plan, - )?, - ); - } - - // initialize session if required - let wait_for_confirmations = !confirmations.is_empty(); - if !wait_for_confirmations { - data.active_key_sessions.get_mut(&key_id) - .expect("!wait_for_confirmations is true only if this is the only session participant; if this is session participant, session is created above; qed") - .initialize()?; - } else { - data.sessions_initialization_state.insert( - key_id, - SessionInitializationData { - master: selected_master, - confirmations: confirmations, - }, - ); - } - - Ok(true) - } - - /// Return delegated session to master. - fn return_delegated_session(core: &SessionCore, key_id: &SessionId) -> Result<(), Error> { - assert!(core.meta.self_node_id != core.meta.master_node_id); - core.cluster.send( - &core.meta.master_node_id, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegateResponse( - ServersSetChangeDelegateResponse { - session: core.meta.id.clone().into(), - session_nonce: core.nonce, - key_id: key_id.clone().into(), - }, - )), - ) - } - - /// Complete key session. - fn complete_key_session( - core: &SessionCore, - data: &mut SessionData, - is_master: bool, - session_id: SessionId, - ) -> Result<(), Error> { - data.active_key_sessions.remove(&session_id); - let is_general_master = core.meta.self_node_id == core.meta.master_node_id; - if is_master && !is_general_master { - Self::return_delegated_session(core, &session_id)?; - } - if is_general_master { - Self::disseminate_session_initialization_requests(core, data)?; - } - - if data.result.is_some() && data.active_key_sessions.len() == 0 { - data.state = SessionState::Finished; - core.completed.notify_all(); - } - - Ok(()) - } - - /// Complete servers set change session. - fn complete_session(core: &SessionCore, data: &mut SessionData) -> Result<(), Error> { - debug_assert_eq!(core.meta.self_node_id, core.meta.master_node_id); - - // send completion notification - core.cluster.broadcast(Message::ServersSetChange( - ServersSetChangeMessage::ServersSetChangeCompleted(ServersSetChangeCompleted { - session: core.meta.id.clone().into(), - session_nonce: core.nonce, - }), - ))?; - - // if we are on the set of nodes that are being removed from the cluster, let's clear database - if !data.new_nodes_set.as_ref() - .expect("new_nodes_set is filled during initialization; session is completed after initialization; qed") - .contains(&core.meta.self_node_id) { - core.key_storage.clear()?; - } - - data.state = SessionState::Finished; - data.result = Some(Ok(())); - core.completed.notify_all(); - - Ok(()) - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionId; - - fn type_name() -> &'static str { - "servers set change" - } - - fn id(&self) -> SessionId { - self.core.meta.id.clone() - } - - fn is_finished(&self) -> bool { - self.data.lock().state == SessionState::Finished - } - - fn on_session_timeout(&self) { - self.on_session_error(&self.core.meta.self_node_id, Error::NodeDisconnected); - } - - fn on_node_timeout(&self, node: &NodeId) { - self.on_session_error(node, Error::NodeDisconnected); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - // error in generation session is considered fatal - // => broadcast error if error occured on this node - if *node == self.core.meta.self_node_id { - // do not bother processing send error, as we already processing error - let _ = self.core.cluster.broadcast(Message::ServersSetChange( - ServersSetChangeMessage::ServersSetChangeError(ServersSetChangeError { - session: self.core.meta.id.clone().into(), - session_nonce: self.core.nonce, - error: error.clone().into(), - }), - )); - } - - let mut data = self.data.lock(); - - warn!(target: "secretstore_net", "{}: servers set change session failed: {} on {}", - self.core.meta.self_node_id, error, node); - - data.state = SessionState::Finished; - data.result = Some(Err(error)); - self.core.completed.notify_all(); - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::ServersSetChange(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl JobTransport for ServersSetChangeConsensusTransport { - type PartialJobRequest = ServersSetChangeAccessRequest; - type PartialJobResponse = bool; - - fn send_partial_request( - &self, - node: &NodeId, - request: ServersSetChangeAccessRequest, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeConsensusMessage( - ServersSetChangeConsensusMessage { - session: self.id.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessageWithServersSet::InitializeConsensusSession( - InitializeConsensusSessionWithServersSet { - migration_id: self.migration_id.clone().map(Into::into), - old_nodes_set: request - .old_servers_set - .into_iter() - .map(Into::into) - .collect(), - new_nodes_set: request - .new_servers_set - .into_iter() - .map(Into::into) - .collect(), - old_set_signature: request.old_set_signature.into(), - new_set_signature: request.new_set_signature.into(), - }, - ), - }, - )), - ) - } - - fn send_partial_response(&self, node: &NodeId, response: bool) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeConsensusMessage( - ServersSetChangeConsensusMessage { - session: self.id.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessageWithServersSet::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: response, - }, - ), - }, - )), - ) - } -} - -impl JobTransport for UnknownSessionsJobTransport { - type PartialJobRequest = NodeId; - type PartialJobResponse = BTreeSet; - - fn send_partial_request(&self, node: &NodeId, _request: NodeId) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::UnknownSessionsRequest( - UnknownSessionsRequest { - session: self.id.clone().into(), - session_nonce: self.nonce, - }, - )), - ) - } - - fn send_partial_response( - &self, - node: &NodeId, - response: BTreeSet, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::UnknownSessions(UnknownSessions { - session: self.id.clone().into(), - session_nonce: self.nonce, - unknown_sessions: response.into_iter().map(Into::into).collect(), - })), - ) - } -} - -impl KeyVersionNegotiationTransport for ServersSetChangeKeyVersionNegotiationTransport { - fn broadcast(&self, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster.broadcast(Message::ServersSetChange( - ServersSetChangeMessage::ShareChangeKeyVersionNegotiation( - ShareChangeKeyVersionNegotiation { - session: self.id.clone().into(), - session_nonce: self.nonce, - message: message, - }, - ), - )) - } - - fn send(&self, node: &NodeId, message: KeyVersionNegotiationMessage) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::ShareChangeKeyVersionNegotiation( - ShareChangeKeyVersionNegotiation { - session: self.id.clone().into(), - session_nonce: self.nonce, - message: message, - }, - )), - ) - } -} - -fn check_nodes_set( - all_nodes_set: &BTreeSet, - new_nodes_set: &BTreeSet, -) -> Result<(), Error> { - // all_nodes_set is the set of nodes we're currently connected to (and configured for) - match new_nodes_set.iter().any(|n| !all_nodes_set.contains(n)) { - true => Err(Error::NodeDisconnected), - false => Ok(()), - } -} - -#[cfg(test)] -pub mod tests { - use super::{SessionImpl, SessionParams}; - use ethereum_types::H256; - use ethkey::{sign, Generator, KeyPair, Public, Random, Signature}; - use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, cluster::tests::MessageLoop as ClusterMessageLoop, - cluster_sessions::ClusterSession, - generation_session::tests::MessageLoop as GenerationMessageLoop, - jobs::servers_set_change_access_job::ordered_nodes_hash, math, message::Message, Error, - KeyStorage, NodeId, NodeKeyPair, PlainNodeKeyPair, SessionId, - }; - use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, - sync::Arc, - }; - - pub trait AdminSessionAdapter { - const SIGN_NEW_NODES: bool; - - fn create( - meta: ShareChangeSessionMeta, - admin_public: Public, - all_nodes_set: BTreeSet, - ml: &ClusterMessageLoop, - idx: usize, - ) -> S; - } - - pub struct MessageLoop { - pub ml: ClusterMessageLoop, - pub admin_key_pair: KeyPair, - pub original_key_pair: KeyPair, - pub original_key_version: H256, - pub all_nodes_set: BTreeSet, - pub new_nodes_set: BTreeSet, - pub all_set_signature: Signature, - pub new_set_signature: Signature, - pub sessions: BTreeMap, - pub queue: VecDeque<(NodeId, NodeId, Message)>, - } - - impl ::std::fmt::Debug for MessageLoop { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{:?}", self.ml) - } - } - - struct Adapter; - - impl AdminSessionAdapter for Adapter { - const SIGN_NEW_NODES: bool = true; - - fn create( - mut meta: ShareChangeSessionMeta, - admin_public: Public, - all_nodes_set: BTreeSet, - ml: &ClusterMessageLoop, - idx: usize, - ) -> SessionImpl { - meta.self_node_id = *ml.node_key_pair(idx).public(); - SessionImpl::new(SessionParams { - meta: meta, - all_nodes_set: all_nodes_set, - cluster: ml.cluster(idx).view().unwrap(), - key_storage: ml.key_storage(idx).clone(), - nonce: 1, - admin_public: admin_public, - migration_id: None, - }) - .unwrap() - } - } - - impl MessageLoop { - pub fn with_gml>( - gml: GenerationMessageLoop, - master: NodeId, - add: Option>, - removed_nodes_ids: Option>, - isolated_nodes_ids: Option>, - ) -> Self { - // read generated key data - let original_key_pair = gml.compute_key_pair(); - let original_key_version = gml.key_version(); - Self::with_ml::( - gml.0, - original_key_pair, - original_key_version, - master, - add, - removed_nodes_ids, - isolated_nodes_ids, - ) - } - - pub fn and_then>( - self, - master: NodeId, - add: Option>, - removed_nodes_ids: Option>, - isolated_nodes_ids: Option>, - ) -> Self { - Self::with_ml::( - self.ml, - self.original_key_pair, - self.original_key_version, - master, - add, - removed_nodes_ids, - isolated_nodes_ids, - ) - } - - pub fn with_ml>( - mut ml: ClusterMessageLoop, - original_key_pair: KeyPair, - original_key_version: H256, - master: NodeId, - add: Option>, - removed_nodes_ids: Option>, - isolated_nodes_ids: Option>, - ) -> Self { - let add = add.unwrap_or_default(); - let removed_nodes_ids = removed_nodes_ids.unwrap_or_default(); - let isolated_nodes_ids = isolated_nodes_ids.unwrap_or_default(); - - // generate admin key pair - let admin_key_pair = Random.generate().unwrap(); - let admin_public = admin_key_pair.public().clone(); - - // all active nodes set - let mut all_nodes_set: BTreeSet<_> = ml - .nodes() - .into_iter() - .filter(|n| !isolated_nodes_ids.contains(n)) - .collect(); - // new nodes set includes all old nodes, except nodes being removed + all nodes being added - let new_nodes_set: BTreeSet = all_nodes_set - .iter() - .cloned() - .chain(add.iter().map(|kp| *kp.public())) - .filter(|n| !removed_nodes_ids.contains(n)) - .collect(); - let mut old_set_to_sign = all_nodes_set.clone(); - all_nodes_set.extend(add.iter().map(|kp| *kp.public())); - if C::SIGN_NEW_NODES { - old_set_to_sign.extend(add.iter().map(|kp| *kp.public())); - } - for isolated_node_id in &isolated_nodes_ids { - all_nodes_set.remove(isolated_node_id); - } - - let meta = ShareChangeSessionMeta { - self_node_id: master, - master_node_id: master, - id: SessionId::default(), - configured_nodes_count: all_nodes_set.len(), - connected_nodes_count: all_nodes_set.len(), - }; - - // include new nodes in the cluster - for node_key_pair in &add { - ml.include(Arc::new(PlainNodeKeyPair::new(node_key_pair.clone()))); - } - // isolate nodes from the cluster - for isolated_node_id in &isolated_nodes_ids { - let idx = ml - .nodes() - .iter() - .position(|n| n == isolated_node_id) - .unwrap(); - ml.exclude(idx); - } - - // prepare set of nodes - let sessions: BTreeMap<_, _> = (0..ml.nodes().len()) - .map(|idx| { - ( - ml.node(idx), - C::create(meta.clone(), admin_public, all_nodes_set.clone(), &ml, idx), - ) - }) - .collect(); - - let all_set_signature = sign( - admin_key_pair.secret(), - &ordered_nodes_hash(&old_set_to_sign), - ) - .unwrap(); - let new_set_signature = - sign(admin_key_pair.secret(), &ordered_nodes_hash(&new_nodes_set)).unwrap(); - - MessageLoop { - ml, - admin_key_pair: admin_key_pair, - original_key_pair, - original_key_version, - all_nodes_set: all_nodes_set.clone(), - new_nodes_set: new_nodes_set, - all_set_signature: all_set_signature, - new_set_signature: new_set_signature, - sessions, - queue: Default::default(), - } - } - - pub fn run(&mut self) { - // run session until completion - while let Some((from, to, message)) = self.take_message() { - self.process_message((from, to, message)).unwrap(); - } - - // check that all sessions have finished - assert!(self.sessions.values().all(|s| s.is_finished())); - } - - pub fn take_message(&mut self) -> Option<(NodeId, NodeId, Message)> { - self.ml.take_message().or_else(|| self.queue.pop_front()) - } - - pub fn process_message(&mut self, msg: (NodeId, NodeId, Message)) -> Result<(), Error> { - match self.sessions[&msg.1].on_message(&msg.0, &msg.2) { - Ok(_) => Ok(()), - Err(Error::TooEarlyForRequest) => { - self.queue.push_back(msg); - Ok(()) - } - Err(err) => Err(err), - } - } - - /// This only works for schemes where threshold = 1 - pub fn check_secret_is_preserved<'a, I: IntoIterator>(&self, nodes: I) { - let nodes: Vec<_> = nodes.into_iter().collect(); - let key_storages: Vec<_> = nodes.iter().map(|n| self.ml.key_storage_of(n)).collect(); - let n = nodes.len(); - let document_secret_plain = math::generate_random_point().unwrap(); - for n1 in 0..n { - for n2 in n1 + 1..n { - let share1 = key_storages[n1].get(&SessionId::default()).unwrap(); - let share2 = key_storages[n2].get(&SessionId::default()).unwrap(); - - let id_number1 = share1.as_ref().unwrap().last_version().unwrap().id_numbers - [nodes[n1]] - .clone(); - let id_number2 = share1.as_ref().unwrap().last_version().unwrap().id_numbers - [nodes[n2]] - .clone(); - // now encrypt and decrypt data - let (document_secret_decrypted, document_secret_decrypted_test) = - math::tests::do_encryption_and_decryption( - 1, - self.original_key_pair.public(), - &[id_number1, id_number2], - &[ - share1.unwrap().last_version().unwrap().secret_share.clone(), - share2.unwrap().last_version().unwrap().secret_share.clone(), - ], - Some(self.original_key_pair.secret()), - document_secret_plain.clone(), - ); - - assert_eq!(document_secret_plain, document_secret_decrypted_test); - assert_eq!(document_secret_plain, document_secret_decrypted); - } - } - } - } - - impl MessageLoop { - pub fn run_at(mut self, master: NodeId) -> Self { - self.sessions[&master] - .initialize( - self.new_nodes_set.clone(), - self.all_set_signature.clone(), - self.new_set_signature.clone(), - ) - .unwrap(); - self.run(); - self - } - } - - pub fn generate_key(num_nodes: usize, threshold: usize) -> GenerationMessageLoop { - let gml = GenerationMessageLoop::new(num_nodes) - .init(threshold) - .unwrap(); - gml.0.loop_until(|| gml.0.is_empty()); - gml - } - - #[test] - fn node_added_using_servers_set_change() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // add 1 node so that it becames 2-of-4 session - let add = vec![Random.generate().unwrap()]; - let master = gml.0.node(0); - let ml = - MessageLoop::with_gml::(gml, master, Some(add), None, None).run_at(master); - - // try to recover secret for every possible combination of nodes && check that secret is the same - ml.check_secret_is_preserved(ml.sessions.keys()); - } - - #[test] - fn node_added_using_server_set_change_from_this_node() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // insert 1 node so that it becames 2-of-4 session - // master node is the node we are adding => - // 1) add session is delegated to one of old nodes - // 2) key share is pushed to new node - // 3) delegated session is returned back to added node - let add = vec![Random.generate().unwrap()]; - let master = add[0].public().clone(); - let ml = - MessageLoop::with_gml::(gml, master, Some(add), None, None).run_at(master); - - // try to recover secret for every possible combination of nodes && check that secret is the same - ml.check_secret_is_preserved(ml.sessions.keys()); - } - - #[test] - fn node_moved_using_servers_set_change() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // remove 1 node && insert 1 node so that one share is moved - let master = gml.0.node(0); - let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); - let add = vec![Random.generate().unwrap()]; - let ml = - MessageLoop::with_gml::(gml, master, Some(add), Some(remove.clone()), None) - .run_at(master); - - // check that secret is still the same as before moving the share - ml.check_secret_is_preserved(ml.sessions.keys().filter(|k| !remove.contains(k))); - - // check that all removed nodes do not own key share - assert!(ml.sessions.keys().filter(|k| remove.contains(k)).all(|k| ml - .ml - .key_storage_of(k) - .get(&SessionId::default()) - .unwrap() - .is_none())); - } - - #[test] - fn node_removed_using_servers_set_change() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // remove 1 node so that session becames 2-of-2 - let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(0)).collect(); - let master = gml.0.node(0); - let ml = MessageLoop::with_gml::(gml, master, None, Some(remove.clone()), None) - .run_at(master); - - // try to recover secret for every possible combination of nodes && check that secret is the same - ml.check_secret_is_preserved(ml.sessions.keys().filter(|k| !remove.contains(k))); - - // check that all removed nodes do not own key share - assert!(ml.sessions.keys().filter(|k| remove.contains(k)).all(|k| ml - .ml - .key_storage_of(k) - .get(&SessionId::default()) - .unwrap() - .is_none())); - } - - #[test] - fn isolated_node_removed_using_servers_set_change() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // remove 1 node so that session becames 2-of-2 - let isolate: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); - let master = gml.0.node(0); - let ml = MessageLoop::with_gml::(gml, master, None, None, Some(isolate.clone())) - .run_at(master); - - // try to recover secret for every possible combination of nodes && check that secret is the same - ml.check_secret_is_preserved(ml.sessions.keys().filter(|k| !isolate.contains(k))); - - // check that all isolated nodes still OWN key share - assert!(ml - .sessions - .keys() - .filter(|k| isolate.contains(k)) - .all(|k| ml - .ml - .key_storage_of(k) - .get(&SessionId::default()) - .unwrap() - .is_some())); - } - - #[test] - fn having_less_than_required_nodes_after_change_does_not_fail_change_session() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // remove 2 nodes so that key becomes irrecoverable (make sure the session is completed - // even though key is irrecoverable) - let remove: BTreeSet<_> = gml.0.nodes().into_iter().skip(1).take(2).collect(); - let master = gml.0.node(0); - let ml = MessageLoop::with_gml::(gml, master, None, Some(remove.clone()), None) - .run_at(master); - - // check that all removed nodes do not own key share - assert!(ml.sessions.keys().filter(|k| remove.contains(k)).all(|k| ml - .ml - .key_storage_of(k) - .get(&SessionId::default()) - .unwrap() - .is_none())); - - // and now let's add new node (make sure the session is completed, even though key is still irrecoverable) - // isolated here are not actually isolated, but removed on the previous step - let add = vec![Random.generate().unwrap()]; - let master = add[0].public().clone(); - let ml = ml - .and_then::(master, Some(add.clone()), None, Some(remove)) - .run_at(master); - - // check that all added nodes do not own key share (there's not enough nodes to run share add session) - assert!(ml - .sessions - .keys() - .filter(|k| add.iter().any(|n| n.public() == *k)) - .all(|k| ml - .ml - .key_storage_of(k) - .get(&SessionId::default()) - .unwrap() - .is_none())); - } - - #[test] - fn removing_node_from_cluster_of_2_works() { - // initial 2-of-2 session - let gml = generate_key(2, 1); - - // make 2nd node isolated so that key becomes irrecoverable (make sure the session is completed, - // even though key is irrecoverable) - let isolate: BTreeSet<_> = gml.0.nodes().into_iter().skip(1).take(1).collect(); - let master = gml.0.node(0); - MessageLoop::with_gml::(gml, master, None, None, Some(isolate)).run_at(master); - } - - #[test] - fn adding_node_that_has_lost_its_database_works() { - // initial 2-of-2 session - let gml = generate_key(2, 1); - - // insert 1 node so that it becames 2-of-3 session - let add = vec![Random.generate().unwrap()]; - let master = gml.0.node(0); - let ml = MessageLoop::with_gml::(gml, master, Some(add.clone()), None, None) - .run_at(master); - - // now let's say new node has lost its db and we're trying to join it again - ml.ml.key_storage_of(add[0].public()).clear().unwrap(); - - // this time old nodes have version, where new node is mentioned, but it doesn't report it when negotiating - let ml = ml - .and_then::(master, Some(add), None, None) - .run_at(master); - - // try to recover secret for every possible combination of nodes && check that secret is the same - ml.check_secret_is_preserved(ml.sessions.keys()); - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/sessions_queue.rs b/secret-store/src/key_server_cluster/admin_sessions/sessions_queue.rs deleted file mode 100644 index 8ebe8f6e8d..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/sessions_queue.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{Error, KeyStorage, SessionId}; -use std::{ - collections::{BTreeSet, VecDeque}, - sync::Arc, -}; - -/// Queue of share change sessions. -pub struct SessionsQueue { - /// Sessions, known on this node. - known_sessions: VecDeque, - /// Unknown sessions. - unknown_sessions: VecDeque, -} - -impl SessionsQueue { - /// Create new sessions queue. - pub fn new(key_storage: &Arc, unknown_sessions: BTreeSet) -> Self { - // TODO [Opt]: - // 1) known sessions - change to iter - // 2) unknown sesions - request chunk-by-chunk - SessionsQueue { - known_sessions: key_storage.iter().map(|(k, _)| k).collect(), - unknown_sessions: unknown_sessions.into_iter().collect(), - } - } -} - -impl Iterator for SessionsQueue { - type Item = Result; - - fn next(&mut self) -> Option { - if let Some(known_session) = self.known_sessions.pop_front() { - return Some(Ok(known_session)); - } - - if let Some(unknown_session) = self.unknown_sessions.pop_front() { - return Some(Ok(unknown_session)); - } - - None - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs deleted file mode 100644 index df60e2f393..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ /dev/null @@ -1,1463 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::{Public, Secret, Signature}; -use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::Cluster, - cluster_sessions::ClusterSession, - jobs::{ - consensus_session::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}, - dummy_job::{DummyJob, DummyJobTransport}, - job_session::JobTransport, - servers_set_change_access_job::{ServersSetChangeAccessJob, ServersSetChangeAccessRequest}, - }, - math, - message::{ - CommonKeyData, ConfirmConsensusInitialization, ConsensusMessageOfShareAdd, - InitializeConsensusSessionOfShareAdd, KeyShareCommon, Message, NewKeysDissemination, - ShareAddConsensusMessage, ShareAddError, ShareAddMessage, - }, - DocumentKeyShare, DocumentKeyShareVersion, Error, KeyStorage, NodeId, SessionId, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Share addition session transport. -pub trait SessionTransport: - Clone + JobTransport -{ - /// Get all connected nodes. Since ShareAdd session requires all cluster nodes to be connected, this set equals to all known cluster nodes set. - fn nodes(&self) -> BTreeSet; - /// Send message to given node. - fn send(&self, node: &NodeId, message: ShareAddMessage) -> Result<(), Error>; - /// Set data for master node (sent to slave nodes in consensus session initialization message). - fn set_master_data( - &mut self, - consensus_group: BTreeSet, - version_holders: BTreeSet, - id_numbers: BTreeMap>, - ); -} - -/// Share addition session. -/// Based on "Efficient Multi-Party Digital Signature using Adaptive Secret Sharing for Low-Power Devices in Wireless Networks" paper: -/// http://www.wu.ece.ufl.edu/mypapers/msig.pdf -/// Brief overview: -/// 1) initialization: master node (which has received request for shares addition the message) asks all other nodes to support addition -/// 2) key refreshing distribution (KRD): node generates new random polynom && sends required data to all other nodes -/// 3) key refreshing verification (KRV): node verifies received data -/// 4) node updates its own key share using generated (&& received) data -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex>, -} - -/// Immutable session data. -struct SessionCore { - /// Session metadata. - pub meta: ShareChangeSessionMeta, - /// Session-level nonce. - pub nonce: u64, - /// Original key share (for old nodes only). - pub key_share: Option, - /// Session transport to communicate to other cluster nodes. - pub transport: T, - /// Key storage. - pub key_storage: Arc, - /// Administrator public key. - pub admin_public: Option, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Share add consensus session type. -type ShareAddChangeConsensusSession = - ConsensusSession; - -/// Mutable session data. -struct SessionData { - /// Session state. - pub state: SessionState, - /// Key version to use for decryption. - pub version: Option, - /// Consensus session. - pub consensus_session: Option>, - /// Holders of key version. - pub version_holders: Option>, - /// NewKeyShare (for nodes being added). - pub new_key_share: Option, - /// Nodes id numbers. - pub id_numbers: Option>>, - /// Secret subshares received from nodes. - pub secret_subshares: Option>>, - /// Share add change result. - pub result: Option>, -} - -/// New key share. -struct NewKeyShare { - /// NewKeyShare: threshold. - pub threshold: usize, - /// NewKeyShare: author. - pub author: Address, - /// NewKeyShare: joint public. - pub joint_public: Public, - /// NewKeyShare: Common (shared) encryption point. - pub common_point: Option, - /// NewKeyShare: Encrypted point. - pub encrypted_point: Option, -} - -/// Session state. -#[derive(Debug, PartialEq)] -enum SessionState { - /// State when consensus is establishing. - ConsensusEstablishing, - /// Waiting for keys dissemination. - WaitingForKeysDissemination, - /// Session is completed. - Finished, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// Session metadata. - pub meta: ShareChangeSessionMeta, - /// Session transport. - pub transport: T, - /// Key storage. - pub key_storage: Arc, - /// Administrator public key. - pub admin_public: Option, - /// Session nonce. - pub nonce: u64, -} - -/// Isolated ShareAdd session transport. -#[derive(Clone)] -pub struct IsolatedSessionTransport { - /// Key id. - session: SessionId, - /// Key version. - version: Option, - /// Session-level nonce. - nonce: u64, - /// Holders of key version. - version_holders: Option>, - /// Consensus group. - consensus_group: Option>, - /// Id numbers of all new nodes. - id_numbers: Option>>, - /// Cluster. - cluster: Arc, -} - -impl SessionImpl -where - T: SessionTransport, -{ - /// Create new share addition session. - pub fn new(params: SessionParams) -> Result { - let key_share = params.key_storage.get(¶ms.meta.id)?; - - Ok(SessionImpl { - core: SessionCore { - meta: params.meta, - nonce: params.nonce, - key_share: key_share, - transport: params.transport, - key_storage: params.key_storage, - admin_public: params.admin_public, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - state: SessionState::ConsensusEstablishing, - version: None, - consensus_session: None, - version_holders: None, - new_key_share: None, - id_numbers: None, - secret_subshares: None, - result: None, - }), - }) - } - - /// Set pre-established consensus data. - pub fn set_consensus_output( - &self, - version: &H256, - consensus_group: BTreeSet, - version_holders: BTreeSet, - mut new_nodes_map: BTreeMap>, - ) -> Result<(), Error> { - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::ConsensusEstablishing - || data.consensus_session.is_some() - || data.id_numbers.is_some() - || data.secret_subshares.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - // key share version is required on ShareAdd master node - if let Some(key_share) = self.core.key_share.as_ref() { - if let Ok(key_version) = key_share.version(version) { - let non_isolated_nodes = self.core.transport.nodes(); - for (node, id_number) in &key_version.id_numbers { - { - let external_id_number = new_nodes_map.get(node); - match external_id_number { - Some(&Some(ref external_id_number)) => { - if !version_holders.contains(node) { - // possible when joining version holder, that has lost its database - // and haven't reported version ownership - continue; - } - if external_id_number == id_number { - continue; - } - - return Err(Error::ConsensusUnreachable); - } - Some(&None) => (), - None => { - if non_isolated_nodes.contains(node) { - return Err(Error::ConsensusUnreachable); - } - continue; - } - } - } - - new_nodes_map.insert(node.clone(), Some(id_number.clone())); - } - - // check that all id_numbers are filled - if new_nodes_map.values().any(Option::is_none) { - return Err(Error::ConsensusUnreachable); - } - } - } - - // check passed consensus data - Self::check_nodes_map( - &self.core, - version, - &consensus_group, - &version_holders, - &new_nodes_map, - )?; - - // update data - data.version = Some(version.clone()); - data.id_numbers = Some(new_nodes_map); - data.secret_subshares = Some(consensus_group.into_iter().map(|n| (n, None)).collect()); - data.version_holders = Some(version_holders); - - Ok(()) - } - - /// Initialize share add session on master node. - pub fn initialize( - &self, - version: Option, - new_nodes_set: Option>, - old_set_signature: Option, - new_set_signature: Option, - ) -> Result<(), Error> { - debug_assert_eq!(self.core.meta.self_node_id, self.core.meta.master_node_id); - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::ConsensusEstablishing || data.consensus_session.is_some() { - return Err(Error::InvalidStateForRequest); - } - - // if consensus is pre-established => start sending ShareAdd-specific messages - let is_consensus_pre_established = data.id_numbers.is_some(); - if is_consensus_pre_established { - return Self::on_consensus_established(&self.core, &mut *data); - } - - // else => prepare to start consensus session - // require all initialization params for consensus session - let version = version.ok_or(Error::InvalidMessage)?; - let old_set_signature = old_set_signature.ok_or(Error::InvalidMessage)?; - let new_set_signature = new_set_signature.ok_or(Error::InvalidMessage)?; - let new_nodes_set = new_nodes_set.ok_or(Error::InvalidMessage)?; - let admin_public = self - .core - .admin_public - .as_ref() - .cloned() - .ok_or(Error::ConsensusUnreachable)?; - - // key share version is required on ShareAdd master node - let key_share = self - .core - .key_share - .as_ref() - .ok_or_else(|| Error::ServerKeyIsNotFound)?; - let key_version = key_share.version(&version)?; - - // old nodes set is all non-isolated owners of version holders - let non_isolated_nodes = self.core.transport.nodes(); - let old_nodes_set: BTreeSet<_> = key_version - .id_numbers - .keys() - .filter(|n| non_isolated_nodes.contains(n)) - .cloned() - .collect(); - - // new nodes map contains previous id_numbers for old nodes && random number for new nodes - let mut new_nodes_map = BTreeMap::new(); - for new_node in new_nodes_set - .into_iter() - .filter(|n| non_isolated_nodes.contains(n)) - { - new_nodes_map.insert( - new_node, - match key_version.id_numbers.get(&new_node) { - Some(old_id_number) => Some(old_id_number.clone()), - None => Some(math::generate_random_scalar()?), - }, - ); - } - - // let's select consensus group - let consensus_group: BTreeSet<_> = ::std::iter::once(self.core.meta.self_node_id.clone()) - .chain( - old_nodes_set - .iter() - .filter(|n| { - **n != self.core.meta.self_node_id && non_isolated_nodes.contains(*n) - }) - .take(key_share.threshold) - .cloned(), - ) - .collect(); - let version_holders = &old_nodes_set; - - // now check nodes map - Self::check_nodes_map( - &self.core, - &version, - &consensus_group, - version_holders, - &new_nodes_map, - )?; - - // prepare consensus session transport - let mut consensus_transport = self.core.transport.clone(); - consensus_transport.set_master_data( - consensus_group.clone(), - version_holders.clone(), - new_nodes_map.clone(), - ); - - // create && initialize consensus session - let mut consensus_session = ConsensusSession::new(ConsensusSessionParams { - meta: self - .core - .meta - .clone() - .into_consensus_meta(new_nodes_map.len())?, - consensus_executor: ServersSetChangeAccessJob::new_on_master( - admin_public, - old_nodes_set.clone(), - new_nodes_map.keys().cloned().collect(), - old_set_signature, - new_set_signature, - ), - consensus_transport: consensus_transport, - })?; - - consensus_session.initialize(new_nodes_map.keys().cloned().collect())?; - - // update data - data.version = Some(version); - data.consensus_session = Some(consensus_session); - data.id_numbers = Some(new_nodes_map); - data.secret_subshares = Some(consensus_group.into_iter().map(|n| (n, None)).collect()); - data.version_holders = Some(version_holders.clone()); - - Ok(()) - } - - /// Process single message. - pub fn process_message(&self, sender: &NodeId, message: &ShareAddMessage) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &ShareAddMessage::ShareAddConsensusMessage(ref message) => { - self.on_consensus_message(sender, message) - } - &ShareAddMessage::KeyShareCommon(ref message) => { - self.on_common_key_share_data(sender, message) - } - &ShareAddMessage::NewKeysDissemination(ref message) => { - self.on_new_keys_dissemination(sender, message) - } - &ShareAddMessage::ShareAddError(ref message) => { - self.on_session_error(sender, message.error.clone()); - Ok(()) - } - } - } - - /// When consensus-related message is received. - pub fn on_consensus_message( - &self, - sender: &NodeId, - message: &ShareAddConsensusMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // start slave consensus session if needed - let mut data = self.data.lock(); - match &message.message { - &ConsensusMessageOfShareAdd::InitializeConsensusSession(ref message) - if data.consensus_session.is_none() && sender == &self.core.meta.master_node_id => - { - let admin_public = self - .core - .admin_public - .as_ref() - .cloned() - .ok_or(Error::ConsensusUnreachable)?; - data.consensus_session = Some(ConsensusSession::new(ConsensusSessionParams { - meta: self - .core - .meta - .clone() - .into_consensus_meta(message.new_nodes_map.len())?, - consensus_executor: ServersSetChangeAccessJob::new_on_slave(admin_public), - consensus_transport: self.core.transport.clone(), - })?); - } - _ => (), - }; - - // process consensus message - let ( - is_establishing_consensus, - is_consensus_established, - version, - new_nodes_map, - consensus_group, - version_holders, - ) = { - let consensus_session = data - .consensus_session - .as_mut() - .ok_or(Error::InvalidMessage)?; - let is_establishing_consensus = - consensus_session.state() == ConsensusSessionState::EstablishingConsensus; - - let (version, new_nodes_map, consensus_group, version_holders) = match &message.message - { - &ConsensusMessageOfShareAdd::InitializeConsensusSession(ref message) => { - consensus_session.on_consensus_partial_request( - sender, - ServersSetChangeAccessRequest::from(message), - )?; - - let version = message.version.clone().into(); - let consensus_group = message - .consensus_group - .iter() - .cloned() - .map(Into::into) - .collect(); - let version_holders = message - .version_holders - .iter() - .cloned() - .map(Into::into) - .collect(); - let new_nodes_map: BTreeMap<_, _> = message - .new_nodes_map - .iter() - .map(|(n, nn)| (n.clone().into(), Some(nn.clone().into()))) - .collect(); - - // check that all id_numbers are filled - if new_nodes_map.values().any(Option::is_none) { - return Err(Error::ConsensusUnreachable); - } - - // check old set of nodes - Self::check_nodes_map( - &self.core, - &version, - &consensus_group, - &version_holders, - &new_nodes_map, - )?; - - ( - Some(version), - Some(new_nodes_map), - Some(consensus_group), - Some(version_holders), - ) - } - &ConsensusMessageOfShareAdd::ConfirmConsensusInitialization(ref message) => { - consensus_session - .on_consensus_partial_response(sender, message.is_confirmed)?; - (None, None, None, None) - } - }; - - ( - is_establishing_consensus, - consensus_session.state() == ConsensusSessionState::ConsensusEstablished, - version, - new_nodes_map, - consensus_group, - version_holders, - ) - }; - - // update data - if let Some(version) = version { - data.version = Some(version); - } - if let Some(new_nodes_map) = new_nodes_map { - data.id_numbers = Some(new_nodes_map); - } - if let Some(consensus_group) = consensus_group { - data.secret_subshares = Some(consensus_group.into_iter().map(|n| (n, None)).collect()); - } - if let Some(version_holders) = version_holders { - data.version_holders = Some(version_holders); - } - - // if consensus is stablished, proceed - if !is_establishing_consensus - || !is_consensus_established - || self.core.meta.self_node_id != self.core.meta.master_node_id - { - return Ok(()); - } - - Self::on_consensus_established(&self.core, &mut *data) - } - - /// When common key share data is received by new node. - pub fn on_common_key_share_data( - &self, - sender: &NodeId, - message: &KeyShareCommon, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - // only master can send this message - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::ConsensusEstablishing || data.id_numbers.is_none() { - return Ok(()); - } - - // we only expect this message once - if data.new_key_share.is_some() { - return Err(Error::InvalidStateForRequest); - } - - // check if we actually waiting for this message - { - let version = data.version.as_ref().ok_or(Error::InvalidStateForRequest)?; - let key_version = self - .core - .key_share - .as_ref() - .and_then(|ks| ks.version(version).ok()); - if key_version.is_some() { - return Ok(()); - } - } - - // update data - data.state = SessionState::WaitingForKeysDissemination; - data.new_key_share = Some(NewKeyShare { - threshold: message.key_common.threshold, - author: message.key_common.author.clone().into(), - joint_public: message.key_common.public.clone().into(), - common_point: message.common_point.clone().map(Into::into), - encrypted_point: message.encrypted_point.clone().map(Into::into), - }); - - let id_numbers = data.id_numbers.as_mut() - .expect("common key share data is expected after initialization; id_numbers are filled during initialization; qed"); - for (node, id_number) in &message.id_numbers { - let id_number: Secret = id_number.clone().into(); - { - let local_id_number = id_numbers.get(&node.clone().into()); - match local_id_number { - Some(&Some(ref local_id_number)) => { - if *local_id_number == id_number { - continue; - } - - return Err(Error::ConsensusUnreachable); - } - Some(&None) => (), - None => continue, // can happen for isolated nodes - } - } - - id_numbers.insert(node.clone().into(), Some(id_number)); - } - - Ok(()) - } - - /// When keys dissemination message is received. - pub fn on_new_keys_dissemination( - &self, - sender: &NodeId, - message: &NewKeysDissemination, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - // check state - if data.state == SessionState::ConsensusEstablishing && data.secret_subshares.is_some() { - data.state = SessionState::WaitingForKeysDissemination; - } else if data.state != SessionState::WaitingForKeysDissemination { - return Err(Error::InvalidStateForRequest); - } - - // update data - let explanation = "secret_subshares is filled during initialization; keys are disseminated after initialization; qed"; - { - match data - .secret_subshares - .as_ref() - .expect(explanation) - .get(sender) - { - None => return Err(Error::InvalidMessage), - Some(&Some(_)) => return Err(Error::InvalidMessage), - Some(&None) => (), - }; - - let secret_subshare = Self::compute_secret_subshare( - &self.core, - &mut *data, - sender, - &message.secret_subshare.clone().into(), - )?; - *data - .secret_subshares - .as_mut() - .expect(explanation) - .get_mut(sender) - .expect("checked couple of lines above; qed") = Some(secret_subshare); - } - - // if we have received subshare from master node, it means that we should start dissemination - if sender == &self.core.meta.master_node_id { - Self::on_consensus_established(&self.core, &mut *data)?; - } - - // check if shares from all nodes are received - if data - .secret_subshares - .as_ref() - .expect(explanation) - .values() - .any(|v| v.is_none()) - { - return Ok(()); - } - - // TODO [Trust]: find a way to verificate keys - Self::complete_session(&self.core, &mut *data) - } - - /// Check nodes map. - fn check_nodes_map( - core: &SessionCore, - version: &H256, - consensus_group: &BTreeSet, - version_holders: &BTreeSet, - new_nodes_map: &BTreeMap>, - ) -> Result<(), Error> { - // check if this node has given version - let has_this_version = match core.key_share.as_ref() { - Some(key_share) => key_share.version(version).is_ok(), - None => false, - }; - - // check && update passed data - match has_this_version { - true => { - // check if version exists - let explanation = - "has_this_version is true; it is true if we have given version of the key; qed"; - let key_share = core.key_share.as_ref().expect(explanation); - let key_version = key_share.version(version).expect(explanation); - - // there must be exactly thresold + 1 nodes in consensus group - if consensus_group.len() != key_share.threshold + 1 { - return Err(Error::ConsensusUnreachable); - } - - // every non-isolated node must be a part of new_nodes_set - let non_isolated_nodes = core.transport.nodes(); - if key_version - .id_numbers - .keys() - .any(|n| non_isolated_nodes.contains(n) && !new_nodes_map.contains_key(n)) - { - return Err(Error::ConsensusUnreachable); - } - - // there must be at least one new node in new_nodes_map - if key_version - .id_numbers - .keys() - .filter(|n| non_isolated_nodes.contains(n) && version_holders.contains(n)) - .count() - >= new_nodes_map.len() - { - return Err(Error::ConsensusUnreachable); - } - } - false => { - // if we do not have a share, we should not be a part of consenus group - // but we must be on new nodes set, since this is a ShareAdd session - if consensus_group.contains(&core.meta.self_node_id) - || !new_nodes_map.contains_key(&core.meta.self_node_id) - { - return Err(Error::ConsensusUnreachable); - } - } - } - - // master node must always be a part of consensus group - if !consensus_group.contains(&core.meta.master_node_id) { - return Err(Error::ConsensusUnreachable); - } - - // master node must always be a part of new_nodes_map - if !new_nodes_map.contains_key(&core.meta.master_node_id) { - return Err(Error::ConsensusUnreachable); - } - - Ok(()) - } - - /// Start sending ShareAdd-specific messages, when consensus is established. - fn on_consensus_established( - core: &SessionCore, - data: &mut SessionData, - ) -> Result<(), Error> { - // update state - data.state = SessionState::WaitingForKeysDissemination; - - // if we're not a part of consensus group, wait for secret subshares - let explanation = - "secret_subshares is a result of consensus job; consensus is established; qed"; - let is_consensus_group_node = data - .secret_subshares - .as_ref() - .expect(explanation) - .contains_key(&core.meta.self_node_id); - if !is_consensus_group_node { - return Ok(()); - } - - // else if master => send shared data to every new node - if core.meta.self_node_id == core.meta.master_node_id { - Self::disseminate_common_share_data(core, data)?; - } - - // ...and then disseminate keys - Self::disseminate_keys(core, data)?; - - // ..and check if session could be completed - if data - .secret_subshares - .as_ref() - .expect(explanation) - .values() - .any(|v| v.is_none()) - { - return Ok(()); - } - - // TODO [Trust]: find a way to verificate keys - Self::complete_session(core, data) - } - - /// Send common share data to evey new node. - fn disseminate_common_share_data( - core: &SessionCore, - data: &SessionData, - ) -> Result<(), Error> { - let explanation = "disseminate_common_share_data is only called on master node; master node has specified version of the key; qed"; - let old_key_share = core.key_share.as_ref().expect(explanation); - let old_key_version = old_key_share - .version(data.version.as_ref().expect(explanation)) - .expect(explanation); - let version_holders = data.version_holders.as_ref() - .expect("disseminate_common_share_data is only called on master node; version holders is created during initialization on master node; qed"); - let consensus_group = data.secret_subshares.as_ref() - .expect("disseminate_common_share_data is only called on master node; consensus group is created during initialization on master node; qed"); - let nodes = data.id_numbers.as_ref() - .expect("nodes are filled during consensus establishing; common share data sent after consensus is established; qed") - .keys() - .filter(|n| !consensus_group.contains_key(n)); - for new_node in nodes { - core.transport.send( - new_node, - ShareAddMessage::KeyShareCommon(KeyShareCommon { - session: core.meta.id.clone().into(), - session_nonce: core.nonce, - key_common: CommonKeyData { - threshold: old_key_share.threshold, - author: old_key_share.author.into(), - public: old_key_share.public.into(), - }, - common_point: old_key_share.common_point.clone().map(Into::into), - encrypted_point: old_key_share.encrypted_point.clone().map(Into::into), - id_numbers: old_key_version - .id_numbers - .iter() - .filter(|&(k, _)| version_holders.contains(k)) - .map(|(k, v)| (k.clone().into(), v.clone().into())) - .collect(), - }), - )?; - } - - Ok(()) - } - - /// Disseminate key refreshing data. - fn disseminate_keys(core: &SessionCore, data: &mut SessionData) -> Result<(), Error> { - // generate random polynom with secret share as absolute term - let explanation = "disseminate_keys is only called on consensus group nodes; consensus group nodes have specified version of the key; qed"; - let key_share = core.key_share.as_ref().expect(explanation); - let key_version = key_share - .version(data.version.as_ref().expect(explanation)) - .expect(explanation); - let mut secret_share_polynom = math::generate_random_polynom(key_share.threshold)?; - secret_share_polynom[0] = key_version.secret_share.clone(); - - // calculate secret subshare for every new node (including this node) - let explanation = "disseminate_keys is called after initialization has completed; this field is filled during initialization; qed"; - for (new_node, new_node_number) in data.id_numbers.as_ref().expect(explanation).iter() { - let new_node_number = new_node_number.as_ref().ok_or(Error::InvalidMessage)?; - let secret_subshare = math::compute_polynom(&secret_share_polynom, new_node_number)?; - if new_node != &core.meta.self_node_id { - core.transport.send( - new_node, - ShareAddMessage::NewKeysDissemination(NewKeysDissemination { - session: core.meta.id.clone().into(), - session_nonce: core.nonce, - secret_subshare: secret_subshare.into(), - }), - )?; - } else { - let secret_subshare = - Self::compute_secret_subshare(core, data, new_node, &secret_subshare)?; - *data.secret_subshares.as_mut().expect(explanation) - .get_mut(&core.meta.self_node_id) - .expect("disseminate_keys is only calle on consensus group nodes; there's entry for every consensus node in secret_subshares; qed") - = Some(secret_subshare); - } - } - - Ok(()) - } - - /// Compute secret subshare from passed secret value. - fn compute_secret_subshare( - core: &SessionCore, - data: &SessionData, - sender: &NodeId, - secret_value: &Secret, - ) -> Result { - let explanation = "this field is a result of consensus job; compute_secret_subshare is called after consensus is established"; - let id_numbers = data.id_numbers.as_ref().expect(explanation); - let secret_subshares = data.secret_subshares.as_ref().expect(explanation); - let threshold = core - .key_share - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_else(|| { - data.new_key_share.as_ref() - .expect("computation occurs after receiving key share threshold if not having one already; qed") - .threshold - }); - - let explanation = "id_numbers are checked to have Some value for every consensus group node when consensus is establishe; qed"; - let sender_id_number = id_numbers[sender].as_ref().expect(explanation); - let other_id_numbers = secret_subshares - .keys() - .filter(|k| *k != sender) - .map(|n| id_numbers[n].as_ref().expect(explanation)); - math::compute_secret_subshare(threshold, secret_value, sender_id_number, other_id_numbers) - } - - /// Complete session. - fn complete_session(core: &SessionCore, data: &mut SessionData) -> Result<(), Error> { - // if already completed, do nothing - if data.state == SessionState::Finished { - return Ok(()); - } - - // compose updated key share - let explanation = "this field is a result of consensus job; complete_session is called after consensus is established"; - let id_numbers = data.id_numbers.as_ref().expect(explanation); - let secret_subshares = data.secret_subshares.as_ref() - .expect("nodes are filled during consensus establishing; session is completed after consensus is established; qed"); - let secret_share = math::compute_secret_share(secret_subshares.values().map(|ss| { - ss.as_ref().expect( - "complete_session is only called when subshares from all nodes are received; qed", - ) - }))?; - - let refreshed_key_version = DocumentKeyShareVersion::new(id_numbers.clone().into_iter().map(|(k, v)| (k.clone(), - v.expect("id_numbers are checked to have Some value for every consensus group node when consensus is establishe; qed"))).collect(), - secret_share); - let mut refreshed_key_share = core.key_share.as_ref().cloned().unwrap_or_else(|| { - let new_key_share = data.new_key_share.as_ref() - .expect("this is new node; on new nodes this field is filled before KRD; session is completed after KRD; qed"); - DocumentKeyShare { - author: new_key_share.author.clone(), - threshold: new_key_share.threshold, - public: new_key_share.joint_public.clone(), - common_point: new_key_share.common_point.clone(), - encrypted_point: new_key_share.encrypted_point.clone(), - versions: Vec::new(), - } - }); - refreshed_key_share.versions.push(refreshed_key_version); - - // save encrypted data to the key storage - data.state = SessionState::Finished; - if core.key_share.is_some() { - core.key_storage - .update(core.meta.id.clone(), refreshed_key_share.clone())?; - } else { - core.key_storage - .insert(core.meta.id.clone(), refreshed_key_share.clone())?; - } - - // signal session completion - data.state = SessionState::Finished; - data.result = Some(Ok(())); - core.completed.notify_all(); - - Ok(()) - } -} - -impl ClusterSession for SessionImpl -where - T: SessionTransport, -{ - type Id = SessionId; - - fn type_name() -> &'static str { - "share add" - } - - fn id(&self) -> SessionId { - self.core.meta.id.clone() - } - - fn is_finished(&self) -> bool { - self.data.lock().state == SessionState::Finished - } - - fn on_session_timeout(&self) { - self.on_session_error(&self.core.meta.self_node_id, Error::NodeDisconnected) - } - - fn on_node_timeout(&self, node: &NodeId) { - self.on_session_error(node, Error::NodeDisconnected) - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - // error in generation session is considered fatal - // => broadcast error if error occured on this node - if *node == self.core.meta.self_node_id { - for node in self.core.transport.nodes() { - // do not bother processing send error, as we already processing error - let _ = self.core.transport.send( - &node, - ShareAddMessage::ShareAddError(ShareAddError { - session: self.core.meta.id.clone().into(), - session_nonce: self.core.nonce, - error: error.clone().into(), - }), - ); - } - } - - let mut data = self.data.lock(); - - warn!(target: "secretstore_net", "{}: share add session failed: {} on {}", - self.core.meta.self_node_id, error, node); - - data.state = SessionState::Finished; - data.result = Some(Err(error)); - self.core.completed.notify_all(); - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::ShareAdd(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl IsolatedSessionTransport { - pub fn new( - session_id: SessionId, - version: Option, - nonce: u64, - cluster: Arc, - ) -> Self { - IsolatedSessionTransport { - session: session_id, - version: version, - nonce: nonce, - cluster: cluster, - id_numbers: None, - version_holders: None, - consensus_group: None, - } - } -} - -impl JobTransport for IsolatedSessionTransport { - type PartialJobRequest = ServersSetChangeAccessRequest; - type PartialJobResponse = bool; - - fn send_partial_request( - &self, - node: &NodeId, - request: ServersSetChangeAccessRequest, - ) -> Result<(), Error> { - let explanation = "partial requests are sent from master node only; on master node this field is filled during creation; qed"; - let id_numbers = self.id_numbers.as_ref().expect(explanation); - - self.cluster.send(node, Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage(ShareAddConsensusMessage { - session: self.session.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessageOfShareAdd::InitializeConsensusSession(InitializeConsensusSessionOfShareAdd { - version: self.version.clone().expect(explanation).into(), - version_holders: self.version_holders.as_ref().expect(explanation).iter().cloned().map(Into::into).collect(), - consensus_group: self.consensus_group.as_ref().expect(explanation).iter().cloned().map(Into::into).collect(), - old_nodes_set: request.old_servers_set.into_iter().map(Into::into).collect(), - new_nodes_map: request.new_servers_set.into_iter() - .filter_map(|n| id_numbers.get(&n) - .map(|id| (n.into(), id.clone() - .expect("partial requests are sent from master node only after consensus is established; - on master id_numbers are initialized with Some id_number for every consensus group node; qed").into()))) - .collect(), - old_set_signature: request.old_set_signature.into(), - new_set_signature: request.new_set_signature.into(), - }), - }))) - } - - fn send_partial_response(&self, node: &NodeId, response: bool) -> Result<(), Error> { - self.cluster.send( - node, - Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage( - ShareAddConsensusMessage { - session: self.session.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessageOfShareAdd::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: response, - }, - ), - }, - )), - ) - } -} - -impl SessionTransport for IsolatedSessionTransport { - fn nodes(&self) -> BTreeSet { - self.cluster.nodes() - } - - fn set_master_data( - &mut self, - consensus_group: BTreeSet, - version_holders: BTreeSet, - id_numbers: BTreeMap>, - ) { - self.version_holders = Some(version_holders); - self.consensus_group = Some(consensus_group); - self.id_numbers = Some(id_numbers); - } - - fn send(&self, node: &NodeId, message: ShareAddMessage) -> Result<(), Error> { - self.cluster.send(node, Message::ShareAdd(message)) - } -} - -#[cfg(test)] -pub mod tests { - use super::{IsolatedSessionTransport, SessionImpl, SessionParams}; - use ethkey::{Generator, Public, Random}; - use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::tests::MessageLoop as ClusterMessageLoop, - servers_set_change_session::tests::{generate_key, AdminSessionAdapter, MessageLoop}, - Error, KeyStorage, NodeId, NodeKeyPair, - }; - use std::collections::BTreeSet; - - struct Adapter; - - impl AdminSessionAdapter> for Adapter { - const SIGN_NEW_NODES: bool = false; - - fn create( - mut meta: ShareChangeSessionMeta, - admin_public: Public, - _: BTreeSet, - ml: &ClusterMessageLoop, - idx: usize, - ) -> SessionImpl { - let key_storage = ml.key_storage(idx).clone(); - let key_version = key_storage - .get(&meta.id) - .unwrap() - .map(|ks| ks.last_version().unwrap().hash); - - meta.self_node_id = *ml.node_key_pair(idx).public(); - SessionImpl::new(SessionParams { - meta: meta.clone(), - transport: IsolatedSessionTransport::new( - meta.id, - key_version, - 1, - ml.cluster(idx).view().unwrap(), - ), - key_storage, - admin_public: Some(admin_public), - nonce: 1, - }) - .unwrap() - } - } - - impl MessageLoop> { - pub fn init_at(self, master: NodeId) -> Result { - self.sessions[&master].initialize( - Some(self.original_key_version), - Some(self.new_nodes_set.clone()), - Some(self.all_set_signature.clone()), - Some(self.new_set_signature.clone()), - )?; - Ok(self) - } - - pub fn run_at(self, master: NodeId) -> Result { - let mut ml = self.init_at(master)?; - ml.run(); - Ok(ml) - } - } - - #[test] - fn node_add_fails_if_nodes_removed() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // try to remove 1 node - let add = vec![Random.generate().unwrap()]; - let remove: BTreeSet<_> = ::std::iter::once(gml.0.node(1)).collect(); - let master = gml.0.node(0); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), Some(remove), None) - .run_at(master) - .unwrap_err(), - Error::ConsensusUnreachable - ); - } - - #[test] - fn node_add_fails_if_no_nodes_added() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // try to add 0 nodes - let add = vec![]; - let master = gml.0.node(0); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), None, None) - .run_at(master) - .unwrap_err(), - Error::ConsensusUnreachable - ); - } - - #[test] - fn node_add_fails_if_started_on_adding_node() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // try to add 1 node using this node as a master node - let add = vec![Random.generate().unwrap()]; - let master = *add[0].public(); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), None, None) - .run_at(master) - .unwrap_err(), - Error::ServerKeyIsNotFound - ); - } - - #[test] - fn node_add_fails_if_initialized_twice() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // try to add 1 node using this node as a master node - let add = vec![Random.generate().unwrap()]; - let master = gml.0.node(0); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), None, None) - .init_at(master) - .unwrap() - .init_at(master) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn node_add_fails_if_started_without_signatures() { - // initial 2-of-3 session - let gml = generate_key(3, 1); - - // try to add 1 node using this node as a master node - let add = vec![Random.generate().unwrap()]; - let master = gml.0.node(0); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), None, None).sessions[&master] - .initialize(None, None, None, None) - .unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn nodes_added_using_share_add() { - let test_cases = vec![(3, 1), (3, 3)]; - for (n, add) in test_cases { - // generate key - let gml = generate_key(n, 1); - - // run share add session - let add = (0..add).map(|_| Random.generate().unwrap()).collect(); - let master = gml.0.node(0); - let ml = MessageLoop::with_gml::(gml, master, Some(add), None, None) - .run_at(master) - .unwrap(); - - // check that secret is still the same as before adding the share - ml.check_secret_is_preserved(ml.sessions.keys()); - } - } - - #[test] - fn nodes_added_using_share_add_with_isolated_nodes() { - let (n, add) = (3, 3); - - // generate key - let gml = generate_key(n, 1); - - // run share add session - let master = gml.0.node(0); - let node_to_isolate = gml.0.node(1); - let add = (0..add).map(|_| Random.generate().unwrap()).collect(); - let isolate = ::std::iter::once(node_to_isolate).collect(); - let ml = MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) - .run_at(master) - .unwrap(); - - // check that secret is still the same as before adding the share - ml.check_secret_is_preserved(ml.sessions.keys()); - } - - #[test] - fn nodes_add_to_the_node_with_obsolete_version() { - let (n, add) = (3, 3); - - // generate key - let gml = generate_key(n, 1); - - // run share add session - let master = gml.0.node(0); - let node_to_isolate_key_pair = gml.0.node_key_pair(1).clone(); - let node_to_isolate = gml.0.node(1); - let isolated_key_storage = gml.0.key_storage(1).clone(); - let mut oldest_nodes_set = gml.0.nodes(); - oldest_nodes_set.remove(&node_to_isolate); - let add = (0..add) - .map(|_| Random.generate().unwrap()) - .collect::>(); - let newest_nodes_set = add.iter().map(|kp| *kp.public()).collect::>(); - let isolate = ::std::iter::once(node_to_isolate).collect(); - let ml = MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) - .run_at(master) - .unwrap(); - let new_key_version = ml - .ml - .key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .last_version() - .unwrap() - .hash; - - // now let's add back old node so that key becames 2-of-6 - let add = vec![node_to_isolate_key_pair.key_pair().clone()]; - let mut ml = ml.and_then::(master.clone(), Some(add), None, None); - ml.original_key_version = new_key_version; - ml.ml - .replace_key_storage_of(&node_to_isolate, isolated_key_storage.clone()); - ml.sessions - .get_mut(&node_to_isolate) - .unwrap() - .core - .key_share = isolated_key_storage.get(&Default::default()).unwrap(); - ml.sessions - .get_mut(&node_to_isolate) - .unwrap() - .core - .key_storage = isolated_key_storage; - let ml = ml.run_at(master).unwrap(); - - // check that secret is still the same as before adding the share - ml.check_secret_is_preserved(ml.sessions.keys()); - - // check that all oldest nodes have versions A, B, C - // isolated node has version A, C - // new nodes have versions B, C - let oldest_key_share = ml - .ml - .key_storage_of(oldest_nodes_set.iter().nth(0).unwrap()) - .get(&Default::default()) - .unwrap() - .unwrap(); - debug_assert_eq!(oldest_key_share.versions.len(), 3); - let version_a = oldest_key_share.versions[0].hash.clone(); - let version_b = oldest_key_share.versions[1].hash.clone(); - let version_c = oldest_key_share.versions[2].hash.clone(); - debug_assert!(version_a != version_b && version_b != version_c); - - debug_assert!(oldest_nodes_set.iter().all(|n| vec![ - version_a.clone(), - version_b.clone(), - version_c.clone() - ] == ml - .ml - .key_storage_of(n) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .map(|v| v.hash) - .collect::>())); - debug_assert!(::std::iter::once(&node_to_isolate).all(|n| vec![ - version_a.clone(), - version_c.clone() - ] == ml - .ml - .key_storage_of(n) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .map(|v| v.hash) - .collect::>())); - debug_assert!(newest_nodes_set - .iter() - .all(|n| vec![version_b.clone(), version_c.clone()] - == ml - .ml - .key_storage_of(n) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .map(|v| v.hash) - .collect::>())); - } - - #[test] - fn nodes_add_fails_when_not_enough_share_owners_are_connected() { - let (n, add) = (3, 3); - - // generate key - let gml = generate_key(n, 1); - - // run share add session - let master = gml.0.node(0); - let add = (0..add) - .map(|_| Random.generate().unwrap()) - .collect::>(); - let isolate = vec![gml.0.node(1), gml.0.node(2)].into_iter().collect(); - assert_eq!( - MessageLoop::with_gml::(gml, master, Some(add), None, Some(isolate)) - .run_at(master) - .unwrap_err(), - Error::ConsensusUnreachable - ); - } -} diff --git a/secret-store/src/key_server_cluster/admin_sessions/share_change_session.rs b/secret-store/src/key_server_cluster/admin_sessions/share_change_session.rs deleted file mode 100644 index 336a2e0d85..0000000000 --- a/secret-store/src/key_server_cluster/admin_sessions/share_change_session.rs +++ /dev/null @@ -1,431 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::Secret; -use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::Cluster, - cluster_sessions::ClusterSession, - jobs::{ - job_session::JobTransport, servers_set_change_access_job::ServersSetChangeAccessRequest, - }, - math, - message::{Message, ServersSetChangeMessage, ServersSetChangeShareAddMessage, ShareAddMessage}, - share_add_session::{ - SessionImpl as ShareAddSessionImpl, SessionParams as ShareAddSessionParams, - SessionTransport as ShareAddSessionTransport, - }, - Error, KeyStorage, NodeId, ServerKeyId, SessionId, -}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Single session meta-change session. Brief overview: -/// 1) nodes that have been already removed from cluster (isolated nodes) are removed from session -/// 2) new shares are added to the session -/// 3) shares are moved between nodes -/// 4) shares are removed from nodes -pub struct ShareChangeSession { - /// Servers set change session id. - session_id: SessionId, - /// Session nonce. - nonce: u64, - /// Share change session meta. - meta: ShareChangeSessionMeta, - /// Cluster. - cluster: Arc, - /// Key storage. - key_storage: Arc, - /// Key version. - key_version: H256, - /// Nodes that have reported version ownership. - version_holders: Option>, - /// Consensus group to use in ShareAdd session. - consensus_group: Option>, - /// Nodes to add shares for. - new_nodes_map: Option>>, - /// Share add session. - share_add_session: Option>, - /// Is finished. - is_finished: bool, -} - -/// Share change session plan. -#[derive(Debug)] -pub struct ShareChangeSessionPlan { - /// Key version that plan is valid for. - pub key_version: H256, - /// Nodes that have reported version ownership. - pub version_holders: BTreeSet, - /// Consensus group to use in ShareAdd session. - pub consensus_group: BTreeSet, - /// Nodes to add shares for. - pub new_nodes_map: BTreeMap>, -} - -/// Session parameters. -pub struct ShareChangeSessionParams { - /// Servers set change session id. - pub session_id: SessionId, - /// Session nonce. - pub nonce: u64, - /// Share change session meta. - pub meta: ShareChangeSessionMeta, - /// Cluster. - pub cluster: Arc, - /// Keys storage. - pub key_storage: Arc, - /// Session plan. - pub plan: ShareChangeSessionPlan, -} - -/// Share add session transport. -#[derive(Clone)] -pub struct ShareChangeTransport { - /// Servers set change session id. - session_id: SessionId, - /// Session nonce. - nonce: u64, - /// Cluster. - cluster: Arc, -} - -impl ShareChangeSession { - /// Create new share change session. - pub fn new(params: ShareChangeSessionParams) -> Result { - // we can't create sessions right now, because key share is read when session is created, but it can change in previous session - let key_version = params.plan.key_version; - let consensus_group = if !params.plan.consensus_group.is_empty() { - Some(params.plan.consensus_group) - } else { - None - }; - let version_holders = if !params.plan.version_holders.is_empty() { - Some(params.plan.version_holders) - } else { - None - }; - let new_nodes_map = if !params.plan.new_nodes_map.is_empty() { - Some(params.plan.new_nodes_map) - } else { - None - }; - debug_assert!(new_nodes_map.is_some()); - - let is_finished = new_nodes_map.is_none(); - Ok(ShareChangeSession { - session_id: params.session_id, - nonce: params.nonce, - meta: params.meta, - cluster: params.cluster, - key_storage: params.key_storage, - key_version: key_version, - version_holders: version_holders, - consensus_group: consensus_group, - new_nodes_map: new_nodes_map, - share_add_session: None, - is_finished: is_finished, - }) - } - - /// Is finished?. - pub fn is_finished(&self) -> bool { - self.is_finished - } - - /// Is master node?. - pub fn is_master(&self) -> bool { - self.meta.self_node_id == self.meta.master_node_id - } - - /// Initialize session (on master node). - pub fn initialize(&mut self) -> Result<(), Error> { - self.proceed_to_next_state() - } - - /// When share-add message is received. - pub fn on_share_add_message( - &mut self, - sender: &NodeId, - message: &ShareAddMessage, - ) -> Result<(), Error> { - if self.share_add_session.is_none() { - self.create_share_add_session()?; - } - - let change_state_needed = self - .share_add_session - .as_ref() - .map(|share_add_session| { - let was_finished = share_add_session.is_finished(); - share_add_session - .process_message(sender, message) - .map(|_| share_add_session.is_finished() && !was_finished) - }) - .unwrap_or(Err(Error::InvalidMessage))?; - if change_state_needed { - self.proceed_to_next_state()?; - } - - Ok(()) - } - - /// Create new share add session. - fn create_share_add_session(&mut self) -> Result<(), Error> { - let consensus_group = self - .consensus_group - .take() - .ok_or(Error::InvalidStateForRequest)?; - let version_holders = self - .version_holders - .take() - .ok_or(Error::InvalidStateForRequest)?; - let new_nodes_map = self - .new_nodes_map - .take() - .ok_or(Error::InvalidStateForRequest)?; - let share_add_session = ShareAddSessionImpl::new(ShareAddSessionParams { - meta: self.meta.clone(), - nonce: self.nonce, - transport: ShareChangeTransport::new(self.session_id, self.nonce, self.cluster.clone()), - key_storage: self.key_storage.clone(), - admin_public: None, - })?; - share_add_session.set_consensus_output( - &self.key_version, - consensus_group, - version_holders, - new_nodes_map, - )?; - self.share_add_session = Some(share_add_session); - Ok(()) - } - - /// Proceed to the next state. - fn proceed_to_next_state(&mut self) -> Result<(), Error> { - if self.meta.self_node_id != self.meta.master_node_id { - if self.new_nodes_map.is_none() { - self.is_finished = true; - } - return Ok(()); - } - - if self.new_nodes_map.is_some() { - self.create_share_add_session()?; - return self - .share_add_session - .as_ref() - .expect("either create_share_add_session fails, or session is created; qed") - .initialize(None, None, None, None); - } - - self.is_finished = true; - - Ok(()) - } -} - -impl ShareChangeTransport { - pub fn new(session_id: SessionId, nonce: u64, cluster: Arc) -> Self { - ShareChangeTransport { - session_id: session_id, - nonce: nonce, - cluster: cluster, - } - } -} - -impl JobTransport for ShareChangeTransport { - type PartialJobRequest = ServersSetChangeAccessRequest; - type PartialJobResponse = bool; - - fn send_partial_request( - &self, - _node: &NodeId, - _request: ServersSetChangeAccessRequest, - ) -> Result<(), Error> { - unreachable!("only called when establishing consensus; this transport is never used for establishing consensus; qed") - } - - fn send_partial_response(&self, _node: &NodeId, _response: bool) -> Result<(), Error> { - unreachable!("only called when establishing consensus; this transport is never used for establishing consensus; qed") - } -} - -impl ShareAddSessionTransport for ShareChangeTransport { - fn nodes(&self) -> BTreeSet { - self.cluster.nodes() - } - - fn set_master_data( - &mut self, - _consensus_group: BTreeSet, - _version_holders: BTreeSet, - _id_numbers: BTreeMap>, - ) { - unreachable!("only called when establishing consensus; this transport is never used for establishing consensus; qed") - } - - fn send(&self, node: &NodeId, message: ShareAddMessage) -> Result<(), Error> { - self.cluster.send( - node, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeShareAddMessage( - ServersSetChangeShareAddMessage { - session: self.session_id.clone().into(), - session_nonce: self.nonce, - message: message, - }, - )), - ) - } -} - -/// Prepare share change plan for moving from old `old_key_version_owners` to `new_nodes_set`. -pub fn prepare_share_change_session_plan( - cluster_nodes: &BTreeSet, - threshold: usize, - key_id: &ServerKeyId, - key_version: H256, - master: &NodeId, - old_key_version_owners: &BTreeSet, - new_nodes_set: &BTreeSet, -) -> Result { - // we can't do anything if there are no enought shares - if old_key_version_owners.len() < threshold + 1 { - warn!( - "cannot add shares to key {} with threshold {}: only {} shares owners are available", - key_id, - threshold, - old_key_version_owners.len() - ); - return Ok(ShareChangeSessionPlan { - key_version: key_version, - version_holders: Default::default(), - consensus_group: Default::default(), - new_nodes_map: Default::default(), - }); - } - - // warn if we're loosing the key - if new_nodes_set.len() < threshold + 1 { - warn!( - "losing key {} with threshold {}: only {} nodes left after servers set change session", - key_id, - threshold, - new_nodes_set.len() - ); - } - - // make new nodes map, so that: - // all non-isolated old nodes will have their id number preserved - // all new nodes will have new id number - let mut new_nodes_map = new_nodes_set - .difference(&old_key_version_owners) - .map(|n| math::generate_random_scalar().map(|id| (n.clone(), Some(id)))) - .collect::, _>>()?; - if !new_nodes_map.is_empty() { - for old_node in old_key_version_owners - .iter() - .filter(|n| cluster_nodes.contains(n)) - { - new_nodes_map.insert(old_node.clone(), None); - } - } - - // select consensus group if there are some nodes to add - let consensus_group = if !new_nodes_map.is_empty() { - ::std::iter::once(master.clone()) - .chain( - old_key_version_owners - .iter() - .filter(|n| *n != master && cluster_nodes.contains(*n)) - .take(threshold) - .cloned(), - ) - .collect() - } else { - BTreeSet::new() - }; - - Ok(ShareChangeSessionPlan { - key_version: key_version, - version_holders: old_key_version_owners.clone(), - consensus_group: consensus_group, - new_nodes_map: new_nodes_map, - }) -} - -impl ShareChangeSessionPlan { - /// Is empty (nothing-to-do) plan? - pub fn is_empty(&self) -> bool { - self.new_nodes_map.is_empty() - } -} - -#[cfg(test)] -mod tests { - use super::prepare_share_change_session_plan; - use key_server_cluster::math; - - #[test] - fn share_change_plan_creates_empty_plan() { - let cluster_nodes: Vec<_> = (0..3) - .map(|_| math::generate_random_point().unwrap()) - .collect(); - let master = cluster_nodes[0].clone(); - let old_key_version_owners = cluster_nodes.iter().cloned().collect(); - let new_nodes_set = cluster_nodes.iter().cloned().collect(); - let plan = prepare_share_change_session_plan( - &cluster_nodes.iter().cloned().collect(), - 1, - &Default::default(), - Default::default(), - &master, - &old_key_version_owners, - &new_nodes_set, - ) - .unwrap(); - - assert!(plan.is_empty()); - } - - #[test] - fn share_change_plan_adds_new_nodes() { - let cluster_nodes: Vec<_> = (0..3) - .map(|_| math::generate_random_point().unwrap()) - .collect(); - let master = cluster_nodes[0].clone(); - let old_key_version_owners = cluster_nodes[0..2].iter().cloned().collect(); - let new_nodes_set = cluster_nodes.iter().cloned().collect(); - let plan = prepare_share_change_session_plan( - &cluster_nodes.iter().cloned().collect(), - 1, - &Default::default(), - Default::default(), - &master, - &old_key_version_owners, - &new_nodes_set, - ) - .unwrap(); - - assert!(!plan.is_empty()); - assert_eq!(old_key_version_owners, plan.consensus_group); - assert_eq!(new_nodes_set, plan.new_nodes_map.keys().cloned().collect()); - } -} diff --git a/secret-store/src/key_server_cluster/client_sessions/decryption_session.rs b/secret-store/src/key_server_cluster/client_sessions/decryption_session.rs deleted file mode 100644 index 6cd01b6068..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/decryption_session.rs +++ /dev/null @@ -1,2211 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::Secret; -use key_server_cluster::{ - cluster::Cluster, - cluster_sessions::{ClusterSession, SessionIdWithSubSession}, - jobs::{ - consensus_session::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}, - decryption_job::{DecryptionJob, PartialDecryptionRequest, PartialDecryptionResponse}, - job_session::{JobSession, JobSessionState, JobTransport}, - key_access_job::KeyAccessJob, - }, - message::{ - ConfirmConsensusInitialization, ConsensusMessage, DecryptionConsensusMessage, - DecryptionMessage, DecryptionSessionCompleted, DecryptionSessionDelegation, - DecryptionSessionDelegationCompleted, DecryptionSessionError, InitializeConsensusSession, - Message, PartialDecryption, RequestPartialDecryption, - }, - AclStorage, DocumentKeyShare, EncryptedDocumentKeyShadow, Error, NodeId, Requester, SessionId, - SessionMeta, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, - time, -}; - -/// Distributed decryption session. -/// Based on "ECDKG: A Distributed Key Generation Protocol Based on Elliptic Curve Discrete Logarithm" paper: -/// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.4128&rep=rep1&type=pdf -/// Brief overview: -/// 1) initialization: master node (which has received request for decrypting the secret) requests all other nodes to decrypt the secret -/// 2) ACL check: all nodes which have received the request are querying ACL-contract to check if requestor has access to the document -/// 3) partial decryption: every node which has succussfully checked access for the requestor do a partial decryption -/// 4) decryption: master node receives all partial decryptions of the secret and restores the secret -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex, -} - -/// Immutable session data. -struct SessionCore { - /// Session metadata. - pub meta: SessionMeta, - /// Decryption session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// Cluster which allows this node to send messages to other nodes in the cluster. - pub cluster: Arc, - /// Session-level nonce. - pub nonce: u64, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Decryption consensus session type. -type DecryptionConsensusSession = ConsensusSession< - KeyAccessJob, - DecryptionConsensusTransport, - DecryptionJob, - DecryptionJobTransport, ->; -/// Broadcast decryption job session type. -type BroadcastDecryptionJobSession = JobSession; - -/// Mutable session data. -struct SessionData { - /// Key version to use for decryption. - pub version: Option, - /// Session origin (if any). - pub origin: Option
, - /// Consensus-based decryption session. - pub consensus_session: DecryptionConsensusSession, - /// Broadcast decryption job. - pub broadcast_job_session: Option, - /// Is shadow decryption requested? - pub is_shadow_decryption: Option, - /// Decryption result must be reconstructed on all participating nodes. This is useful - /// for service contract API so that all nodes from consensus group can confirm decryption. - pub is_broadcast_session: Option, - /// Delegation status. - pub delegation_status: Option, - /// Decryption result. - pub result: Option>, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// Session metadata. - pub meta: SessionMeta, - /// Session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// ACL storage. - pub acl_storage: Arc, - /// Cluster. - pub cluster: Arc, - /// Session nonce. - pub nonce: u64, -} - -/// Decryption consensus transport. -struct DecryptionConsensusTransport { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Session origin (if any). - origin: Option
, - /// Selected key version (on master node). - version: Option, - /// Cluster. - cluster: Arc, -} - -/// Decryption job transport -struct DecryptionJobTransport { - /// Session id. - id: SessionId, - //// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Is this a broadcast transport? If true, requests are not send and responses are sent only to non-master nodes. - is_broadcast_transport: bool, - /// Master node id. - master_node_id: NodeId, - /// Cluster. - cluster: Arc, -} - -/// Session delegation status. -enum DelegationStatus { - /// Delegated to other node. - DelegatedTo(NodeId), - /// Delegated from other node. - DelegatedFrom(NodeId, u64), -} - -impl SessionImpl { - /// Create new decryption session. - pub fn new(params: SessionParams, requester: Option) -> Result { - debug_assert_eq!( - params.meta.threshold, - params - .key_share - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default() - ); - - // check that common_point and encrypted_point are already set - if let Some(key_share) = params.key_share.as_ref() { - // encrypted data must be set - if key_share.common_point.is_none() || key_share.encrypted_point.is_none() { - return Err(Error::DocumentKeyIsNotFound); - } - } - - let consensus_transport = DecryptionConsensusTransport { - id: params.meta.id.clone(), - access_key: params.access_key.clone(), - nonce: params.nonce, - origin: None, - version: None, - cluster: params.cluster.clone(), - }; - let consensus_session = ConsensusSession::new(ConsensusSessionParams { - meta: params.meta.clone(), - consensus_executor: match requester { - Some(requester) => KeyAccessJob::new_on_master( - params.meta.id.clone(), - params.acl_storage.clone(), - requester, - ), - None => { - KeyAccessJob::new_on_slave(params.meta.id.clone(), params.acl_storage.clone()) - } - }, - consensus_transport: consensus_transport, - })?; - - Ok(SessionImpl { - core: SessionCore { - meta: params.meta, - access_key: params.access_key, - key_share: params.key_share, - cluster: params.cluster, - nonce: params.nonce, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - version: None, - origin: None, - consensus_session: consensus_session, - broadcast_job_session: None, - is_shadow_decryption: None, - is_broadcast_session: None, - delegation_status: None, - result: None, - }), - }) - } - - /// Get this node id. - #[cfg(test)] - pub fn node(&self) -> &NodeId { - &self.core.meta.self_node_id - } - - /// Get this session access key. - #[cfg(test)] - pub fn access_key(&self) -> &Secret { - &self.core.access_key - } - - /// Get session state. - #[cfg(test)] - pub fn state(&self) -> ConsensusSessionState { - self.data.lock().consensus_session.state() - } - - /// Get decrypted secret - #[cfg(test)] - pub fn decrypted_secret(&self) -> Option> { - self.data.lock().result.clone() - } - - /// Get key requester. - pub fn requester(&self) -> Option { - self.data - .lock() - .consensus_session - .consensus_job() - .executor() - .requester() - .cloned() - } - - /// Get session origin. - pub fn origin(&self) -> Option
{ - self.data.lock().origin.clone() - } - - /// Wait for session completion. - pub fn wait( - &self, - timeout: Option, - ) -> Option> { - Self::wait_session(&self.core.completed, &self.data, timeout, |data| { - data.result.clone() - }) - } - - /// Get broadcasted shadows. - pub fn broadcast_shadows(&self) -> Option>> { - let data = self.data.lock(); - - if data.result.is_none() - || (data.is_broadcast_session, data.is_shadow_decryption) != (Some(true), Some(true)) - { - return None; - } - - let proof = "data.is_shadow_decryption is true; decrypt_shadow.is_some() is checked in DecryptionJob::check_partial_response; qed"; - Some(match self.core.meta.master_node_id == self.core.meta.self_node_id { - true => data.consensus_session.computation_job().responses().iter() - .map(|(n, r)| (n.clone(), r.decrypt_shadow.clone().expect(proof))) - .collect(), - false => data.broadcast_job_session.as_ref().expect("session completed; is_shadow_decryption == true; we're on non-master node; qed").responses().iter() - .map(|(n, r)| (n.clone(), r.decrypt_shadow.clone().expect(proof))) - .collect(), - }) - } - - /// Delegate session to other node. - pub fn delegate( - &self, - master: NodeId, - origin: Option
, - version: H256, - is_shadow_decryption: bool, - is_broadcast_session: bool, - ) -> Result<(), Error> { - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(false); - self.core.cluster.send(&master, Message::Decryption(DecryptionMessage::DecryptionSessionDelegation(DecryptionSessionDelegation { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - origin: origin.map(Into::into), - requester: data.consensus_session.consensus_job().executor().requester() - .expect("signature is passed to master node on creation; session can be delegated from master node only; qed") - .clone().into(), - version: version.into(), - is_shadow_decryption: is_shadow_decryption, - is_broadcast_session: is_broadcast_session, - })))?; - data.delegation_status = Some(DelegationStatus::DelegatedTo(master)); - Ok(()) - } - - /// Initialize decryption session on master node. - pub fn initialize( - &self, - origin: Option
, - version: H256, - is_shadow_decryption: bool, - is_broadcast_session: bool, - ) -> Result<(), Error> { - debug_assert_eq!(self.core.meta.self_node_id, self.core.meta.master_node_id); - - // check if version exists - let key_version = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version)?, - }; - - let mut data = self.data.lock(); - let non_isolated_nodes = self.core.cluster.nodes(); - let mut consensus_nodes: BTreeSet<_> = key_version - .id_numbers - .keys() - .filter(|n| non_isolated_nodes.contains(*n)) - .cloned() - .chain(::std::iter::once(self.core.meta.self_node_id.clone())) - .collect(); - if let Some(&DelegationStatus::DelegatedFrom(delegation_master, _)) = - data.delegation_status.as_ref() - { - consensus_nodes.remove(&delegation_master); - } - - data.consensus_session - .consensus_job_mut() - .transport_mut() - .version = Some(version.clone()); - data.consensus_session - .consensus_job_mut() - .transport_mut() - .origin = origin.clone(); - data.origin = origin; - data.version = Some(version.clone()); - data.is_shadow_decryption = Some(is_shadow_decryption); - data.is_broadcast_session = Some(is_broadcast_session); - data.consensus_session.initialize(consensus_nodes)?; - - if data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished { - Self::disseminate_jobs( - &self.core, - &mut *data, - &version, - is_shadow_decryption, - is_broadcast_session, - )?; - - debug_assert!(data.consensus_session.state() == ConsensusSessionState::Finished); - let result = data.consensus_session.result()?; - Self::set_decryption_result(&self.core, &mut *data, Ok(result)); - } - - Ok(()) - } - - /// Process decryption message. - pub fn process_message( - &self, - sender: &NodeId, - message: &DecryptionMessage, - ) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &DecryptionMessage::DecryptionConsensusMessage(ref message) => { - self.on_consensus_message(sender, message) - } - &DecryptionMessage::RequestPartialDecryption(ref message) => { - self.on_partial_decryption_requested(sender, message) - } - &DecryptionMessage::PartialDecryption(ref message) => { - self.on_partial_decryption(sender, message) - } - &DecryptionMessage::DecryptionSessionError(ref message) => { - self.process_node_error(Some(&sender), message.error.clone()) - } - &DecryptionMessage::DecryptionSessionCompleted(ref message) => { - self.on_session_completed(sender, message) - } - &DecryptionMessage::DecryptionSessionDelegation(ref message) => { - self.on_session_delegated(sender, message) - } - &DecryptionMessage::DecryptionSessionDelegationCompleted(ref message) => { - self.on_session_delegation_completed(sender, message) - } - } - } - - /// When session is delegated to this node. - pub fn on_session_delegated( - &self, - sender: &NodeId, - message: &DecryptionSessionDelegation, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - { - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_requester(message.requester.clone().into()); - data.delegation_status = Some(DelegationStatus::DelegatedFrom( - sender.clone(), - message.session_nonce, - )); - } - - self.initialize( - message.origin.clone().map(Into::into), - message.version.clone().into(), - message.is_shadow_decryption, - message.is_broadcast_session, - ) - } - - /// When delegated session is completed on other node. - pub fn on_session_delegation_completed( - &self, - sender: &NodeId, - message: &DecryptionSessionDelegationCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(ref node)) if node == sender => (), - _ => return Err(Error::InvalidMessage), - } - - Self::set_decryption_result( - &self.core, - &mut *data, - Ok(EncryptedDocumentKeyShadow { - decrypted_secret: message.decrypted_secret.clone().into(), - common_point: message.common_point.clone().map(Into::into), - decrypt_shadows: message.decrypt_shadows.clone().map(Into::into), - }), - ); - - Ok(()) - } - - /// When consensus-related message is received. - pub fn on_consensus_message( - &self, - sender: &NodeId, - message: &DecryptionConsensusMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - let mut data = self.data.lock(); - let is_establishing_consensus = - data.consensus_session.state() == ConsensusSessionState::EstablishingConsensus; - if let &ConsensusMessage::InitializeConsensusSession(ref msg) = &message.message { - let version = msg.version.clone().into(); - let has_key_share = self - .core - .key_share - .as_ref() - .map(|ks| ks.version(&version).is_ok()) - .unwrap_or(false); - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(has_key_share); - data.version = Some(version); - data.origin = message.origin.clone().map(Into::into); - } - data.consensus_session - .on_consensus_message(&sender, &message.message)?; - - let is_consensus_established = - data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished; - if self.core.meta.self_node_id != self.core.meta.master_node_id - || !is_establishing_consensus - || !is_consensus_established - { - return Ok(()); - } - - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let is_shadow_decryption = data.is_shadow_decryption - .expect("we are on master node; on master node is_shadow_decryption is filled in initialize(); on_consensus_message follows initialize (state check in consensus_session); qed"); - let is_broadcast_session = data.is_broadcast_session - .expect("we are on master node; on master node is_broadcast_session is filled in initialize(); on_consensus_message follows initialize (state check in consensus_session); qed"); - Self::disseminate_jobs( - &self.core, - &mut *data, - &version, - is_shadow_decryption, - is_broadcast_session, - ) - } - - /// When partial decryption is requested. - pub fn on_partial_decryption_requested( - &self, - sender: &NodeId, - message: &RequestPartialDecryption, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let key_share = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let mut data = self.data.lock(); - let key_version = key_share - .version(data.version.as_ref().ok_or(Error::InvalidMessage)?)? - .hash - .clone(); - let requester_public = data - .consensus_session - .consensus_job() - .executor() - .requester() - .ok_or(Error::InvalidStateForRequest)? - .public(&self.core.meta.id) - .map_err(Error::InsufficientRequesterData)?; - let decryption_job = DecryptionJob::new_on_slave( - self.core.meta.self_node_id.clone(), - self.core.access_key.clone(), - requester_public.clone(), - key_share.clone(), - key_version, - )?; - let decryption_transport = self.core.decryption_transport(false); - - // update flags if not on master - if self.core.meta.self_node_id != self.core.meta.master_node_id { - data.is_shadow_decryption = Some(message.is_shadow_decryption); - data.is_broadcast_session = Some(message.is_broadcast_session); - } - - // respond to request - let partial_decryption = data.consensus_session.on_job_request( - sender, - PartialDecryptionRequest { - id: message.request_id.clone().into(), - is_shadow_decryption: message.is_shadow_decryption, - is_broadcast_session: message.is_broadcast_session, - other_nodes_ids: message.nodes.iter().cloned().map(Into::into).collect(), - }, - decryption_job, - decryption_transport, - )?; - - // ...and prepare decryption job session if we need to broadcast result - if message.is_broadcast_session { - let consensus_group: BTreeSet<_> = - message.nodes.iter().cloned().map(Into::into).collect(); - let broadcast_decryption_job = DecryptionJob::new_on_master( - self.core.meta.self_node_id.clone(), - self.core.access_key.clone(), - requester_public, - key_share.clone(), - key_version, - message.is_shadow_decryption, - message.is_broadcast_session, - )?; - Self::create_broadcast_decryption_job( - &self.core, - &mut *data, - consensus_group, - broadcast_decryption_job, - message.request_id.clone().into(), - Some(partial_decryption.take_response()), - )?; - } - - Ok(()) - } - - /// When partial decryption is received. - pub fn on_partial_decryption( - &self, - sender: &NodeId, - message: &PartialDecryption, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - let is_master_node = self.core.meta.self_node_id == self.core.meta.master_node_id; - let result = if is_master_node { - data.consensus_session.on_job_response( - sender, - PartialDecryptionResponse { - request_id: message.request_id.clone().into(), - shadow_point: message.shadow_point.clone().into(), - decrypt_shadow: message.decrypt_shadow.clone(), - }, - )?; - - if data.consensus_session.state() != ConsensusSessionState::Finished - && data.consensus_session.state() != ConsensusSessionState::Failed - { - return Ok(()); - } - - // send completion signal to all nodes, except for rejected nodes - if is_master_node { - for node in data.consensus_session.consensus_non_rejected_nodes() { - self.core.cluster.send( - &node, - Message::Decryption(DecryptionMessage::DecryptionSessionCompleted( - DecryptionSessionCompleted { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - }, - )), - )?; - } - } - - data.consensus_session.result() - } else { - match data.broadcast_job_session.as_mut() { - Some(broadcast_job_session) => { - broadcast_job_session.on_partial_response( - sender, - PartialDecryptionResponse { - request_id: message.request_id.clone().into(), - shadow_point: message.shadow_point.clone().into(), - decrypt_shadow: message.decrypt_shadow.clone(), - }, - )?; - - if broadcast_job_session.state() != JobSessionState::Finished - && broadcast_job_session.state() != JobSessionState::Failed - { - return Ok(()); - } - - broadcast_job_session.result() - } - None => return Err(Error::InvalidMessage), - } - }; - - Self::set_decryption_result(&self.core, &mut *data, result); - - Ok(()) - } - - /// When session is completed. - pub fn on_session_completed( - &self, - sender: &NodeId, - message: &DecryptionSessionCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - // if it is a broadcast session, wait for all answers before completing the session - let decryption_result = match data.broadcast_job_session.as_ref() { - Some(broadcast_job_session) => { - if !broadcast_job_session.is_result_ready() { - return Err(Error::TooEarlyForRequest); - } - - Some(broadcast_job_session.result()) - } - None => None, - }; - if let Some(decryption_result) = decryption_result { - Self::set_decryption_result(&self.core, &mut *data, decryption_result); - } - - data.consensus_session.on_session_completed(sender) - } - - /// Process error from the other node. - fn process_node_error(&self, node: Option<&NodeId>, error: Error) -> Result<(), Error> { - let mut data = self.data.lock(); - let is_self_node_error = node - .map(|n| n == &self.core.meta.self_node_id) - .unwrap_or(false); - // error is always fatal if coming from this node - if is_self_node_error { - Self::set_decryption_result(&self.core, &mut *data, Err(error.clone())); - return Err(error); - } - - match { - match node { - Some(node) => data.consensus_session.on_node_error(node, error.clone()), - None => data.consensus_session.on_session_timeout(), - } - } { - Ok(false) => Ok(()), - Ok(true) => { - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let proof = "on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when is_shadow_decryption.is_some(); qed"; - let is_shadow_decryption = data.is_shadow_decryption.expect(proof); - let is_broadcast_session = data.is_broadcast_session.expect(proof); - let disseminate_result = Self::disseminate_jobs( - &self.core, - &mut *data, - &version, - is_shadow_decryption, - is_broadcast_session, - ); - match disseminate_result { - Ok(()) => Ok(()), - Err(err) => { - warn!( - "{}: decryption session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - - Self::set_decryption_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - Err(err) => { - warn!( - "{}: decryption session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - - Self::set_decryption_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - - /// Disseminate jobs on session master. - fn disseminate_jobs( - core: &SessionCore, - data: &mut SessionData, - version: &H256, - is_shadow_decryption: bool, - is_broadcast_session: bool, - ) -> Result<(), Error> { - let key_share = match core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let key_version = key_share.version(version)?.hash.clone(); - let requester = data - .consensus_session - .consensus_job() - .executor() - .requester() - .ok_or(Error::InvalidStateForRequest)? - .clone(); - let requester_public = requester - .public(&core.meta.id) - .map_err(Error::InsufficientRequesterData)?; - let consensus_group = data.consensus_session.select_consensus_group()?.clone(); - let decryption_job = DecryptionJob::new_on_master( - core.meta.self_node_id.clone(), - core.access_key.clone(), - requester_public.clone(), - key_share.clone(), - key_version, - is_shadow_decryption, - is_broadcast_session, - )?; - let decryption_request_id = decryption_job.request_id().clone() - .expect("DecryptionJob always have request_id when created on master; it is created using new_on_master above; qed"); - let decryption_transport = core.decryption_transport(false); - let is_broadcast_session = data.is_broadcast_session - .expect("disseminate_jobs is called on master node only; on master node is_broadcast_session is filled during initialization; qed"); - let self_response = data.consensus_session.disseminate_jobs( - decryption_job, - decryption_transport, - is_broadcast_session, - )?; - - // ...and prepare decryption job session if we need to broadcast result - if is_broadcast_session { - let broadcast_decryption_job = DecryptionJob::new_on_master( - core.meta.self_node_id.clone(), - core.access_key.clone(), - requester_public, - key_share.clone(), - key_version, - is_shadow_decryption, - is_broadcast_session, - )?; - Self::create_broadcast_decryption_job( - &core, - data, - consensus_group, - broadcast_decryption_job, - decryption_request_id, - self_response, - )?; - } - - Ok(()) - } - - /// Create broadcast decryption job. - fn create_broadcast_decryption_job( - core: &SessionCore, - data: &mut SessionData, - mut consensus_group: BTreeSet, - mut job: DecryptionJob, - request_id: Secret, - self_response: Option, - ) -> Result<(), Error> { - consensus_group.insert(core.meta.self_node_id.clone()); - job.set_request_id(request_id.clone().into()); - - let transport = core.decryption_transport(true); - let mut job_session = JobSession::new( - SessionMeta { - id: core.meta.id.clone(), - master_node_id: core.meta.self_node_id.clone(), - self_node_id: core.meta.self_node_id.clone(), - threshold: core.meta.threshold, - configured_nodes_count: core.meta.configured_nodes_count, - connected_nodes_count: core.meta.connected_nodes_count, - }, - job, - transport, - ); - job_session.initialize( - consensus_group, - self_response, - core.meta.self_node_id != core.meta.master_node_id, - )?; - data.broadcast_job_session = Some(job_session); - - Ok(()) - } - - /// Set decryption result. - fn set_decryption_result( - core: &SessionCore, - data: &mut SessionData, - result: Result, - ) { - if let Some(DelegationStatus::DelegatedFrom(master, nonce)) = data.delegation_status.take() - { - // error means can't communicate => ignore it - let _ = match result.as_ref() { - Ok(document_key) => core.cluster.send( - &master, - Message::Decryption(DecryptionMessage::DecryptionSessionDelegationCompleted( - DecryptionSessionDelegationCompleted { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - decrypted_secret: document_key.decrypted_secret.clone().into(), - common_point: document_key.common_point.clone().map(Into::into), - decrypt_shadows: document_key.decrypt_shadows.clone(), - }, - )), - ), - Err(error) => core.cluster.send( - &master, - Message::Decryption(DecryptionMessage::DecryptionSessionError( - DecryptionSessionError { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - error: error.clone().into(), - }, - )), - ), - }; - } - - data.result = Some(result); - core.completed.notify_all(); - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionIdWithSubSession; - - fn type_name() -> &'static str { - "decryption" - } - - fn id(&self) -> SessionIdWithSubSession { - SessionIdWithSubSession::new(self.core.meta.id.clone(), self.core.access_key.clone()) - } - - fn is_finished(&self) -> bool { - let data = self.data.lock(); - data.consensus_session.state() == ConsensusSessionState::Failed - || data.consensus_session.state() == ConsensusSessionState::Finished - || data.result.is_some() - } - - fn on_node_timeout(&self, node: &NodeId) { - // ignore error, only state matters - let _ = self.process_node_error(Some(node), Error::NodeDisconnected); - } - - fn on_session_timeout(&self) { - // ignore error, only state matters - let _ = self.process_node_error(None, Error::NodeDisconnected); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - let is_fatal = self.process_node_error(Some(node), error.clone()).is_err(); - let is_this_node_error = *node == self.core.meta.self_node_id; - if is_fatal || is_this_node_error { - // error in signing session is non-fatal, if occurs on slave node - // => either respond with error - // => or broadcast error - let message = Message::Decryption(DecryptionMessage::DecryptionSessionError( - DecryptionSessionError { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - error: error.clone().into(), - }, - )); - - // do not bother processing send error, as we already processing error - let _ = if self.core.meta.master_node_id == self.core.meta.self_node_id { - self.core.cluster.broadcast(message) - } else { - self.core - .cluster - .send(&self.core.meta.master_node_id, message) - }; - } - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::Decryption(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl SessionCore { - pub fn decryption_transport(&self, is_broadcast_transport: bool) -> DecryptionJobTransport { - DecryptionJobTransport { - id: self.meta.id.clone(), - access_key: self.access_key.clone(), - nonce: self.nonce, - is_broadcast_transport: is_broadcast_transport, - master_node_id: self.meta.master_node_id.clone(), - cluster: self.cluster.clone(), - } - } -} - -impl JobTransport for DecryptionConsensusTransport { - type PartialJobRequest = Requester; - type PartialJobResponse = bool; - - fn send_partial_request(&self, node: &NodeId, request: Requester) -> Result<(), Error> { - let version = self.version.as_ref() - .expect("send_partial_request is called on initialized master node only; version is filled in before initialization starts on master node; qed"); - self.cluster.send( - node, - Message::Decryption(DecryptionMessage::DecryptionConsensusMessage( - DecryptionConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - origin: self.origin.clone().map(Into::into), - message: ConsensusMessage::InitializeConsensusSession( - InitializeConsensusSession { - requester: request.into(), - version: version.clone().into(), - }, - ), - }, - )), - ) - } - - fn send_partial_response(&self, node: &NodeId, response: bool) -> Result<(), Error> { - self.cluster.send( - node, - Message::Decryption(DecryptionMessage::DecryptionConsensusMessage( - DecryptionConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - origin: None, - message: ConsensusMessage::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: response, - }, - ), - }, - )), - ) - } -} - -impl JobTransport for DecryptionJobTransport { - type PartialJobRequest = PartialDecryptionRequest; - type PartialJobResponse = PartialDecryptionResponse; - - fn send_partial_request( - &self, - node: &NodeId, - request: PartialDecryptionRequest, - ) -> Result<(), Error> { - if !self.is_broadcast_transport { - self.cluster.send( - node, - Message::Decryption(DecryptionMessage::RequestPartialDecryption( - RequestPartialDecryption { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: request.id.into(), - is_shadow_decryption: request.is_shadow_decryption, - is_broadcast_session: request.is_broadcast_session, - nodes: request - .other_nodes_ids - .into_iter() - .map(Into::into) - .collect(), - }, - )), - )?; - } - - Ok(()) - } - - fn send_partial_response( - &self, - node: &NodeId, - response: PartialDecryptionResponse, - ) -> Result<(), Error> { - if !self.is_broadcast_transport || *node != self.master_node_id { - self.cluster.send( - node, - Message::Decryption(DecryptionMessage::PartialDecryption(PartialDecryption { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: response.request_id.into(), - shadow_point: response.shadow_point.into(), - decrypt_shadow: response.decrypt_shadow, - })), - )?; - } - - Ok(()) - } -} - -#[cfg(test)] -pub fn create_default_decryption_session() -> Arc { - use acl_storage::DummyAclStorage; - use key_server_cluster::cluster::tests::DummyCluster; - - Arc::new( - SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: Default::default(), - self_node_id: Default::default(), - master_node_id: Default::default(), - threshold: 0, - configured_nodes_count: 0, - connected_nodes_count: 0, - }, - access_key: Secret::zero(), - key_share: Default::default(), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(Default::default())), - nonce: 0, - }, - Some(Requester::Public(2.into())), - ) - .unwrap(), - ) -} - -#[cfg(test)] -mod tests { - use acl_storage::DummyAclStorage; - use ethkey::{self, public_to_address, Generator, KeyPair, Public, Random, Secret}; - use key_server_cluster::{ - cluster::tests::DummyCluster, - cluster_sessions::ClusterSession, - decryption_session::{SessionImpl, SessionParams}, - jobs::consensus_session::ConsensusSessionState, - math, - message::{self, DecryptionMessage, Message}, - DocumentKeyShare, DocumentKeyShareVersion, EncryptedDocumentKeyShadow, Error, NodeId, - Requester, SessionId, SessionMeta, - }; - use std::{ - collections::{BTreeMap, VecDeque}, - sync::Arc, - }; - - const SECRET_PLAIN: &'static str = "d2b57ae7619e070af0af6bc8c703c0cd27814c54d5d6a999cacac0da34ede279ca0d9216e85991029e54e2f0c92ee0bd30237725fa765cbdbfc4529489864c5f"; - - fn prepare_decryption_sessions() -> ( - KeyPair, - Vec>, - Vec>, - Vec, - ) { - // prepare encrypted data + cluster configuration for scheme 4-of-5 - let session_id = SessionId::default(); - let access_key = Random.generate().unwrap().secret().clone(); - let secret_shares: Vec = vec![ - "834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec" - .parse() - .unwrap(), - "5a3c1d90fafafa66bb808bcc464354a98b05e6b2c95b5f609d4511cdd1b17a0b" - .parse() - .unwrap(), - "71bf61e7848e08e3a8486c308ce521bdacfebcf9116a0151447eb301f3a2d0e9" - .parse() - .unwrap(), - "80c0e5e2bea66fa9b2e07f7ce09630a9563e8242446d5ee63221feb09c4338f4" - .parse() - .unwrap(), - "c06546b5669877ba579ca437a5602e89425c53808c708d44ccd6afcaa4610fad" - .parse() - .unwrap(), - ]; - let id_numbers: Vec<(NodeId, Secret)> = vec![ - ("b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse().unwrap()), - ("1395568277679f7f583ab7c0992da35f26cde57149ee70e524e49bdae62db3e18eb96122501e7cbb798b784395d7bb5a499edead0706638ad056d886e56cf8fb".into(), - "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse().unwrap()), - ("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into(), - "f43ac0fba42a5b6ed95707d2244659e89ba877b1c9b82c0d0a9dcf834e80fc62".parse().unwrap()), - ("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into(), - "5a324938dfb2516800487d25ab7289ba8ec38811f77c3df602e4e65e3c9acd9f".parse().unwrap()), - ("321977760d1d8e15b047a309e4c7fe6f355c10bb5a06c68472b676926427f69f229024fa2692c10da167d14cdc77eb95d0fce68af0a0f704f0d3db36baa83bb2".into(), - "12cf422d50002d04e52bd4906fd7f5f235f051ca36abfe37e061f8da248008d8".parse().unwrap()), - ]; - let common_point: Public = "6962be696e1bcbba8e64cc7fddf140f854835354b5804f3bb95ae5a2799130371b589a131bd39699ac7174ccb35fc4342dab05331202209582fc8f3a40916ab0".into(); - let encrypted_point: Public = "b07031982bde9890e12eff154765f03c56c3ab646ad47431db5dd2d742a9297679c4c65b998557f8008469afd0c43d40b6c5f6c6a1c7354875da4115237ed87a".into(); - let encrypted_datas: Vec<_> = (0..5) - .map(|i| DocumentKeyShare { - author: Default::default(), - threshold: 3, - public: Default::default(), - common_point: Some(common_point.clone()), - encrypted_point: Some(encrypted_point.clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: id_numbers.clone().into_iter().collect(), - secret_share: secret_shares[i].clone(), - }], - }) - .collect(); - let acl_storages: Vec<_> = (0..5) - .map(|_| Arc::new(DummyAclStorage::default())) - .collect(); - let clusters: Vec<_> = (0..5) - .map(|i| { - let cluster = Arc::new(DummyCluster::new( - id_numbers.iter().nth(i).clone().unwrap().0, - )); - for id_number in &id_numbers { - cluster.add_node(id_number.0.clone()); - } - cluster - }) - .collect(); - let requester = Random.generate().unwrap(); - let signature = Some(ethkey::sign(requester.secret(), &SessionId::default()).unwrap()); - let sessions: Vec<_> = (0..5) - .map(|i| { - SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: session_id.clone(), - self_node_id: id_numbers.iter().nth(i).clone().unwrap().0, - master_node_id: id_numbers.iter().nth(0).clone().unwrap().0, - threshold: encrypted_datas[i].threshold, - configured_nodes_count: 5, - connected_nodes_count: 5, - }, - access_key: access_key.clone(), - key_share: Some(encrypted_datas[i].clone()), - acl_storage: acl_storages[i].clone(), - cluster: clusters[i].clone(), - nonce: 0, - }, - if i == 0 { - signature.clone().map(Into::into) - } else { - None - }, - ) - .unwrap() - }) - .collect(); - - (requester, clusters, acl_storages, sessions) - } - - fn do_messages_exchange( - clusters: &[Arc], - sessions: &[SessionImpl], - ) -> Result<(), Error> { - do_messages_exchange_until(clusters, sessions, |_, _, _| false) - } - - fn do_messages_exchange_until( - clusters: &[Arc], - sessions: &[SessionImpl], - mut cond: F, - ) -> Result<(), Error> - where - F: FnMut(&NodeId, &NodeId, &Message) -> bool, - { - let mut queue: VecDeque<(NodeId, NodeId, Message)> = VecDeque::new(); - while let Some((mut from, mut to, mut message)) = clusters - .iter() - .filter_map(|c| c.take_message().map(|(to, msg)| (c.node(), to, msg))) - .next() - { - if cond(&from, &to, &message) { - break; - } - - let mut is_queued_message = false; - loop { - let session = &sessions[sessions.iter().position(|s| s.node() == &to).unwrap()]; - match session.on_message(&from, &message) { - Ok(_) => { - if let Some(qmessage) = queue.pop_front() { - from = qmessage.0; - to = qmessage.1; - message = qmessage.2; - is_queued_message = true; - continue; - } - break; - } - Err(Error::TooEarlyForRequest) => { - if is_queued_message { - queue.push_front((from, to, message)); - } else { - queue.push_back((from, to, message)); - } - break; - } - Err(err) => return Err(err), - } - } - } - - Ok(()) - } - - #[test] - fn constructs_in_cluster_of_single_node() { - let mut nodes = BTreeMap::new(); - let self_node_id = Random.generate().unwrap().public().clone(); - nodes.insert(self_node_id, Random.generate().unwrap().secret().clone()); - match SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 0, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: Some(DocumentKeyShare { - author: Default::default(), - threshold: 0, - public: Default::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: nodes, - secret_share: Random.generate().unwrap().secret().clone(), - }], - }), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, - Some(Requester::Signature( - ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - )), - ) { - Ok(_) => (), - _ => panic!("unexpected"), - } - } - - #[test] - fn fails_to_initialize_if_does_not_have_a_share() { - let self_node_id = Random.generate().unwrap().public().clone(); - let session = SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 0, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: None, - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, - Some(Requester::Signature( - ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - )), - ) - .unwrap(); - assert_eq!( - session.initialize(Default::default(), Default::default(), false, false), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn fails_to_initialize_if_threshold_is_wrong() { - let mut nodes = BTreeMap::new(); - let self_node_id = Random.generate().unwrap().public().clone(); - nodes.insert( - self_node_id.clone(), - Random.generate().unwrap().secret().clone(), - ); - nodes.insert( - Random.generate().unwrap().public().clone(), - Random.generate().unwrap().secret().clone(), - ); - let session = SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self_node_id.clone(), - master_node_id: self_node_id.clone(), - threshold: 2, - configured_nodes_count: 1, - connected_nodes_count: 1, - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: Some(DocumentKeyShare { - author: Default::default(), - threshold: 2, - public: Default::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: nodes, - secret_share: Random.generate().unwrap().secret().clone(), - }], - }), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: Arc::new(DummyCluster::new(self_node_id.clone())), - nonce: 0, - }, - Some(Requester::Signature( - ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - )), - ) - .unwrap(); - assert_eq!( - session.initialize(Default::default(), Default::default(), false, false), - Err(Error::ConsensusUnreachable) - ); - } - - #[test] - fn fails_to_initialize_when_already_initialized() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(), - () - ); - assert_eq!( - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn fails_to_accept_initialization_when_already_initialized() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(), - () - ); - assert_eq!( - sessions[0] - .on_consensus_message( - sessions[1].node(), - &message::DecryptionConsensusMessage { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - origin: None, - message: message::ConsensusMessage::InitializeConsensusSession( - message::InitializeConsensusSession { - requester: Requester::Signature( - ethkey::sign( - Random.generate().unwrap().secret(), - &SessionId::default() - ) - .unwrap() - ) - .into(), - version: Default::default(), - } - ), - } - ) - .unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn fails_to_partial_decrypt_if_requested_by_slave() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[1] - .on_consensus_message( - sessions[0].node(), - &message::DecryptionConsensusMessage { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - origin: None, - message: message::ConsensusMessage::InitializeConsensusSession( - message::InitializeConsensusSession { - requester: Requester::Signature( - ethkey::sign( - Random.generate().unwrap().secret(), - &SessionId::default() - ) - .unwrap() - ) - .into(), - version: Default::default(), - } - ), - } - ) - .unwrap(), - () - ); - assert_eq!( - sessions[1] - .on_partial_decryption_requested( - sessions[2].node(), - &message::RequestPartialDecryption { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - request_id: Random.generate().unwrap().secret().clone().into(), - is_shadow_decryption: false, - is_broadcast_session: false, - nodes: sessions - .iter() - .map(|s| s.node().clone().into()) - .take(4) - .collect(), - } - ) - .unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn fails_to_partial_decrypt_if_wrong_number_of_nodes_participating() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[1] - .on_consensus_message( - sessions[0].node(), - &message::DecryptionConsensusMessage { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - origin: None, - message: message::ConsensusMessage::InitializeConsensusSession( - message::InitializeConsensusSession { - requester: Requester::Signature( - ethkey::sign( - Random.generate().unwrap().secret(), - &SessionId::default() - ) - .unwrap() - ) - .into(), - version: Default::default(), - } - ), - } - ) - .unwrap(), - () - ); - assert_eq!( - sessions[1] - .on_partial_decryption_requested( - sessions[0].node(), - &message::RequestPartialDecryption { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - request_id: Random.generate().unwrap().secret().clone().into(), - is_shadow_decryption: false, - is_broadcast_session: false, - nodes: sessions - .iter() - .map(|s| s.node().clone().into()) - .take(2) - .collect(), - } - ) - .unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn fails_to_accept_partial_decrypt_if_not_waiting() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[0] - .on_partial_decryption( - sessions[1].node(), - &message::PartialDecryption { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 0, - request_id: Random.generate().unwrap().secret().clone().into(), - shadow_point: Random.generate().unwrap().public().clone().into(), - decrypt_shadow: None, - } - ) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn fails_to_accept_partial_decrypt_twice() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - let mut pd_from = None; - let mut pd_msg = None; - do_messages_exchange_until(&clusters, &sessions, |from, _, msg| match msg { - &Message::Decryption(DecryptionMessage::PartialDecryption(ref msg)) => { - pd_from = Some(from.clone()); - pd_msg = Some(msg.clone()); - true - } - _ => false, - }) - .unwrap(); - - assert_eq!( - sessions[0] - .on_partial_decryption(pd_from.as_ref().unwrap(), &pd_msg.clone().unwrap()) - .unwrap(), - () - ); - assert_eq!( - sessions[0] - .on_partial_decryption(pd_from.as_ref().unwrap(), &pd_msg.unwrap()) - .unwrap_err(), - Error::InvalidNodeForRequest - ); - } - - #[test] - fn decryption_fails_on_session_timeout() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert!(sessions[0].decrypted_secret().is_none()); - sessions[0].on_session_timeout(); - assert_eq!( - sessions[0].decrypted_secret().unwrap().unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } - - #[test] - fn node_is_marked_rejected_when_timed_out_during_initialization_confirmation() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - // 1 node disconnects => we still can recover secret - sessions[0].on_node_timeout(sessions[1].node()); - assert!(sessions[0] - .data - .lock() - .consensus_session - .consensus_job() - .rejects() - .contains_key(sessions[1].node())); - assert!(sessions[0].state() == ConsensusSessionState::EstablishingConsensus); - - // 2 node are disconnected => we can not recover secret - sessions[0].on_node_timeout(sessions[2].node()); - assert!(sessions[0].state() == ConsensusSessionState::Failed); - } - - #[test] - fn session_does_not_fail_if_rejected_node_disconnects() { - let (_, clusters, acl_storages, sessions) = prepare_decryption_sessions(); - let key_pair = Random.generate().unwrap(); - - acl_storages[1].prohibit(public_to_address(key_pair.public()), SessionId::default()); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange_until(&clusters, &sessions, |_, _, _| { - sessions[0].state() == ConsensusSessionState::WaitingForPartialResults - }) - .unwrap(); - - // 1st node disconnects => ignore this - sessions[0].on_node_timeout(sessions[1].node()); - assert_eq!( - sessions[0].state(), - ConsensusSessionState::EstablishingConsensus - ); - } - - #[test] - fn session_does_not_fail_if_requested_node_disconnects() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange_until(&clusters, &sessions, |_, _, _| { - sessions[0].state() == ConsensusSessionState::WaitingForPartialResults - }) - .unwrap(); - - // 1 node disconnects => we still can recover secret - sessions[0].on_node_timeout(sessions[1].node()); - assert!(sessions[0].state() == ConsensusSessionState::EstablishingConsensus); - - // 2 node are disconnected => we can not recover secret - sessions[0].on_node_timeout(sessions[2].node()); - assert!(sessions[0].state() == ConsensusSessionState::Failed); - } - - #[test] - fn session_does_not_fail_if_node_with_shadow_point_disconnects() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange_until(&clusters, &sessions, |_, _, _| { - sessions[0].state() == ConsensusSessionState::WaitingForPartialResults - && sessions[0] - .data - .lock() - .consensus_session - .computation_job() - .responses() - .len() - == 2 - }) - .unwrap(); - - // disconnects from the node which has already sent us its own shadow point - let disconnected = sessions[0] - .data - .lock() - .consensus_session - .computation_job() - .responses() - .keys() - .filter(|n| *n != sessions[0].node()) - .cloned() - .nth(0) - .unwrap(); - sessions[0].on_node_timeout(&disconnected); - assert_eq!( - sessions[0].state(), - ConsensusSessionState::EstablishingConsensus - ); - } - - #[test] - fn session_restarts_if_confirmed_node_disconnects() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange_until(&clusters, &sessions, |_, _, _| { - sessions[0].state() == ConsensusSessionState::WaitingForPartialResults - }) - .unwrap(); - - // disconnects from the node which has already confirmed its participation - let disconnected = sessions[0] - .data - .lock() - .consensus_session - .computation_job() - .requests() - .iter() - .cloned() - .nth(0) - .unwrap(); - sessions[0].on_node_timeout(&disconnected); - assert_eq!( - sessions[0].state(), - ConsensusSessionState::EstablishingConsensus - ); - assert!(sessions[0] - .data - .lock() - .consensus_session - .computation_job() - .rejects() - .contains_key(&disconnected)); - assert!(!sessions[0] - .data - .lock() - .consensus_session - .computation_job() - .requests() - .contains(&disconnected)); - } - - #[test] - fn session_does_not_fail_if_non_master_node_disconnects_from_non_master_node() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange_until(&clusters, &sessions, |_, _, _| { - sessions[0].state() == ConsensusSessionState::WaitingForPartialResults - }) - .unwrap(); - - // disconnects from the node which has already confirmed its participation - sessions[1].on_node_timeout(sessions[2].node()); - assert!(sessions[0].state() == ConsensusSessionState::WaitingForPartialResults); - assert!(sessions[1].state() == ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn complete_dec_session() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - - // now let's try to do a decryption - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange(&clusters, &sessions).unwrap(); - - // now check that: - // 1) 5 of 5 sessions are in Finished state - assert_eq!( - sessions - .iter() - .filter(|s| s.state() == ConsensusSessionState::Finished) - .count(), - 5 - ); - // 2) 1 session has decrypted key value - assert!(sessions - .iter() - .skip(1) - .all(|s| s.decrypted_secret().is_none())); - - assert_eq!( - sessions[0].decrypted_secret().unwrap().unwrap(), - EncryptedDocumentKeyShadow { - decrypted_secret: SECRET_PLAIN.into(), - common_point: None, - decrypt_shadows: None, - } - ); - } - - #[test] - fn complete_shadow_dec_session() { - let (key_pair, clusters, _, sessions) = prepare_decryption_sessions(); - - // now let's try to do a decryption - sessions[0] - .initialize(Default::default(), Default::default(), true, false) - .unwrap(); - - do_messages_exchange(&clusters, &sessions).unwrap(); - - // now check that: - // 1) 5 of 5 sessions are in Finished state - assert_eq!( - sessions - .iter() - .filter(|s| s.state() == ConsensusSessionState::Finished) - .count(), - 5 - ); - // 2) 1 session has decrypted key value - assert!(sessions - .iter() - .skip(1) - .all(|s| s.decrypted_secret().is_none())); - - let decrypted_secret = sessions[0].decrypted_secret().unwrap().unwrap(); - // check that decrypted_secret != SECRET_PLAIN - assert!(decrypted_secret.decrypted_secret != SECRET_PLAIN.into()); - // check that common point && shadow coefficients are returned - assert!(decrypted_secret.common_point.is_some()); - assert!(decrypted_secret.decrypt_shadows.is_some()); - // check that KS client is able to restore original secret - use crypto::DEFAULT_MAC; - use ethkey::crypto::ecies::decrypt; - let decrypt_shadows: Vec<_> = decrypted_secret - .decrypt_shadows - .unwrap() - .into_iter() - .map(|c| { - Secret::from_slice(&decrypt(key_pair.secret(), &DEFAULT_MAC, &c).unwrap()).unwrap() - }) - .collect(); - let decrypted_secret = math::decrypt_with_shadow_coefficients( - decrypted_secret.decrypted_secret, - decrypted_secret.common_point.unwrap(), - decrypt_shadows, - ) - .unwrap(); - assert_eq!(decrypted_secret, SECRET_PLAIN.into()); - } - - #[test] - fn failed_dec_session() { - let (key_pair, clusters, acl_storages, sessions) = prepare_decryption_sessions(); - - // now let's try to do a decryption - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - // we need 4 out of 5 nodes to agree to do a decryption - // let's say that 2 of these nodes are disagree - acl_storages[1].prohibit(public_to_address(key_pair.public()), SessionId::default()); - acl_storages[2].prohibit(public_to_address(key_pair.public()), SessionId::default()); - - assert_eq!( - do_messages_exchange(&clusters, &sessions).unwrap_err(), - Error::ConsensusUnreachable - ); - - // check that 3 nodes have failed state - assert_eq!(sessions[0].state(), ConsensusSessionState::Failed); - assert_eq!( - sessions - .iter() - .filter(|s| s.state() == ConsensusSessionState::Failed) - .count(), - 3 - ); - } - - #[test] - fn complete_dec_session_with_acl_check_failed_on_master() { - let (key_pair, clusters, acl_storages, sessions) = prepare_decryption_sessions(); - - // we need 4 out of 5 nodes to agree to do a decryption - // let's say that 1 of these nodes (master) is disagree - acl_storages[0].prohibit(public_to_address(key_pair.public()), SessionId::default()); - - // now let's try to do a decryption - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - - do_messages_exchange(&clusters, &sessions).unwrap(); - - // now check that: - // 1) 4 of 5 sessions are in Finished state - assert_eq!( - sessions - .iter() - .filter(|s| s.state() == ConsensusSessionState::Finished) - .count(), - 5 - ); - // 2) 1 session has decrypted key value - assert!(sessions - .iter() - .skip(1) - .all(|s| s.decrypted_secret().is_none())); - assert_eq!( - sessions[0].decrypted_secret().unwrap().unwrap(), - EncryptedDocumentKeyShadow { - decrypted_secret: SECRET_PLAIN.into(), - common_point: None, - decrypt_shadows: None, - } - ); - } - - #[test] - fn decryption_message_fails_when_nonce_is_wrong() { - let (_, _, _, sessions) = prepare_decryption_sessions(); - assert_eq!( - sessions[1].process_message( - sessions[0].node(), - &message::DecryptionMessage::DecryptionSessionCompleted( - message::DecryptionSessionCompleted { - session: SessionId::default().into(), - sub_session: sessions[0].access_key().clone().into(), - session_nonce: 10, - } - ) - ), - Err(Error::ReplayProtection) - ); - } - - #[test] - fn decryption_works_when_delegated_to_other_node() { - let (_, clusters, _, mut sessions) = prepare_decryption_sessions(); - - // let's say node1 doesn't have a share && delegates decryption request to node0 - // initially session is created on node1 => node1 is master for itself, but for other nodes node0 is still master - sessions[1].core.meta.master_node_id = sessions[1].core.meta.self_node_id.clone(); - sessions[1] - .data - .lock() - .consensus_session - .consensus_job_mut() - .executor_mut() - .set_requester( - sessions[0] - .data - .lock() - .consensus_session - .consensus_job() - .executor() - .requester() - .unwrap() - .clone(), - ); - - // now let's try to do a decryption - sessions[1] - .delegate( - sessions[0].core.meta.self_node_id.clone(), - Default::default(), - Default::default(), - false, - false, - ) - .unwrap(); - do_messages_exchange(&clusters, &sessions).unwrap(); - - // now check that: - // 1) 4 of 5 sessions are in Finished state - assert_eq!( - sessions - .iter() - .filter(|s| s.state() == ConsensusSessionState::Finished) - .count(), - 4 - ); - // 2) 1 session has decrypted key value - assert_eq!( - sessions[1].decrypted_secret().unwrap().unwrap(), - EncryptedDocumentKeyShadow { - decrypted_secret: SECRET_PLAIN.into(), - common_point: None, - decrypt_shadows: None, - } - ); - } - - #[test] - fn decryption_works_when_share_owners_are_isolated() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - - // we need 4 out of 5 nodes to agree to do a decryption - // let's say that 1 of these nodes (master) is isolated - let isolated_node_id = sessions[4].core.meta.self_node_id.clone(); - for cluster in &clusters { - cluster.remove_node(&isolated_node_id); - } - - // now let's try to do a decryption - sessions[0] - .initialize(Default::default(), Default::default(), false, false) - .unwrap(); - do_messages_exchange(&clusters, &sessions).unwrap(); - - assert_eq!( - sessions[0].decrypted_secret().unwrap().unwrap(), - EncryptedDocumentKeyShadow { - decrypted_secret: SECRET_PLAIN.into(), - common_point: None, - decrypt_shadows: None, - } - ); - } - - #[test] - fn decryption_result_restored_on_all_nodes_if_broadcast_session_is_completed() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), false, true) - .unwrap(); - do_messages_exchange(&clusters, &sessions).unwrap(); - - // decryption result must be the same and available on 4 nodes - let result = sessions[0].decrypted_secret(); - assert!(result.clone().unwrap().is_ok()); - assert_eq!( - result.clone().unwrap().unwrap(), - EncryptedDocumentKeyShadow { - decrypted_secret: SECRET_PLAIN.into(), - common_point: None, - decrypt_shadows: None, - } - ); - assert_eq!( - 3, - sessions - .iter() - .skip(1) - .filter(|s| s.decrypted_secret() == result) - .count() - ); - assert_eq!( - 1, - sessions - .iter() - .skip(1) - .filter(|s| s.decrypted_secret().is_none()) - .count() - ); - } - - #[test] - fn decryption_shadows_restored_on_all_nodes_if_shadow_broadcast_session_is_completed() { - let (key_pair, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Default::default(), Default::default(), true, true) - .unwrap(); - do_messages_exchange(&clusters, &sessions).unwrap(); - - // decryption shadows must be the same and available on 4 nodes - let broadcast_shadows = sessions[0].broadcast_shadows(); - assert!(broadcast_shadows.is_some()); - assert_eq!( - 3, - sessions - .iter() - .skip(1) - .filter(|s| s.broadcast_shadows() == broadcast_shadows) - .count() - ); - assert_eq!( - 1, - sessions - .iter() - .skip(1) - .filter(|s| s.broadcast_shadows().is_none()) - .count() - ); - - // 4 nodes must be able to recover original secret - use crypto::DEFAULT_MAC; - use ethkey::crypto::ecies::decrypt; - let result = sessions[0].decrypted_secret().unwrap().unwrap(); - assert_eq!( - 3, - sessions - .iter() - .skip(1) - .filter(|s| s.decrypted_secret() == Some(Ok(result.clone()))) - .count() - ); - let decrypt_shadows: Vec<_> = result - .decrypt_shadows - .unwrap() - .into_iter() - .map(|c| { - Secret::from_slice(&decrypt(key_pair.secret(), &DEFAULT_MAC, &c).unwrap()).unwrap() - }) - .collect(); - let decrypted_secret = math::decrypt_with_shadow_coefficients( - result.decrypted_secret, - result.common_point.unwrap(), - decrypt_shadows, - ) - .unwrap(); - assert_eq!(decrypted_secret, SECRET_PLAIN.into()); - } - - #[test] - fn decryption_session_origin_is_known_to_all_initialized_nodes() { - let (_, clusters, _, sessions) = prepare_decryption_sessions(); - sessions[0] - .initialize(Some(1.into()), Default::default(), true, true) - .unwrap(); - do_messages_exchange(&clusters, &sessions).unwrap(); - - // all session must have origin set - assert_eq!( - 5, - sessions - .iter() - .filter(|s| s.origin() == Some(1.into())) - .count() - ); - } -} diff --git a/secret-store/src/key_server_cluster/client_sessions/encryption_session.rs b/secret-store/src/key_server_cluster/client_sessions/encryption_session.rs deleted file mode 100644 index 09176fd0ce..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/encryption_session.rs +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::Address; -use ethkey::Public; -use key_server_cluster::{ - cluster::Cluster, - cluster_sessions::ClusterSession, - message::{ - ConfirmEncryptionInitialization, EncryptionMessage, EncryptionSessionError, - InitializeEncryptionSession, Message, - }, - DocumentKeyShare, Error, KeyStorage, NodeId, Requester, ServerKeyId, SessionId, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::BTreeMap, - fmt::{Debug, Error as FmtError, Formatter}, - sync::Arc, - time, -}; - -/// Encryption (distributed key generation) session. -/// Based on "ECDKG: A Distributed Key Generation Protocol Based on Elliptic Curve Discrete Logarithm" paper: -/// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.4128&rep=rep1&type=pdf -/// Brief overview: -/// 1) initialization: master node (which has received request for storing the secret) initializes the session on all other nodes -/// 2) master node sends common_point + encrypted_point to all other nodes -/// 3) common_point + encrypted_point are saved on all nodes -/// 4) in case of error, previous values are restored -pub struct SessionImpl { - /// Unique session id. - id: SessionId, - /// Public identifier of this node. - self_node_id: NodeId, - /// Encrypted data. - encrypted_data: Option, - /// Key storage. - key_storage: Arc, - /// Cluster which allows this node to send messages to other nodes in the cluster. - cluster: Arc, - /// Session nonce. - nonce: u64, - /// SessionImpl completion condvar. - completed: Condvar, - /// Mutable session data. - data: Mutex, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// SessionImpl identifier. - pub id: SessionId, - /// Id of node, on which this session is running. - pub self_node_id: Public, - /// Encrypted data (result of running generation_session::SessionImpl). - pub encrypted_data: Option, - /// Key storage. - pub key_storage: Arc, - /// Cluster - pub cluster: Arc, - /// Session nonce. - pub nonce: u64, -} - -/// Mutable data of encryption (distributed key generation) session. -#[derive(Debug)] -struct SessionData { - /// Current state of the session. - state: SessionState, - /// Nodes-specific data. - nodes: BTreeMap, - /// Encryption session result. - result: Option>, -} - -/// Mutable node-specific data. -#[derive(Debug, Clone)] -struct NodeData { - // === Values, filled during initialization phase === - /// Flags marking that node has confirmed session initialization. - pub initialization_confirmed: bool, -} - -/// Encryption (distributed key generation) session state. -#[derive(Debug, Clone, PartialEq)] -pub enum SessionState { - // === Initialization states === - /// Every node starts in this state. - WaitingForInitialization, - /// Master node waits for every other node to confirm initialization. - WaitingForInitializationConfirm, - - // === Final states of the session === - /// Encryption data is saved. - Finished, - /// Failed to save encryption data. - Failed, -} - -impl SessionImpl { - /// Create new encryption session. - pub fn new(params: SessionParams) -> Result { - check_encrypted_data(params.encrypted_data.as_ref())?; - - Ok(SessionImpl { - id: params.id, - self_node_id: params.self_node_id, - encrypted_data: params.encrypted_data, - key_storage: params.key_storage, - cluster: params.cluster, - nonce: params.nonce, - completed: Condvar::new(), - data: Mutex::new(SessionData { - state: SessionState::WaitingForInitialization, - nodes: BTreeMap::new(), - result: None, - }), - }) - } - - /// Get this node Id. - pub fn node(&self) -> &NodeId { - &self.self_node_id - } - - /// Wait for session completion. - pub fn wait(&self, timeout: Option) -> Result<(), Error> { - Self::wait_session(&self.completed, &self.data, timeout, |data| { - data.result.clone() - }) - .expect("wait_session returns Some if called without timeout; qed") - } - - /// Start new session initialization. This must be called on master node. - pub fn initialize( - &self, - requester: Requester, - common_point: Public, - encrypted_point: Public, - ) -> Result<(), Error> { - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // update state - data.state = SessionState::WaitingForInitializationConfirm; - data.nodes.extend(self.cluster.nodes().into_iter().map(|n| { - ( - n, - NodeData { - initialization_confirmed: &n == self.node(), - }, - ) - })); - - // TODO [Sec]: id signature is not enough here, as it was already used in key generation - // TODO [Reliability]: there could be situation when some nodes have failed to store encrypted data - // => potential problems during restore. some confirmation step is needed (2pc)? - // save encryption data - if let Some(encrypted_data) = self.encrypted_data.clone() { - let requester_address = requester - .address(&self.id) - .map_err(Error::InsufficientRequesterData)?; - update_encrypted_data( - &self.key_storage, - self.id.clone(), - encrypted_data, - requester_address, - common_point.clone(), - encrypted_point.clone(), - )?; - } - - // start initialization - if data.nodes.len() > 1 { - self.cluster.broadcast(Message::Encryption( - EncryptionMessage::InitializeEncryptionSession(InitializeEncryptionSession { - session: self.id.clone().into(), - session_nonce: self.nonce, - requester: requester.into(), - common_point: common_point.into(), - encrypted_point: encrypted_point.into(), - }), - )) - } else { - data.state = SessionState::Finished; - data.result = Some(Ok(())); - self.completed.notify_all(); - - Ok(()) - } - } - - /// When session initialization message is received. - pub fn on_initialize_session( - &self, - sender: NodeId, - message: &InitializeEncryptionSession, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // check that the requester is the author of the encrypted data - if let Some(encrypted_data) = self.encrypted_data.clone() { - let requester: Requester = message.requester.clone().into(); - let requester_address = requester - .address(&self.id) - .map_err(Error::InsufficientRequesterData)?; - update_encrypted_data( - &self.key_storage, - self.id.clone(), - encrypted_data, - requester_address, - message.common_point.clone().into(), - message.encrypted_point.clone().into(), - )?; - } - - // update state - data.state = SessionState::Finished; - - // send confirmation back to master node - self.cluster.send( - &sender, - Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization( - ConfirmEncryptionInitialization { - session: self.id.clone().into(), - session_nonce: self.nonce, - }, - )), - ) - } - - /// When session initialization confirmation message is reeived. - pub fn on_confirm_initialization( - &self, - sender: NodeId, - message: &ConfirmEncryptionInitialization, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - debug_assert!(data.nodes.contains_key(&sender)); - - // check if all nodes have confirmed initialization - data.nodes - .get_mut(&sender) - .expect("message is received from cluster; nodes contains all cluster nodes; qed") - .initialization_confirmed = true; - if !data.nodes.values().all(|n| n.initialization_confirmed) { - return Ok(()); - } - - // update state - data.state = SessionState::Finished; - data.result = Some(Ok(())); - self.completed.notify_all(); - - Ok(()) - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionId; - - fn type_name() -> &'static str { - "encryption" - } - - fn id(&self) -> SessionId { - self.id.clone() - } - - fn is_finished(&self) -> bool { - let data = self.data.lock(); - data.state == SessionState::Failed || data.state == SessionState::Finished - } - - fn on_node_timeout(&self, node: &NodeId) { - let mut data = self.data.lock(); - - warn!( - "{}: encryption session failed because {} connection has timeouted", - self.node(), - node - ); - - data.state = SessionState::Failed; - data.result = Some(Err(Error::NodeDisconnected)); - self.completed.notify_all(); - } - - fn on_session_timeout(&self) { - let mut data = self.data.lock(); - - warn!("{}: encryption session failed with timeout", self.node()); - - data.state = SessionState::Failed; - data.result = Some(Err(Error::NodeDisconnected)); - self.completed.notify_all(); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - // error in encryption session is considered fatal - // => broadcast error if error occured on this node - if *node == self.self_node_id { - // do not bother processing send error, as we already processing error - let _ = self.cluster.broadcast(Message::Encryption( - EncryptionMessage::EncryptionSessionError(EncryptionSessionError { - session: self.id.clone().into(), - session_nonce: self.nonce, - error: error.clone().into(), - }), - )); - } - - let mut data = self.data.lock(); - - warn!( - "{}: encryption session failed with error: {} from {}", - self.node(), - error, - node - ); - - data.state = SessionState::Failed; - data.result = Some(Err(error)); - self.completed.notify_all(); - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - if Some(self.nonce) != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &Message::Encryption(ref message) => match message { - &EncryptionMessage::InitializeEncryptionSession(ref message) => { - self.on_initialize_session(sender.clone(), message) - } - &EncryptionMessage::ConfirmEncryptionInitialization(ref message) => { - self.on_confirm_initialization(sender.clone(), message) - } - &EncryptionMessage::EncryptionSessionError(ref message) => { - self.on_session_error(sender, message.error.clone()); - Ok(()) - } - }, - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl Debug for SessionImpl { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - write!(f, "Encryption session {} on {}", self.id, self.self_node_id) - } -} - -/// Check that common_point and encrypted point are not yet set in key share. -pub fn check_encrypted_data(key_share: Option<&DocumentKeyShare>) -> Result<(), Error> { - if let Some(key_share) = key_share { - // check that common_point and encrypted_point are still not set yet - if key_share.common_point.is_some() || key_share.encrypted_point.is_some() { - return Err(Error::DocumentKeyAlreadyStored); - } - } - - Ok(()) -} - -/// Update key share with encrypted document key. -pub fn update_encrypted_data( - key_storage: &Arc, - key_id: ServerKeyId, - mut key_share: DocumentKeyShare, - author: Address, - common_point: Public, - encrypted_point: Public, -) -> Result<(), Error> { - // author must be the same - if key_share.author != author { - return Err(Error::AccessDenied); - } - - // save encryption data - key_share.common_point = Some(common_point); - key_share.encrypted_point = Some(encrypted_point); - key_storage.update(key_id, key_share) -} diff --git a/secret-store/src/key_server_cluster/client_sessions/generation_session.rs b/secret-store/src/key_server_cluster/client_sessions/generation_session.rs deleted file mode 100644 index aebba16160..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/generation_session.rs +++ /dev/null @@ -1,1571 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::Address; -use ethkey::{Public, Secret}; -use key_server_cluster::{ - cluster::Cluster, - cluster_sessions::ClusterSession, - math, - message::{ - CompleteInitialization, ConfirmInitialization, GenerationMessage, InitializeSession, - KeysDissemination, Message, PublicKeyShare, SessionCompleted, SessionError, - }, - DocumentKeyShare, DocumentKeyShareVersion, Error, KeyStorage, NodeId, SessionId, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, - fmt::{Debug, Error as FmtError, Formatter}, - sync::Arc, - time::Duration, -}; - -/// Distributed key generation session. -/// Based on "ECDKG: A Distributed Key Generation Protocol Based on Elliptic Curve Discrete Logarithm" paper: -/// http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.4128&rep=rep1&type=pdf -/// Brief overview: -/// 1) initialization: master node (which has received request for generating joint public + secret) initializes the session on all other nodes -/// 2) key dissemination (KD): all nodes are generating secret + public values and send these to appropriate nodes -/// 3) key verification (KV): all nodes are checking values, received for other nodes -/// 4) key generation phase (KG): nodes are exchanging with information, enough to generate joint public key -pub struct SessionImpl { - /// Unique session id. - id: SessionId, - /// Public identifier of this node. - self_node_id: NodeId, - /// Key storage. - key_storage: Option>, - /// Cluster which allows this node to send messages to other nodes in the cluster. - cluster: Arc, - /// Session-level nonce. - nonce: u64, - /// SessionImpl completion condvar. - completed: Condvar, - /// Mutable session data. - data: Mutex, -} - -/// SessionImpl creation parameters -pub struct SessionParams { - /// SessionImpl identifier. - pub id: SessionId, - /// Id of node, on which this session is running. - pub self_node_id: Public, - /// Key storage. - pub key_storage: Option>, - /// Cluster - pub cluster: Arc, - /// Session nonce. - pub nonce: Option, -} - -/// Mutable data of distributed key generation session. -#[derive(Debug)] -struct SessionData { - /// Current state of the session. - state: SessionState, - /// Simulate faulty behaviour? - simulate_faulty_behaviour: bool, - - // === Values, filled when session initialization just starts === - /// Reference to the node, which has started this session. - master: Option, - /// Address of the creator of the session. - author: Option
, - - // === Values, filled when session initialization is completed === - /// Session origin (if any). - origin: Option
, - /// Is zero secret generation session? - is_zero: Option, - /// Threshold value for this DKG. Only `threshold + 1` will be able to collectively recreate joint secret, - /// and thus - decrypt message, encrypted with joint public. - threshold: Option, - /// Random point, jointly generated by every node in the cluster. - derived_point: Option, - /// Nodes-specific data. - nodes: BTreeMap, - - // === Values, filled during KD phase === - /// Polynom1. - polynom1: Option>, - /// Value of polynom1[0], generated by this node. - secret_coeff: Option, - - // === Values, filled during KG phase === - /// Secret share, which this node holds. Persistent + private. - secret_share: Option, - - /// === Values, filled when DKG session is completed successfully === - /// Key share. - key_share: Option>, - /// Jointly generated public key, which can be used to encrypt secret. Public. - joint_public_and_secret: Option>, -} - -/// Mutable node-specific data. -#[derive(Debug, Clone)] -struct NodeData { - /// Random unique scalar. Persistent. - pub id_number: Secret, - - // === Values, filled during KD phase === - /// Secret value1, which has been received from this node. - pub secret1: Option, - /// Secret value2, which has been received from this node. - pub secret2: Option, - /// Public values, which have been received from this node. - pub publics: Option>, - - // === Values, filled during KG phase === - /// Public share, which has been received from this node. - pub public_share: Option, - - // === Values, filled during completion phase === - /// Flags marking that node has confirmed session completion (generated key is stored). - pub completion_confirmed: bool, -} - -/// Schedule for visiting other nodes of cluster. -#[derive(Debug, Clone, PartialEq)] -pub struct EveryOtherNodeVisitor { - /// Already visited nodes. - visited: BTreeSet, - /// Not yet visited nodes. - unvisited: VecDeque, - /// Nodes, which are currently visited. - in_progress: BTreeSet, -} - -/// Distributed key generation session state. -#[derive(Debug, Clone, PartialEq)] -pub enum SessionState { - // === Initialization states === - /// Every node starts in this state. - WaitingForInitialization, - /// Master node asks every other node to confirm initialization. - /// Derived point is generated by all nodes in the cluster. - WaitingForInitializationConfirm(EveryOtherNodeVisitor), - /// Slave nodes are in this state until initialization completion is reported by master node. - WaitingForInitializationComplete, - - // === KD phase states === - /// Node is waiting for generated keys from every other node. - WaitingForKeysDissemination, - - // === KG phase states === - /// Node is waiting for joint public key share to be received from every other node. - WaitingForPublicKeyShare, - - // === Generation phase states === - /// Node is waiting for session completion/session completion confirmation. - WaitingForGenerationConfirmation, - - // === Final states of the session === - /// Joint public key generation is completed. - Finished, - /// Joint public key generation is failed. - Failed, -} - -pub enum InitializationNodes { - RandomNumbers(BTreeSet), - SpecificNumbers(BTreeMap), -} - -impl InitializationNodes { - pub fn set(&self) -> BTreeSet { - match *self { - InitializationNodes::RandomNumbers(ref nodes) => nodes.clone(), - InitializationNodes::SpecificNumbers(ref nodes) => nodes.keys().cloned().collect(), - } - } -} - -impl From> for InitializationNodes { - fn from(nodes: BTreeSet) -> Self { - InitializationNodes::RandomNumbers(nodes) - } -} - -impl From> for InitializationNodes { - fn from(nodes: BTreeMap) -> Self { - InitializationNodes::SpecificNumbers(nodes) - } -} - -impl SessionImpl { - /// Create new generation session. - pub fn new(params: SessionParams) -> Self { - SessionImpl { - id: params.id, - self_node_id: params.self_node_id, - key_storage: params.key_storage, - cluster: params.cluster, - // when nonce.is_nonce(), generation session is wrapped - // => nonce is checked somewhere else && we can pass any value - nonce: params.nonce.unwrap_or_default(), - completed: Condvar::new(), - data: Mutex::new(SessionData { - state: SessionState::WaitingForInitialization, - simulate_faulty_behaviour: false, - master: None, - author: None, - origin: None, - is_zero: None, - threshold: None, - derived_point: None, - nodes: BTreeMap::new(), - polynom1: None, - secret_coeff: None, - secret_share: None, - key_share: None, - joint_public_and_secret: None, - }), - } - } - - /// Get this node Id. - pub fn node(&self) -> &NodeId { - &self.self_node_id - } - - /// Get derived point. - #[cfg(test)] - pub fn derived_point(&self) -> Option { - self.data.lock().derived_point.clone() - } - - /// Simulate faulty generation session behaviour. - pub fn simulate_faulty_behaviour(&self) { - self.data.lock().simulate_faulty_behaviour = true; - } - - /// Get session state. - pub fn state(&self) -> SessionState { - self.data.lock().state.clone() - } - - /// Get session origin. - pub fn origin(&self) -> Option
{ - self.data.lock().origin.clone() - } - - /// Wait for session completion. - pub fn wait(&self, timeout: Option) -> Option> { - Self::wait_session(&self.completed, &self.data, timeout, |data| { - data.joint_public_and_secret - .clone() - .map(|r| r.map(|r| r.0.clone())) - }) - } - - /// Get generated public and secret (if any). - pub fn joint_public_and_secret(&self) -> Option> { - self.data.lock().joint_public_and_secret.clone() - } - - /// Start new session initialization. This must be called on master node. - pub fn initialize( - &self, - origin: Option
, - author: Address, - is_zero: bool, - threshold: usize, - nodes: InitializationNodes, - ) -> Result<(), Error> { - check_cluster_nodes(self.node(), &nodes.set())?; - check_threshold(threshold, &nodes.set())?; - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // update state - data.master = Some(self.node().clone()); - data.author = Some(author.clone()); - data.origin = origin.clone(); - data.is_zero = Some(is_zero); - data.threshold = Some(threshold); - match nodes { - InitializationNodes::RandomNumbers(nodes) => { - for node_id in nodes { - // generate node identification parameter - let node_id_number = math::generate_random_scalar()?; - data.nodes - .insert(node_id, NodeData::with_id_number(node_id_number)); - } - } - InitializationNodes::SpecificNumbers(nodes) => { - for (node_id, node_id_number) in nodes { - data.nodes - .insert(node_id, NodeData::with_id_number(node_id_number)); - } - } - } - - let mut visit_policy = EveryOtherNodeVisitor::new(self.node(), data.nodes.keys().cloned()); - let derived_point = math::generate_random_point()?; - match visit_policy.next_node() { - Some(next_node) => { - data.state = SessionState::WaitingForInitializationConfirm(visit_policy); - - // start initialization - self.cluster.send(&next_node, Message::Generation(GenerationMessage::InitializeSession(InitializeSession { - session: self.id.clone().into(), - session_nonce: self.nonce, - origin: origin.map(Into::into), - author: author.into(), - nodes: data.nodes.iter().map(|(k, v)| (k.clone().into(), v.id_number.clone().into())).collect(), - is_zero: data.is_zero.expect("is_zero is filled in initialization phase; KD phase follows initialization phase; qed"), - threshold: data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"), - derived_point: derived_point.into(), - }))) - } - None => { - drop(data); - self.complete_initialization(derived_point)?; - self.disseminate_keys()?; - self.verify_keys()?; - self.complete_generation()?; - - self.data.lock().state = SessionState::Finished; - self.completed.notify_all(); - - Ok(()) - } - } - } - - /// Process single message. - pub fn process_message( - &self, - sender: &NodeId, - message: &GenerationMessage, - ) -> Result<(), Error> { - if self.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &GenerationMessage::InitializeSession(ref message) => { - self.on_initialize_session(sender.clone(), message) - } - &GenerationMessage::ConfirmInitialization(ref message) => { - self.on_confirm_initialization(sender.clone(), message) - } - &GenerationMessage::CompleteInitialization(ref message) => { - self.on_complete_initialization(sender.clone(), message) - } - &GenerationMessage::KeysDissemination(ref message) => { - self.on_keys_dissemination(sender.clone(), message) - } - &GenerationMessage::PublicKeyShare(ref message) => { - self.on_public_key_share(sender.clone(), message) - } - &GenerationMessage::SessionError(ref message) => { - self.on_session_error(sender, message.error.clone()); - Ok(()) - } - &GenerationMessage::SessionCompleted(ref message) => { - self.on_session_completed(sender.clone(), message) - } - } - } - - /// When session initialization message is received. - pub fn on_initialize_session( - &self, - sender: NodeId, - message: &InitializeSession, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - // check message - let nodes_ids = message.nodes.keys().cloned().map(Into::into).collect(); - check_threshold(message.threshold, &nodes_ids)?; - check_cluster_nodes(self.node(), &nodes_ids)?; - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForInitialization { - return Err(Error::InvalidStateForRequest); - } - - // update derived point with random scalar - let mut derived_point = message.derived_point.clone().into(); - math::update_random_point(&mut derived_point)?; - - // send confirmation back to master node - self.cluster.send( - &sender, - Message::Generation(GenerationMessage::ConfirmInitialization( - ConfirmInitialization { - session: self.id.clone().into(), - session_nonce: self.nonce, - derived_point: derived_point.into(), - }, - )), - )?; - - // update state - data.master = Some(sender); - data.author = Some(message.author.clone().into()); - data.state = SessionState::WaitingForInitializationComplete; - data.nodes = message - .nodes - .iter() - .map(|(id, number)| { - ( - id.clone().into(), - NodeData::with_id_number(number.clone().into()), - ) - }) - .collect(); - data.origin = message.origin.clone().map(Into::into); - data.is_zero = Some(message.is_zero); - data.threshold = Some(message.threshold); - - Ok(()) - } - - /// When session initialization confirmation message is reeived. - pub fn on_confirm_initialization( - &self, - sender: NodeId, - message: &ConfirmInitialization, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - debug_assert!(data.nodes.contains_key(&sender)); - - // check state && select new node to be initialized - let next_receiver = match data.state { - SessionState::WaitingForInitializationConfirm(ref mut visit_policy) => { - if !visit_policy.mark_visited(&sender) { - return Err(Error::InvalidStateForRequest); - } - - visit_policy.next_node() - } - _ => return Err(Error::InvalidStateForRequest), - }; - - // proceed message - if let Some(next_receiver) = next_receiver { - return self.cluster.send(&next_receiver, Message::Generation(GenerationMessage::InitializeSession(InitializeSession { - session: self.id.clone().into(), - session_nonce: self.nonce, - origin: data.origin.clone().map(Into::into), - author: data.author.as_ref().expect("author is filled on initialization step; confrm initialization follows initialization; qed").clone().into(), - nodes: data.nodes.iter().map(|(k, v)| (k.clone().into(), v.id_number.clone().into())).collect(), - is_zero: data.is_zero.expect("is_zero is filled in initialization phase; KD phase follows initialization phase; qed"), - threshold: data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"), - derived_point: message.derived_point.clone().into(), - }))); - } - - // now it is time for keys dissemination (KD) phase - drop(data); - self.complete_initialization(message.derived_point.clone().into())?; - self.disseminate_keys() - } - - /// When session initialization completion message is received. - pub fn on_complete_initialization( - &self, - sender: NodeId, - message: &CompleteInitialization, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForInitializationComplete { - return Err(Error::InvalidStateForRequest); - } - if data.master != Some(sender) { - return Err(Error::InvalidMessage); - } - - // remember passed data - data.derived_point = Some(message.derived_point.clone().into()); - - // now it is time for keys dissemination (KD) phase - drop(data); - self.disseminate_keys() - } - - /// When keys dissemination message is received. - pub fn on_keys_dissemination( - &self, - sender: NodeId, - message: &KeysDissemination, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - - // simulate failure, if required - if data.simulate_faulty_behaviour { - return Err(Error::Internal("simulated error".into())); - } - - // check state - if data.state != SessionState::WaitingForKeysDissemination { - match data.state { - SessionState::WaitingForInitializationComplete - | SessionState::WaitingForInitializationConfirm(_) => { - return Err(Error::TooEarlyForRequest) - } - _ => return Err(Error::InvalidStateForRequest), - } - } - debug_assert!(data.nodes.contains_key(&sender)); - - // check message - let is_zero = data.is_zero.expect( - "is_zero is filled in initialization phase; KD phase follows initialization phase; qed", - ); - let threshold = data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"); - if !is_zero && message.publics.len() != threshold + 1 { - return Err(Error::InvalidMessage); - } - - // update node data - { - let node_data = data.nodes.get_mut(&sender).ok_or(Error::InvalidMessage)?; - if node_data.secret1.is_some() - || node_data.secret2.is_some() - || node_data.publics.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - node_data.secret1 = Some(message.secret1.clone().into()); - node_data.secret2 = Some(message.secret2.clone().into()); - node_data.publics = Some(message.publics.iter().cloned().map(Into::into).collect()); - } - - // check if we have received keys from every other node - if data.nodes.iter().any(|(node_id, node_data)| { - node_id != self.node() - && (node_data.publics.is_none() - || node_data.secret1.is_none() - || node_data.secret2.is_none()) - }) { - return Ok(()); - } - - drop(data); - self.verify_keys() - } - - /// When public key share is received. - pub fn on_public_key_share( - &self, - sender: NodeId, - message: &PublicKeyShare, - ) -> Result<(), Error> { - let mut data = self.data.lock(); - - // check state - if data.state != SessionState::WaitingForPublicKeyShare { - match data.state { - SessionState::WaitingForInitializationComplete - | SessionState::WaitingForKeysDissemination => { - return Err(Error::TooEarlyForRequest) - } - _ => return Err(Error::InvalidStateForRequest), - } - } - - // update node data with received public share - { - let node_data = &mut data.nodes.get_mut(&sender).ok_or(Error::InvalidMessage)?; - if node_data.public_share.is_some() { - return Err(Error::InvalidMessage); - } - - node_data.public_share = Some(message.public_share.clone().into()); - } - - // if there's also nodes, which has not sent us their public shares - do nothing - if data - .nodes - .iter() - .any(|(node_id, node_data)| node_id != self.node() && node_data.public_share.is_none()) - { - return Ok(()); - } - - drop(data); - self.complete_generation() - } - - /// When session completion message is received. - pub fn on_session_completed( - &self, - sender: NodeId, - message: &SessionCompleted, - ) -> Result<(), Error> { - debug_assert!(self.id == *message.session); - debug_assert!(&sender != self.node()); - - let mut data = self.data.lock(); - debug_assert!(data.nodes.contains_key(&sender)); - - // check state - if data.state != SessionState::WaitingForGenerationConfirmation { - match data.state { - SessionState::WaitingForPublicKeyShare => return Err(Error::TooEarlyForRequest), - _ => return Err(Error::InvalidStateForRequest), - } - } - - // if we are not masters, save result and respond with confirmation - if data.master.as_ref() != Some(self.node()) { - // check that we have received message from master - if data.master.as_ref() != Some(&sender) { - return Err(Error::InvalidMessage); - } - - // calculate joint public key - let is_zero = data.is_zero.expect("is_zero is filled in initialization phase; KG phase follows initialization phase; qed"); - let joint_public = if !is_zero { - let public_shares = data.nodes.values().map(|n| { - n.public_share - .as_ref() - .expect("keys received on KD phase; KG phase follows KD phase; qed") - }); - math::compute_joint_public(public_shares)? - } else { - Default::default() - }; - - // save encrypted data to key storage - let encrypted_data = DocumentKeyShare { - author: data.author.as_ref().expect("author is filled in initialization phase; KG phase follows initialization phase; qed").clone(), - threshold: data.threshold.expect("threshold is filled in initialization phase; KG phase follows initialization phase; qed"), - public: joint_public, - common_point: None, - encrypted_point: None, - versions: vec![DocumentKeyShareVersion::new( - data.nodes.iter().map(|(node_id, node_data)| (node_id.clone(), node_data.id_number.clone())).collect(), - data.secret_share.as_ref().expect("secret_share is filled in KG phase; we are at the end of KG phase; qed").clone(), - )], - }; - - if let Some(ref key_storage) = self.key_storage { - key_storage.insert(self.id.clone(), encrypted_data.clone())?; - } - - // then respond with confirmation - data.state = SessionState::Finished; - return self.cluster.send( - &sender, - Message::Generation(GenerationMessage::SessionCompleted(SessionCompleted { - session: self.id.clone().into(), - session_nonce: self.nonce, - })), - ); - } - - // remember that we have received confirmation from sender node - { - let sender_node = data - .nodes - .get_mut(&sender) - .expect("node is always qualified by himself; qed"); - if sender_node.completion_confirmed { - return Err(Error::InvalidMessage); - } - - sender_node.completion_confirmed = true; - } - - // check if we have received confirmations from all cluster nodes - if data - .nodes - .iter() - .any(|(_, node_data)| !node_data.completion_confirmed) - { - return Ok(()); - } - - // we have received enough confirmations => complete session - data.state = SessionState::Finished; - self.completed.notify_all(); - - Ok(()) - } - - /// Complete initialization (when all other nodex has responded with confirmation) - fn complete_initialization(&self, mut derived_point: Public) -> Result<(), Error> { - // update point once again to make sure that derived point is not generated by last node - math::update_random_point(&mut derived_point)?; - - // remember derived point - let mut data = self.data.lock(); - data.derived_point = Some(derived_point.clone().into()); - - // broadcast derived point && other session paraeters to every other node - self.cluster.broadcast(Message::Generation( - GenerationMessage::CompleteInitialization(CompleteInitialization { - session: self.id.clone().into(), - session_nonce: self.nonce, - derived_point: derived_point.into(), - }), - )) - } - - /// Keys dissemination (KD) phase - fn disseminate_keys(&self) -> Result<(), Error> { - let mut data = self.data.lock(); - - // pick 2t + 2 random numbers as polynomial coefficients for 2 polynoms - let threshold = data.threshold.expect("threshold is filled on initialization phase; KD phase follows initialization phase; qed"); - let is_zero = data.is_zero.expect( - "is_zero is filled on initialization phase; KD phase follows initialization phase; qed", - ); - let mut polynom1 = math::generate_random_polynom(threshold)?; - if is_zero { - polynom1[0] = math::zero_scalar(); - } - let polynom2 = math::generate_random_polynom(threshold)?; - data.polynom1 = Some(polynom1.clone()); - data.secret_coeff = Some(polynom1[0].clone()); - - // compute t+1 public values - let publics = match is_zero { - false => math::public_values_generation( - threshold, - data.derived_point - .as_ref() - .expect("keys dissemination occurs after derived point is agreed; qed"), - &polynom1, - &polynom2, - )?, - true => Default::default(), - }; - - // compute secret values for every other node - for (node, node_data) in data.nodes.iter_mut() { - let secret1 = math::compute_polynom(&polynom1, &node_data.id_number)?; - let secret2 = math::compute_polynom(&polynom2, &node_data.id_number)?; - - // send a message containing secret1 && secret2 to other node - if node != self.node() { - self.cluster.send( - &node, - Message::Generation(GenerationMessage::KeysDissemination(KeysDissemination { - session: self.id.clone().into(), - session_nonce: self.nonce, - secret1: secret1.into(), - secret2: secret2.into(), - publics: publics.iter().cloned().map(Into::into).collect(), - })), - )?; - } else { - node_data.secret1 = Some(secret1); - node_data.secret2 = Some(secret2); - node_data.publics = Some(publics.clone()); - } - } - - // update state - data.state = SessionState::WaitingForKeysDissemination; - - Ok(()) - } - - /// Keys verification (KV) phase - fn verify_keys(&self) -> Result<(), Error> { - let mut data = self.data.lock(); - - // key verification (KV) phase: check that other nodes have passed correct secrets - let threshold = data.threshold.expect("threshold is filled in initialization phase; KV phase follows initialization phase; qed"); - let is_zero = data.is_zero.expect( - "is_zero is filled in initialization phase; KV phase follows initialization phase; qed", - ); - let self_public_share = { - if !is_zero { - let derived_point = data.derived_point.clone().expect("derived point generated on initialization phase; KV phase follows initialization phase; qed"); - let number_id = data.nodes[self.node()].id_number.clone(); - for (_, node_data) in data - .nodes - .iter_mut() - .filter(|&(node_id, _)| node_id != self.node()) - { - let secret1 = node_data - .secret1 - .as_ref() - .expect("keys received on KD phase; KV phase follows KD phase; qed"); - let secret2 = node_data - .secret2 - .as_ref() - .expect("keys received on KD phase; KV phase follows KD phase; qed"); - let publics = node_data - .publics - .as_ref() - .expect("keys received on KD phase; KV phase follows KD phase; qed"); - let is_key_verification_ok = math::keys_verification( - threshold, - &derived_point, - &number_id, - secret1, - secret2, - publics, - )?; - - if !is_key_verification_ok { - // node has sent us incorrect values. In original ECDKG protocol we should have sent complaint here. - return Err(Error::InvalidMessage); - } - } - - // calculate public share - let self_public_share = { - let self_secret_coeff = data.secret_coeff.as_ref().expect( - "secret_coeff is generated on KD phase; KG phase follows KD phase; qed", - ); - math::compute_public_share(self_secret_coeff)? - }; - - self_public_share - } else { - // TODO [Trust]: add verification when available - Default::default() - } - }; - - // calculate self secret + public shares - let self_secret_share = { - let secret_values_iter = data.nodes.values().map(|n| { - n.secret1 - .as_ref() - .expect("keys received on KD phase; KG phase follows KD phase; qed") - }); - math::compute_secret_share(secret_values_iter)? - }; - - // update state - data.state = SessionState::WaitingForPublicKeyShare; - data.secret_share = Some(self_secret_share); - let self_node = data - .nodes - .get_mut(self.node()) - .expect("node is always qualified by himself; qed"); - self_node.public_share = Some(self_public_share.clone()); - - // broadcast self public key share - self.cluster - .broadcast(Message::Generation(GenerationMessage::PublicKeyShare( - PublicKeyShare { - session: self.id.clone().into(), - session_nonce: self.nonce, - public_share: self_public_share.into(), - }, - ))) - } - - /// Complete generation - fn complete_generation(&self) -> Result<(), Error> { - let mut data = self.data.lock(); - - // calculate joint public key - let is_zero = data.is_zero.expect( - "is_zero is filled in initialization phase; KG phase follows initialization phase; qed", - ); - let joint_public = if !is_zero { - let public_shares = data.nodes.values().map(|n| { - n.public_share - .as_ref() - .expect("keys received on KD phase; KG phase follows KD phase; qed") - }); - math::compute_joint_public(public_shares)? - } else { - Default::default() - }; - - // prepare key data - let secret_share = data - .secret_share - .as_ref() - .expect("secret_share is filled in KG phase; we are at the end of KG phase; qed") - .clone(); - let encrypted_data = DocumentKeyShare { - author: data.author.as_ref().expect("author is filled in initialization phase; KG phase follows initialization phase; qed").clone(), - threshold: data.threshold.expect("threshold is filled in initialization phase; KG phase follows initialization phase; qed"), - public: joint_public.clone(), - common_point: None, - encrypted_point: None, - versions: vec![DocumentKeyShareVersion::new( - data.nodes.iter().map(|(node_id, node_data)| (node_id.clone(), node_data.id_number.clone())).collect(), - secret_share.clone(), - )], - }; - - // if we are at the slave node - wait for session completion - let secret_coeff = data.secret_coeff.as_ref().expect("secret coeff is selected on initialization phase; current phase follows initialization; qed").clone(); - if data.master.as_ref() != Some(self.node()) { - data.key_share = Some(Ok(encrypted_data)); - data.joint_public_and_secret = Some(Ok((joint_public, secret_coeff, secret_share))); - data.state = SessionState::WaitingForGenerationConfirmation; - return Ok(()); - } - - // then save encrypted data to the key storage - if let Some(ref key_storage) = self.key_storage { - key_storage.insert(self.id.clone(), encrypted_data.clone())?; - } - - // then distribute encrypted data to every other node - self.cluster - .broadcast(Message::Generation(GenerationMessage::SessionCompleted( - SessionCompleted { - session: self.id.clone().into(), - session_nonce: self.nonce, - }, - )))?; - - // then wait for confirmation from all other nodes - { - let self_node = data - .nodes - .get_mut(self.node()) - .expect("node is always qualified by himself; qed"); - self_node.completion_confirmed = true; - } - data.key_share = Some(Ok(encrypted_data)); - data.joint_public_and_secret = Some(Ok((joint_public, secret_coeff, secret_share))); - data.state = SessionState::WaitingForGenerationConfirmation; - - Ok(()) - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionId; - - fn type_name() -> &'static str { - "generation" - } - - fn id(&self) -> SessionId { - self.id.clone() - } - - fn is_finished(&self) -> bool { - let data = self.data.lock(); - data.state == SessionState::Failed || data.state == SessionState::Finished - } - - fn on_node_timeout(&self, node: &NodeId) { - let mut data = self.data.lock(); - - // all nodes are required for generation session - // => fail without check - warn!( - "{}: generation session failed because {} connection has timeouted", - self.node(), - node - ); - - data.state = SessionState::Failed; - data.key_share = Some(Err(Error::NodeDisconnected)); - data.joint_public_and_secret = Some(Err(Error::NodeDisconnected)); - self.completed.notify_all(); - } - - fn on_session_timeout(&self) { - let mut data = self.data.lock(); - - warn!("{}: generation session failed with timeout", self.node()); - - data.state = SessionState::Failed; - data.key_share = Some(Err(Error::NodeDisconnected)); - data.joint_public_and_secret = Some(Err(Error::NodeDisconnected)); - self.completed.notify_all(); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - // error in generation session is considered fatal - // => broadcast error if error occured on this node - if *node == self.self_node_id { - // do not bother processing send error, as we already processing error - let _ = self - .cluster - .broadcast(Message::Generation(GenerationMessage::SessionError( - SessionError { - session: self.id.clone().into(), - session_nonce: self.nonce, - error: error.clone().into(), - }, - ))); - } - - let mut data = self.data.lock(); - data.state = SessionState::Failed; - data.key_share = Some(Err(error.clone())); - data.joint_public_and_secret = Some(Err(error)); - self.completed.notify_all(); - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::Generation(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl EveryOtherNodeVisitor { - pub fn new(self_id: &NodeId, nodes: I) -> Self - where - I: Iterator, - { - EveryOtherNodeVisitor { - visited: BTreeSet::new(), - unvisited: nodes.filter(|n| n != self_id).collect(), - in_progress: BTreeSet::new(), - } - } - - pub fn next_node(&mut self) -> Option { - let next_node = self.unvisited.pop_front(); - if let Some(ref next_node) = next_node { - self.in_progress.insert(next_node.clone()); - } - next_node - } - - pub fn mark_visited(&mut self, node: &NodeId) -> bool { - if !self.in_progress.remove(node) { - return false; - } - self.visited.insert(node.clone()) - } -} - -impl NodeData { - fn with_id_number(node_id_number: Secret) -> Self { - NodeData { - id_number: node_id_number, - secret1: None, - secret2: None, - publics: None, - public_share: None, - completion_confirmed: false, - } - } -} - -impl Debug for SessionImpl { - fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - write!(f, "Generation session {} on {}", self.id, self.self_node_id) - } -} - -fn check_cluster_nodes(self_node_id: &NodeId, nodes: &BTreeSet) -> Result<(), Error> { - assert!(nodes.contains(self_node_id)); - Ok(()) -} - -fn check_threshold(threshold: usize, nodes: &BTreeSet) -> Result<(), Error> { - // at least threshold + 1 nodes are required to collectively decrypt message - if threshold >= nodes.len() { - return Err(Error::NotEnoughNodesForThreshold); - } - - Ok(()) -} - -#[cfg(test)] -pub mod tests { - use ethereum_types::H256; - use ethkey::{Generator, KeyPair, Random, Secret}; - use key_server_cluster::{ - cluster::tests::{make_clusters_and_preserve_sessions, MessageLoop as ClusterMessageLoop}, - cluster_sessions::ClusterSession, - generation_session::{SessionImpl, SessionState}, - math, - math::tests::do_encryption_and_decryption, - message::{ - self, ConfirmInitialization, GenerationMessage, KeysDissemination, Message, - PublicKeyShare, - }, - Error, KeyStorage, NodeId, - }; - use std::sync::Arc; - - #[derive(Debug)] - pub struct MessageLoop(pub ClusterMessageLoop); - - impl MessageLoop { - pub fn new(num_nodes: usize) -> Self { - MessageLoop(make_clusters_and_preserve_sessions(num_nodes)) - } - - pub fn init(self, threshold: usize) -> Result { - self.0 - .cluster(0) - .client() - .new_generation_session(Default::default(), None, Default::default(), threshold) - .map(|_| self) - } - - pub fn session_at(&self, idx: usize) -> Arc { - self.0.sessions(idx).generation_sessions.first().unwrap() - } - - pub fn session_of(&self, node: &NodeId) -> Arc { - self.0 - .sessions_of(node) - .generation_sessions - .first() - .unwrap() - } - - pub fn take_message_confirm_initialization( - &self, - ) -> (NodeId, NodeId, ConfirmInitialization) { - match self.0.take_message() { - Some(( - from, - to, - Message::Generation(GenerationMessage::ConfirmInitialization(msg)), - )) => (from, to, msg), - _ => panic!("unexpected"), - } - } - - pub fn take_message_keys_dissemination(&self) -> (NodeId, NodeId, KeysDissemination) { - match self.0.take_message() { - Some(( - from, - to, - Message::Generation(GenerationMessage::KeysDissemination(msg)), - )) => (from, to, msg), - _ => panic!("unexpected"), - } - } - - pub fn take_message_public_key_share(&self) -> (NodeId, NodeId, PublicKeyShare) { - match self.0.take_message() { - Some((from, to, Message::Generation(GenerationMessage::PublicKeyShare(msg)))) => { - (from, to, msg) - } - _ => panic!("unexpected"), - } - } - - pub fn nodes_id_numbers(&self) -> Vec { - let session = self.session_at(0); - let session_data = session.data.lock(); - session_data - .nodes - .values() - .map(|n| n.id_number.clone()) - .collect() - } - - pub fn nodes_secret_shares(&self) -> Vec { - (0..self.0.nodes().len()) - .map(|i| { - let session = self.session_at(i); - let session_data = session.data.lock(); - session_data.secret_share.as_ref().unwrap().clone() - }) - .collect() - } - - pub fn compute_key_pair(&self) -> KeyPair { - let t = self - .0 - .key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .threshold; - let secret_shares = self.nodes_secret_shares(); - let id_numbers = self.nodes_id_numbers(); - let secret_shares = secret_shares.iter().take(t + 1).collect::>(); - let id_numbers = id_numbers.iter().take(t + 1).collect::>(); - let joint_secret = - math::compute_joint_secret_from_shares(t, &secret_shares, &id_numbers).unwrap(); - - KeyPair::from_secret(joint_secret).unwrap() - } - - pub fn key_version(&self) -> H256 { - self.0 - .key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .last() - .unwrap() - .hash - } - } - - #[test] - fn initializes_in_cluster_of_single_node() { - MessageLoop::new(1).init(0).unwrap(); - } - - #[test] - fn fails_to_initialize_if_threshold_is_wrong() { - assert_eq!( - MessageLoop::new(2).init(2).unwrap_err(), - Error::NotEnoughNodesForThreshold - ); - } - - #[test] - fn fails_to_initialize_when_already_initialized() { - let ml = MessageLoop::new(2).init(0).unwrap(); - assert_eq!( - ml.session_at(0).initialize( - Default::default(), - Default::default(), - false, - 0, - ml.0.nodes().into() - ), - Err(Error::InvalidStateForRequest), - ); - } - - #[test] - fn fails_to_accept_initialization_when_already_initialized() { - let ml = MessageLoop::new(2).init(0).unwrap(); - let (from, to, msg) = ml.0.take_message().unwrap(); - ml.0.process_message(from, to, msg.clone()); - assert_eq!( - ml.session_of(&to).on_message(&from, &msg), - Err(Error::InvalidStateForRequest), - ); - } - - #[test] - fn slave_updates_derived_point_on_initialization() { - let ml = MessageLoop::new(2).init(0).unwrap(); - let original_point = match ml.0.take_message().unwrap() { - (from, to, Message::Generation(GenerationMessage::InitializeSession(msg))) => { - let original_point = msg.derived_point.clone(); - let msg = Message::Generation(GenerationMessage::InitializeSession(msg)); - ml.0.process_message(from, to, msg); - original_point - } - _ => panic!("unexpected"), - }; - - match ml.0.take_message().unwrap() { - (_, _, Message::Generation(GenerationMessage::ConfirmInitialization(msg))) => { - assert!(original_point != msg.derived_point) - } - _ => panic!("unexpected"), - } - } - - #[test] - fn fails_to_accept_initialization_confirmation_if_already_accepted_from_the_same_node() { - let ml = MessageLoop::new(3).init(0).unwrap(); - ml.0.take_and_process_message(); - - let (from, to, msg) = ml.take_message_confirm_initialization(); - ml.0.process_message( - from, - to, - Message::Generation(GenerationMessage::ConfirmInitialization(msg.clone())), - ); - assert_eq!( - ml.session_of(&to).on_confirm_initialization(from, &msg), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn fails_to_accept_initialization_confirmation_if_initialization_already_completed() { - let ml = MessageLoop::new(2).init(0).unwrap(); - ml.0.take_and_process_message(); - ml.0.take_and_process_message(); - assert_eq!( - ml.session_at(0).on_confirm_initialization( - ml.0.node(1), - &message::ConfirmInitialization { - session: Default::default(), - session_nonce: 0, - derived_point: math::generate_random_point().unwrap().into(), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn master_updates_derived_point_on_initialization_completion() { - let ml = MessageLoop::new(2).init(0).unwrap(); - ml.0.take_and_process_message(); - let original_point = match ml.0.take_message().unwrap() { - (from, to, Message::Generation(GenerationMessage::ConfirmInitialization(msg))) => { - let original_point = msg.derived_point.clone(); - let msg = Message::Generation(GenerationMessage::ConfirmInitialization(msg)); - ml.session_of(&to).on_message(&from, &msg).unwrap(); - original_point - } - _ => panic!("unexpected"), - }; - - assert!(ml.session_at(0).derived_point().unwrap() != original_point.into()); - } - - #[test] - fn fails_to_complete_initialization_if_not_waiting_for_it() { - let ml = MessageLoop::new(2).init(0).unwrap(); - ml.0.take_and_process_message(); - assert_eq!( - ml.session_at(0).on_complete_initialization( - ml.0.node(1), - &message::CompleteInitialization { - session: Default::default(), - session_nonce: 0, - derived_point: math::generate_random_point().unwrap().into(), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn fails_to_complete_initialization_from_non_master_node() { - let ml = MessageLoop::new(3).init(0).unwrap(); - ml.0.take_and_process_message(); - ml.0.take_and_process_message(); - ml.0.take_and_process_message(); - ml.0.take_and_process_message(); - assert_eq!( - ml.session_at(1).on_complete_initialization( - ml.0.node(2), - &message::CompleteInitialization { - session: Default::default(), - session_nonce: 0, - derived_point: math::generate_random_point().unwrap().into(), - } - ), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn fails_to_accept_keys_dissemination_if_not_waiting_for_it() { - let ml = MessageLoop::new(2).init(0).unwrap(); - assert_eq!( - ml.session_at(0).on_keys_dissemination( - ml.0.node(1), - &message::KeysDissemination { - session: Default::default(), - session_nonce: 0, - secret1: math::generate_random_scalar().unwrap().into(), - secret2: math::generate_random_scalar().unwrap().into(), - publics: vec![math::generate_random_point().unwrap().into()], - } - ), - Err(Error::TooEarlyForRequest) - ); - } - - #[test] - fn fails_to_accept_keys_dissemination_if_wrong_number_of_publics_passed() { - let ml = MessageLoop::new(3).init(0).unwrap(); - ml.0.take_and_process_message(); // m -> s1: InitializeSession - ml.0.take_and_process_message(); // m -> s2: InitializeSession - ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // m -> s1: CompleteInitialization - ml.0.take_and_process_message(); // m -> s2: CompleteInitialization - - let (from, to, mut msg) = ml.take_message_keys_dissemination(); - msg.publics.clear(); - assert_eq!( - ml.session_of(&to).on_keys_dissemination(from, &msg), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn fails_to_accept_keys_dissemination_second_time_from_the_same_node() { - let ml = MessageLoop::new(3).init(0).unwrap(); - ml.0.take_and_process_message(); // m -> s1: InitializeSession - ml.0.take_and_process_message(); // m -> s2: InitializeSession - ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // m -> s1: CompleteInitialization - ml.0.take_and_process_message(); // m -> s2: CompleteInitialization - - let (from, to, msg) = ml.take_message_keys_dissemination(); - ml.0.process_message( - from, - to, - Message::Generation(GenerationMessage::KeysDissemination(msg.clone())), - ); - assert_eq!( - ml.session_of(&to).on_keys_dissemination(from, &msg), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn should_not_accept_public_key_share_when_is_not_waiting_for_it() { - let ml = MessageLoop::new(3).init(1).unwrap(); - assert_eq!( - ml.session_at(0).on_public_key_share( - ml.0.node(1), - &message::PublicKeyShare { - session: Default::default(), - session_nonce: 0, - public_share: math::generate_random_point().unwrap().into(), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn should_not_accept_public_key_share_when_receiving_twice() { - let ml = MessageLoop::new(3).init(0).unwrap(); - ml.0.take_and_process_message(); // m -> s1: InitializeSession - ml.0.take_and_process_message(); // m -> s2: InitializeSession - ml.0.take_and_process_message(); // s1 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // s2 -> m: ConfirmInitialization - ml.0.take_and_process_message(); // m -> s1: CompleteInitialization - ml.0.take_and_process_message(); // m -> s2: CompleteInitialization - ml.0.take_and_process_message(); // m -> s1: KeysDissemination - ml.0.take_and_process_message(); // m -> s2: KeysDissemination - ml.0.take_and_process_message(); // s1 -> m: KeysDissemination - ml.0.take_and_process_message(); // s1 -> s2: KeysDissemination - ml.0.take_and_process_message(); // s2 -> m: KeysDissemination - ml.0.take_and_process_message(); // s2 -> s1: KeysDissemination - - let (from, to, msg) = ml.take_message_public_key_share(); - ml.0.process_message( - from, - to, - Message::Generation(GenerationMessage::PublicKeyShare(msg.clone())), - ); - assert_eq!( - ml.session_of(&to).on_public_key_share(from, &msg), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn encryption_fails_on_session_timeout() { - let ml = MessageLoop::new(2).init(0).unwrap(); - assert!(ml.session_at(0).joint_public_and_secret().is_none()); - ml.session_at(0).on_session_timeout(); - assert_eq!( - ml.session_at(0).joint_public_and_secret().unwrap(), - Err(Error::NodeDisconnected) - ); - } - - #[test] - fn encryption_fails_on_node_timeout() { - let ml = MessageLoop::new(2).init(0).unwrap(); - assert!(ml.session_at(0).joint_public_and_secret().is_none()); - ml.session_at(0).on_node_timeout(&ml.0.node(1)); - assert_eq!( - ml.session_at(0).joint_public_and_secret().unwrap(), - Err(Error::NodeDisconnected) - ); - } - - #[test] - fn complete_enc_dec_session() { - let test_cases = [(0, 5), (2, 5), (3, 5)]; - for &(threshold, num_nodes) in &test_cases { - let ml = MessageLoop::new(num_nodes).init(threshold).unwrap(); - ml.0.loop_until(|| ml.0.is_empty()); - - // check that all nodes has finished joint public generation - let joint_public_key = ml - .session_at(0) - .joint_public_and_secret() - .unwrap() - .unwrap() - .0; - for i in 0..num_nodes { - let session = ml.session_at(i); - assert_eq!(session.state(), SessionState::Finished); - assert_eq!( - session.joint_public_and_secret().map(|p| p.map(|p| p.0)), - Some(Ok(joint_public_key)) - ); - } - - // now let's encrypt some secret (which is a point on EC) - let document_secret_plain = Random.generate().unwrap().public().clone(); - let all_nodes_id_numbers = ml.nodes_id_numbers(); - let all_nodes_secret_shares = ml.nodes_secret_shares(); - let document_secret_decrypted = do_encryption_and_decryption( - threshold, - &joint_public_key, - &all_nodes_id_numbers, - &all_nodes_secret_shares, - None, - document_secret_plain.clone(), - ) - .0; - assert_eq!(document_secret_plain, document_secret_decrypted); - } - } - - #[test] - fn generation_message_fails_when_nonce_is_wrong() { - let ml = MessageLoop::new(2).init(0).unwrap(); - ml.0.take_and_process_message(); - - let msg = message::GenerationMessage::KeysDissemination(message::KeysDissemination { - session: Default::default(), - session_nonce: 10, - secret1: math::generate_random_scalar().unwrap().into(), - secret2: math::generate_random_scalar().unwrap().into(), - publics: vec![math::generate_random_point().unwrap().into()], - }); - assert_eq!( - ml.session_at(1) - .process_message(&ml.0.node(0), &msg) - .unwrap_err(), - Error::ReplayProtection - ); - } -} diff --git a/secret-store/src/key_server_cluster/client_sessions/mod.rs b/secret-store/src/key_server_cluster/client_sessions/mod.rs deleted file mode 100644 index 4ac68dcc17..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -pub mod decryption_session; -pub mod encryption_session; -pub mod generation_session; -pub mod signing_session_ecdsa; -pub mod signing_session_schnorr; diff --git a/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs b/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs deleted file mode 100644 index 1c066a4611..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs +++ /dev/null @@ -1,1626 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{sign, Public, Secret, Signature}; -use key_server_cluster::{ - cluster::Cluster, - cluster_sessions::{ClusterSession, SessionIdWithSubSession}, - generation_session::{ - SessionImpl as GenerationSession, SessionParams as GenerationSessionParams, - SessionState as GenerationSessionState, - }, - jobs::{ - consensus_session::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}, - job_session::JobTransport, - key_access_job::KeyAccessJob, - signing_job_ecdsa::{ - EcdsaPartialSigningRequest, EcdsaPartialSigningResponse, EcdsaSigningJob, - }, - }, - math, - message::{ - ConfirmConsensusInitialization, ConsensusMessage, EcdsaInversionNonceGenerationMessage, - EcdsaInversionZeroGenerationMessage, EcdsaPartialSignature, EcdsaRequestPartialSignature, - EcdsaSignatureNonceGenerationMessage, EcdsaSigningConsensusMessage, - EcdsaSigningInversedNonceCoeffShare, EcdsaSigningMessage, EcdsaSigningSessionCompleted, - EcdsaSigningSessionDelegation, EcdsaSigningSessionDelegationCompleted, - EcdsaSigningSessionError, GenerationMessage, InitializeConsensusSession, Message, - }, - AclStorage, DocumentKeyShare, Error, NodeId, Requester, SessionId, SessionMeta, -}; -use parking_lot::{Condvar, Mutex}; -use std::{ - collections::{btree_map::Entry, BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Distributed ECDSA-signing session. -/// Based on "A robust threshold elliptic curve digital signature providing a new verifiable secret sharing scheme" paper. -/// WARNING: can only be used if 2*t < N is true for key generation scheme -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex, -} - -/// Immutable session data. -struct SessionCore { - /// Session metadata. - pub meta: SessionMeta, - /// Signing session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// Cluster which allows this node to send messages to other nodes in the cluster. - pub cluster: Arc, - /// Session-level nonce. - pub nonce: u64, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Signing consensus session type. -type SigningConsensusSession = - ConsensusSession; - -/// Mutable session data. -struct SessionData { - /// Session state. - pub state: SessionState, - /// Message hash. - pub message_hash: Option, - /// Key version to use for decryption. - pub version: Option, - /// Consensus-based signing session. - pub consensus_session: SigningConsensusSession, - /// Signature nonce generation session. - pub sig_nonce_generation_session: Option, - /// Inversion nonce generation session. - pub inv_nonce_generation_session: Option, - /// Inversion zero generation session. - pub inv_zero_generation_session: Option, - /// Inversed nonce coefficient shares. - pub inversed_nonce_coeff_shares: Option>, - /// Delegation status. - pub delegation_status: Option, - /// Decryption result. - pub result: Option>, -} - -/// Signing session state. -#[derive(Debug, PartialEq)] -pub enum SessionState { - /// Consensus is establishing. - ConsensusEstablishing, - /// Nonces (signature, inversion && zero) are generating. - NoncesGenerating, - /// Waiting for inversed nonce shares. - WaitingForInversedNonceShares, - /// State when signature is computing. - SignatureComputing, -} - -/// Session creation parameters -pub struct SessionParams { - /// Session metadata. - pub meta: SessionMeta, - /// Session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// ACL storage. - pub acl_storage: Arc, - /// Cluster - pub cluster: Arc, - /// Session nonce. - pub nonce: u64, -} - -/// Signing consensus transport. -struct SigningConsensusTransport { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Selected key version (on master node). - version: Option, - /// Cluster. - cluster: Arc, -} - -/// Signing key generation transport. -struct NonceGenerationTransport< - F: Fn(SessionId, Secret, u64, GenerationMessage) -> EcdsaSigningMessage + Send + Sync, -> { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Cluster. - cluster: Arc, - /// Other nodes ids. - other_nodes_ids: BTreeSet, - /// Message mapping function. - map: F, -} - -/// Signing job transport -struct SigningJobTransport { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Cluster. - cluster: Arc, -} - -/// Session delegation status. -enum DelegationStatus { - /// Delegated to other node. - DelegatedTo(NodeId), - /// Delegated from other node. - DelegatedFrom(NodeId, u64), -} - -impl SessionImpl { - /// Create new signing session. - pub fn new(params: SessionParams, requester: Option) -> Result { - debug_assert_eq!( - params.meta.threshold, - params - .key_share - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default() - ); - - let consensus_transport = SigningConsensusTransport { - id: params.meta.id.clone(), - access_key: params.access_key.clone(), - nonce: params.nonce, - version: None, - cluster: params.cluster.clone(), - }; - let consensus_session = ConsensusSession::new(ConsensusSessionParams { - // this session requires responses from 2 * t nodes - meta: SessionMeta { - id: params.meta.id, - master_node_id: params.meta.master_node_id, - self_node_id: params.meta.self_node_id, - threshold: params.meta.threshold * 2, - configured_nodes_count: params.meta.configured_nodes_count, - connected_nodes_count: params.meta.connected_nodes_count, - }, - consensus_executor: match requester { - Some(requester) => KeyAccessJob::new_on_master( - params.meta.id.clone(), - params.acl_storage.clone(), - requester, - ), - None => { - KeyAccessJob::new_on_slave(params.meta.id.clone(), params.acl_storage.clone()) - } - }, - consensus_transport: consensus_transport, - })?; - - Ok(SessionImpl { - core: SessionCore { - meta: params.meta, - access_key: params.access_key, - key_share: params.key_share, - cluster: params.cluster, - nonce: params.nonce, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - state: SessionState::ConsensusEstablishing, - message_hash: None, - version: None, - consensus_session: consensus_session, - sig_nonce_generation_session: None, - inv_nonce_generation_session: None, - inv_zero_generation_session: None, - inversed_nonce_coeff_shares: None, - delegation_status: None, - result: None, - }), - }) - } - - /// Wait for session completion. - pub fn wait(&self) -> Result { - Self::wait_session(&self.core.completed, &self.data, None, |data| { - data.result.clone() - }) - .expect("wait_session returns Some if called without timeout; qed") - } - - /// Delegate session to other node. - pub fn delegate(&self, master: NodeId, version: H256, message_hash: H256) -> Result<(), Error> { - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(false); - self.core.cluster.send(&master, Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegation(EcdsaSigningSessionDelegation { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - requester: data.consensus_session.consensus_job().executor().requester() - .expect("requester is passed to master node on creation; session can be delegated from master node only; qed") - .clone().into(), - version: version.into(), - message_hash: message_hash.into(), - })))?; - data.delegation_status = Some(DelegationStatus::DelegatedTo(master)); - Ok(()) - } - - /// Initialize signing session on master node. - pub fn initialize(&self, version: H256, message_hash: H256) -> Result<(), Error> { - debug_assert_eq!(self.core.meta.self_node_id, self.core.meta.master_node_id); - - // check if version exists - let key_version = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version)?, - }; - - // select nodes to participate in consensus etablish session - let mut data = self.data.lock(); - let non_isolated_nodes = self.core.cluster.nodes(); - let mut consensus_nodes: BTreeSet<_> = key_version - .id_numbers - .keys() - .filter(|n| non_isolated_nodes.contains(*n)) - .cloned() - .chain(::std::iter::once(self.core.meta.self_node_id.clone())) - .collect(); - if let Some(&DelegationStatus::DelegatedFrom(delegation_master, _)) = - data.delegation_status.as_ref() - { - consensus_nodes.remove(&delegation_master); - } - - // start consensus establish sesssion - data.consensus_session - .consensus_job_mut() - .transport_mut() - .version = Some(version.clone()); - data.version = Some(version.clone()); - data.message_hash = Some(message_hash); - data.consensus_session.initialize(consensus_nodes)?; - - // consensus established => threshold is 0 => we can generate signature on this node - if data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished { - data.result = Some(sign(&key_version.secret_share, &message_hash).map_err(Into::into)); - self.core.completed.notify_all(); - } - - Ok(()) - } - - /// Process signing message. - pub fn process_message( - &self, - sender: &NodeId, - message: &EcdsaSigningMessage, - ) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref message) => { - self.on_consensus_message(sender, message) - } - &EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage(ref message) => { - self.on_signature_nonce_generation_message(sender, message) - } - &EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage(ref message) => { - self.on_inversion_nonce_generation_message(sender, message) - } - &EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage(ref message) => { - self.on_inversion_zero_generation_message(sender, message) - } - &EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare(ref message) => { - self.on_inversed_nonce_coeff_share(sender, message) - } - &EcdsaSigningMessage::EcdsaRequestPartialSignature(ref message) => { - self.on_partial_signature_requested(sender, message) - } - &EcdsaSigningMessage::EcdsaPartialSignature(ref message) => { - self.on_partial_signature(sender, message) - } - &EcdsaSigningMessage::EcdsaSigningSessionError(ref message) => { - self.process_node_error(Some(&sender), message.error.clone()) - } - &EcdsaSigningMessage::EcdsaSigningSessionCompleted(ref message) => { - self.on_session_completed(sender, message) - } - &EcdsaSigningMessage::EcdsaSigningSessionDelegation(ref message) => { - self.on_session_delegated(sender, message) - } - &EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted(ref message) => { - self.on_session_delegation_completed(sender, message) - } - } - } - - /// When session is delegated to this node. - pub fn on_session_delegated( - &self, - sender: &NodeId, - message: &EcdsaSigningSessionDelegation, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - { - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_requester(message.requester.clone().into()); - data.delegation_status = Some(DelegationStatus::DelegatedFrom( - sender.clone(), - message.session_nonce, - )); - } - - self.initialize( - message.version.clone().into(), - message.message_hash.clone().into(), - ) - } - - /// When delegated session is completed on other node. - pub fn on_session_delegation_completed( - &self, - sender: &NodeId, - message: &EcdsaSigningSessionDelegationCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(ref node)) if node == sender => (), - _ => return Err(Error::InvalidMessage), - } - - Self::set_signing_result(&self.core, &mut *data, Ok(message.signature.clone().into())); - - Ok(()) - } - - /// When consensus-related message is received. - pub fn on_consensus_message( - &self, - sender: &NodeId, - message: &EcdsaSigningConsensusMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - let is_establishing_consensus = - data.consensus_session.state() == ConsensusSessionState::EstablishingConsensus; - - if let &ConsensusMessage::InitializeConsensusSession(ref msg) = &message.message { - let version = msg.version.clone().into(); - let has_key_share = self - .core - .key_share - .as_ref() - .map(|ks| ks.version(&version).is_ok()) - .unwrap_or(false); - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(has_key_share); - data.version = Some(version); - } - data.consensus_session - .on_consensus_message(&sender, &message.message)?; - - let is_consensus_established = - data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished; - if self.core.meta.self_node_id != self.core.meta.master_node_id - || !is_establishing_consensus - || !is_consensus_established - { - return Ok(()); - } - - let key_share = - self.core.key_share.as_ref().expect( - "this is master node; master node is selected so that it has key version; qed", - ); - let key_version = key_share.version(data.version.as_ref().expect( - "this is master node; master node is selected so that it has key version; qed", - ))?; - - let consensus_group = data.consensus_session.select_consensus_group()?.clone(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - let consensus_group_map: BTreeMap<_, _> = consensus_group - .iter() - .map(|n| (n.clone(), key_version.id_numbers[n].clone())) - .collect(); - - // start generation of signature nonce - let sig_nonce_generation_session = Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - |s, k, n, m| { - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage( - EcdsaSignatureNonceGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - ); - sig_nonce_generation_session.initialize( - Default::default(), - Default::default(), - false, - key_share.threshold, - consensus_group_map.clone().into(), - )?; - data.sig_nonce_generation_session = Some(sig_nonce_generation_session); - - // start generation of inversed nonce computation session - let inv_nonce_generation_session = Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - move |s, k, n, m| { - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage( - EcdsaInversionNonceGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - ); - inv_nonce_generation_session.initialize( - Default::default(), - Default::default(), - false, - key_share.threshold, - consensus_group_map.clone().into(), - )?; - data.inv_nonce_generation_session = Some(inv_nonce_generation_session); - - // start generation of zero-secret shares for inversed nonce computation session - let inv_zero_generation_session = Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - move |s, k, n, m| { - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage( - EcdsaInversionZeroGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - ); - inv_zero_generation_session.initialize( - Default::default(), - Default::default(), - true, - key_share.threshold * 2, - consensus_group_map.clone().into(), - )?; - data.inv_zero_generation_session = Some(inv_zero_generation_session); - - data.state = SessionState::NoncesGenerating; - - Ok(()) - } - - /// When signature nonce generation message is received. - pub fn on_signature_nonce_generation_message( - &self, - sender: &NodeId, - message: &EcdsaSignatureNonceGenerationMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - if let &GenerationMessage::InitializeSession(ref message) = &message.message { - if &self.core.meta.master_node_id != sender { - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(s)) if s == *sender => (), - _ => return Err(Error::InvalidMessage), - } - } - - let consensus_group: BTreeSet = - message.nodes.keys().cloned().map(Into::into).collect(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - - data.sig_nonce_generation_session = Some(Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - |s, k, n, m| { - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage( - EcdsaSignatureNonceGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - )); - - data.state = SessionState::NoncesGenerating; - } - - { - let generation_session = data - .sig_nonce_generation_session - .as_ref() - .ok_or(Error::InvalidStateForRequest)?; - let is_key_generating = generation_session.state() != GenerationSessionState::Finished; - generation_session.process_message(sender, &message.message)?; - - let is_key_generated = generation_session.state() == GenerationSessionState::Finished; - if !is_key_generating || !is_key_generated { - return Ok(()); - } - } - - if !Self::check_nonces_generated(&*data) { - return Ok(()); - } - - Self::send_inversed_nonce_coeff_share(&self.core, &mut *data)?; - data.state = if self.core.meta.master_node_id != self.core.meta.self_node_id { - SessionState::SignatureComputing - } else { - SessionState::WaitingForInversedNonceShares - }; - - Ok(()) - } - - /// When inversion nonce generation message is received. - pub fn on_inversion_nonce_generation_message( - &self, - sender: &NodeId, - message: &EcdsaInversionNonceGenerationMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - if let &GenerationMessage::InitializeSession(ref message) = &message.message { - if &self.core.meta.master_node_id != sender { - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(s)) if s == *sender => (), - _ => return Err(Error::InvalidMessage), - } - } - - let consensus_group: BTreeSet = - message.nodes.keys().cloned().map(Into::into).collect(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - - data.inv_nonce_generation_session = Some(Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - |s, k, n, m| { - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage( - EcdsaInversionNonceGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - )); - - data.state = SessionState::NoncesGenerating; - } - - { - let generation_session = data - .inv_nonce_generation_session - .as_ref() - .ok_or(Error::InvalidStateForRequest)?; - let is_key_generating = generation_session.state() != GenerationSessionState::Finished; - generation_session.process_message(sender, &message.message)?; - - let is_key_generated = generation_session.state() == GenerationSessionState::Finished; - if !is_key_generating || !is_key_generated { - return Ok(()); - } - } - - if !Self::check_nonces_generated(&*data) { - return Ok(()); - } - - Self::send_inversed_nonce_coeff_share(&self.core, &mut *data)?; - data.state = if self.core.meta.master_node_id != self.core.meta.self_node_id { - SessionState::SignatureComputing - } else { - SessionState::WaitingForInversedNonceShares - }; - - Ok(()) - } - - /// When inversion zero generation message is received. - pub fn on_inversion_zero_generation_message( - &self, - sender: &NodeId, - message: &EcdsaInversionZeroGenerationMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - if let &GenerationMessage::InitializeSession(ref message) = &message.message { - if &self.core.meta.master_node_id != sender { - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(s)) if s == *sender => (), - _ => return Err(Error::InvalidMessage), - } - } - - let consensus_group: BTreeSet = - message.nodes.keys().cloned().map(Into::into).collect(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - - data.inv_zero_generation_session = Some(Self::start_generation_session( - &self.core, - &other_consensus_group_nodes, - |s, k, n, m| { - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage( - EcdsaInversionZeroGenerationMessage { - session: s.into(), - sub_session: k.into(), - session_nonce: n, - message: m, - }, - ) - }, - )); - - data.state = SessionState::NoncesGenerating; - } - - { - let generation_session = data - .inv_zero_generation_session - .as_ref() - .ok_or(Error::InvalidStateForRequest)?; - let is_key_generating = generation_session.state() != GenerationSessionState::Finished; - generation_session.process_message(sender, &message.message)?; - - let is_key_generated = generation_session.state() == GenerationSessionState::Finished; - if !is_key_generating || !is_key_generated { - return Ok(()); - } - } - - if !Self::check_nonces_generated(&*data) { - return Ok(()); - } - - Self::send_inversed_nonce_coeff_share(&self.core, &mut *data)?; - data.state = if self.core.meta.master_node_id != self.core.meta.self_node_id { - SessionState::SignatureComputing - } else { - SessionState::WaitingForInversedNonceShares - }; - - Ok(()) - } - - /// When inversed nonce share is received. - pub fn on_inversed_nonce_coeff_share( - &self, - sender: &NodeId, - message: &EcdsaSigningInversedNonceCoeffShare, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - if self.core.meta.self_node_id != self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - match data.state { - SessionState::WaitingForInversedNonceShares => (), - SessionState::NoncesGenerating => return Err(Error::TooEarlyForRequest), - _ => return Err(Error::InvalidStateForRequest), - } - - let inversed_nonce_coeff = { - let consensus_group = data.consensus_session.select_consensus_group()?.clone(); - { - let inversed_nonce_coeff_shares = data.inversed_nonce_coeff_shares.as_mut() - .expect("we are in WaitingForInversedNonceShares state; inversed_nonce_coeff_shares are filled before this state; qed"); - match inversed_nonce_coeff_shares.entry(sender.clone()) { - Entry::Occupied(_) => return Err(Error::InvalidStateForRequest), - Entry::Vacant(entry) => { - entry.insert(message.inversed_nonce_coeff_share.clone().into()); - } - } - - if consensus_group - .iter() - .any(|n| !inversed_nonce_coeff_shares.contains_key(n)) - { - return Ok(()); - } - } - - Self::compute_inversed_nonce_coeff(&self.core, &*data)? - }; - - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let message_hash = data.message_hash - .expect("we are on master node; on master node message_hash is filled in initialize(); on_generation_message follows initialize; qed"); - - let nonce_exists_proof = "nonce is generated before signature is computed; we are in SignatureComputing state; qed"; - let sig_nonce_public = data - .sig_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .0; - let inv_nonce_share = data - .inv_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .2; - - self.core.disseminate_jobs( - &mut data.consensus_session, - &version, - sig_nonce_public, - inv_nonce_share, - inversed_nonce_coeff, - message_hash, - ) - } - - /// When partial signature is requested. - pub fn on_partial_signature_requested( - &self, - sender: &NodeId, - message: &EcdsaRequestPartialSignature, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let key_share = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let mut data = self.data.lock(); - - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if data.state != SessionState::SignatureComputing { - return Err(Error::InvalidStateForRequest); - } - - let nonce_exists_proof = "nonce is generated before signature is computed; we are in SignatureComputing state; qed"; - let sig_nonce_public = data - .sig_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .0; - let inv_nonce_share = data - .inv_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .2; - - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let key_version = key_share.version(&version)?.hash.clone(); - - let signing_job = EcdsaSigningJob::new_on_slave( - key_share.clone(), - key_version, - sig_nonce_public, - inv_nonce_share, - )?; - let signing_transport = self.core.signing_transport(); - - data.consensus_session - .on_job_request( - sender, - EcdsaPartialSigningRequest { - id: message.request_id.clone().into(), - inversed_nonce_coeff: message.inversed_nonce_coeff.clone().into(), - message_hash: message.message_hash.clone().into(), - }, - signing_job, - signing_transport, - ) - .map(|_| ()) - } - - /// When partial signature is received. - pub fn on_partial_signature( - &self, - sender: &NodeId, - message: &EcdsaPartialSignature, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - data.consensus_session.on_job_response( - sender, - EcdsaPartialSigningResponse { - request_id: message.request_id.clone().into(), - partial_signature_s: message.partial_signature_s.clone().into(), - }, - )?; - - if data.consensus_session.state() != ConsensusSessionState::Finished { - return Ok(()); - } - - // send compeltion signal to all nodes, except for rejected nodes - for node in data.consensus_session.consensus_non_rejected_nodes() { - self.core.cluster.send( - &node, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionCompleted( - EcdsaSigningSessionCompleted { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - }, - )), - )?; - } - - let result = data.consensus_session.result()?; - Self::set_signing_result(&self.core, &mut *data, Ok(result)); - - Ok(()) - } - - /// When session is completed. - pub fn on_session_completed( - &self, - sender: &NodeId, - message: &EcdsaSigningSessionCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - self.data - .lock() - .consensus_session - .on_session_completed(sender) - } - - /// Process error from the other node. - fn process_node_error(&self, node: Option<&NodeId>, error: Error) -> Result<(), Error> { - let mut data = self.data.lock(); - let is_self_node_error = node - .map(|n| n == &self.core.meta.self_node_id) - .unwrap_or(false); - // error is always fatal if coming from this node - if is_self_node_error { - Self::set_signing_result(&self.core, &mut *data, Err(error.clone())); - return Err(error); - } - - match { - match node { - Some(node) => data.consensus_session.on_node_error(node, error.clone()), - None => data.consensus_session.on_session_timeout(), - } - } { - Ok(false) => Ok(()), - Ok(true) => { - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - - let message_hash = data.message_hash.as_ref().cloned() - .expect("on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when message_hash.is_some(); qed"); - - let nonce_exists_proof = "on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when nonces generation has completed; qed"; - let sig_nonce_public = data - .sig_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .0; - let inv_nonce_share = data - .inv_nonce_generation_session - .as_ref() - .expect(nonce_exists_proof) - .joint_public_and_secret() - .expect(nonce_exists_proof)? - .2; - - let inversed_nonce_coeff = Self::compute_inversed_nonce_coeff(&self.core, &*data)?; - - let disseminate_result = self.core.disseminate_jobs( - &mut data.consensus_session, - &version, - sig_nonce_public, - inv_nonce_share, - inversed_nonce_coeff, - message_hash, - ); - match disseminate_result { - Ok(()) => Ok(()), - Err(err) => { - warn!( - "{}: ECDSA signing session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - Self::set_signing_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - Err(err) => { - warn!( - "{}: ECDSA signing session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - Self::set_signing_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - - /// Start generation session. - fn start_generation_session( - core: &SessionCore, - other_consensus_group_nodes: &BTreeSet, - map_message: F, - ) -> GenerationSession - where - F: Fn(SessionId, Secret, u64, GenerationMessage) -> EcdsaSigningMessage - + Send - + Sync - + 'static, - { - GenerationSession::new(GenerationSessionParams { - id: core.meta.id.clone(), - self_node_id: core.meta.self_node_id.clone(), - key_storage: None, - cluster: Arc::new(NonceGenerationTransport { - id: core.meta.id.clone(), - access_key: core.access_key.clone(), - nonce: core.nonce, - cluster: core.cluster.clone(), - other_nodes_ids: other_consensus_group_nodes.clone(), - map: map_message, - }), - nonce: None, - }) - } - - /// Set signing session result. - fn set_signing_result( - core: &SessionCore, - data: &mut SessionData, - result: Result, - ) { - if let Some(DelegationStatus::DelegatedFrom(master, nonce)) = data.delegation_status.take() - { - // error means can't communicate => ignore it - let _ = match result.as_ref() { - Ok(signature) => core.cluster.send( - &master, - Message::EcdsaSigning( - EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted( - EcdsaSigningSessionDelegationCompleted { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - signature: signature.clone().into(), - }, - ), - ), - ), - Err(error) => core.cluster.send( - &master, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionError( - EcdsaSigningSessionError { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - error: error.clone().into(), - }, - )), - ), - }; - } - - data.result = Some(result); - core.completed.notify_all(); - } - - /// Check if all nonces are generated. - fn check_nonces_generated(data: &SessionData) -> bool { - let expect_proof = - "check_nonces_generated is called when som nonce-gen session is completed; - all nonce-gen sessions are created at once; qed"; - let sig_nonce_generation_session = data - .sig_nonce_generation_session - .as_ref() - .expect(expect_proof); - let inv_nonce_generation_session = data - .inv_nonce_generation_session - .as_ref() - .expect(expect_proof); - let inv_zero_generation_session = data - .inv_zero_generation_session - .as_ref() - .expect(expect_proof); - - sig_nonce_generation_session.state() == GenerationSessionState::Finished - && inv_nonce_generation_session.state() == GenerationSessionState::Finished - && inv_zero_generation_session.state() == GenerationSessionState::Finished - } - - /// Broadcast inversed nonce share. - fn send_inversed_nonce_coeff_share( - core: &SessionCore, - data: &mut SessionData, - ) -> Result<(), Error> { - let proof = "inversed nonce coeff share is sent after nonces generation is completed; qed"; - - let sig_nonce_generation_session = data.sig_nonce_generation_session.as_ref().expect(proof); - let sig_nonce = sig_nonce_generation_session - .joint_public_and_secret() - .expect(proof) - .expect(proof) - .2; - - let inv_nonce_generation_session = data.inv_nonce_generation_session.as_ref().expect(proof); - let inv_nonce = inv_nonce_generation_session - .joint_public_and_secret() - .expect(proof) - .expect(proof) - .2; - - let inv_zero_generation_session = data.inv_zero_generation_session.as_ref().expect(proof); - let inv_zero = inv_zero_generation_session - .joint_public_and_secret() - .expect(proof) - .expect(proof) - .2; - - let inversed_nonce_coeff_share = - math::compute_ecdsa_inversed_secret_coeff_share(&sig_nonce, &inv_nonce, &inv_zero)?; - if core.meta.self_node_id == core.meta.master_node_id { - let mut inversed_nonce_coeff_shares = BTreeMap::new(); - inversed_nonce_coeff_shares - .insert(core.meta.self_node_id.clone(), inversed_nonce_coeff_share); - data.inversed_nonce_coeff_shares = Some(inversed_nonce_coeff_shares); - Ok(()) - } else { - core.cluster.send( - &core.meta.master_node_id, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare( - EcdsaSigningInversedNonceCoeffShare { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: core.nonce, - inversed_nonce_coeff_share: inversed_nonce_coeff_share.into(), - }, - )), - ) - } - } - - /// Compute inversed nonce coefficient on master node. - fn compute_inversed_nonce_coeff( - core: &SessionCore, - data: &SessionData, - ) -> Result { - let proof = - "inversed nonce coeff is computed on master node; key version exists on master node"; - let key_share = core.key_share.as_ref().expect(proof); - let key_version = key_share - .version(data.version.as_ref().expect(proof)) - .expect(proof); - - let proof = "inversed nonce coeff is computed after all shares are received; qed"; - let inversed_nonce_coeff_shares = data.inversed_nonce_coeff_shares.as_ref().expect(proof); - - math::compute_ecdsa_inversed_secret_coeff_from_shares( - key_share.threshold, - &inversed_nonce_coeff_shares - .keys() - .map(|n| key_version.id_numbers[n].clone()) - .collect::>(), - &inversed_nonce_coeff_shares - .values() - .cloned() - .collect::>(), - ) - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionIdWithSubSession; - - fn type_name() -> &'static str { - "ecdsa_signing" - } - - fn id(&self) -> SessionIdWithSubSession { - SessionIdWithSubSession::new(self.core.meta.id.clone(), self.core.access_key.clone()) - } - - fn is_finished(&self) -> bool { - let data = self.data.lock(); - data.consensus_session.state() == ConsensusSessionState::Failed - || data.consensus_session.state() == ConsensusSessionState::Finished - || data.result.is_some() - } - - fn on_node_timeout(&self, node: &NodeId) { - // ignore error, only state matters - let _ = self.process_node_error(Some(node), Error::NodeDisconnected); - } - - fn on_session_timeout(&self) { - // ignore error, only state matters - let _ = self.process_node_error(None, Error::NodeDisconnected); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - let is_fatal = self.process_node_error(Some(node), error.clone()).is_err(); - let is_this_node_error = *node == self.core.meta.self_node_id; - if is_fatal || is_this_node_error { - // error in signing session is non-fatal, if occurs on slave node - // => either respond with error - // => or broadcast error - let message = Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionError( - EcdsaSigningSessionError { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - error: error.clone().into(), - }, - )); - - // do not bother processing send error, as we already processing error - let _ = if self.core.meta.master_node_id == self.core.meta.self_node_id { - self.core.cluster.broadcast(message) - } else { - self.core - .cluster - .send(&self.core.meta.master_node_id, message) - }; - } - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::EcdsaSigning(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl NonceGenerationTransport -where - F: Fn(SessionId, Secret, u64, GenerationMessage) -> EcdsaSigningMessage + Send + Sync, -{ - fn map_message(&self, message: Message) -> Result { - match message { - Message::Generation(message) => Ok(Message::EcdsaSigning((self.map)( - self.id.clone(), - self.access_key.clone(), - self.nonce, - message, - ))), - _ => Err(Error::InvalidMessage), - } - } -} - -impl Cluster for NonceGenerationTransport -where - F: Fn(SessionId, Secret, u64, GenerationMessage) -> EcdsaSigningMessage + Send + Sync, -{ - fn broadcast(&self, message: Message) -> Result<(), Error> { - let message = self.map_message(message)?; - for to in &self.other_nodes_ids { - self.cluster.send(to, message.clone())?; - } - Ok(()) - } - - fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { - debug_assert!(self.other_nodes_ids.contains(to)); - self.cluster.send(to, self.map_message(message)?) - } - - fn is_connected(&self, node: &NodeId) -> bool { - self.cluster.is_connected(node) - } - - fn nodes(&self) -> BTreeSet { - self.cluster.nodes() - } - - fn configured_nodes_count(&self) -> usize { - self.cluster.configured_nodes_count() - } - - fn connected_nodes_count(&self) -> usize { - self.cluster.connected_nodes_count() - } -} - -impl SessionCore { - pub fn signing_transport(&self) -> SigningJobTransport { - SigningJobTransport { - id: self.meta.id.clone(), - access_key: self.access_key.clone(), - nonce: self.nonce, - cluster: self.cluster.clone(), - } - } - - pub fn disseminate_jobs( - &self, - consensus_session: &mut SigningConsensusSession, - version: &H256, - nonce_public: Public, - inv_nonce_share: Secret, - inversed_nonce_coeff: Secret, - message_hash: H256, - ) -> Result<(), Error> { - let key_share = match self.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let key_version = key_share.version(version)?.hash.clone(); - let signing_job = EcdsaSigningJob::new_on_master( - key_share.clone(), - key_version, - nonce_public, - inv_nonce_share, - inversed_nonce_coeff, - message_hash, - )?; - consensus_session - .disseminate_jobs(signing_job, self.signing_transport(), false) - .map(|_| ()) - } -} - -impl JobTransport for SigningConsensusTransport { - type PartialJobRequest = Requester; - type PartialJobResponse = bool; - - fn send_partial_request(&self, node: &NodeId, request: Requester) -> Result<(), Error> { - let version = self.version.as_ref() - .expect("send_partial_request is called on initialized master node only; version is filled in before initialization starts on master node; qed"); - self.cluster.send( - node, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage( - EcdsaSigningConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessage::InitializeConsensusSession( - InitializeConsensusSession { - requester: request.into(), - version: version.clone().into(), - }, - ), - }, - )), - ) - } - - fn send_partial_response(&self, node: &NodeId, response: bool) -> Result<(), Error> { - self.cluster.send( - node, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage( - EcdsaSigningConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessage::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: response, - }, - ), - }, - )), - ) - } -} - -impl JobTransport for SigningJobTransport { - type PartialJobRequest = EcdsaPartialSigningRequest; - type PartialJobResponse = EcdsaPartialSigningResponse; - - fn send_partial_request( - &self, - node: &NodeId, - request: EcdsaPartialSigningRequest, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaRequestPartialSignature( - EcdsaRequestPartialSignature { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: request.id.into(), - inversed_nonce_coeff: request.inversed_nonce_coeff.into(), - message_hash: request.message_hash.into(), - }, - )), - ) - } - - fn send_partial_response( - &self, - node: &NodeId, - response: EcdsaPartialSigningResponse, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaPartialSignature( - EcdsaPartialSignature { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: response.request_id.into(), - partial_signature_s: response.partial_signature_s.into(), - }, - )), - ) - } -} - -#[cfg(test)] -mod tests { - use ethereum_types::H256; - use ethkey::{self, public_to_address, verify_public, Generator, Public, Random}; - use key_server_cluster::{ - cluster::tests::MessageLoop as ClusterMessageLoop, - generation_session::tests::MessageLoop as GenerationMessageLoop, - signing_session_ecdsa::SessionImpl, Error, KeyStorage, SessionId, - }; - use std::sync::Arc; - - #[derive(Debug)] - pub struct MessageLoop(pub ClusterMessageLoop); - - impl MessageLoop { - pub fn new(num_nodes: usize, threshold: usize) -> Result { - let ml = GenerationMessageLoop::new(num_nodes).init(threshold)?; - ml.0.loop_until(|| ml.0.is_empty()); // complete generation session - - Ok(MessageLoop(ml.0)) - } - - pub fn init_with_version( - self, - key_version: Option, - ) -> Result<(Self, Public, H256), Error> { - let message_hash = H256::random(); - let requester = Random.generate().unwrap(); - let signature = ethkey::sign(requester.secret(), &SessionId::default()).unwrap(); - self.0 - .cluster(0) - .client() - .new_ecdsa_signing_session( - Default::default(), - signature.into(), - key_version, - message_hash, - ) - .map(|_| (self, *requester.public(), message_hash)) - } - - pub fn init(self) -> Result<(Self, Public, H256), Error> { - let key_version = self - .0 - .key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .last() - .unwrap() - .hash; - self.init_with_version(Some(key_version)) - } - - pub fn init_delegated(self) -> Result<(Self, Public, H256), Error> { - self.0.key_storage(0).remove(&Default::default()).unwrap(); - self.init_with_version(None) - } - - pub fn init_with_isolated(self) -> Result<(Self, Public, H256), Error> { - self.0.isolate(1); - self.init() - } - - pub fn session_at(&self, idx: usize) -> Arc { - self.0.sessions(idx).ecdsa_signing_sessions.first().unwrap() - } - - pub fn ensure_completed(&self) { - self.0.loop_until(|| self.0.is_empty()); - assert!(self.session_at(0).wait().is_ok()); - } - } - - #[test] - fn failed_gen_ecdsa_sign_session_when_threshold_is_too_low() { - let test_cases = [(1, 2), (2, 4), (3, 6), (4, 6)]; - for &(threshold, num_nodes) in &test_cases { - assert_eq!( - MessageLoop::new(num_nodes, threshold) - .unwrap() - .init() - .unwrap_err(), - Error::ConsensusUnreachable - ); - } - } - - #[test] - fn complete_gen_ecdsa_sign_session() { - let test_cases = [(0, 1), (2, 5), (2, 6), (3, 11), (4, 11)]; - for &(threshold, num_nodes) in &test_cases { - let (ml, _, message) = MessageLoop::new(num_nodes, threshold) - .unwrap() - .init() - .unwrap(); - ml.0.loop_until(|| ml.0.is_empty()); - - let signer_public = - ml.0.key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .public; - let signature = ml.session_at(0).wait().unwrap(); - assert!(verify_public(&signer_public, &signature, &message).unwrap()); - } - } - - #[test] - fn ecdsa_complete_signing_session_with_single_node_failing() { - let (ml, requester, _) = MessageLoop::new(4, 1).unwrap().init().unwrap(); - - // we need at least 3-of-4 nodes to agree to reach consensus - // let's say 1 of 4 nodes disagee - ml.0.acl_storage(1) - .prohibit(public_to_address(&requester), Default::default()); - - // then consensus reachable, but single node will disagree - ml.ensure_completed(); - } - - #[test] - fn ecdsa_complete_signing_session_with_acl_check_failed_on_master() { - let (ml, requester, _) = MessageLoop::new(4, 1).unwrap().init().unwrap(); - - // we need at least 3-of-4 nodes to agree to reach consensus - // let's say 1 of 4 nodes (here: master) disagee - ml.0.acl_storage(0) - .prohibit(public_to_address(&requester), Default::default()); - - // then consensus reachable, but single node will disagree - ml.ensure_completed(); - } - - #[test] - fn ecdsa_signing_works_when_delegated_to_other_node() { - MessageLoop::new(4, 1) - .unwrap() - .init_delegated() - .unwrap() - .0 - .ensure_completed(); - } - - #[test] - fn ecdsa_signing_works_when_share_owners_are_isolated() { - MessageLoop::new(6, 2) - .unwrap() - .init_with_isolated() - .unwrap() - .0 - .ensure_completed(); - } -} diff --git a/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs b/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs deleted file mode 100644 index e307240d9c..0000000000 --- a/secret-store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs +++ /dev/null @@ -1,1478 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{Public, Secret}; -use key_server_cluster::{ - cluster::Cluster, - cluster_sessions::{ClusterSession, SessionIdWithSubSession}, - generation_session::{ - SessionImpl as GenerationSession, SessionParams as GenerationSessionParams, - SessionState as GenerationSessionState, - }, - jobs::{ - consensus_session::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}, - job_session::JobTransport, - key_access_job::KeyAccessJob, - signing_job_schnorr::{ - SchnorrPartialSigningRequest, SchnorrPartialSigningResponse, SchnorrSigningJob, - }, - }, - message::{ - ConfirmConsensusInitialization, ConsensusMessage, GenerationMessage, - InitializeConsensusSession, Message, SchnorrPartialSignature, - SchnorrRequestPartialSignature, SchnorrSigningConsensusMessage, - SchnorrSigningGenerationMessage, SchnorrSigningMessage, SchnorrSigningSessionCompleted, - SchnorrSigningSessionDelegation, SchnorrSigningSessionDelegationCompleted, - SchnorrSigningSessionError, - }, - AclStorage, DocumentKeyShare, Error, NodeId, Requester, SessionId, SessionMeta, -}; -use parking_lot::{Condvar, Mutex}; -use std::{collections::BTreeSet, sync::Arc}; - -/// Distributed Schnorr-signing session. -/// Based on "Efficient Multi-Party Digital Signature using Adaptive Secret Sharing for Low-Power Devices in Wireless Network" paper. -/// Brief overview: -/// 1) initialization: master node (which has received request for signing the message) requests all other nodes to sign the message -/// 2) ACL check: all nodes which have received the request are querying ACL-contract to check if requestor has access to the private key -/// 3) partial signing: every node which has succussfully checked access for the requestor do a partial signing -/// 4) signing: master node receives all partial signatures of the secret and computes the signature -pub struct SessionImpl { - /// Session core. - core: SessionCore, - /// Session data. - data: Mutex, -} - -/// Immutable session data. -struct SessionCore { - /// Session metadata. - pub meta: SessionMeta, - /// Signing session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// Cluster which allows this node to send messages to other nodes in the cluster. - pub cluster: Arc, - /// Session-level nonce. - pub nonce: u64, - /// SessionImpl completion condvar. - pub completed: Condvar, -} - -/// Signing consensus session type. -type SigningConsensusSession = ConsensusSession< - KeyAccessJob, - SigningConsensusTransport, - SchnorrSigningJob, - SigningJobTransport, ->; - -/// Mutable session data. -struct SessionData { - /// Session state. - pub state: SessionState, - /// Message hash. - pub message_hash: Option, - /// Key version to use for decryption. - pub version: Option, - /// Consensus-based signing session. - pub consensus_session: SigningConsensusSession, - /// Session key generation session. - pub generation_session: Option, - /// Delegation status. - pub delegation_status: Option, - /// Decryption result. - pub result: Option>, -} - -/// Signing session state. -#[derive(Debug, PartialEq)] -#[cfg_attr(test, derive(Clone, Copy))] -pub enum SessionState { - /// State when consensus is establishing. - ConsensusEstablishing, - /// State when session key is generating. - SessionKeyGeneration, - /// State when signature is computing. - SignatureComputing, -} - -/// Session creation parameters -pub struct SessionParams { - /// Session metadata. - pub meta: SessionMeta, - /// Session access key. - pub access_key: Secret, - /// Key share. - pub key_share: Option, - /// ACL storage. - pub acl_storage: Arc, - /// Cluster - pub cluster: Arc, - /// Session nonce. - pub nonce: u64, -} - -/// Signing consensus transport. -struct SigningConsensusTransport { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Selected key version (on master node). - version: Option, - /// Cluster. - cluster: Arc, -} - -/// Signing key generation transport. -struct SessionKeyGenerationTransport { - /// Session access key. - access_key: Secret, - /// Cluster. - cluster: Arc, - /// Session-level nonce. - nonce: u64, - /// Other nodes ids. - other_nodes_ids: BTreeSet, -} - -/// Signing job transport -struct SigningJobTransport { - /// Session id. - id: SessionId, - /// Session access key. - access_key: Secret, - /// Session-level nonce. - nonce: u64, - /// Cluster. - cluster: Arc, -} - -/// Session delegation status. -enum DelegationStatus { - /// Delegated to other node. - DelegatedTo(NodeId), - /// Delegated from other node. - DelegatedFrom(NodeId, u64), -} - -impl SessionImpl { - /// Create new signing session. - pub fn new(params: SessionParams, requester: Option) -> Result { - debug_assert_eq!( - params.meta.threshold, - params - .key_share - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default() - ); - - let consensus_transport = SigningConsensusTransport { - id: params.meta.id.clone(), - access_key: params.access_key.clone(), - nonce: params.nonce, - version: None, - cluster: params.cluster.clone(), - }; - let consensus_session = ConsensusSession::new(ConsensusSessionParams { - meta: params.meta.clone(), - consensus_executor: match requester { - Some(requester) => KeyAccessJob::new_on_master( - params.meta.id.clone(), - params.acl_storage.clone(), - requester, - ), - None => { - KeyAccessJob::new_on_slave(params.meta.id.clone(), params.acl_storage.clone()) - } - }, - consensus_transport: consensus_transport, - })?; - - Ok(SessionImpl { - core: SessionCore { - meta: params.meta, - access_key: params.access_key, - key_share: params.key_share, - cluster: params.cluster, - nonce: params.nonce, - completed: Condvar::new(), - }, - data: Mutex::new(SessionData { - state: SessionState::ConsensusEstablishing, - message_hash: None, - version: None, - consensus_session: consensus_session, - generation_session: None, - delegation_status: None, - result: None, - }), - }) - } - - /// Get session state. - #[cfg(test)] - pub fn state(&self) -> SessionState { - self.data.lock().state - } - - /// Wait for session completion. - pub fn wait(&self) -> Result<(Secret, Secret), Error> { - Self::wait_session(&self.core.completed, &self.data, None, |data| { - data.result.clone() - }) - .expect("wait_session returns Some if called without timeout; qed") - } - - /// Delegate session to other node. - pub fn delegate(&self, master: NodeId, version: H256, message_hash: H256) -> Result<(), Error> { - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(false); - self.core.cluster.send(&master, Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionDelegation(SchnorrSigningSessionDelegation { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - requester: data.consensus_session.consensus_job().executor().requester() - .expect("requester is passed to master node on creation; session can be delegated from master node only; qed") - .clone().into(), - version: version.into(), - message_hash: message_hash.into(), - })))?; - data.delegation_status = Some(DelegationStatus::DelegatedTo(master)); - Ok(()) - } - - /// Initialize signing session on master node. - pub fn initialize(&self, version: H256, message_hash: H256) -> Result<(), Error> { - debug_assert_eq!(self.core.meta.self_node_id, self.core.meta.master_node_id); - - // check if version exists - let key_version = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version)?, - }; - - let mut data = self.data.lock(); - let non_isolated_nodes = self.core.cluster.nodes(); - let mut consensus_nodes: BTreeSet<_> = key_version - .id_numbers - .keys() - .filter(|n| non_isolated_nodes.contains(*n)) - .cloned() - .chain(::std::iter::once(self.core.meta.self_node_id.clone())) - .collect(); - if let Some(&DelegationStatus::DelegatedFrom(delegation_master, _)) = - data.delegation_status.as_ref() - { - consensus_nodes.remove(&delegation_master); - } - - data.consensus_session - .consensus_job_mut() - .transport_mut() - .version = Some(version.clone()); - data.version = Some(version.clone()); - data.message_hash = Some(message_hash); - data.consensus_session.initialize(consensus_nodes)?; - - if data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished { - let generation_session = GenerationSession::new(GenerationSessionParams { - id: self.core.meta.id.clone(), - self_node_id: self.core.meta.self_node_id.clone(), - key_storage: None, - cluster: Arc::new(SessionKeyGenerationTransport { - access_key: self.core.access_key.clone(), - cluster: self.core.cluster.clone(), - nonce: self.core.nonce, - other_nodes_ids: BTreeSet::new(), - }), - nonce: None, - }); - generation_session.initialize( - Default::default(), - Default::default(), - false, - 0, - vec![self.core.meta.self_node_id.clone()] - .into_iter() - .collect::>() - .into(), - )?; - - debug_assert_eq!(generation_session.state(), GenerationSessionState::Finished); - let joint_public_and_secret = generation_session - .joint_public_and_secret() - .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed")?; - data.generation_session = Some(generation_session); - data.state = SessionState::SignatureComputing; - - self.core.disseminate_jobs( - &mut data.consensus_session, - &version, - joint_public_and_secret.0, - joint_public_and_secret.1, - message_hash, - )?; - - debug_assert!(data.consensus_session.state() == ConsensusSessionState::Finished); - let result = data.consensus_session.result()?; - Self::set_signing_result(&self.core, &mut *data, Ok(result)); - } - - Ok(()) - } - - /// Process signing message. - pub fn process_message( - &self, - sender: &NodeId, - message: &SchnorrSigningMessage, - ) -> Result<(), Error> { - if self.core.nonce != message.session_nonce() { - return Err(Error::ReplayProtection); - } - - match message { - &SchnorrSigningMessage::SchnorrSigningConsensusMessage(ref message) => { - self.on_consensus_message(sender, message) - } - &SchnorrSigningMessage::SchnorrSigningGenerationMessage(ref message) => { - self.on_generation_message(sender, message) - } - &SchnorrSigningMessage::SchnorrRequestPartialSignature(ref message) => { - self.on_partial_signature_requested(sender, message) - } - &SchnorrSigningMessage::SchnorrPartialSignature(ref message) => { - self.on_partial_signature(sender, message) - } - &SchnorrSigningMessage::SchnorrSigningSessionError(ref message) => { - self.process_node_error(Some(&sender), message.error.clone()) - } - &SchnorrSigningMessage::SchnorrSigningSessionCompleted(ref message) => { - self.on_session_completed(sender, message) - } - &SchnorrSigningMessage::SchnorrSigningSessionDelegation(ref message) => { - self.on_session_delegated(sender, message) - } - &SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(ref message) => { - self.on_session_delegation_completed(sender, message) - } - } - } - - /// When session is delegated to this node. - pub fn on_session_delegated( - &self, - sender: &NodeId, - message: &SchnorrSigningSessionDelegation, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - { - let mut data = self.data.lock(); - if data.consensus_session.state() != ConsensusSessionState::WaitingForInitialization - || data.delegation_status.is_some() - { - return Err(Error::InvalidStateForRequest); - } - - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_requester(message.requester.clone().into()); - data.delegation_status = Some(DelegationStatus::DelegatedFrom( - sender.clone(), - message.session_nonce, - )); - } - - self.initialize( - message.version.clone().into(), - message.message_hash.clone().into(), - ) - } - - /// When delegated session is completed on other node. - pub fn on_session_delegation_completed( - &self, - sender: &NodeId, - message: &SchnorrSigningSessionDelegationCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Err(Error::InvalidStateForRequest); - } - - let mut data = self.data.lock(); - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(ref node)) if node == sender => (), - _ => return Err(Error::InvalidMessage), - } - - Self::set_signing_result( - &self.core, - &mut *data, - Ok(( - message.signature_c.clone().into(), - message.signature_s.clone().into(), - )), - ); - - Ok(()) - } - - /// When consensus-related message is received. - pub fn on_consensus_message( - &self, - sender: &NodeId, - message: &SchnorrSigningConsensusMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - let is_establishing_consensus = - data.consensus_session.state() == ConsensusSessionState::EstablishingConsensus; - - if let &ConsensusMessage::InitializeConsensusSession(ref msg) = &message.message { - let version = msg.version.clone().into(); - let has_key_share = self - .core - .key_share - .as_ref() - .map(|ks| ks.version(&version).is_ok()) - .unwrap_or(false); - data.consensus_session - .consensus_job_mut() - .executor_mut() - .set_has_key_share(has_key_share); - data.version = Some(version); - } - data.consensus_session - .on_consensus_message(&sender, &message.message)?; - - let is_consensus_established = - data.consensus_session.state() == ConsensusSessionState::ConsensusEstablished; - if self.core.meta.self_node_id != self.core.meta.master_node_id - || !is_establishing_consensus - || !is_consensus_established - { - return Ok(()); - } - - let consensus_group = data.consensus_session.select_consensus_group()?.clone(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - - let key_share = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let generation_session = GenerationSession::new(GenerationSessionParams { - id: self.core.meta.id.clone(), - self_node_id: self.core.meta.self_node_id.clone(), - key_storage: None, - cluster: Arc::new(SessionKeyGenerationTransport { - access_key: self.core.access_key.clone(), - cluster: self.core.cluster.clone(), - nonce: self.core.nonce, - other_nodes_ids: other_consensus_group_nodes, - }), - nonce: None, - }); - - generation_session.initialize( - Default::default(), - Default::default(), - false, - key_share.threshold, - consensus_group.into(), - )?; - data.generation_session = Some(generation_session); - data.state = SessionState::SessionKeyGeneration; - - Ok(()) - } - - /// When session key related message is received. - pub fn on_generation_message( - &self, - sender: &NodeId, - message: &SchnorrSigningGenerationMessage, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - - if let &GenerationMessage::InitializeSession(ref message) = &message.message { - if &self.core.meta.master_node_id != sender { - match data.delegation_status.as_ref() { - Some(&DelegationStatus::DelegatedTo(s)) if s == *sender => (), - _ => return Err(Error::InvalidMessage), - } - } - - let consensus_group: BTreeSet = - message.nodes.keys().cloned().map(Into::into).collect(); - let mut other_consensus_group_nodes = consensus_group.clone(); - other_consensus_group_nodes.remove(&self.core.meta.self_node_id); - - let generation_session = GenerationSession::new(GenerationSessionParams { - id: self.core.meta.id.clone(), - self_node_id: self.core.meta.self_node_id.clone(), - key_storage: None, - cluster: Arc::new(SessionKeyGenerationTransport { - access_key: self.core.access_key.clone(), - cluster: self.core.cluster.clone(), - nonce: self.core.nonce, - other_nodes_ids: other_consensus_group_nodes, - }), - nonce: None, - }); - data.generation_session = Some(generation_session); - data.state = SessionState::SessionKeyGeneration; - } - - { - let generation_session = data - .generation_session - .as_ref() - .ok_or(Error::InvalidStateForRequest)?; - let is_key_generating = generation_session.state() != GenerationSessionState::Finished; - generation_session.process_message(sender, &message.message)?; - - let is_key_generated = generation_session.state() == GenerationSessionState::Finished; - if !is_key_generating || !is_key_generated { - return Ok(()); - } - } - - data.state = SessionState::SignatureComputing; - if self.core.meta.master_node_id != self.core.meta.self_node_id { - return Ok(()); - } - - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let message_hash = data.message_hash - .expect("we are on master node; on master node message_hash is filled in initialize(); on_generation_message follows initialize; qed"); - let joint_public_and_secret = data.generation_session.as_ref() - .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed") - .joint_public_and_secret() - .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed")?; - self.core.disseminate_jobs( - &mut data.consensus_session, - &version, - joint_public_and_secret.0, - joint_public_and_secret.1, - message_hash, - ) - } - - /// When partial signature is requested. - pub fn on_partial_signature_requested( - &self, - sender: &NodeId, - message: &SchnorrRequestPartialSignature, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let key_share = match self.core.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let mut data = self.data.lock(); - - if sender != &self.core.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if data.state != SessionState::SignatureComputing { - return Err(Error::InvalidStateForRequest); - } - - let joint_public_and_secret = data.generation_session.as_ref() - .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed") - .joint_public_and_secret() - .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed")?; - let key_version = key_share - .version(data.version.as_ref().ok_or(Error::InvalidMessage)?)? - .hash - .clone(); - let signing_job = SchnorrSigningJob::new_on_slave( - self.core.meta.self_node_id.clone(), - key_share.clone(), - key_version, - joint_public_and_secret.0, - joint_public_and_secret.1, - )?; - let signing_transport = self.core.signing_transport(); - - data.consensus_session - .on_job_request( - sender, - SchnorrPartialSigningRequest { - id: message.request_id.clone().into(), - message_hash: message.message_hash.clone().into(), - other_nodes_ids: message.nodes.iter().cloned().map(Into::into).collect(), - }, - signing_job, - signing_transport, - ) - .map(|_| ()) - } - - /// When partial signature is received. - pub fn on_partial_signature( - &self, - sender: &NodeId, - message: &SchnorrPartialSignature, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - let mut data = self.data.lock(); - data.consensus_session.on_job_response( - sender, - SchnorrPartialSigningResponse { - request_id: message.request_id.clone().into(), - partial_signature: message.partial_signature.clone().into(), - }, - )?; - - if data.consensus_session.state() != ConsensusSessionState::Finished { - return Ok(()); - } - - // send compeltion signal to all nodes, except for rejected nodes - for node in data.consensus_session.consensus_non_rejected_nodes() { - self.core.cluster.send( - &node, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionCompleted( - SchnorrSigningSessionCompleted { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - }, - )), - )?; - } - - let result = data.consensus_session.result()?; - Self::set_signing_result(&self.core, &mut *data, Ok(result)); - - Ok(()) - } - - /// When session is completed. - pub fn on_session_completed( - &self, - sender: &NodeId, - message: &SchnorrSigningSessionCompleted, - ) -> Result<(), Error> { - debug_assert!(self.core.meta.id == *message.session); - debug_assert!(self.core.access_key == *message.sub_session); - debug_assert!(sender != &self.core.meta.self_node_id); - - self.data - .lock() - .consensus_session - .on_session_completed(sender) - } - - /// Process error from the other node. - fn process_node_error(&self, node: Option<&NodeId>, error: Error) -> Result<(), Error> { - let mut data = self.data.lock(); - let is_self_node_error = node - .map(|n| n == &self.core.meta.self_node_id) - .unwrap_or(false); - // error is always fatal if coming from this node - if is_self_node_error { - Self::set_signing_result(&self.core, &mut *data, Err(error.clone())); - return Err(error); - } - - match { - match node { - Some(node) => data.consensus_session.on_node_error(node, error.clone()), - None => data.consensus_session.on_session_timeout(), - } - } { - Ok(false) => Ok(()), - Ok(true) => { - let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let message_hash = data.message_hash.as_ref().cloned() - .expect("on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when message_hash.is_some(); qed"); - let joint_public_and_secret = data.generation_session.as_ref() - .expect("on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when message_hash.is_some(); qed") - .joint_public_and_secret() - .expect("on_node_error returned true; this means that jobs must be REsent; this means that jobs already have been sent; jobs are sent when message_hash.is_some(); qed")?; - let disseminate_result = self.core.disseminate_jobs( - &mut data.consensus_session, - &version, - joint_public_and_secret.0, - joint_public_and_secret.1, - message_hash, - ); - match disseminate_result { - Ok(()) => Ok(()), - Err(err) => { - warn!( - "{}: signing session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - Self::set_signing_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - Err(err) => { - warn!( - "{}: signing session failed with error: {:?} from {:?}", - &self.core.meta.self_node_id, error, node - ); - Self::set_signing_result(&self.core, &mut *data, Err(err.clone())); - Err(err) - } - } - } - - /// Set signing session result. - fn set_signing_result( - core: &SessionCore, - data: &mut SessionData, - result: Result<(Secret, Secret), Error>, - ) { - if let Some(DelegationStatus::DelegatedFrom(master, nonce)) = data.delegation_status.take() - { - // error means can't communicate => ignore it - let _ = match result.as_ref() { - Ok(signature) => core.cluster.send( - &master, - Message::SchnorrSigning( - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted( - SchnorrSigningSessionDelegationCompleted { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - signature_c: signature.0.clone().into(), - signature_s: signature.1.clone().into(), - }, - ), - ), - ), - Err(error) => core.cluster.send( - &master, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionError( - SchnorrSigningSessionError { - session: core.meta.id.clone().into(), - sub_session: core.access_key.clone().into(), - session_nonce: nonce, - error: error.clone().into(), - }, - )), - ), - }; - } - - data.result = Some(result); - core.completed.notify_all(); - } -} - -impl ClusterSession for SessionImpl { - type Id = SessionIdWithSubSession; - - fn type_name() -> &'static str { - "signing" - } - - fn id(&self) -> SessionIdWithSubSession { - SessionIdWithSubSession::new(self.core.meta.id.clone(), self.core.access_key.clone()) - } - - fn is_finished(&self) -> bool { - let data = self.data.lock(); - data.consensus_session.state() == ConsensusSessionState::Failed - || data.consensus_session.state() == ConsensusSessionState::Finished - || data.result.is_some() - } - - fn on_node_timeout(&self, node: &NodeId) { - // ignore error, only state matters - let _ = self.process_node_error(Some(node), Error::NodeDisconnected); - } - - fn on_session_timeout(&self) { - // ignore error, only state matters - let _ = self.process_node_error(None, Error::NodeDisconnected); - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - let is_fatal = self.process_node_error(Some(node), error.clone()).is_err(); - let is_this_node_error = *node == self.core.meta.self_node_id; - if is_fatal || is_this_node_error { - // error in signing session is non-fatal, if occurs on slave node - // => either respond with error - // => or broadcast error - let message = Message::SchnorrSigning( - SchnorrSigningMessage::SchnorrSigningSessionError(SchnorrSigningSessionError { - session: self.core.meta.id.clone().into(), - sub_session: self.core.access_key.clone().into(), - session_nonce: self.core.nonce, - error: error.clone().into(), - }), - ); - - // do not bother processing send error, as we already processing error - let _ = if self.core.meta.master_node_id == self.core.meta.self_node_id { - self.core.cluster.broadcast(message) - } else { - self.core - .cluster - .send(&self.core.meta.master_node_id, message) - }; - } - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *message { - Message::SchnorrSigning(ref message) => self.process_message(sender, message), - _ => unreachable!("cluster checks message to be correct before passing; qed"), - } - } -} - -impl SessionKeyGenerationTransport { - fn map_message(&self, message: Message) -> Result { - match message { - Message::Generation(message) => Ok(Message::SchnorrSigning( - SchnorrSigningMessage::SchnorrSigningGenerationMessage( - SchnorrSigningGenerationMessage { - session: message.session_id().clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - message: message, - }, - ), - )), - _ => Err(Error::InvalidMessage), - } - } -} - -impl Cluster for SessionKeyGenerationTransport { - fn broadcast(&self, message: Message) -> Result<(), Error> { - let message = self.map_message(message)?; - for to in &self.other_nodes_ids { - self.cluster.send(to, message.clone())?; - } - Ok(()) - } - - fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { - debug_assert!(self.other_nodes_ids.contains(to)); - self.cluster.send(to, self.map_message(message)?) - } - - fn is_connected(&self, node: &NodeId) -> bool { - self.cluster.is_connected(node) - } - - fn nodes(&self) -> BTreeSet { - self.cluster.nodes() - } - - fn configured_nodes_count(&self) -> usize { - self.cluster.configured_nodes_count() - } - - fn connected_nodes_count(&self) -> usize { - self.cluster.connected_nodes_count() - } -} - -impl SessionCore { - pub fn signing_transport(&self) -> SigningJobTransport { - SigningJobTransport { - id: self.meta.id.clone(), - access_key: self.access_key.clone(), - nonce: self.nonce, - cluster: self.cluster.clone(), - } - } - - pub fn disseminate_jobs( - &self, - consensus_session: &mut SigningConsensusSession, - version: &H256, - session_public: Public, - session_secret_share: Secret, - message_hash: H256, - ) -> Result<(), Error> { - let key_share = match self.key_share.as_ref() { - None => return Err(Error::InvalidMessage), - Some(key_share) => key_share, - }; - - let key_version = key_share.version(version)?.hash.clone(); - let signing_job = SchnorrSigningJob::new_on_master( - self.meta.self_node_id.clone(), - key_share.clone(), - key_version, - session_public, - session_secret_share, - message_hash, - )?; - consensus_session - .disseminate_jobs(signing_job, self.signing_transport(), false) - .map(|_| ()) - } -} - -impl JobTransport for SigningConsensusTransport { - type PartialJobRequest = Requester; - type PartialJobResponse = bool; - - fn send_partial_request(&self, node: &NodeId, request: Requester) -> Result<(), Error> { - let version = self.version.as_ref() - .expect("send_partial_request is called on initialized master node only; version is filled in before initialization starts on master node; qed"); - self.cluster.send( - node, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage( - SchnorrSigningConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessage::InitializeConsensusSession( - InitializeConsensusSession { - requester: request.into(), - version: version.clone().into(), - }, - ), - }, - )), - ) - } - - fn send_partial_response(&self, node: &NodeId, response: bool) -> Result<(), Error> { - self.cluster.send( - node, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage( - SchnorrSigningConsensusMessage { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - message: ConsensusMessage::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: response, - }, - ), - }, - )), - ) - } -} - -impl JobTransport for SigningJobTransport { - type PartialJobRequest = SchnorrPartialSigningRequest; - type PartialJobResponse = SchnorrPartialSigningResponse; - - fn send_partial_request( - &self, - node: &NodeId, - request: SchnorrPartialSigningRequest, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrRequestPartialSignature( - SchnorrRequestPartialSignature { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: request.id.into(), - message_hash: request.message_hash.into(), - nodes: request - .other_nodes_ids - .into_iter() - .map(Into::into) - .collect(), - }, - )), - ) - } - - fn send_partial_response( - &self, - node: &NodeId, - response: SchnorrPartialSigningResponse, - ) -> Result<(), Error> { - self.cluster.send( - node, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrPartialSignature( - SchnorrPartialSignature { - session: self.id.clone().into(), - sub_session: self.access_key.clone().into(), - session_nonce: self.nonce, - request_id: response.request_id.into(), - partial_signature: response.partial_signature.into(), - }, - )), - ) - } -} - -#[cfg(test)] -mod tests { - use acl_storage::DummyAclStorage; - use ethereum_types::{Address, H256}; - use ethkey::{self, public_to_address, Generator, Public, Random, Secret}; - use key_server_cluster::{ - cluster::tests::MessageLoop as ClusterMessageLoop, - generation_session::tests::MessageLoop as GenerationMessageLoop, - math, - message::{ - ConfirmConsensusInitialization, ConfirmInitialization, ConsensusMessage, - GenerationMessage, InitializeSession, SchnorrRequestPartialSignature, - SchnorrSigningConsensusMessage, SchnorrSigningGenerationMessage, SchnorrSigningMessage, - }, - signing_session_schnorr::{SessionImpl, SessionParams, SessionState}, - Error, KeyStorage, Requester, SessionId, SessionMeta, - }; - use std::{collections::BTreeMap, str::FromStr, sync::Arc}; - - #[derive(Debug)] - pub struct MessageLoop(pub ClusterMessageLoop); - - impl MessageLoop { - pub fn new(num_nodes: usize, threshold: usize) -> Result { - let ml = GenerationMessageLoop::new(num_nodes).init(threshold)?; - ml.0.loop_until(|| ml.0.is_empty()); // complete generation session - - Ok(MessageLoop(ml.0)) - } - - pub fn into_session(&self, at_node: usize) -> SessionImpl { - let requester = Some(Requester::Signature( - ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - )); - SessionImpl::new( - SessionParams { - meta: SessionMeta { - id: SessionId::default(), - self_node_id: self.0.node(at_node), - master_node_id: self.0.node(0), - threshold: self - .0 - .key_storage(at_node) - .get(&Default::default()) - .unwrap() - .unwrap() - .threshold, - configured_nodes_count: self.0.nodes().len(), - connected_nodes_count: self.0.nodes().len(), - }, - access_key: Random.generate().unwrap().secret().clone(), - key_share: self - .0 - .key_storage(at_node) - .get(&Default::default()) - .unwrap(), - acl_storage: Arc::new(DummyAclStorage::default()), - cluster: self.0.cluster(0).view().unwrap(), - nonce: 0, - }, - requester, - ) - .unwrap() - } - - pub fn init_with_version( - self, - key_version: Option, - ) -> Result<(Self, Public, H256), Error> { - let message_hash = H256::random(); - let requester = Random.generate().unwrap(); - let signature = ethkey::sign(requester.secret(), &SessionId::default()).unwrap(); - self.0 - .cluster(0) - .client() - .new_schnorr_signing_session( - Default::default(), - signature.into(), - key_version, - message_hash, - ) - .map(|_| (self, *requester.public(), message_hash)) - } - - pub fn init(self) -> Result<(Self, Public, H256), Error> { - let key_version = self.key_version(); - self.init_with_version(Some(key_version)) - } - - pub fn init_delegated(self) -> Result<(Self, Public, H256), Error> { - self.0.key_storage(0).remove(&Default::default()).unwrap(); - self.init_with_version(None) - } - - pub fn init_with_isolated(self) -> Result<(Self, Public, H256), Error> { - self.0.isolate(1); - self.init() - } - - pub fn init_without_share(self) -> Result<(Self, Public, H256), Error> { - let key_version = self.key_version(); - self.0.key_storage(0).remove(&Default::default()).unwrap(); - self.init_with_version(Some(key_version)) - } - - pub fn session_at(&self, idx: usize) -> Arc { - self.0 - .sessions(idx) - .schnorr_signing_sessions - .first() - .unwrap() - } - - pub fn ensure_completed(&self) { - self.0.loop_until(|| self.0.is_empty()); - assert!(self.session_at(0).wait().is_ok()); - } - - pub fn key_version(&self) -> H256 { - self.0 - .key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .versions - .iter() - .last() - .unwrap() - .hash - } - } - - #[test] - fn schnorr_complete_gen_sign_session() { - let test_cases = [(0, 1), (0, 5), (2, 5), (3, 5)]; - for &(threshold, num_nodes) in &test_cases { - let (ml, _, message) = MessageLoop::new(num_nodes, threshold) - .unwrap() - .init() - .unwrap(); - ml.0.loop_until(|| ml.0.is_empty()); - - let signer_public = - ml.0.key_storage(0) - .get(&Default::default()) - .unwrap() - .unwrap() - .public; - let signature = ml.session_at(0).wait().unwrap(); - assert!(math::verify_schnorr_signature(&signer_public, &signature, &message).unwrap()); - } - } - - #[test] - fn schnorr_constructs_in_cluster_of_single_node() { - MessageLoop::new(1, 0).unwrap().init().unwrap(); - } - - #[test] - fn schnorr_fails_to_initialize_if_does_not_have_a_share() { - assert!(MessageLoop::new(2, 1) - .unwrap() - .init_without_share() - .is_err()); - } - - #[test] - fn schnorr_fails_to_initialize_if_threshold_is_wrong() { - let mut ml = MessageLoop::new(3, 2).unwrap(); - ml.0.exclude(2); - assert_eq!(ml.init().unwrap_err(), Error::ConsensusUnreachable); - } - - #[test] - fn schnorr_fails_to_initialize_when_already_initialized() { - let (ml, _, _) = MessageLoop::new(1, 0).unwrap().init().unwrap(); - assert_eq!( - ml.session_at(0).initialize(ml.key_version(), 777.into()), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn schnorr_does_not_fail_when_consensus_message_received_after_consensus_established() { - let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); - - // consensus is established - let session = ml.session_at(0); - ml.0.loop_until(|| session.state() == SessionState::SessionKeyGeneration); - - // but 3rd node continues to send its messages - // this should not fail session - let consensus_group = session - .data - .lock() - .consensus_session - .select_consensus_group() - .unwrap() - .clone(); - let mut had_3rd_message = false; - while let Some((from, to, message)) = ml.0.take_message() { - if !consensus_group.contains(&from) { - had_3rd_message = true; - ml.0.process_message(from, to, message); - } - } - assert!(had_3rd_message); - } - - #[test] - fn schnorr_fails_when_consensus_message_is_received_when_not_initialized() { - let ml = MessageLoop::new(3, 1).unwrap(); - let session = ml.into_session(0); - assert_eq!( - session.on_consensus_message( - &ml.0.node(1), - &SchnorrSigningConsensusMessage { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 0, - message: ConsensusMessage::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { is_confirmed: true } - ), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn schnorr_fails_when_generation_message_is_received_when_not_initialized() { - let ml = MessageLoop::new(3, 1).unwrap(); - let session = ml.into_session(0); - assert_eq!( - session.on_generation_message( - &ml.0.node(1), - &SchnorrSigningGenerationMessage { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 0, - message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { - session: SessionId::default().into(), - session_nonce: 0, - derived_point: Public::default().into(), - }), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn schnorr_fails_when_generation_sesson_is_initialized_by_slave_node() { - let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); - let session = ml.session_at(0); - ml.0.loop_until(|| session.state() == SessionState::SessionKeyGeneration); - - let slave2_id = ml.0.node(2); - let slave1_session = ml.session_at(1); - - assert_eq!( - slave1_session.on_generation_message( - &slave2_id, - &SchnorrSigningGenerationMessage { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 0, - message: GenerationMessage::InitializeSession(InitializeSession { - session: SessionId::default().into(), - session_nonce: 0, - origin: None, - author: Address::default().into(), - nodes: BTreeMap::new(), - is_zero: false, - threshold: 1, - derived_point: Public::default().into(), - }) - } - ), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn schnorr_fails_when_signature_requested_when_not_initialized() { - let ml = MessageLoop::new(3, 1).unwrap(); - let session = ml.into_session(1); - assert_eq!( - session.on_partial_signature_requested( - &ml.0.node(0), - &SchnorrRequestPartialSignature { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 0, - request_id: Secret::from_str( - "0000000000000000000000000000000000000000000000000000000000000001" - ) - .unwrap() - .into(), - message_hash: H256::default().into(), - nodes: Default::default(), - } - ), - Err(Error::InvalidStateForRequest) - ); - } - - #[test] - fn schnorr_fails_when_signature_requested_by_slave_node() { - let ml = MessageLoop::new(3, 1).unwrap(); - let session = ml.into_session(0); - assert_eq!( - session.on_partial_signature_requested( - &ml.0.node(1), - &SchnorrRequestPartialSignature { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 0, - request_id: Secret::from_str( - "0000000000000000000000000000000000000000000000000000000000000001" - ) - .unwrap() - .into(), - message_hash: H256::default().into(), - nodes: Default::default(), - } - ), - Err(Error::InvalidMessage) - ); - } - - #[test] - fn schnorr_failed_signing_session() { - let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); - - // we need at least 2-of-3 nodes to agree to reach consensus - // let's say 2 of 3 nodes disagee - ml.0.acl_storage(1) - .prohibit(public_to_address(&requester), SessionId::default()); - ml.0.acl_storage(2) - .prohibit(public_to_address(&requester), SessionId::default()); - - // then consensus is unreachable - ml.0.loop_until(|| ml.0.is_empty()); - assert_eq!( - ml.session_at(0).wait().unwrap_err(), - Error::ConsensusUnreachable - ); - } - - #[test] - fn schnorr_complete_signing_session_with_single_node_failing() { - let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); - - // we need at least 2-of-3 nodes to agree to reach consensus - // let's say 1 of 3 nodes disagee - ml.0.acl_storage(1) - .prohibit(public_to_address(&requester), SessionId::default()); - - // then consensus reachable, but single node will disagree - ml.ensure_completed(); - } - - #[test] - fn schnorr_complete_signing_session_with_acl_check_failed_on_master() { - let (ml, requester, _) = MessageLoop::new(3, 1).unwrap().init().unwrap(); - - // we need at least 2-of-3 nodes to agree to reach consensus - // let's say 1 of 3 nodes disagee - ml.0.acl_storage(0) - .prohibit(public_to_address(&requester), SessionId::default()); - - // then consensus reachable, but single node will disagree - ml.ensure_completed(); - } - - #[test] - fn schnorr_signing_message_fails_when_nonce_is_wrong() { - let ml = MessageLoop::new(3, 1).unwrap(); - let session = ml.into_session(1); - let msg = SchnorrSigningMessage::SchnorrSigningGenerationMessage( - SchnorrSigningGenerationMessage { - session: SessionId::default().into(), - sub_session: session.core.access_key.clone().into(), - session_nonce: 10, - message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { - session: SessionId::default().into(), - session_nonce: 0, - derived_point: Public::default().into(), - }), - }, - ); - assert_eq!( - session.process_message(&ml.0.node(1), &msg), - Err(Error::ReplayProtection) - ); - } - - #[test] - fn schnorr_signing_works_when_delegated_to_other_node() { - let (ml, _, _) = MessageLoop::new(3, 1).unwrap().init_delegated().unwrap(); - ml.ensure_completed(); - } - - #[test] - fn schnorr_signing_works_when_share_owners_are_isolated() { - let (ml, _, _) = MessageLoop::new(3, 1) - .unwrap() - .init_with_isolated() - .unwrap(); - ml.ensure_completed(); - } -} diff --git a/secret-store/src/key_server_cluster/cluster.rs b/secret-store/src/key_server_cluster/cluster.rs deleted file mode 100644 index 05fa633218..0000000000 --- a/secret-store/src/key_server_cluster/cluster.rs +++ /dev/null @@ -1,1805 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::{Generator, Public, Random, Signature}; -use key_server_cluster::{ - cluster_connections::{ConnectionManager, ConnectionProvider}, - cluster_connections_net::{ - NetConnectionsContainer, NetConnectionsManager, NetConnectionsManagerConfig, - }, - cluster_message_processor::{MessageProcessor, SessionsMessageProcessor}, - cluster_sessions::{ - create_cluster_view, AdminSession, AdminSessionCreationData, ClusterSession, - ClusterSessions, ClusterSessionsContainer, ClusterSessionsListener, - SessionIdWithSubSession, SERVERS_SET_CHANGE_SESSION_ID, - }, - cluster_sessions_creator::ClusterSessionCreator, - connection_trigger::{ - ConnectionTrigger, ServersSetChangeSessionCreatorConnector, SimpleConnectionTrigger, - }, - connection_trigger_with_migration::ConnectionTriggerWithMigration, - decryption_session::SessionImpl as DecryptionSession, - encryption_session::SessionImpl as EncryptionSession, - generation_session::SessionImpl as GenerationSession, - key_version_negotiation_session::{ - ContinueAction, IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, - SessionImpl as KeyVersionNegotiationSession, - }, - message::Message, - signing_session_ecdsa::SessionImpl as EcdsaSigningSession, - signing_session_schnorr::SessionImpl as SchnorrSigningSession, - AclStorage, Error, KeyServerSet, KeyStorage, NodeId, NodeKeyPair, Requester, SessionId, -}; -use parity_runtime::Executor; -use parking_lot::RwLock; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -#[cfg(test)] -use key_server_cluster::cluster_connections::tests::{ - new_test_connections, MessagesQueue, TestConnections, -}; - -/// Cluster interface for external clients. -pub trait ClusterClient: Send + Sync { - /// Start new generation session. - fn new_generation_session( - &self, - session_id: SessionId, - origin: Option
, - author: Address, - threshold: usize, - ) -> Result, Error>; - /// Start new encryption session. - fn new_encryption_session( - &self, - session_id: SessionId, - author: Requester, - common_point: Public, - encrypted_point: Public, - ) -> Result, Error>; - /// Start new decryption session. - fn new_decryption_session( - &self, - session_id: SessionId, - origin: Option
, - requester: Requester, - version: Option, - is_shadow_decryption: bool, - is_broadcast_decryption: bool, - ) -> Result, Error>; - /// Start new Schnorr signing session. - fn new_schnorr_signing_session( - &self, - session_id: SessionId, - requester: Requester, - version: Option, - message_hash: H256, - ) -> Result, Error>; - /// Start new ECDSA session. - fn new_ecdsa_signing_session( - &self, - session_id: SessionId, - requester: Requester, - version: Option, - message_hash: H256, - ) -> Result, Error>; - /// Start new key version negotiation session. - fn new_key_version_negotiation_session( - &self, - session_id: SessionId, - ) -> Result>, Error>; - /// Start new servers set change session. - fn new_servers_set_change_session( - &self, - session_id: Option, - migration_id: Option, - new_nodes_set: BTreeSet, - old_set_signature: Signature, - new_set_signature: Signature, - ) -> Result, Error>; - - /// Listen for new generation sessions. - fn add_generation_listener( - &self, - listener: Arc>, - ); - /// Listen for new decryption sessions. - fn add_decryption_listener( - &self, - listener: Arc>, - ); - /// Listen for new key version negotiation sessions. - fn add_key_version_negotiation_listener( - &self, - listener: Arc< - dyn ClusterSessionsListener< - KeyVersionNegotiationSession, - >, - >, - ); - - /// Ask node to make 'faulty' generation sessions. - #[cfg(test)] - fn make_faulty_generation_sessions(&self); - /// Get active generation session with given id. - #[cfg(test)] - fn generation_session(&self, session_id: &SessionId) -> Option>; - #[cfg(test)] - fn is_fully_connected(&self) -> bool; - /// Try connect to disconnected nodes. - #[cfg(test)] - fn connect(&self); -} - -/// Cluster access for single session participant. -pub trait Cluster: Send + Sync { - /// Broadcast message to all other nodes. - fn broadcast(&self, message: Message) -> Result<(), Error>; - /// Send message to given node. - fn send(&self, to: &NodeId, message: Message) -> Result<(), Error>; - /// Is connected to given node? - fn is_connected(&self, node: &NodeId) -> bool; - /// Get a set of connected nodes. - fn nodes(&self) -> BTreeSet; - /// Get total count of configured key server nodes (valid at the time of ClusterView creation). - fn configured_nodes_count(&self) -> usize; - /// Get total count of connected key server nodes (valid at the time of ClusterView creation). - fn connected_nodes_count(&self) -> usize; -} - -/// Cluster initialization parameters. -#[derive(Clone)] -pub struct ClusterConfiguration { - /// KeyPair this node holds. - pub self_key_pair: Arc, - /// Cluster nodes set. - pub key_server_set: Arc, - /// Reference to key storage - pub key_storage: Arc, - /// Reference to ACL storage - pub acl_storage: Arc, - /// Administrator public key. - pub admin_public: Option, - /// Do not remove sessions from container. - pub preserve_sessions: bool, -} - -/// Network cluster implementation. -pub struct ClusterCore { - /// Cluster data. - data: Arc>, -} - -/// Network cluster client interface implementation. -pub struct ClusterClientImpl { - /// Cluster data. - data: Arc>, -} - -/// Network cluster view. It is a communication channel, required in single session. -pub struct ClusterView { - configured_nodes_count: usize, - connected_nodes: BTreeSet, - connections: Arc, - self_key_pair: Arc, -} - -/// Cross-thread shareable cluster data. -pub struct ClusterData { - /// Cluster configuration. - pub config: ClusterConfiguration, - /// KeyPair this node holds. - pub self_key_pair: Arc, - /// Connections data. - pub connections: C, - /// Active sessions data. - pub sessions: Arc, - // Messages processor. - pub message_processor: Arc, - /// Link between servers set chnage session and the connections manager. - pub servers_set_change_creator_connector: Arc, -} - -/// Create new network-backed cluster. -pub fn new_network_cluster( - executor: Executor, - config: ClusterConfiguration, - net_config: NetConnectionsManagerConfig, -) -> Result>, Error> { - let mut nodes = config.key_server_set.snapshot().current_set; - let is_isolated = nodes.remove(config.self_key_pair.public()).is_none(); - let connections_data = Arc::new(RwLock::new(NetConnectionsContainer { - is_isolated, - nodes, - connections: BTreeMap::new(), - })); - - let connection_trigger: Box = - match net_config.auto_migrate_enabled { - false => Box::new(SimpleConnectionTrigger::with_config(&config)), - true if config.admin_public.is_none() => { - Box::new(ConnectionTriggerWithMigration::with_config(&config)) - } - true => return Err(Error::Internal( - "secret store admininstrator public key is specified with auto-migration enabled" - .into(), - )), - }; - - let servers_set_change_creator_connector = - connection_trigger.servers_set_change_creator_connector(); - let sessions = Arc::new(ClusterSessions::new( - &config, - servers_set_change_creator_connector.clone(), - )); - let message_processor = Arc::new(SessionsMessageProcessor::new( - config.self_key_pair.clone(), - servers_set_change_creator_connector.clone(), - sessions.clone(), - connections_data.clone(), - )); - - let connections = NetConnectionsManager::new( - executor, - message_processor.clone(), - connection_trigger, - connections_data, - &config, - net_config, - )?; - connections.start()?; - - ClusterCore::new( - sessions, - message_processor, - connections, - servers_set_change_creator_connector, - config, - ) -} - -/// Create new in-memory backed cluster -#[cfg(test)] -pub fn new_test_cluster( - messages: MessagesQueue, - config: ClusterConfiguration, -) -> Result>>, Error> { - let nodes = config.key_server_set.snapshot().current_set; - let connections = new_test_connections( - messages, - *config.self_key_pair.public(), - nodes.keys().cloned().collect(), - ); - - let connection_trigger = Box::new(SimpleConnectionTrigger::with_config(&config)); - let servers_set_change_creator_connector = - connection_trigger.servers_set_change_creator_connector(); - let mut sessions = ClusterSessions::new(&config, servers_set_change_creator_connector.clone()); - if config.preserve_sessions { - sessions.preserve_sessions(); - } - let sessions = Arc::new(sessions); - - let message_processor = Arc::new(SessionsMessageProcessor::new( - config.self_key_pair.clone(), - servers_set_change_creator_connector.clone(), - sessions.clone(), - connections.provider(), - )); - - ClusterCore::new( - sessions, - message_processor, - connections, - servers_set_change_creator_connector, - config, - ) -} - -impl ClusterCore { - pub fn new( - sessions: Arc, - message_processor: Arc, - connections: C, - servers_set_change_creator_connector: Arc, - config: ClusterConfiguration, - ) -> Result, Error> { - Ok(Arc::new(ClusterCore { - data: Arc::new(ClusterData { - self_key_pair: config.self_key_pair.clone(), - connections, - sessions: sessions.clone(), - config, - message_processor, - servers_set_change_creator_connector, - }), - })) - } - - /// Create new client interface. - pub fn client(&self) -> Arc { - Arc::new(ClusterClientImpl::new(self.data.clone())) - } - - /// Run cluster. - pub fn run(&self) -> Result<(), Error> { - self.data.connections.connect(); - Ok(()) - } - - #[cfg(test)] - pub fn view(&self) -> Result, Error> { - let connections = self.data.connections.provider(); - let mut connected_nodes = connections.connected_nodes()?; - let disconnected_nodes = connections.disconnected_nodes(); - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let connected_nodes_count = connected_nodes.len(); - let disconnected_nodes_count = disconnected_nodes.len(); - Ok(Arc::new(ClusterView::new( - self.data.self_key_pair.clone(), - connections, - connected_nodes, - connected_nodes_count + disconnected_nodes_count, - ))) - } -} - -impl ClusterView { - pub fn new( - self_key_pair: Arc, - connections: Arc, - nodes: BTreeSet, - configured_nodes_count: usize, - ) -> Self { - ClusterView { - configured_nodes_count: configured_nodes_count, - connected_nodes: nodes, - connections, - self_key_pair, - } - } -} - -impl Cluster for ClusterView { - fn broadcast(&self, message: Message) -> Result<(), Error> { - for node in self - .connected_nodes - .iter() - .filter(|n| *n != self.self_key_pair.public()) - { - trace!(target: "secretstore_net", "{}: sent message {} to {}", self.self_key_pair.public(), message, node); - let connection = self - .connections - .connection(node) - .ok_or(Error::NodeDisconnected)?; - connection.send_message(message.clone()); - } - Ok(()) - } - - fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { - trace!(target: "secretstore_net", "{}: sent message {} to {}", self.self_key_pair.public(), message, to); - let connection = self - .connections - .connection(to) - .ok_or(Error::NodeDisconnected)?; - connection.send_message(message); - Ok(()) - } - - fn is_connected(&self, node: &NodeId) -> bool { - self.connected_nodes.contains(node) - } - - fn nodes(&self) -> BTreeSet { - self.connected_nodes.clone() - } - - fn configured_nodes_count(&self) -> usize { - self.configured_nodes_count - } - - fn connected_nodes_count(&self) -> usize { - self.connected_nodes.len() - } -} - -impl ClusterClientImpl { - pub fn new(data: Arc>) -> Self { - ClusterClientImpl { data: data } - } - - fn create_key_version_negotiation_session( - &self, - session_id: SessionId, - ) -> Result>, Error> - { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let access_key = Random.generate()?.secret().clone(); - let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - false, - )?; - let session = self.data.sessions.negotiation_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id.clone(), - None, - false, - None, - )?; - match session.initialize(connected_nodes) { - Ok(()) => Ok(session), - Err(error) => { - self.data - .sessions - .negotiation_sessions - .remove(&session.id()); - Err(error) - } - } - } -} - -impl ClusterClient for ClusterClientImpl { - fn new_generation_session( - &self, - session_id: SessionId, - origin: Option
, - author: Address, - threshold: usize, - ) -> Result, Error> { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - true, - )?; - let session = self.data.sessions.generation_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id, - None, - false, - None, - )?; - process_initialization_result( - session.initialize(origin, author, false, threshold, connected_nodes.into()), - session, - &self.data.sessions.generation_sessions, - ) - } - - fn new_encryption_session( - &self, - session_id: SessionId, - requester: Requester, - common_point: Public, - encrypted_point: Public, - ) -> Result, Error> { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - true, - )?; - let session = self.data.sessions.encryption_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id, - None, - false, - None, - )?; - process_initialization_result( - session.initialize(requester, common_point, encrypted_point), - session, - &self.data.sessions.encryption_sessions, - ) - } - - fn new_decryption_session( - &self, - session_id: SessionId, - origin: Option
, - requester: Requester, - version: Option, - is_shadow_decryption: bool, - is_broadcast_decryption: bool, - ) -> Result, Error> { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let access_key = Random.generate()?.secret().clone(); - let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - false, - )?; - let session = self.data.sessions.decryption_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id.clone(), - None, - false, - Some(requester), - )?; - - let initialization_result = match version { - Some(version) => session.initialize( - origin, - version, - is_shadow_decryption, - is_broadcast_decryption, - ), - None => self - .create_key_version_negotiation_session(session_id.id.clone()) - .map(|version_session| { - version_session.set_continue_action(ContinueAction::Decrypt( - session.clone(), - origin, - is_shadow_decryption, - is_broadcast_decryption, - )); - self.data - .message_processor - .try_continue_session(Some(version_session)); - }), - }; - - process_initialization_result( - initialization_result, - session, - &self.data.sessions.decryption_sessions, - ) - } - - fn new_schnorr_signing_session( - &self, - session_id: SessionId, - requester: Requester, - version: Option, - message_hash: H256, - ) -> Result, Error> { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let access_key = Random.generate()?.secret().clone(); - let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - false, - )?; - let session = self.data.sessions.schnorr_signing_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id.clone(), - None, - false, - Some(requester), - )?; - - let initialization_result = match version { - Some(version) => session.initialize(version, message_hash), - None => self - .create_key_version_negotiation_session(session_id.id.clone()) - .map(|version_session| { - version_session.set_continue_action(ContinueAction::SchnorrSign( - session.clone(), - message_hash, - )); - self.data - .message_processor - .try_continue_session(Some(version_session)); - }), - }; - - process_initialization_result( - initialization_result, - session, - &self.data.sessions.schnorr_signing_sessions, - ) - } - - fn new_ecdsa_signing_session( - &self, - session_id: SessionId, - requester: Requester, - version: Option, - message_hash: H256, - ) -> Result, Error> { - let mut connected_nodes = self.data.connections.provider().connected_nodes()?; - connected_nodes.insert(self.data.self_key_pair.public().clone()); - - let access_key = Random.generate()?.secret().clone(); - let session_id = SessionIdWithSubSession::new(session_id, access_key); - let cluster = create_cluster_view( - self.data.self_key_pair.clone(), - self.data.connections.provider(), - false, - )?; - let session = self.data.sessions.ecdsa_signing_sessions.insert( - cluster, - self.data.self_key_pair.public().clone(), - session_id.clone(), - None, - false, - Some(requester), - )?; - - let initialization_result = match version { - Some(version) => session.initialize(version, message_hash), - None => self - .create_key_version_negotiation_session(session_id.id.clone()) - .map(|version_session| { - version_session.set_continue_action(ContinueAction::EcdsaSign( - session.clone(), - message_hash, - )); - self.data - .message_processor - .try_continue_session(Some(version_session)); - }), - }; - - process_initialization_result( - initialization_result, - session, - &self.data.sessions.ecdsa_signing_sessions, - ) - } - - fn new_key_version_negotiation_session( - &self, - session_id: SessionId, - ) -> Result>, Error> - { - let session = self.create_key_version_negotiation_session(session_id)?; - Ok(session) - } - - fn new_servers_set_change_session( - &self, - session_id: Option, - migration_id: Option, - new_nodes_set: BTreeSet, - old_set_signature: Signature, - new_set_signature: Signature, - ) -> Result, Error> { - new_servers_set_change_session( - self.data.self_key_pair.clone(), - &self.data.sessions, - self.data.connections.provider(), - self.data.servers_set_change_creator_connector.clone(), - ServersSetChangeParams { - session_id, - migration_id, - new_nodes_set, - old_set_signature, - new_set_signature, - }, - ) - } - - fn add_generation_listener( - &self, - listener: Arc>, - ) { - self.data - .sessions - .generation_sessions - .add_listener(listener); - } - - fn add_decryption_listener( - &self, - listener: Arc>, - ) { - self.data - .sessions - .decryption_sessions - .add_listener(listener); - } - - fn add_key_version_negotiation_listener( - &self, - listener: Arc< - dyn ClusterSessionsListener< - KeyVersionNegotiationSession, - >, - >, - ) { - self.data - .sessions - .negotiation_sessions - .add_listener(listener); - } - - #[cfg(test)] - fn make_faulty_generation_sessions(&self) { - self.data.sessions.make_faulty_generation_sessions(); - } - - #[cfg(test)] - fn generation_session(&self, session_id: &SessionId) -> Option> { - self.data - .sessions - .generation_sessions - .get(session_id, false) - } - - #[cfg(test)] - fn is_fully_connected(&self) -> bool { - self.data - .connections - .provider() - .disconnected_nodes() - .is_empty() - } - - #[cfg(test)] - fn connect(&self) { - self.data.connections.connect() - } -} - -pub struct ServersSetChangeParams { - pub session_id: Option, - pub migration_id: Option, - pub new_nodes_set: BTreeSet, - pub old_set_signature: Signature, - pub new_set_signature: Signature, -} - -pub fn new_servers_set_change_session( - self_key_pair: Arc, - sessions: &ClusterSessions, - connections: Arc, - servers_set_change_creator_connector: Arc, - params: ServersSetChangeParams, -) -> Result, Error> { - let session_id = match params.session_id { - Some(session_id) if session_id == *SERVERS_SET_CHANGE_SESSION_ID => session_id, - Some(_) => return Err(Error::InvalidMessage), - None => *SERVERS_SET_CHANGE_SESSION_ID, - }; - - let cluster = create_cluster_view(self_key_pair.clone(), connections, true)?; - let creation_data = AdminSessionCreationData::ServersSetChange( - params.migration_id, - params.new_nodes_set.clone(), - ); - let session = sessions.admin_sessions.insert( - cluster, - *self_key_pair.public(), - session_id, - None, - true, - Some(creation_data), - )?; - let initialization_result = session - .as_servers_set_change() - .expect("servers set change session is created; qed") - .initialize( - params.new_nodes_set, - params.old_set_signature, - params.new_set_signature, - ); - - if initialization_result.is_ok() { - servers_set_change_creator_connector.set_key_servers_set_change_session(session.clone()); - } - - process_initialization_result(initialization_result, session, &sessions.admin_sessions) -} - -fn process_initialization_result( - result: Result<(), Error>, - session: Arc, - sessions: &ClusterSessionsContainer, -) -> Result, Error> -where - S: ClusterSession, - SC: ClusterSessionCreator, -{ - match result { - Ok(()) if session.is_finished() => { - sessions.remove(&session.id()); - Ok(session) - } - Ok(()) => Ok(session), - Err(error) => { - sessions.remove(&session.id()); - Err(error) - } - } -} - -#[cfg(test)] -pub mod tests { - use ethereum_types::{Address, H256}; - use ethkey::{sign, Generator, Public, Random, Signature}; - use key_server_cluster::{ - cluster::{new_test_cluster, Cluster, ClusterClient, ClusterConfiguration, ClusterCore}, - cluster_connections::{ - tests::{MessagesQueue, TestConnections}, - ConnectionManager, - }, - cluster_sessions::{ - AdminSession, ClusterSession, ClusterSessions, ClusterSessionsListener, - }, - decryption_session::SessionImpl as DecryptionSession, - encryption_session::SessionImpl as EncryptionSession, - generation_session::{ - SessionImpl as GenerationSession, SessionState as GenerationSessionState, - }, - key_version_negotiation_session::{ - IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, - SessionImpl as KeyVersionNegotiationSession, - }, - message::Message, - signing_session_ecdsa::SessionImpl as EcdsaSigningSession, - signing_session_schnorr::SessionImpl as SchnorrSigningSession, - DummyAclStorage, DummyKeyStorage, Error, MapKeyServerSet, NodeId, NodeKeyPair, - PlainNodeKeyPair, Requester, SessionId, - }; - use parking_lot::{Mutex, RwLock}; - use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, - }; - - #[derive(Default)] - pub struct DummyClusterClient { - pub generation_requests_count: AtomicUsize, - } - - #[derive(Debug)] - pub struct DummyCluster { - id: NodeId, - data: RwLock, - } - - #[derive(Debug, Default)] - struct DummyClusterData { - nodes: BTreeSet, - messages: VecDeque<(NodeId, Message)>, - } - - impl ClusterClient for DummyClusterClient { - fn new_generation_session( - &self, - _session_id: SessionId, - _origin: Option
, - _author: Address, - _threshold: usize, - ) -> Result, Error> { - self.generation_requests_count - .fetch_add(1, Ordering::Relaxed); - Err(Error::Internal("test-error".into())) - } - fn new_encryption_session( - &self, - _session_id: SessionId, - _requester: Requester, - _common_point: Public, - _encrypted_point: Public, - ) -> Result, Error> { - unimplemented!("test-only") - } - fn new_decryption_session( - &self, - _session_id: SessionId, - _origin: Option
, - _requester: Requester, - _version: Option, - _is_shadow_decryption: bool, - _is_broadcast_session: bool, - ) -> Result, Error> { - unimplemented!("test-only") - } - fn new_schnorr_signing_session( - &self, - _session_id: SessionId, - _requester: Requester, - _version: Option, - _message_hash: H256, - ) -> Result, Error> { - unimplemented!("test-only") - } - fn new_ecdsa_signing_session( - &self, - _session_id: SessionId, - _requester: Requester, - _version: Option, - _message_hash: H256, - ) -> Result, Error> { - unimplemented!("test-only") - } - - fn new_key_version_negotiation_session( - &self, - _session_id: SessionId, - ) -> Result>, Error> - { - unimplemented!("test-only") - } - fn new_servers_set_change_session( - &self, - _session_id: Option, - _migration_id: Option, - _new_nodes_set: BTreeSet, - _old_set_signature: Signature, - _new_set_signature: Signature, - ) -> Result, Error> { - unimplemented!("test-only") - } - - fn add_generation_listener( - &self, - _listener: Arc>, - ) { - } - fn add_decryption_listener( - &self, - _listener: Arc>, - ) { - } - fn add_key_version_negotiation_listener( - &self, - _listener: Arc< - dyn ClusterSessionsListener< - KeyVersionNegotiationSession, - >, - >, - ) { - } - - fn make_faulty_generation_sessions(&self) { - unimplemented!("test-only") - } - fn generation_session(&self, _session_id: &SessionId) -> Option> { - unimplemented!("test-only") - } - fn is_fully_connected(&self) -> bool { - true - } - fn connect(&self) {} - } - - impl DummyCluster { - pub fn new(id: NodeId) -> Self { - DummyCluster { - id: id, - data: RwLock::new(DummyClusterData::default()), - } - } - - pub fn node(&self) -> NodeId { - self.id.clone() - } - - pub fn add_node(&self, node: NodeId) { - self.data.write().nodes.insert(node); - } - - pub fn add_nodes>(&self, nodes: I) { - self.data.write().nodes.extend(nodes) - } - - pub fn remove_node(&self, node: &NodeId) { - self.data.write().nodes.remove(node); - } - - pub fn take_message(&self) -> Option<(NodeId, Message)> { - self.data.write().messages.pop_front() - } - } - - impl Cluster for DummyCluster { - fn broadcast(&self, message: Message) -> Result<(), Error> { - let mut data = self.data.write(); - let all_nodes: Vec<_> = data - .nodes - .iter() - .cloned() - .filter(|n| n != &self.id) - .collect(); - for node in all_nodes { - data.messages.push_back((node, message.clone())); - } - Ok(()) - } - - fn send(&self, to: &NodeId, message: Message) -> Result<(), Error> { - debug_assert!(&self.id != to); - self.data.write().messages.push_back((to.clone(), message)); - Ok(()) - } - - fn is_connected(&self, node: &NodeId) -> bool { - let data = self.data.read(); - &self.id == node || data.nodes.contains(node) - } - - fn nodes(&self) -> BTreeSet { - self.data.read().nodes.iter().cloned().collect() - } - - fn configured_nodes_count(&self) -> usize { - self.data.read().nodes.len() - } - - fn connected_nodes_count(&self) -> usize { - self.data.read().nodes.len() - } - } - - /// Test message loop. - pub struct MessageLoop { - messages: MessagesQueue, - preserve_sessions: bool, - key_pairs_map: BTreeMap>, - acl_storages_map: BTreeMap>, - key_storages_map: BTreeMap>, - clusters_map: BTreeMap>>>, - } - - impl ::std::fmt::Debug for MessageLoop { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "MessageLoop({})", self.clusters_map.len()) - } - } - - impl MessageLoop { - /// Returns set of all nodes ids. - pub fn nodes(&self) -> BTreeSet { - self.clusters_map.keys().cloned().collect() - } - - /// Returns nodes id by its index. - pub fn node(&self, idx: usize) -> NodeId { - *self.clusters_map.keys().nth(idx).unwrap() - } - - /// Returns key pair of the node by its idx. - pub fn node_key_pair(&self, idx: usize) -> &Arc { - self.key_pairs_map.values().nth(idx).unwrap() - } - - /// Get cluster reference by its index. - pub fn cluster(&self, idx: usize) -> &Arc>> { - self.clusters_map.values().nth(idx).unwrap() - } - - /// Get keys storage reference by its index. - pub fn key_storage(&self, idx: usize) -> &Arc { - self.key_storages_map.values().nth(idx).unwrap() - } - - /// Get keys storage reference by node id. - pub fn key_storage_of(&self, node: &NodeId) -> &Arc { - &self.key_storages_map[node] - } - - /// Replace key storage of the node by its id. - pub fn replace_key_storage_of(&mut self, node: &NodeId, key_storage: Arc) { - *self.key_storages_map.get_mut(node).unwrap() = key_storage; - } - - /// Get ACL storage reference by its index. - pub fn acl_storage(&self, idx: usize) -> &Arc { - self.acl_storages_map.values().nth(idx).unwrap() - } - - /// Get sessions container reference by its index. - pub fn sessions(&self, idx: usize) -> &Arc { - &self.cluster(idx).data.sessions - } - - /// Get sessions container reference by node id. - pub fn sessions_of(&self, node: &NodeId) -> &Arc { - &self.clusters_map[node].data.sessions - } - - /// Isolate node from others. - pub fn isolate(&self, idx: usize) { - let node = self.node(idx); - for (i, cluster) in self.clusters_map.values().enumerate() { - if i == idx { - cluster.data.connections.isolate(); - } else { - cluster.data.connections.disconnect(node); - } - } - } - - /// Exclude node from cluster. - pub fn exclude(&mut self, idx: usize) { - let node = self.node(idx); - for (i, cluster) in self.clusters_map.values().enumerate() { - if i != idx { - cluster.data.connections.exclude(node); - } - } - self.key_storages_map.remove(&node); - self.acl_storages_map.remove(&node); - self.key_pairs_map.remove(&node); - self.clusters_map.remove(&node); - } - - /// Include new node to the cluster. - pub fn include(&mut self, node_key_pair: Arc) -> usize { - let key_storage = Arc::new(DummyKeyStorage::default()); - let acl_storage = Arc::new(DummyAclStorage::default()); - let cluster_params = ClusterConfiguration { - self_key_pair: node_key_pair.clone(), - key_server_set: Arc::new(MapKeyServerSet::new( - false, - self.nodes() - .iter() - .chain(::std::iter::once(node_key_pair.public())) - .map(|n| (*n, format!("127.0.0.1:{}", 13).parse().unwrap())) - .collect(), - )), - key_storage: key_storage.clone(), - acl_storage: acl_storage.clone(), - admin_public: None, - preserve_sessions: self.preserve_sessions, - }; - let cluster = new_test_cluster(self.messages.clone(), cluster_params).unwrap(); - - for cluster in self.clusters_map.values() { - cluster - .data - .connections - .include(node_key_pair.public().clone()); - } - self.acl_storages_map - .insert(*node_key_pair.public(), acl_storage); - self.key_storages_map - .insert(*node_key_pair.public(), key_storage); - self.clusters_map.insert(*node_key_pair.public(), cluster); - self.key_pairs_map - .insert(*node_key_pair.public(), node_key_pair.clone()); - self.clusters_map - .keys() - .position(|k| k == node_key_pair.public()) - .unwrap() - } - - /// Is empty message queue? - pub fn is_empty(&self) -> bool { - self.messages.lock().is_empty() - } - - /// Takes next message from the queue. - pub fn take_message(&self) -> Option<(NodeId, NodeId, Message)> { - self.messages.lock().pop_front() - } - - /// Process single message. - pub fn process_message(&self, from: NodeId, to: NodeId, message: Message) { - let cluster_data = &self.clusters_map[&to].data; - let connection = cluster_data - .connections - .provider() - .connection(&from) - .unwrap(); - cluster_data - .message_processor - .process_connection_message(connection, message); - } - - /// Take next message and process it. - pub fn take_and_process_message(&self) -> bool { - let (from, to, message) = match self.take_message() { - Some((from, to, message)) => (from, to, message), - None => return false, - }; - - self.process_message(from, to, message); - true - } - - /// Loops until `predicate` returns `true` or there are no messages in the queue. - pub fn loop_until(&self, predicate: F) - where - F: Fn() -> bool, - { - while !predicate() { - if !self.take_and_process_message() { - panic!("message queue is empty but goal is not achieved"); - } - } - } - } - - pub fn make_clusters(num_nodes: usize) -> MessageLoop { - do_make_clusters(num_nodes, false) - } - - pub fn make_clusters_and_preserve_sessions(num_nodes: usize) -> MessageLoop { - do_make_clusters(num_nodes, true) - } - - fn do_make_clusters(num_nodes: usize, preserve_sessions: bool) -> MessageLoop { - let ports_begin = 0; - let messages = Arc::new(Mutex::new(VecDeque::new())); - let key_pairs: Vec<_> = (0..num_nodes) - .map(|_| Arc::new(PlainNodeKeyPair::new(Random.generate().unwrap()))) - .collect(); - let key_storages: Vec<_> = (0..num_nodes) - .map(|_| Arc::new(DummyKeyStorage::default())) - .collect(); - let acl_storages: Vec<_> = (0..num_nodes) - .map(|_| Arc::new(DummyAclStorage::default())) - .collect(); - let cluster_params: Vec<_> = (0..num_nodes) - .map(|i| ClusterConfiguration { - self_key_pair: key_pairs[i].clone(), - key_server_set: Arc::new(MapKeyServerSet::new( - false, - key_pairs - .iter() - .enumerate() - .map(|(j, kp)| { - ( - *kp.public(), - format!("127.0.0.1:{}", ports_begin + j as u16) - .parse() - .unwrap(), - ) - }) - .collect(), - )), - key_storage: key_storages[i].clone(), - acl_storage: acl_storages[i].clone(), - admin_public: None, - preserve_sessions, - }) - .collect(); - let clusters: Vec<_> = cluster_params - .into_iter() - .map(|params| new_test_cluster(messages.clone(), params).unwrap()) - .collect(); - - let clusters_map = clusters - .iter() - .map(|c| (*c.data.config.self_key_pair.public(), c.clone())) - .collect(); - let key_pairs_map = key_pairs.into_iter().map(|kp| (*kp.public(), kp)).collect(); - let key_storages_map = clusters - .iter() - .zip(key_storages.into_iter()) - .map(|(c, ks)| (*c.data.config.self_key_pair.public(), ks)) - .collect(); - let acl_storages_map = clusters - .iter() - .zip(acl_storages.into_iter()) - .map(|(c, acls)| (*c.data.config.self_key_pair.public(), acls)) - .collect(); - MessageLoop { - preserve_sessions, - messages, - key_pairs_map, - acl_storages_map, - key_storages_map, - clusters_map, - } - } - - #[test] - fn cluster_wont_start_generation_session_if_not_fully_connected() { - let ml = make_clusters(3); - ml.cluster(0) - .data - .connections - .disconnect(*ml.cluster(0).data.self_key_pair.public()); - match ml.cluster(0).client().new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) { - Err(Error::NodeDisconnected) => (), - Err(e) => panic!("unexpected error {:?}", e), - _ => panic!("unexpected success"), - } - } - - #[test] - fn error_in_generation_session_broadcasted_to_all_other_nodes() { - let _ = ::env_logger::try_init(); - let ml = make_clusters(3); - - // ask one of nodes to produce faulty generation sessions - ml.cluster(1).client().make_faulty_generation_sessions(); - - // start && wait for generation session to fail - let session = ml - .cluster(0) - .client() - .new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) - .unwrap(); - ml.loop_until(|| { - session.joint_public_and_secret().is_some() - && ml - .cluster(0) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_err()); - - // check that faulty session is either removed from all nodes, or nonexistent (already removed) - for i in 1..3 { - if let Some(session) = ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - { - // wait for both session completion && session removal (session completion event is fired - // before session is removed from its own container by cluster) - ml.loop_until(|| { - session.joint_public_and_secret().is_some() - && ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_err()); - } - } - } - - #[test] - fn generation_session_completion_signalled_if_failed_on_master() { - let _ = ::env_logger::try_init(); - let ml = make_clusters(3); - - // ask one of nodes to produce faulty generation sessions - ml.cluster(0).client().make_faulty_generation_sessions(); - - // start && wait for generation session to fail - let session = ml - .cluster(0) - .client() - .new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) - .unwrap(); - ml.loop_until(|| { - session.joint_public_and_secret().is_some() - && ml - .cluster(0) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_err()); - - // check that faulty session is either removed from all nodes, or nonexistent (already removed) - for i in 1..3 { - if let Some(session) = ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - { - let session = session.clone(); - // wait for both session completion && session removal (session completion event is fired - // before session is removed from its own container by cluster) - ml.loop_until(|| { - session.joint_public_and_secret().is_some() - && ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_err()); - } - } - } - - #[test] - fn generation_session_is_removed_when_succeeded() { - let _ = ::env_logger::try_init(); - let ml = make_clusters(3); - - // start && wait for generation session to complete - let session = ml - .cluster(0) - .client() - .new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) - .unwrap(); - ml.loop_until(|| { - (session.state() == GenerationSessionState::Finished - || session.state() == GenerationSessionState::Failed) - && ml - .cluster(0) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_ok()); - - // check that on non-master nodes session is either: - // already removed - // or it is removed right after completion - for i in 1..3 { - if let Some(session) = ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - { - // run to completion if completion message is still on the way - // AND check that it is actually removed from cluster sessions - ml.loop_until(|| { - (session.state() == GenerationSessionState::Finished - || session.state() == GenerationSessionState::Failed) - && ml - .cluster(i) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - } - } - } - - #[test] - fn sessions_are_removed_when_initialization_fails() { - let ml = make_clusters(3); - let client = ml.cluster(0).client(); - - // generation session - { - // try to start generation session => fail in initialization - assert_eq!( - client - .new_generation_session(SessionId::default(), None, Default::default(), 100) - .map(|_| ()), - Err(Error::NotEnoughNodesForThreshold) - ); - - // try to start generation session => fails in initialization - assert_eq!( - client - .new_generation_session(SessionId::default(), None, Default::default(), 100) - .map(|_| ()), - Err(Error::NotEnoughNodesForThreshold) - ); - - assert!(ml.cluster(0).data.sessions.generation_sessions.is_empty()); - } - - // decryption session - { - // try to start decryption session => fails in initialization - assert_eq!( - client - .new_decryption_session( - Default::default(), - Default::default(), - Default::default(), - Some(Default::default()), - false, - false - ) - .map(|_| ()), - Err(Error::InvalidMessage) - ); - - // try to start generation session => fails in initialization - assert_eq!( - client - .new_decryption_session( - Default::default(), - Default::default(), - Default::default(), - Some(Default::default()), - false, - false - ) - .map(|_| ()), - Err(Error::InvalidMessage) - ); - - assert!(ml.cluster(0).data.sessions.decryption_sessions.is_empty()); - assert!(ml.cluster(0).data.sessions.negotiation_sessions.is_empty()); - } - } - - #[test] - fn schnorr_signing_session_completes_if_node_does_not_have_a_share() { - let _ = ::env_logger::try_init(); - let ml = make_clusters(3); - - // start && wait for generation session to complete - let session = ml - .cluster(0) - .client() - .new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) - .unwrap(); - ml.loop_until(|| { - (session.state() == GenerationSessionState::Finished - || session.state() == GenerationSessionState::Failed) - && ml - .cluster(0) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_ok()); - - // now remove share from node2 - assert!((0..3).all(|i| ml.cluster(i).data.sessions.generation_sessions.is_empty())); - ml.cluster(2) - .data - .config - .key_storage - .remove(&Default::default()) - .unwrap(); - - // and try to sign message with generated key - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session0 = ml - .cluster(0) - .client() - .new_schnorr_signing_session( - Default::default(), - signature.into(), - None, - Default::default(), - ) - .unwrap(); - let session = ml - .cluster(0) - .data - .sessions - .schnorr_signing_sessions - .first() - .unwrap(); - - ml.loop_until(|| { - session.is_finished() - && (0..3).all(|i| { - ml.cluster(i) - .data - .sessions - .schnorr_signing_sessions - .is_empty() - }) - }); - session0.wait().unwrap(); - - // and try to sign message with generated key using node that has no key share - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session2 = ml - .cluster(2) - .client() - .new_schnorr_signing_session( - Default::default(), - signature.into(), - None, - Default::default(), - ) - .unwrap(); - let session = ml - .cluster(2) - .data - .sessions - .schnorr_signing_sessions - .first() - .unwrap(); - - ml.loop_until(|| { - session.is_finished() - && (0..3).all(|i| { - ml.cluster(i) - .data - .sessions - .schnorr_signing_sessions - .is_empty() - }) - }); - session2.wait().unwrap(); - - // now remove share from node1 - ml.cluster(1) - .data - .config - .key_storage - .remove(&Default::default()) - .unwrap(); - - // and try to sign message with generated key - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session1 = ml - .cluster(0) - .client() - .new_schnorr_signing_session( - Default::default(), - signature.into(), - None, - Default::default(), - ) - .unwrap(); - let session = ml - .cluster(0) - .data - .sessions - .schnorr_signing_sessions - .first() - .unwrap(); - - ml.loop_until(|| session.is_finished()); - session1.wait().unwrap_err(); - } - - #[test] - fn ecdsa_signing_session_completes_if_node_does_not_have_a_share() { - let _ = ::env_logger::try_init(); - let ml = make_clusters(4); - - // start && wait for generation session to complete - let session = ml - .cluster(0) - .client() - .new_generation_session( - SessionId::default(), - Default::default(), - Default::default(), - 1, - ) - .unwrap(); - ml.loop_until(|| { - (session.state() == GenerationSessionState::Finished - || session.state() == GenerationSessionState::Failed) - && ml - .cluster(0) - .client() - .generation_session(&SessionId::default()) - .is_none() - }); - assert!(session.joint_public_and_secret().unwrap().is_ok()); - - // now remove share from node2 - assert!((0..3).all(|i| ml.cluster(i).data.sessions.generation_sessions.is_empty())); - ml.cluster(2) - .data - .config - .key_storage - .remove(&Default::default()) - .unwrap(); - - // and try to sign message with generated key - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session0 = ml - .cluster(0) - .client() - .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()) - .unwrap(); - let session = ml - .cluster(0) - .data - .sessions - .ecdsa_signing_sessions - .first() - .unwrap(); - - ml.loop_until(|| { - session.is_finished() - && (0..3).all(|i| { - ml.cluster(i) - .data - .sessions - .ecdsa_signing_sessions - .is_empty() - }) - }); - session0.wait().unwrap(); - - // and try to sign message with generated key using node that has no key share - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session2 = ml - .cluster(2) - .client() - .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()) - .unwrap(); - let session = ml - .cluster(2) - .data - .sessions - .ecdsa_signing_sessions - .first() - .unwrap(); - ml.loop_until(|| { - session.is_finished() - && (0..3).all(|i| { - ml.cluster(i) - .data - .sessions - .ecdsa_signing_sessions - .is_empty() - }) - }); - session2.wait().unwrap(); - - // now remove share from node1 - ml.cluster(1) - .data - .config - .key_storage - .remove(&Default::default()) - .unwrap(); - - // and try to sign message with generated key - let signature = sign(Random.generate().unwrap().secret(), &Default::default()).unwrap(); - let session1 = ml - .cluster(0) - .client() - .new_ecdsa_signing_session(Default::default(), signature.into(), None, H256::random()) - .unwrap(); - let session = ml - .cluster(0) - .data - .sessions - .ecdsa_signing_sessions - .first() - .unwrap(); - ml.loop_until(|| session.is_finished()); - session1.wait().unwrap_err(); - } -} diff --git a/secret-store/src/key_server_cluster/cluster_connections.rs b/secret-store/src/key_server_cluster/cluster_connections.rs deleted file mode 100644 index 97b7b85fb5..0000000000 --- a/secret-store/src/key_server_cluster/cluster_connections.rs +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{message::Message, Error, NodeId}; -use std::{collections::BTreeSet, sync::Arc}; - -/// Connection to the single node. Provides basic information about connected node and -/// allows sending messages to this node. -pub trait Connection: Send + Sync { - /// Is this inbound connection? This only matters when both nodes are simultaneously establishing - /// two connections to each other. The agreement is that the inbound connection from the node with - /// lower NodeId is used and the other connection is closed. - fn is_inbound(&self) -> bool; - /// Returns id of the connected node. - fn node_id(&self) -> &NodeId; - /// Returns 'address' of the node to use in traces. - fn node_address(&self) -> String; - /// Send message to the connected node. - fn send_message(&self, message: Message); -} - -/// Connections manager. Responsible for keeping us connected to all required nodes. -pub trait ConnectionManager: 'static + Send + Sync { - /// Returns shared reference to connections provider. - fn provider(&self) -> Arc; - /// Try to reach all disconnected nodes immediately. This method is exposed mostly for - /// tests, where all 'nodes' are starting listening for incoming connections first and - /// only after this, they're actually start connecting to each other. - fn connect(&self); -} - -/// Connections provider. Holds all active connections and the set of nodes that we need to -/// connect to. At any moment connection could be lost and the set of connected/disconnected -/// nodes could change (at behalf of the connection manager). -/// Clone operation should be cheap (Arc). -pub trait ConnectionProvider: Send + Sync { - /// Returns the set of currently connected nodes. Error is returned when our node is - /// not a part of the cluster ('isolated' node). - fn connected_nodes(&self) -> Result, Error>; - /// Returns the set of currently disconnected nodes. - fn disconnected_nodes(&self) -> BTreeSet; - /// Returns the reference to the active node connection or None if the node is not connected. - fn connection(&self, node: &NodeId) -> Option>; -} - -#[cfg(test)] -pub mod tests { - use super::{Connection, ConnectionManager, ConnectionProvider}; - use key_server_cluster::{message::Message, Error, NodeId}; - use parking_lot::Mutex; - use std::{ - collections::{BTreeSet, VecDeque}, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, - }; - - /// Shared messages queue. - pub type MessagesQueue = Arc>>; - - /// Single node connections. - pub struct TestConnections { - node: NodeId, - is_isolated: AtomicBool, - connected_nodes: Mutex>, - disconnected_nodes: Mutex>, - messages: MessagesQueue, - } - - /// Single connection. - pub struct TestConnection { - from: NodeId, - to: NodeId, - messages: MessagesQueue, - } - - impl TestConnections { - pub fn isolate(&self) { - let connected_nodes = - ::std::mem::replace(&mut *self.connected_nodes.lock(), Default::default()); - self.is_isolated.store(true, Ordering::Relaxed); - self.disconnected_nodes.lock().extend(connected_nodes) - } - - pub fn disconnect(&self, node: NodeId) { - self.connected_nodes.lock().remove(&node); - self.disconnected_nodes.lock().insert(node); - } - - pub fn exclude(&self, node: NodeId) { - self.connected_nodes.lock().remove(&node); - self.disconnected_nodes.lock().remove(&node); - } - - pub fn include(&self, node: NodeId) { - self.connected_nodes.lock().insert(node); - } - } - - impl ConnectionManager for Arc { - fn provider(&self) -> Arc { - self.clone() - } - - fn connect(&self) {} - } - - impl ConnectionProvider for TestConnections { - fn connected_nodes(&self) -> Result, Error> { - match self.is_isolated.load(Ordering::Relaxed) { - false => Ok(self.connected_nodes.lock().clone()), - true => Err(Error::NodeDisconnected), - } - } - - fn disconnected_nodes(&self) -> BTreeSet { - self.disconnected_nodes.lock().clone() - } - - fn connection(&self, node: &NodeId) -> Option> { - match self.connected_nodes.lock().contains(node) { - true => Some(Arc::new(TestConnection { - from: self.node, - to: *node, - messages: self.messages.clone(), - })), - false => None, - } - } - } - - impl Connection for TestConnection { - fn is_inbound(&self) -> bool { - false - } - - fn node_id(&self) -> &NodeId { - &self.to - } - - fn node_address(&self) -> String { - format!("{}", self.to) - } - - fn send_message(&self, message: Message) { - self.messages - .lock() - .push_back((self.from, self.to, message)) - } - } - - pub fn new_test_connections( - messages: MessagesQueue, - node: NodeId, - mut nodes: BTreeSet, - ) -> Arc { - let is_isolated = !nodes.remove(&node); - Arc::new(TestConnections { - node, - is_isolated: AtomicBool::new(is_isolated), - connected_nodes: Mutex::new(nodes), - disconnected_nodes: Default::default(), - messages, - }) - } -} diff --git a/secret-store/src/key_server_cluster/cluster_connections_net.rs b/secret-store/src/key_server_cluster/cluster_connections_net.rs deleted file mode 100644 index 7e89a91eca..0000000000 --- a/secret-store/src/key_server_cluster/cluster_connections_net.rs +++ /dev/null @@ -1,588 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::KeyPair; -use futures::{future, Future, Stream}; -use key_server_cluster::{ - cluster_connections::{Connection, ConnectionManager, ConnectionProvider}, - cluster_message_processor::MessageProcessor, - connection_trigger::{ConnectionTrigger, Maintain}, - io::{ - read_encrypted_message, write_encrypted_message, DeadlineStatus, ReadMessage, - SharedTcpStream, WriteMessage, - }, - message::{self, ClusterMessage, Message}, - net::{ - accept_connection as io_accept_connection, connect as io_connect, - Connection as IoConnection, - }, - ClusterConfiguration, Error, NodeId, NodeKeyPair, -}; -use parity_runtime::Executor; -use parking_lot::{Mutex, RwLock}; -use std::{ - collections::{btree_map::Entry, BTreeMap, BTreeSet}, - io, - net::{IpAddr, SocketAddr}, - sync::Arc, - time::{Duration, Instant}, -}; -use tokio::{ - net::{TcpListener, TcpStream}, - timer::{timeout::Error as TimeoutError, Interval}, -}; -use tokio_io::IoFuture; - -/// Empty future. -pub type BoxedEmptyFuture = Box + Send>; - -/// Maintain interval (seconds). Every MAINTAIN_INTERVAL seconds node: -/// 1) checks if connected nodes are responding to KeepAlive messages -/// 2) tries to connect to disconnected nodes -/// 3) checks if enc/dec sessions are time-outed -const MAINTAIN_INTERVAL: u64 = 10; - -/// When no messages have been received from node within KEEP_ALIVE_SEND_INTERVAL seconds, -/// we must send KeepAlive message to the node to check if it still responds to messages. -const KEEP_ALIVE_SEND_INTERVAL: Duration = Duration::from_secs(30); -/// When no messages have been received from node within KEEP_ALIVE_DISCONNECT_INTERVAL seconds, -/// we must treat this node as non-responding && disconnect from it. -const KEEP_ALIVE_DISCONNECT_INTERVAL: Duration = Duration::from_secs(60); - -/// Network connection manager configuration. -pub struct NetConnectionsManagerConfig { - /// Allow connecting to 'higher' nodes. - pub allow_connecting_to_higher_nodes: bool, - /// Interface to listen to. - pub listen_address: (String, u16), - /// True if we should autostart key servers set change session when servers set changes? - /// This will only work when servers set is configured using KeyServerSet contract. - pub auto_migrate_enabled: bool, -} - -/// Network connections manager. -pub struct NetConnectionsManager { - /// Address we're listening for incoming connections. - listen_address: SocketAddr, - /// Shared cluster connections data reference. - data: Arc, -} - -/// Network connections data. Shared among NetConnectionsManager and spawned futures. -struct NetConnectionsData { - /// Allow connecting to 'higher' nodes. - allow_connecting_to_higher_nodes: bool, - /// Reference to tokio task executor. - executor: Executor, - /// Key pair of this node. - self_key_pair: Arc, - /// Network messages processor. - message_processor: Arc, - /// Connections trigger. - trigger: Mutex>, - /// Mutable connection data. - container: Arc>, -} - -/// Network connections container. This is the only mutable data of NetConnectionsManager. -/// The set of nodes is mutated by the connection trigger and the connections set is also -/// mutated by spawned futures. -pub struct NetConnectionsContainer { - /// Is this node isolated from cluster? - pub is_isolated: bool, - /// Current key servers set. - pub nodes: BTreeMap, - /// Active connections to key servers. - pub connections: BTreeMap>, -} - -/// Network connection to single key server node. -pub struct NetConnection { - executor: Executor, - /// Id of the peer node. - node_id: NodeId, - /// Address of the peer node. - node_address: SocketAddr, - /// Is this inbound (true) or outbound (false) connection? - is_inbound: bool, - /// Key pair that is used to encrypt connection' messages. - key: KeyPair, - /// Last message time. - last_message_time: RwLock, - /// Underlying TCP stream. - stream: SharedTcpStream, -} - -impl NetConnectionsManager { - /// Create new network connections manager. - pub fn new( - executor: Executor, - message_processor: Arc, - trigger: Box, - container: Arc>, - config: &ClusterConfiguration, - net_config: NetConnectionsManagerConfig, - ) -> Result { - let listen_address = - make_socket_address(&net_config.listen_address.0, net_config.listen_address.1)?; - - Ok(NetConnectionsManager { - listen_address, - data: Arc::new(NetConnectionsData { - allow_connecting_to_higher_nodes: net_config.allow_connecting_to_higher_nodes, - executor, - message_processor, - self_key_pair: config.self_key_pair.clone(), - trigger: Mutex::new(trigger), - container, - }), - }) - } - - /// Start listening for connections and schedule connections maintenance. - pub fn start(&self) -> Result<(), Error> { - net_listen(&self.listen_address, self.data.clone())?; - net_schedule_maintain(self.data.clone()); - Ok(()) - } -} - -impl ConnectionManager for NetConnectionsManager { - fn provider(&self) -> Arc { - self.data.container.clone() - } - - fn connect(&self) { - net_connect_disconnected(self.data.clone()); - } -} - -impl ConnectionProvider for RwLock { - fn connected_nodes(&self) -> Result, Error> { - let connections = self.read(); - if connections.is_isolated { - return Err(Error::NodeDisconnected); - } - - Ok(connections.connections.keys().cloned().collect()) - } - - fn disconnected_nodes(&self) -> BTreeSet { - let connections = self.read(); - connections - .nodes - .keys() - .filter(|node_id| !connections.connections.contains_key(node_id)) - .cloned() - .collect() - } - - fn connection(&self, node: &NodeId) -> Option> { - match self.read().connections.get(node).cloned() { - Some(connection) => Some(connection), - None => None, - } - } -} - -impl NetConnection { - /// Create new connection. - pub fn new(executor: Executor, is_inbound: bool, connection: IoConnection) -> NetConnection { - NetConnection { - executor, - node_id: connection.node_id, - node_address: connection.address, - is_inbound: is_inbound, - stream: connection.stream, - key: connection.key, - last_message_time: RwLock::new(Instant::now()), - } - } - - /// Get last message time. - pub fn last_message_time(&self) -> Instant { - *self.last_message_time.read() - } - - /// Update last message time - pub fn set_last_message_time(&self, last_message_time: Instant) { - *self.last_message_time.write() = last_message_time - } - - /// Returns future that sends encrypted message over this connection. - pub fn send_message_future(&self, message: Message) -> WriteMessage { - write_encrypted_message(self.stream.clone(), &self.key, message) - } - - /// Returns future that reads encrypted message from this connection. - pub fn read_message_future(&self) -> ReadMessage { - read_encrypted_message(self.stream.clone(), self.key.clone()) - } -} - -impl Connection for NetConnection { - fn is_inbound(&self) -> bool { - self.is_inbound - } - - fn node_id(&self) -> &NodeId { - &self.node_id - } - - fn node_address(&self) -> String { - format!("{}", self.node_address) - } - - fn send_message(&self, message: Message) { - execute( - &self.executor, - self.send_message_future(message).then(|_| Ok(())), - ); - } -} - -impl NetConnectionsData { - /// Executes closure for each active connection. - pub fn active_connections(&self) -> Vec> { - self.container - .read() - .connections - .values() - .cloned() - .collect() - } - - /// Executes closure for each disconnected node. - pub fn disconnected_nodes(&self) -> Vec<(NodeId, SocketAddr)> { - let container = self.container.read(); - container - .nodes - .iter() - .filter(|(node_id, _)| !container.connections.contains_key(node_id)) - .map(|(node_id, addr)| (*node_id, *addr)) - .collect() - } - - /// Try to insert new connection. Returns true if connection has been inserted. - /// Returns false (and ignores connections) if: - /// - we do not expect connection from this node - /// - we are already connected to the node and existing connection 'supersede' - /// new connection by agreement - pub fn insert(&self, connection: Arc) -> bool { - let node = *connection.node_id(); - let mut container = self.container.write(); - if !container.nodes.contains_key(&node) { - trace!(target: "secretstore_net", "{}: ignoring unknown connection from {} at {}", - self.self_key_pair.public(), node, connection.node_address()); - return false; - } - - if container.connections.contains_key(&node) { - // we have already connected to the same node - // the agreement is that node with lower id must establish connection to node with higher id - if (*self.self_key_pair.public() < node && connection.is_inbound()) - || (*self.self_key_pair.public() > node && !connection.is_inbound()) - { - return false; - } - } - - trace!(target: "secretstore_net", - "{}: inserting connection to {} at {}. Connected to {} of {} nodes", - self.self_key_pair.public(), node, connection.node_address(), - container.connections.len() + 1, container.nodes.len()); - container.connections.insert(node, connection); - - true - } - - /// Tries to remove connection. Returns true if connection has been removed. - /// Returns false if we do not know this connection. - pub fn remove(&self, connection: &NetConnection) -> bool { - let node_id = *connection.node_id(); - let is_inbound = connection.is_inbound(); - let mut container = self.container.write(); - if let Entry::Occupied(entry) = container.connections.entry(node_id) { - if entry.get().is_inbound() != is_inbound { - return false; - } - - trace!(target: "secretstore_net", "{}: removing connection to {} at {}", - self.self_key_pair.public(), node_id, entry.get().node_address()); - entry.remove_entry(); - - true - } else { - false - } - } -} - -/// Listen incoming connections. -fn net_listen(listen_address: &SocketAddr, data: Arc) -> Result<(), Error> { - execute( - &data.executor, - net_listen_future(listen_address, data.clone())?, - ); - Ok(()) -} - -/// Listen incoming connections future. -fn net_listen_future( - listen_address: &SocketAddr, - data: Arc, -) -> Result { - Ok(Box::new( - TcpListener::bind(listen_address)? - .incoming() - .and_then(move |stream| { - net_accept_connection(data.clone(), stream); - Ok(()) - }) - .for_each(|_| Ok(())) - .then(|_| future::ok(())), - )) -} - -/// Accept incoming connection. -fn net_accept_connection(data: Arc, stream: TcpStream) { - execute( - &data.executor, - net_accept_connection_future(data.clone(), stream), - ); -} - -/// Accept incoming connection future. -fn net_accept_connection_future( - data: Arc, - stream: TcpStream, -) -> BoxedEmptyFuture { - Box::new( - io_accept_connection(stream, data.self_key_pair.clone()) - .then(move |result| net_process_connection_result(data, None, result)) - .then(|_| future::ok(())), - ) -} - -/// Connect to remote node. -fn net_connect(data: Arc, remote: SocketAddr) { - execute(&data.executor, net_connect_future(data.clone(), remote)); -} - -/// Connect to remote node future. -fn net_connect_future(data: Arc, remote: SocketAddr) -> BoxedEmptyFuture { - let disconnected_nodes = data.container.disconnected_nodes(); - Box::new( - io_connect(&remote, data.self_key_pair.clone(), disconnected_nodes) - .then(move |result| net_process_connection_result(data, Some(remote), result)) - .then(|_| future::ok(())), - ) -} - -/// Process network connection result. -fn net_process_connection_result( - data: Arc, - outbound_addr: Option, - result: Result>, TimeoutError>, -) -> IoFuture> { - match result { - Ok(DeadlineStatus::Meet(Ok(connection))) => { - let connection = Arc::new(NetConnection::new( - data.executor.clone(), - outbound_addr.is_none(), - connection, - )); - if data.insert(connection.clone()) { - let maintain_action = data - .trigger - .lock() - .on_connection_established(connection.node_id()); - maintain_connection_trigger(data.clone(), maintain_action); - - return net_process_connection_messages(data, connection); - } - } - Ok(DeadlineStatus::Meet(Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - } - Ok(DeadlineStatus::Timeout) => { - warn!(target: "secretstore_net", "{}: timeout when establishing {} connection{}", - data.self_key_pair.public(), if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - } - Err(err) => { - warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - } - } - - Box::new(future::ok(Ok(()))) -} - -/// Process connection messages. -fn net_process_connection_messages( - data: Arc, - connection: Arc, -) -> IoFuture> { - Box::new(connection - .read_message_future() - .then(move |result| - match result { - Ok((_, Ok(message))) => { - connection.set_last_message_time(Instant::now()); - data.message_processor.process_connection_message(connection.clone(), message); - // continue serving connection - let process_messages_future = net_process_connection_messages( - data.clone(), connection).then(|_| Ok(())); - execute(&data.executor, process_messages_future); - Box::new(future::ok(Ok(()))) - }, - Ok((_, Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", - data.self_key_pair.public(), err, connection.node_id()); - // continue serving connection - let process_messages_future = net_process_connection_messages( - data.clone(), connection).then(|_| Ok(())); - execute(&data.executor, process_messages_future); - Box::new(future::ok(Err(err))) - }, - Err(err) => { - let node_id = *connection.node_id(); - warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", - data.self_key_pair.public(), err, node_id); - // close connection - if data.remove(&*connection) { - let maintain_action = data.trigger.lock().on_connection_closed(&node_id); - maintain_connection_trigger(data, maintain_action); - } - Box::new(future::err(err)) - }, - } - )) -} - -/// Schedule connections. maintain. -fn net_schedule_maintain(data: Arc) { - let closure_data = data.clone(); - execute( - &data.executor, - Interval::new_interval(Duration::new(MAINTAIN_INTERVAL, 0)) - .and_then(move |_| Ok(net_maintain(closure_data.clone()))) - .for_each(|_| Ok(())) - .then(|_| future::ok(())), - ); -} - -/// Maintain network connections. -fn net_maintain(data: Arc) { - trace!(target: "secretstore_net", "{}: executing maintain procedures", data.self_key_pair.public()); - - update_nodes_set(data.clone()); - data.message_processor.maintain_sessions(); - net_keep_alive(data.clone()); - net_connect_disconnected(data); -} - -/// Send keep alive messages to remote nodes. -fn net_keep_alive(data: Arc) { - let active_connections = data.active_connections(); - for connection in active_connections { - // the last_message_time could change after active_connections() call - // => we always need to call Instant::now() after getting last_message_time - let last_message_time = connection.last_message_time(); - let now = Instant::now(); - let last_message_diff = now - last_message_time; - if last_message_diff > KEEP_ALIVE_DISCONNECT_INTERVAL { - warn!(target: "secretstore_net", "{}: keep alive timeout for node {}", - data.self_key_pair.public(), connection.node_id()); - - let node_id = *connection.node_id(); - if data.remove(&*connection) { - let maintain_action = data.trigger.lock().on_connection_closed(&node_id); - maintain_connection_trigger(data.clone(), maintain_action); - } - data.message_processor.process_disconnect(&node_id); - } else if last_message_diff > KEEP_ALIVE_SEND_INTERVAL { - connection.send_message(Message::Cluster(ClusterMessage::KeepAlive( - message::KeepAlive {}, - ))); - } - } -} - -/// Connect disconnected nodes. -fn net_connect_disconnected(data: Arc) { - let disconnected_nodes = data.disconnected_nodes(); - for (node_id, address) in disconnected_nodes { - if data.allow_connecting_to_higher_nodes || *data.self_key_pair.public() < node_id { - net_connect(data.clone(), address); - } - } -} - -/// Schedule future execution. -fn execute + Send + 'static>(executor: &Executor, f: F) { - if let Err(err) = future::Executor::execute(executor, Box::new(f)) { - error!( - "Secret store runtime unable to spawn task. Runtime is shutting down. ({:?})", - err - ); - } -} - -/// Try to update active nodes set from connection trigger. -fn update_nodes_set(data: Arc) { - let maintain_action = data.trigger.lock().on_maintain(); - maintain_connection_trigger(data, maintain_action); -} - -/// Execute maintain procedures of connections trigger. -fn maintain_connection_trigger(data: Arc, maintain_action: Option) { - if maintain_action == Some(Maintain::SessionAndConnections) - || maintain_action == Some(Maintain::Session) - { - let session_params = data.trigger.lock().maintain_session(); - if let Some(session_params) = session_params { - let session = data - .message_processor - .start_servers_set_change_session(session_params); - match session { - Ok(_) => trace!(target: "secretstore_net", "{}: started auto-migrate session", - data.self_key_pair.public()), - Err(err) => { - trace!(target: "secretstore_net", "{}: failed to start auto-migrate session with: {}", - data.self_key_pair.public(), err) - } - } - } - } - if maintain_action == Some(Maintain::SessionAndConnections) - || maintain_action == Some(Maintain::Connections) - { - let mut trigger = data.trigger.lock(); - let mut data = data.container.write(); - trigger.maintain_connections(&mut *data); - } -} - -/// Compose SocketAddr from configuration' address and port. -fn make_socket_address(address: &str, port: u16) -> Result { - let ip_address: IpAddr = address.parse().map_err(|_| Error::InvalidNodeAddress)?; - Ok(SocketAddr::new(ip_address, port)) -} diff --git a/secret-store/src/key_server_cluster/cluster_message_processor.rs b/secret-store/src/key_server_cluster/cluster_message_processor.rs deleted file mode 100644 index 6536a6e238..0000000000 --- a/secret-store/src/key_server_cluster/cluster_message_processor.rs +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{ - cluster::{new_servers_set_change_session, ServersSetChangeParams}, - cluster_connections::{Connection, ConnectionProvider}, - cluster_sessions::{ - create_cluster_view, AdminSession, ClusterSession, ClusterSessions, - ClusterSessionsContainer, - }, - cluster_sessions_creator::{ClusterSessionCreator, IntoSessionId}, - connection_trigger::ServersSetChangeSessionCreatorConnector, - key_version_negotiation_session::{ - ContinueAction, IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, - SessionImpl as KeyVersionNegotiationSession, - }, - message::{self, ClusterMessage, Message}, - Error, NodeId, NodeKeyPair, -}; -use std::sync::Arc; - -/// Something that is able to process signals/messages from other nodes. -pub trait MessageProcessor: Send + Sync { - /// Process disconnect from the remote node. - fn process_disconnect(&self, node: &NodeId); - /// Process single message from the connection. - fn process_connection_message(&self, connection: Arc, message: Message); - - /// Start servers set change session. This is typically used by ConnectionManager when - /// it detects that auto-migration session needs to be started. - fn start_servers_set_change_session( - &self, - params: ServersSetChangeParams, - ) -> Result, Error>; - /// Try to continue session after key version negotiation session is completed. - fn try_continue_session( - &self, - session: Option>>, - ); - /// Maintain active sessions. Typically called by the ConnectionManager at some intervals. - /// Should cancel stalled sessions and send keep-alive messages for sessions that support it. - fn maintain_sessions(&self); -} - -/// Bridge between ConnectionManager and ClusterSessions. -pub struct SessionsMessageProcessor { - self_key_pair: Arc, - servers_set_change_creator_connector: Arc, - sessions: Arc, - connections: Arc, -} - -impl SessionsMessageProcessor { - /// Create new instance of SessionsMessageProcessor. - pub fn new( - self_key_pair: Arc, - servers_set_change_creator_connector: Arc, - sessions: Arc, - connections: Arc, - ) -> Self { - SessionsMessageProcessor { - self_key_pair, - servers_set_change_creator_connector, - sessions, - connections, - } - } - - /// Process single session message from connection. - fn process_message, D>( - &self, - sessions: &ClusterSessionsContainer, - connection: Arc, - mut message: Message, - ) -> Option> - where - Message: IntoSessionId, - { - // get or create new session, if required - let mut sender = *connection.node_id(); - let session = self.prepare_session(sessions, &sender, &message); - // send error if session is not found, or failed to create - let session = match session { - Ok(session) => session, - Err(error) => { - // this is new session => it is not yet in container - warn!(target: "secretstore_net", - "{}: {} session read error '{}' when requested for session from node {}", - self.self_key_pair.public(), S::type_name(), error, sender); - if !message.is_error_message() { - let qed = "session_id only fails for cluster messages; - only session messages are passed to process_message; - qed"; - let session_id = message.into_session_id().expect(qed); - let session_nonce = message.session_nonce().expect(qed); - - connection.send_message(SC::make_error_message( - session_id, - session_nonce, - error, - )); - } - return None; - } - }; - - let session_id = session.id(); - let mut is_queued_message = false; - loop { - let message_result = session.on_message(&sender, &message); - match message_result { - Ok(_) => { - // if session is completed => stop - if session.is_finished() { - info!(target: "secretstore_net", - "{}: {} session completed", self.self_key_pair.public(), S::type_name()); - sessions.remove(&session_id); - return Some(session); - } - - // try to dequeue message - match sessions.dequeue_message(&session_id) { - Some((msg_sender, msg)) => { - is_queued_message = true; - sender = msg_sender; - message = msg; - } - None => return Some(session), - } - } - Err(Error::TooEarlyForRequest) => { - sessions.enqueue_message(&session_id, sender, message, is_queued_message); - return Some(session); - } - Err(err) => { - warn!( - target: "secretstore_net", - "{}: {} session error '{}' when processing message {} from node {}", - self.self_key_pair.public(), - S::type_name(), - err, - message, - sender); - session.on_session_error(self.self_key_pair.public(), err); - sessions.remove(&session_id); - return Some(session); - } - } - } - } - - /// Get or insert new session. - fn prepare_session, D>( - &self, - sessions: &ClusterSessionsContainer, - sender: &NodeId, - message: &Message, - ) -> Result, Error> - where - Message: IntoSessionId, - { - fn requires_all_connections(message: &Message) -> bool { - match *message { - Message::Generation(_) => true, - Message::ShareAdd(_) => true, - Message::ServersSetChange(_) => true, - _ => false, - } - } - - // get or create new session, if required - let session_id = message.into_session_id().expect( - "into_session_id fails for cluster messages only; - only session messages are passed to prepare_session; - qed", - ); - let is_initialization_message = message.is_initialization_message(); - let is_delegation_message = message.is_delegation_message(); - match is_initialization_message || is_delegation_message { - false => sessions - .get(&session_id, true) - .ok_or(Error::NoActiveSessionWithId), - true => { - let creation_data = SC::creation_data_from_message(&message)?; - let master = if is_initialization_message { - *sender - } else { - *self.self_key_pair.public() - }; - let cluster = create_cluster_view( - self.self_key_pair.clone(), - self.connections.clone(), - requires_all_connections(&message), - )?; - - let nonce = Some(message.session_nonce().ok_or(Error::InvalidMessage)?); - let exclusive = message.is_exclusive_session_message(); - sessions.insert(cluster, master, session_id, nonce, exclusive, creation_data) - } - } - } - - /// Process single cluster message from the connection. - fn process_cluster_message(&self, connection: Arc, message: ClusterMessage) { - match message { - ClusterMessage::KeepAlive(_) => { - let msg = Message::Cluster(ClusterMessage::KeepAliveResponse( - message::KeepAliveResponse { session_id: None }, - )); - connection.send_message(msg) - } - ClusterMessage::KeepAliveResponse(msg) => { - if let Some(session_id) = msg.session_id { - self.sessions - .on_session_keep_alive(connection.node_id(), session_id.into()); - } - } - _ => { - warn!(target: "secretstore_net", "{}: received unexpected message {} from node {} at {}", - self.self_key_pair.public(), message, connection.node_id(), connection.node_address()) - } - } - } -} - -impl MessageProcessor for SessionsMessageProcessor { - fn process_disconnect(&self, node: &NodeId) { - self.sessions.on_connection_timeout(node); - } - - fn process_connection_message(&self, connection: Arc, message: Message) { - trace!(target: "secretstore_net", "{}: received message {} from {}", - self.self_key_pair.public(), message, connection.node_id()); - - // error is ignored as we only process errors on session level - match message { - Message::Generation(message) => self - .process_message( - &self.sessions.generation_sessions, - connection, - Message::Generation(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::Encryption(message) => self - .process_message( - &self.sessions.encryption_sessions, - connection, - Message::Encryption(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::Decryption(message) => self - .process_message( - &self.sessions.decryption_sessions, - connection, - Message::Decryption(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::SchnorrSigning(message) => self - .process_message( - &self.sessions.schnorr_signing_sessions, - connection, - Message::SchnorrSigning(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::EcdsaSigning(message) => self - .process_message( - &self.sessions.ecdsa_signing_sessions, - connection, - Message::EcdsaSigning(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::ServersSetChange(message) => { - let message = Message::ServersSetChange(message); - let is_initialization_message = message.is_initialization_message(); - let session = - self.process_message(&self.sessions.admin_sessions, connection, message); - if is_initialization_message { - if let Some(session) = session { - self.servers_set_change_creator_connector - .set_key_servers_set_change_session(session.clone()); - } - } - } - Message::KeyVersionNegotiation(message) => { - let session = self.process_message( - &self.sessions.negotiation_sessions, - connection, - Message::KeyVersionNegotiation(message), - ); - self.try_continue_session(session); - } - Message::ShareAdd(message) => self - .process_message( - &self.sessions.admin_sessions, - connection, - Message::ShareAdd(message), - ) - .map(|_| ()) - .unwrap_or_default(), - Message::Cluster(message) => self.process_cluster_message(connection, message), - } - } - - fn try_continue_session( - &self, - session: Option>>, - ) { - if let Some(session) = session { - let meta = session.meta(); - let is_master_node = meta.self_node_id == meta.master_node_id; - if is_master_node && session.is_finished() { - self.sessions.negotiation_sessions.remove(&session.id()); - match session.wait() { - Ok(Some((version, master))) => match session.take_continue_action() { - Some(ContinueAction::Decrypt( - session, - origin, - is_shadow_decryption, - is_broadcast_decryption, - )) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize( - origin, - version, - is_shadow_decryption, - is_broadcast_decryption, - ) - } else { - session.delegate( - master, - origin, - version, - is_shadow_decryption, - is_broadcast_decryption, - ) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.decryption_sessions.remove(&session.id()); - } - } - Some(ContinueAction::SchnorrSign(session, message_hash)) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.schnorr_signing_sessions.remove(&session.id()); - } - } - Some(ContinueAction::EcdsaSign(session, message_hash)) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.ecdsa_signing_sessions.remove(&session.id()); - } - } - None => (), - }, - Ok(None) => unreachable!( - "is_master_node; session is finished; - negotiation version always finished with result on master; - qed" - ), - Err(error) => match session.take_continue_action() { - Some(ContinueAction::Decrypt(session, _, _, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.decryption_sessions.remove(&session.id()); - } - Some(ContinueAction::SchnorrSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.schnorr_signing_sessions.remove(&session.id()); - } - Some(ContinueAction::EcdsaSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.ecdsa_signing_sessions.remove(&session.id()); - } - None => (), - }, - } - } - } - } - - fn maintain_sessions(&self) { - self.sessions.stop_stalled_sessions(); - self.sessions.sessions_keep_alive(); - } - - fn start_servers_set_change_session( - &self, - params: ServersSetChangeParams, - ) -> Result, Error> { - new_servers_set_change_session( - self.self_key_pair.clone(), - &*self.sessions, - self.connections.clone(), - self.servers_set_change_creator_connector.clone(), - params, - ) - } -} diff --git a/secret-store/src/key_server_cluster/cluster_sessions.rs b/secret-store/src/key_server_cluster/cluster_sessions.rs deleted file mode 100644 index a9a97b8058..0000000000 --- a/secret-store/src/key_server_cluster/cluster_sessions.rs +++ /dev/null @@ -1,937 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::Secret; -use key_server_cluster::{ - cluster::{Cluster, ClusterConfiguration, ClusterView}, - cluster_connections::ConnectionProvider, - connection_trigger::ServersSetChangeSessionCreatorConnector, - decryption_session::SessionImpl as DecryptionSessionImpl, - encryption_session::SessionImpl as EncryptionSessionImpl, - generation_session::SessionImpl as GenerationSessionImpl, - key_version_negotiation_session::{ - IsolatedSessionTransport as VersionNegotiationTransport, - SessionImpl as KeyVersionNegotiationSessionImpl, - }, - message::{self, Message}, - servers_set_change_session::SessionImpl as ServersSetChangeSessionImpl, - share_add_session::{ - IsolatedSessionTransport as ShareAddTransport, SessionImpl as ShareAddSessionImpl, - }, - signing_session_ecdsa::SessionImpl as EcdsaSigningSessionImpl, - signing_session_schnorr::SessionImpl as SchnorrSigningSessionImpl, - Error, NodeId, NodeKeyPair, Requester, SessionId, -}; -use parking_lot::{Condvar, Mutex, RwLock}; -use std::{ - collections::{BTreeMap, BTreeSet, VecDeque}, - sync::{atomic::AtomicBool, Arc, Weak}, - time::{Duration, Instant}, -}; - -use key_server_cluster::cluster_sessions_creator::{ - AdminSessionCreator, ClusterSessionCreator, DecryptionSessionCreator, - EcdsaSigningSessionCreator, EncryptionSessionCreator, GenerationSessionCreator, - KeyVersionNegotiationSessionCreator, SchnorrSigningSessionCreator, SessionCreatorCore, -}; - -/// When there are no session-related messages for SESSION_TIMEOUT_INTERVAL seconds, -/// we must treat this session as stalled && finish it with an error. -/// This timeout is for cases when node is responding to KeepAlive messages, but intentionally ignores -/// session messages. -const SESSION_TIMEOUT_INTERVAL: Duration = Duration::from_secs(60); -/// Interval to send session-level KeepAlive-messages. -const SESSION_KEEP_ALIVE_INTERVAL: Duration = Duration::from_secs(30); - -lazy_static! { - /// Servers set change session id (there could be at most 1 session => hardcoded id). - pub static ref SERVERS_SET_CHANGE_SESSION_ID: SessionId = "10b7af423bb551d5dc8645db754163a2145d37d78d468fa7330435ed77064c1c" - .parse() - .expect("hardcoded id should parse without errors; qed"); -} - -/// Session id with sub session. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct SessionIdWithSubSession { - /// Key id. - pub id: SessionId, - /// Sub session id. - pub access_key: Secret, -} - -/// Generic cluster session. -pub trait ClusterSession { - /// Session identifier type. - type Id: ::std::fmt::Debug + Ord + Clone; - - /// Session type name. - fn type_name() -> &'static str; - /// Get session id. - fn id(&self) -> Self::Id; - /// If session is finished (either with succcess or not). - fn is_finished(&self) -> bool; - /// When it takes too much time to complete session. - fn on_session_timeout(&self); - /// When it takes too much time to receive response from the node. - fn on_node_timeout(&self, node_id: &NodeId); - /// Process error that has occured during session + propagate this error to required nodes. - fn on_session_error(&self, sender: &NodeId, error: Error); - /// Process session message. - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error>; - - /// 'Wait for session completion' helper. - fn wait_session Option>>( - completion_event: &Condvar, - session_data: &Mutex, - timeout: Option, - result_reader: F, - ) -> Option> { - let mut locked_data = session_data.lock(); - match result_reader(&locked_data) { - Some(result) => Some(result), - None => { - match timeout { - None => completion_event.wait(&mut locked_data), - Some(timeout) => { - completion_event.wait_for(&mut locked_data, timeout); - } - } - - result_reader(&locked_data) - } - } - } -} - -/// Administrative session. -pub enum AdminSession { - /// Share add session. - ShareAdd(ShareAddSessionImpl), - /// Servers set change session. - ServersSetChange(ServersSetChangeSessionImpl), -} - -/// Administrative session creation data. -pub enum AdminSessionCreationData { - /// Share add session (key id). - ShareAdd(H256), - /// Servers set change session (block id, new_server_set). - ServersSetChange(Option, BTreeSet), -} - -/// Active sessions on this cluster. -pub struct ClusterSessions { - /// Key generation sessions. - pub generation_sessions: - ClusterSessionsContainer, - /// Encryption sessions. - pub encryption_sessions: - ClusterSessionsContainer, - /// Decryption sessions. - pub decryption_sessions: - ClusterSessionsContainer, - /// Schnorr signing sessions. - pub schnorr_signing_sessions: ClusterSessionsContainer< - SchnorrSigningSessionImpl, - SchnorrSigningSessionCreator, - Requester, - >, - /// ECDSA signing sessions. - pub ecdsa_signing_sessions: - ClusterSessionsContainer, - /// Key version negotiation sessions. - pub negotiation_sessions: ClusterSessionsContainer< - KeyVersionNegotiationSessionImpl, - KeyVersionNegotiationSessionCreator, - (), - >, - /// Administrative sessions. - pub admin_sessions: - ClusterSessionsContainer, - /// Self node id. - self_node_id: NodeId, - /// Creator core. - creator_core: Arc, -} - -/// Active sessions container listener. -pub trait ClusterSessionsListener: Send + Sync { - /// When new session is inserted to the container. - fn on_session_inserted(&self, _session: Arc) {} - /// When session is removed from the container. - fn on_session_removed(&self, _session: Arc) {} -} - -/// Active sessions container. -pub struct ClusterSessionsContainer, D> { - /// Sessions creator. - pub creator: SC, - /// Active sessions. - sessions: RwLock>>, - /// Listeners. Lock order: sessions -> listeners. - listeners: Mutex>>>, - /// Sessions container state. - container_state: Arc>, - /// Do not actually remove sessions. - preserve_sessions: bool, - /// Phantom data. - _pd: ::std::marker::PhantomData, -} - -/// Session and its message queue. -pub struct QueuedSession { - /// Session master. - pub master: NodeId, - /// Cluster view. - pub cluster_view: Arc, - /// Last keep alive time. - pub last_keep_alive_time: Instant, - /// Last received message time. - pub last_message_time: Instant, - /// Generation session. - pub session: Arc, - /// Messages queue. - pub queue: VecDeque<(NodeId, Message)>, -} - -/// Cluster sessions container state. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ClusterSessionsContainerState { - /// There's no active sessions => any session can be started. - Idle, - /// There are active sessions => exclusive session can't be started right now. - Active(usize), - /// Exclusive session is active => can't start any other sessions. - Exclusive, -} - -impl ClusterSessions { - /// Create new cluster sessions container. - pub fn new( - config: &ClusterConfiguration, - servers_set_change_session_creator_connector: Arc< - dyn ServersSetChangeSessionCreatorConnector, - >, - ) -> Self { - let container_state = Arc::new(Mutex::new(ClusterSessionsContainerState::Idle)); - let creator_core = Arc::new(SessionCreatorCore::new(config)); - ClusterSessions { - self_node_id: config.self_key_pair.public().clone(), - generation_sessions: ClusterSessionsContainer::new( - GenerationSessionCreator { - core: creator_core.clone(), - make_faulty_generation_sessions: AtomicBool::new(false), - }, - container_state.clone(), - ), - encryption_sessions: ClusterSessionsContainer::new( - EncryptionSessionCreator { - core: creator_core.clone(), - }, - container_state.clone(), - ), - decryption_sessions: ClusterSessionsContainer::new( - DecryptionSessionCreator { - core: creator_core.clone(), - }, - container_state.clone(), - ), - schnorr_signing_sessions: ClusterSessionsContainer::new( - SchnorrSigningSessionCreator { - core: creator_core.clone(), - }, - container_state.clone(), - ), - ecdsa_signing_sessions: ClusterSessionsContainer::new( - EcdsaSigningSessionCreator { - core: creator_core.clone(), - }, - container_state.clone(), - ), - negotiation_sessions: ClusterSessionsContainer::new( - KeyVersionNegotiationSessionCreator { - core: creator_core.clone(), - }, - container_state.clone(), - ), - admin_sessions: ClusterSessionsContainer::new( - AdminSessionCreator { - core: creator_core.clone(), - servers_set_change_session_creator_connector: - servers_set_change_session_creator_connector, - admin_public: config.admin_public.clone(), - }, - container_state, - ), - creator_core: creator_core, - } - } - - #[cfg(test)] - pub fn make_faulty_generation_sessions(&self) { - self.generation_sessions - .creator - .make_faulty_generation_sessions(); - } - - #[cfg(test)] - pub fn preserve_sessions(&mut self) { - self.generation_sessions.preserve_sessions = true; - self.encryption_sessions.preserve_sessions = true; - self.decryption_sessions.preserve_sessions = true; - self.schnorr_signing_sessions.preserve_sessions = true; - self.ecdsa_signing_sessions.preserve_sessions = true; - self.negotiation_sessions.preserve_sessions = true; - self.admin_sessions.preserve_sessions = true; - } - - /// Send session-level keep-alive messages. - pub fn sessions_keep_alive(&self) { - self.admin_sessions - .send_keep_alive(&*SERVERS_SET_CHANGE_SESSION_ID, &self.self_node_id); - } - - /// When session-level keep-alive response is received. - pub fn on_session_keep_alive(&self, sender: &NodeId, session_id: SessionId) { - if session_id == *SERVERS_SET_CHANGE_SESSION_ID { - self.admin_sessions.on_keep_alive(&session_id, sender); - } - } - - /// Stop sessions that are stalling. - pub fn stop_stalled_sessions(&self) { - self.generation_sessions.stop_stalled_sessions(); - self.encryption_sessions.stop_stalled_sessions(); - self.decryption_sessions.stop_stalled_sessions(); - self.schnorr_signing_sessions.stop_stalled_sessions(); - self.ecdsa_signing_sessions.stop_stalled_sessions(); - self.negotiation_sessions.stop_stalled_sessions(); - self.admin_sessions.stop_stalled_sessions(); - } - - /// When connection to node is lost. - pub fn on_connection_timeout(&self, node_id: &NodeId) { - self.generation_sessions.on_connection_timeout(node_id); - self.encryption_sessions.on_connection_timeout(node_id); - self.decryption_sessions.on_connection_timeout(node_id); - self.schnorr_signing_sessions.on_connection_timeout(node_id); - self.ecdsa_signing_sessions.on_connection_timeout(node_id); - self.negotiation_sessions.on_connection_timeout(node_id); - self.admin_sessions.on_connection_timeout(node_id); - self.creator_core.on_connection_timeout(node_id); - } -} - -impl ClusterSessionsContainer -where - S: ClusterSession, - SC: ClusterSessionCreator, -{ - pub fn new(creator: SC, container_state: Arc>) -> Self { - ClusterSessionsContainer { - creator: creator, - sessions: RwLock::new(BTreeMap::new()), - listeners: Mutex::new(Vec::new()), - container_state: container_state, - preserve_sessions: false, - _pd: Default::default(), - } - } - - pub fn add_listener(&self, listener: Arc>) { - self.listeners.lock().push(Arc::downgrade(&listener)); - } - - #[cfg(test)] - pub fn is_empty(&self) -> bool { - self.sessions.read().is_empty() - } - - pub fn get(&self, session_id: &S::Id, update_last_message_time: bool) -> Option> { - let mut sessions = self.sessions.write(); - sessions.get_mut(session_id).map(|s| { - if update_last_message_time { - s.last_message_time = Instant::now(); - } - s.session.clone() - }) - } - - #[cfg(test)] - pub fn first(&self) -> Option> { - self.sessions - .read() - .values() - .nth(0) - .map(|s| s.session.clone()) - } - - pub fn insert( - &self, - cluster: Arc, - master: NodeId, - session_id: S::Id, - session_nonce: Option, - is_exclusive_session: bool, - creation_data: Option, - ) -> Result, Error> { - let mut sessions = self.sessions.write(); - if sessions.contains_key(&session_id) { - return Err(Error::DuplicateSessionId); - } - - // create cluster - // let cluster = create_cluster_view(data, requires_all_connections)?; - // create session - let session = self.creator.create( - cluster.clone(), - master.clone(), - session_nonce, - session_id.clone(), - creation_data, - )?; - // check if session can be started - self.container_state - .lock() - .on_session_starting(is_exclusive_session)?; - - // insert session - let queued_session = QueuedSession { - master: master, - cluster_view: cluster, - last_keep_alive_time: Instant::now(), - last_message_time: Instant::now(), - session: session.clone(), - queue: VecDeque::new(), - }; - sessions.insert(session_id, queued_session); - self.notify_listeners(|l| l.on_session_inserted(session.clone())); - - Ok(session) - } - - pub fn remove(&self, session_id: &S::Id) { - self.do_remove(session_id, &mut *self.sessions.write()); - } - - pub fn enqueue_message( - &self, - session_id: &S::Id, - sender: NodeId, - message: Message, - is_queued_message: bool, - ) { - self.sessions.write().get_mut(session_id).map(|session| { - if is_queued_message { - session.queue.push_front((sender, message)) - } else { - session.queue.push_back((sender, message)) - } - }); - } - - pub fn dequeue_message(&self, session_id: &S::Id) -> Option<(NodeId, Message)> { - self.sessions - .write() - .get_mut(session_id) - .and_then(|session| session.queue.pop_front()) - } - - pub fn stop_stalled_sessions(&self) { - let mut sessions = self.sessions.write(); - for sid in sessions.keys().cloned().collect::>() { - let remove_session = { - let session = sessions - .get(&sid) - .expect("enumerating only existing sessions; qed"); - if Instant::now() - session.last_message_time > SESSION_TIMEOUT_INTERVAL { - session.session.on_session_timeout(); - session.session.is_finished() - } else { - false - } - }; - - if remove_session { - self.do_remove(&sid, &mut *sessions); - } - } - } - - pub fn on_connection_timeout(&self, node_id: &NodeId) { - let mut sessions = self.sessions.write(); - for sid in sessions.keys().cloned().collect::>() { - let remove_session = { - let session = sessions - .get(&sid) - .expect("enumerating only existing sessions; qed"); - session.session.on_node_timeout(node_id); - session.session.is_finished() - }; - - if remove_session { - self.do_remove(&sid, &mut *sessions); - } - } - } - - fn do_remove(&self, session_id: &S::Id, sessions: &mut BTreeMap>) { - if !self.preserve_sessions { - if let Some(session) = sessions.remove(session_id) { - self.container_state.lock().on_session_completed(); - self.notify_listeners(|l| l.on_session_removed(session.session.clone())); - } - } - } - - fn notify_listeners) -> ()>(&self, callback: F) { - let mut listeners = self.listeners.lock(); - let mut listener_index = 0; - while listener_index < listeners.len() { - match listeners[listener_index].upgrade() { - Some(listener) => { - callback(&*listener); - listener_index += 1; - } - None => { - listeners.swap_remove(listener_index); - } - } - } - } -} - -impl ClusterSessionsContainer -where - S: ClusterSession, - SC: ClusterSessionCreator, - SessionId: From, -{ - pub fn send_keep_alive(&self, session_id: &S::Id, self_node_id: &NodeId) { - if let Some(session) = self.sessions.write().get_mut(session_id) { - let now = Instant::now(); - if self_node_id == &session.master - && now - session.last_keep_alive_time > SESSION_KEEP_ALIVE_INTERVAL - { - session.last_keep_alive_time = now; - // since we send KeepAlive message to prevent nodes from disconnecting - // && worst thing that can happen if node is disconnected is that session is failed - // => ignore error here, because probably this node is not need for the rest of the session at all - let _ = session.cluster_view.broadcast(Message::Cluster( - message::ClusterMessage::KeepAliveResponse(message::KeepAliveResponse { - session_id: Some(session_id.clone().into()), - }), - )); - } - } - } - - pub fn on_keep_alive(&self, session_id: &S::Id, sender: &NodeId) { - if let Some(session) = self.sessions.write().get_mut(session_id) { - let now = Instant::now(); - // we only accept keep alive from master node of ServersSetChange session - if sender == &session.master { - session.last_keep_alive_time = now; - } - } - } -} - -impl ClusterSessionsContainerState { - /// When session is starting. - pub fn on_session_starting(&mut self, is_exclusive_session: bool) -> Result<(), Error> { - match *self { - ClusterSessionsContainerState::Idle if is_exclusive_session => { - *self = ClusterSessionsContainerState::Exclusive; - } - ClusterSessionsContainerState::Idle => { - *self = ClusterSessionsContainerState::Active(1); - } - ClusterSessionsContainerState::Active(_) if is_exclusive_session => { - return Err(Error::HasActiveSessions) - } - ClusterSessionsContainerState::Active(sessions_count) => { - *self = ClusterSessionsContainerState::Active(sessions_count + 1); - } - ClusterSessionsContainerState::Exclusive => return Err(Error::ExclusiveSessionActive), - } - Ok(()) - } - - /// When session is completed. - pub fn on_session_completed(&mut self) { - match *self { - ClusterSessionsContainerState::Idle => - unreachable!("idle means that there are no active sessions; on_session_completed is only called once after active session is completed; qed"), - ClusterSessionsContainerState::Active(sessions_count) if sessions_count == 1 => { - *self = ClusterSessionsContainerState::Idle; - }, - ClusterSessionsContainerState::Active(sessions_count) => { - *self = ClusterSessionsContainerState::Active(sessions_count - 1); - } - ClusterSessionsContainerState::Exclusive => { - *self = ClusterSessionsContainerState::Idle; - }, - } - } -} - -impl SessionIdWithSubSession { - /// Create new decryption session Id. - pub fn new(session_id: SessionId, sub_session_id: Secret) -> Self { - SessionIdWithSubSession { - id: session_id, - access_key: sub_session_id, - } - } -} - -impl PartialOrd for SessionIdWithSubSession { - fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for SessionIdWithSubSession { - fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { - match self.id.cmp(&other.id) { - ::std::cmp::Ordering::Equal => self.access_key.cmp(&other.access_key), - r @ _ => r, - } - } -} - -impl AdminSession { - pub fn as_servers_set_change(&self) -> Option<&ServersSetChangeSessionImpl> { - match *self { - AdminSession::ServersSetChange(ref session) => Some(session), - _ => None, - } - } -} - -impl ClusterSession for AdminSession { - type Id = SessionId; - - fn type_name() -> &'static str { - "admin" - } - - fn id(&self) -> SessionId { - match *self { - AdminSession::ShareAdd(ref session) => session.id().clone(), - AdminSession::ServersSetChange(ref session) => session.id().clone(), - } - } - - fn is_finished(&self) -> bool { - match *self { - AdminSession::ShareAdd(ref session) => session.is_finished(), - AdminSession::ServersSetChange(ref session) => session.is_finished(), - } - } - - fn on_session_timeout(&self) { - match *self { - AdminSession::ShareAdd(ref session) => session.on_session_timeout(), - AdminSession::ServersSetChange(ref session) => session.on_session_timeout(), - } - } - - fn on_node_timeout(&self, node_id: &NodeId) { - match *self { - AdminSession::ShareAdd(ref session) => session.on_node_timeout(node_id), - AdminSession::ServersSetChange(ref session) => session.on_node_timeout(node_id), - } - } - - fn on_session_error(&self, node: &NodeId, error: Error) { - match *self { - AdminSession::ShareAdd(ref session) => session.on_session_error(node, error), - AdminSession::ServersSetChange(ref session) => session.on_session_error(node, error), - } - } - - fn on_message(&self, sender: &NodeId, message: &Message) -> Result<(), Error> { - match *self { - AdminSession::ShareAdd(ref session) => session.on_message(sender, message), - AdminSession::ServersSetChange(ref session) => session.on_message(sender, message), - } - } -} - -pub fn create_cluster_view( - self_key_pair: Arc, - connections: Arc, - requires_all_connections: bool, -) -> Result, Error> { - let mut connected_nodes = connections.connected_nodes()?; - let disconnected_nodes = connections.disconnected_nodes(); - - let disconnected_nodes_count = disconnected_nodes.len(); - if requires_all_connections { - if disconnected_nodes_count != 0 { - return Err(Error::NodeDisconnected); - } - } - - connected_nodes.insert(self_key_pair.public().clone()); - - let connected_nodes_count = connected_nodes.len(); - Ok(Arc::new(ClusterView::new( - self_key_pair, - connections, - connected_nodes, - connected_nodes_count + disconnected_nodes_count, - ))) -} - -#[cfg(test)] -mod tests { - use super::{ - AdminSessionCreationData, ClusterSessions, ClusterSessionsContainerState, - ClusterSessionsListener, SESSION_TIMEOUT_INTERVAL, - }; - use ethkey::{Generator, Random}; - use key_server_cluster::{ - cluster::{tests::DummyCluster, ClusterConfiguration}, - connection_trigger::SimpleServersSetChangeSessionCreatorConnector, - generation_session::SessionImpl as GenerationSession, - DummyAclStorage, DummyKeyStorage, Error, MapKeyServerSet, PlainNodeKeyPair, - }; - use std::sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }; - - pub fn make_cluster_sessions() -> ClusterSessions { - let key_pair = Random.generate().unwrap(); - let config = ClusterConfiguration { - self_key_pair: Arc::new(PlainNodeKeyPair::new(key_pair.clone())), - key_server_set: Arc::new(MapKeyServerSet::new( - false, - vec![( - key_pair.public().clone(), - format!("127.0.0.1:{}", 100).parse().unwrap(), - )] - .into_iter() - .collect(), - )), - key_storage: Arc::new(DummyKeyStorage::default()), - acl_storage: Arc::new(DummyAclStorage::default()), - admin_public: Some(Random.generate().unwrap().public().clone()), - preserve_sessions: false, - }; - ClusterSessions::new( - &config, - Arc::new(SimpleServersSetChangeSessionCreatorConnector { - admin_public: Some(Random.generate().unwrap().public().clone()), - }), - ) - } - - #[test] - fn cluster_session_cannot_be_started_if_exclusive_session_is_active() { - let sessions = make_cluster_sessions(); - sessions - .generation_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) - .unwrap(); - match sessions.admin_sessions.insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - true, - Some(AdminSessionCreationData::ShareAdd(Default::default())), - ) { - Err(Error::HasActiveSessions) => (), - Err(e) => unreachable!(format!("{}", e)), - Ok(_) => unreachable!("OK"), - } - } - - #[test] - fn exclusive_session_cannot_be_started_if_other_session_is_active() { - let sessions = make_cluster_sessions(); - - sessions - .admin_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - true, - Some(AdminSessionCreationData::ShareAdd(Default::default())), - ) - .unwrap(); - match sessions.generation_sessions.insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) { - Err(Error::ExclusiveSessionActive) => (), - Err(e) => unreachable!(format!("{}", e)), - Ok(_) => unreachable!("OK"), - } - } - - #[test] - fn session_listener_works() { - #[derive(Default)] - struct GenerationSessionListener { - inserted: AtomicUsize, - removed: AtomicUsize, - } - - impl ClusterSessionsListener for GenerationSessionListener { - fn on_session_inserted(&self, _session: Arc) { - self.inserted.fetch_add(1, Ordering::Relaxed); - } - - fn on_session_removed(&self, _session: Arc) { - self.removed.fetch_add(1, Ordering::Relaxed); - } - } - - let listener = Arc::new(GenerationSessionListener::default()); - let sessions = make_cluster_sessions(); - sessions.generation_sessions.add_listener(listener.clone()); - - sessions - .generation_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) - .unwrap(); - assert_eq!(listener.inserted.load(Ordering::Relaxed), 1); - assert_eq!(listener.removed.load(Ordering::Relaxed), 0); - - sessions.generation_sessions.remove(&Default::default()); - assert_eq!(listener.inserted.load(Ordering::Relaxed), 1); - assert_eq!(listener.removed.load(Ordering::Relaxed), 1); - } - - #[test] - fn last_session_removal_sets_container_state_to_idle() { - let sessions = make_cluster_sessions(); - - sessions - .generation_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) - .unwrap(); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Active(1) - ); - - sessions.generation_sessions.remove(&Default::default()); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Idle - ); - } - - #[test] - fn last_session_removal_by_timeout_sets_container_state_to_idle() { - let sessions = make_cluster_sessions(); - - sessions - .generation_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) - .unwrap(); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Active(1) - ); - - sessions - .generation_sessions - .sessions - .write() - .get_mut(&Default::default()) - .unwrap() - .last_message_time -= SESSION_TIMEOUT_INTERVAL * 2; - - sessions.generation_sessions.stop_stalled_sessions(); - assert_eq!(sessions.generation_sessions.sessions.read().len(), 0); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Idle - ); - } - - #[test] - fn last_session_removal_by_node_timeout_sets_container_state_to_idle() { - let sessions = make_cluster_sessions(); - - sessions - .generation_sessions - .insert( - Arc::new(DummyCluster::new(Default::default())), - Default::default(), - Default::default(), - None, - false, - None, - ) - .unwrap(); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Active(1) - ); - - sessions - .generation_sessions - .on_connection_timeout(&Default::default()); - assert_eq!(sessions.generation_sessions.sessions.read().len(), 0); - assert_eq!( - *sessions.generation_sessions.container_state.lock(), - ClusterSessionsContainerState::Idle - ); - } -} diff --git a/secret-store/src/key_server_cluster/cluster_sessions_creator.rs b/secret-store/src/key_server_cluster/cluster_sessions_creator.rs deleted file mode 100644 index 0f41bbbe66..0000000000 --- a/secret-store/src/key_server_cluster/cluster_sessions_creator.rs +++ /dev/null @@ -1,678 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::Public; -use key_server_cluster::{ - admin_sessions::ShareChangeSessionMeta, - cluster::{Cluster, ClusterConfiguration}, - cluster_sessions::{ - AdminSession, AdminSessionCreationData, ClusterSession, SessionIdWithSubSession, - }, - connection_trigger::ServersSetChangeSessionCreatorConnector, - decryption_session::{ - SessionImpl as DecryptionSessionImpl, SessionParams as DecryptionSessionParams, - }, - encryption_session::{ - SessionImpl as EncryptionSessionImpl, SessionParams as EncryptionSessionParams, - }, - generation_session::{ - SessionImpl as GenerationSessionImpl, SessionParams as GenerationSessionParams, - }, - key_version_negotiation_session::{ - FastestResultComputer as FastestResultKeyVersionsResultComputer, - IsolatedSessionTransport as VersionNegotiationTransport, - SessionImpl as KeyVersionNegotiationSessionImpl, - SessionParams as KeyVersionNegotiationSessionParams, - }, - message::{ - self, ConsensusMessage, ConsensusMessageOfShareAdd, ConsensusMessageWithServersSet, - DecryptionMessage, EcdsaSigningMessage, Message, SchnorrSigningMessage, - ServersSetChangeMessage, ShareAddMessage, - }, - servers_set_change_session::{ - SessionImpl as ServersSetChangeSessionImpl, SessionParams as ServersSetChangeSessionParams, - }, - share_add_session::{ - IsolatedSessionTransport as ShareAddTransport, SessionImpl as ShareAddSessionImpl, - SessionParams as ShareAddSessionParams, - }, - signing_session_ecdsa::{ - SessionImpl as EcdsaSigningSessionImpl, SessionParams as EcdsaSigningSessionParams, - }, - signing_session_schnorr::{ - SessionImpl as SchnorrSigningSessionImpl, SessionParams as SchnorrSigningSessionParams, - }, - AclStorage, DocumentKeyShare, Error, KeyStorage, NodeId, Requester, SessionId, SessionMeta, -}; -use parking_lot::RwLock; -use std::{ - collections::BTreeMap, - sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, - Arc, - }, -}; - -/// Generic cluster session creator. -pub trait ClusterSessionCreator { - /// Get creation data from message. - fn creation_data_from_message(_message: &Message) -> Result, Error> { - Ok(None) - } - - /// Prepare error message. - fn make_error_message(sid: S::Id, nonce: u64, err: Error) -> Message; - - /// Create cluster session. - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: S::Id, - creation_data: Option, - ) -> Result, Error>; -} - -/// Message with session id. -pub trait IntoSessionId { - /// Get session id. - fn into_session_id(&self) -> Result; -} - -pub struct SessionCreatorCore { - /// Self node id. - self_node_id: NodeId, - /// Reference to key storage - key_storage: Arc, - /// Reference to ACL storage - acl_storage: Arc, - /// Always-increasing sessions counter. Is used as session nonce to prevent replay attacks: - /// 1) during handshake, KeyServers generate new random key to encrypt messages - /// => there's no way to use messages from previous connections for replay attacks - /// 2) when session (of any type) is started, master node increases its own session counter and broadcasts it - /// 3) when slave KeyServer receives session initialization message, it checks that new nonce is larger than previous (from the same master) - /// => there's no way to use messages from previous sessions for replay attacks - /// 4) KeyServer checks that each session message contains the same nonce that initialization message - /// Given that: (A) handshake is secure and (B) session itself is initially replay-protected - /// => this guarantees that sessions are replay-protected. - session_counter: AtomicUsize, - /// Maximal session nonce, received from given connection. - max_nonce: RwLock>, -} - -impl SessionCreatorCore { - /// Create new session creator core. - pub fn new(config: &ClusterConfiguration) -> Self { - SessionCreatorCore { - self_node_id: config.self_key_pair.public().clone(), - acl_storage: config.acl_storage.clone(), - key_storage: config.key_storage.clone(), - session_counter: AtomicUsize::new(0), - max_nonce: RwLock::new(BTreeMap::new()), - } - } - - /// When node has teimtouted. - pub fn on_connection_timeout(&self, node_id: &NodeId) { - self.max_nonce.write().remove(node_id); - } - - /// Check or generate new session nonce. - fn check_session_nonce(&self, master: &NodeId, nonce: Option) -> Result { - // if we're master node of the session, then nonce should be generated - // if we're slave node of the session, then nonce should be passed from outside - match nonce { - Some(nonce) => match nonce > *self.max_nonce.write().entry(master.clone()).or_insert(0) - { - true => Ok(nonce), - false => Err(Error::ReplayProtection), - }, - None => Ok(self.session_counter.fetch_add(1, Ordering::Relaxed) as u64 + 1), - } - } - - /// Read key share && remove disconnected nodes. - fn read_key_share(&self, key_id: &SessionId) -> Result, Error> { - self.key_storage.get(key_id) - } -} - -/// Generation session creator. -pub struct GenerationSessionCreator { - /// True if generation sessions must fail. - pub make_faulty_generation_sessions: AtomicBool, - /// Creator core. - pub core: Arc, -} - -impl GenerationSessionCreator { - #[cfg(test)] - pub fn make_faulty_generation_sessions(&self) { - self.make_faulty_generation_sessions - .store(true, Ordering::Relaxed); - } -} - -impl ClusterSessionCreator for GenerationSessionCreator { - fn make_error_message(sid: SessionId, nonce: u64, err: Error) -> Message { - message::Message::Generation(message::GenerationMessage::SessionError( - message::SessionError { - session: sid.into(), - session_nonce: nonce, - error: err.into(), - }, - )) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionId, - _creation_data: Option<()>, - ) -> Result, Error> { - // check that there's no finished encryption session with the same id - if self.core.key_storage.contains(&id) { - return Err(Error::ServerKeyAlreadyGenerated); - } - - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(GenerationSessionImpl::new(GenerationSessionParams { - id: id.clone(), - self_node_id: self.core.self_node_id.clone(), - key_storage: Some(self.core.key_storage.clone()), - cluster: cluster, - nonce: Some(nonce), - })) - .map(|session| { - if self.make_faulty_generation_sessions.load(Ordering::Relaxed) { - session.simulate_faulty_behaviour(); - } - session - }) - .map(Arc::new) - } -} - -/// Encryption session creator. -pub struct EncryptionSessionCreator { - /// Creator core. - pub core: Arc, -} - -impl ClusterSessionCreator for EncryptionSessionCreator { - fn make_error_message(sid: SessionId, nonce: u64, err: Error) -> Message { - message::Message::Encryption(message::EncryptionMessage::EncryptionSessionError( - message::EncryptionSessionError { - session: sid.into(), - session_nonce: nonce, - error: err.into(), - }, - )) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionId, - _creation_data: Option<()>, - ) -> Result, Error> { - let encrypted_data = self.core.read_key_share(&id)?; - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(Arc::new(EncryptionSessionImpl::new( - EncryptionSessionParams { - id: id, - self_node_id: self.core.self_node_id.clone(), - encrypted_data: encrypted_data, - key_storage: self.core.key_storage.clone(), - cluster: cluster, - nonce: nonce, - }, - )?)) - } -} - -/// Decryption session creator. -pub struct DecryptionSessionCreator { - /// Creator core. - pub core: Arc, -} - -impl ClusterSessionCreator for DecryptionSessionCreator { - fn creation_data_from_message(message: &Message) -> Result, Error> { - match *message { - Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(ref message)) => { - match &message.message { - &ConsensusMessage::InitializeConsensusSession(ref message) => { - Ok(Some(message.requester.clone().into())) - } - _ => Err(Error::InvalidMessage), - } - } - Message::Decryption(DecryptionMessage::DecryptionSessionDelegation(ref message)) => { - Ok(Some(message.requester.clone().into())) - } - _ => Err(Error::InvalidMessage), - } - } - - fn make_error_message(sid: SessionIdWithSubSession, nonce: u64, err: Error) -> Message { - message::Message::Decryption(message::DecryptionMessage::DecryptionSessionError( - message::DecryptionSessionError { - session: sid.id.into(), - sub_session: sid.access_key.into(), - session_nonce: nonce, - error: err.into(), - }, - )) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionIdWithSubSession, - requester: Option, - ) -> Result, Error> { - let encrypted_data = self.core.read_key_share(&id.id)?; - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(Arc::new(DecryptionSessionImpl::new( - DecryptionSessionParams { - meta: SessionMeta { - id: id.id, - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - threshold: encrypted_data - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default(), - configured_nodes_count: cluster.configured_nodes_count(), - connected_nodes_count: cluster.connected_nodes_count(), - }, - access_key: id.access_key, - key_share: encrypted_data, - acl_storage: self.core.acl_storage.clone(), - cluster: cluster, - nonce: nonce, - }, - requester, - )?)) - } -} - -/// Schnorr signing session creator. -pub struct SchnorrSigningSessionCreator { - /// Creator core. - pub core: Arc, -} - -impl ClusterSessionCreator for SchnorrSigningSessionCreator { - fn creation_data_from_message(message: &Message) -> Result, Error> { - match *message { - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage( - ref message, - )) => match &message.message { - &ConsensusMessage::InitializeConsensusSession(ref message) => { - Ok(Some(message.requester.clone().into())) - } - _ => Err(Error::InvalidMessage), - }, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionDelegation( - ref message, - )) => Ok(Some(message.requester.clone().into())), - _ => Err(Error::InvalidMessage), - } - } - - fn make_error_message(sid: SessionIdWithSubSession, nonce: u64, err: Error) -> Message { - message::Message::SchnorrSigning( - message::SchnorrSigningMessage::SchnorrSigningSessionError( - message::SchnorrSigningSessionError { - session: sid.id.into(), - sub_session: sid.access_key.into(), - session_nonce: nonce, - error: err.into(), - }, - ), - ) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionIdWithSubSession, - requester: Option, - ) -> Result, Error> { - let encrypted_data = self.core.read_key_share(&id.id)?; - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(Arc::new(SchnorrSigningSessionImpl::new( - SchnorrSigningSessionParams { - meta: SessionMeta { - id: id.id, - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - threshold: encrypted_data - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default(), - configured_nodes_count: cluster.configured_nodes_count(), - connected_nodes_count: cluster.connected_nodes_count(), - }, - access_key: id.access_key, - key_share: encrypted_data, - acl_storage: self.core.acl_storage.clone(), - cluster: cluster, - nonce: nonce, - }, - requester, - )?)) - } -} - -/// ECDSA signing session creator. -pub struct EcdsaSigningSessionCreator { - /// Creator core. - pub core: Arc, -} - -impl ClusterSessionCreator for EcdsaSigningSessionCreator { - fn creation_data_from_message(message: &Message) -> Result, Error> { - match *message { - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage( - ref message, - )) => match &message.message { - &ConsensusMessage::InitializeConsensusSession(ref message) => { - Ok(Some(message.requester.clone().into())) - } - _ => Err(Error::InvalidMessage), - }, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegation( - ref message, - )) => Ok(Some(message.requester.clone().into())), - _ => Err(Error::InvalidMessage), - } - } - - fn make_error_message(sid: SessionIdWithSubSession, nonce: u64, err: Error) -> Message { - message::Message::EcdsaSigning(message::EcdsaSigningMessage::EcdsaSigningSessionError( - message::EcdsaSigningSessionError { - session: sid.id.into(), - sub_session: sid.access_key.into(), - session_nonce: nonce, - error: err.into(), - }, - )) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionIdWithSubSession, - requester: Option, - ) -> Result, Error> { - let encrypted_data = self.core.read_key_share(&id.id)?; - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(Arc::new(EcdsaSigningSessionImpl::new( - EcdsaSigningSessionParams { - meta: SessionMeta { - id: id.id, - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - threshold: encrypted_data - .as_ref() - .map(|ks| ks.threshold) - .unwrap_or_default(), - configured_nodes_count: cluster.configured_nodes_count(), - connected_nodes_count: cluster.connected_nodes_count(), - }, - access_key: id.access_key, - key_share: encrypted_data, - acl_storage: self.core.acl_storage.clone(), - cluster: cluster, - nonce: nonce, - }, - requester, - )?)) - } -} - -/// Key version negotiation session creator. -pub struct KeyVersionNegotiationSessionCreator { - /// Creator core. - pub core: Arc, -} - -impl ClusterSessionCreator, ()> - for KeyVersionNegotiationSessionCreator -{ - fn make_error_message(sid: SessionIdWithSubSession, nonce: u64, err: Error) -> Message { - message::Message::KeyVersionNegotiation( - message::KeyVersionNegotiationMessage::KeyVersionsError(message::KeyVersionsError { - session: sid.id.into(), - sub_session: sid.access_key.into(), - session_nonce: nonce, - error: err.into(), - // we don't care about continue action here. it only matters when we're completing the session with confirmed - // fatal error from result computer - continue_with: None, - }), - ) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionIdWithSubSession, - _creation_data: Option<()>, - ) -> Result>, Error> { - let configured_nodes_count = cluster.configured_nodes_count(); - let connected_nodes_count = cluster.connected_nodes_count(); - let encrypted_data = self.core.read_key_share(&id.id)?; - let nonce = self.core.check_session_nonce(&master, nonce)?; - let computer = Arc::new(FastestResultKeyVersionsResultComputer::new( - self.core.self_node_id.clone(), - encrypted_data.as_ref(), - configured_nodes_count, - configured_nodes_count, - )); - Ok(Arc::new(KeyVersionNegotiationSessionImpl::new( - KeyVersionNegotiationSessionParams { - meta: ShareChangeSessionMeta { - id: id.id.clone(), - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - configured_nodes_count: configured_nodes_count, - connected_nodes_count: connected_nodes_count, - }, - sub_session: id.access_key.clone(), - key_share: encrypted_data, - result_computer: computer, - transport: VersionNegotiationTransport { - cluster: cluster, - key_id: id.id, - sub_session: id.access_key.clone(), - nonce: nonce, - }, - nonce: nonce, - }, - ))) - } -} - -/// Administrative session creator. -pub struct AdminSessionCreator { - /// Creator core. - pub core: Arc, - /// Administrator public. - pub admin_public: Option, - /// Servers set change sessions creator connector. - pub servers_set_change_session_creator_connector: - Arc, -} - -impl ClusterSessionCreator for AdminSessionCreator { - fn creation_data_from_message( - message: &Message, - ) -> Result, Error> { - match *message { - Message::ServersSetChange( - ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref message), - ) => match &message.message { - &ConsensusMessageWithServersSet::InitializeConsensusSession(ref message) => { - Ok(Some(AdminSessionCreationData::ServersSetChange( - message.migration_id.clone().map(Into::into), - message - .new_nodes_set - .clone() - .into_iter() - .map(Into::into) - .collect(), - ))) - } - _ => Err(Error::InvalidMessage), - }, - Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage(ref message)) => { - match &message.message { - &ConsensusMessageOfShareAdd::InitializeConsensusSession(ref message) => { - Ok(Some(AdminSessionCreationData::ShareAdd( - message.version.clone().into(), - ))) - } - _ => Err(Error::InvalidMessage), - } - } - _ => Err(Error::InvalidMessage), - } - } - - fn make_error_message(sid: SessionId, nonce: u64, err: Error) -> Message { - message::Message::ServersSetChange(message::ServersSetChangeMessage::ServersSetChangeError( - message::ServersSetChangeError { - session: sid.into(), - session_nonce: nonce, - error: err.into(), - }, - )) - } - - fn create( - &self, - cluster: Arc, - master: NodeId, - nonce: Option, - id: SessionId, - creation_data: Option, - ) -> Result, Error> { - let nonce = self.core.check_session_nonce(&master, nonce)?; - Ok(Arc::new(match creation_data { - Some(AdminSessionCreationData::ShareAdd(version)) => { - AdminSession::ShareAdd(ShareAddSessionImpl::new(ShareAddSessionParams { - meta: ShareChangeSessionMeta { - id: id.clone(), - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - configured_nodes_count: cluster.configured_nodes_count(), - connected_nodes_count: cluster.connected_nodes_count(), - }, - transport: ShareAddTransport::new(id.clone(), Some(version), nonce, cluster), - key_storage: self.core.key_storage.clone(), - nonce: nonce, - admin_public: Some(self.admin_public.clone().ok_or(Error::AccessDenied)?), - })?) - } - Some(AdminSessionCreationData::ServersSetChange(migration_id, new_nodes_set)) => { - let admin_public = self - .servers_set_change_session_creator_connector - .admin_public(migration_id.as_ref(), new_nodes_set) - .map_err(|_| Error::AccessDenied)?; - - AdminSession::ServersSetChange(ServersSetChangeSessionImpl::new( - ServersSetChangeSessionParams { - meta: ShareChangeSessionMeta { - id: id.clone(), - self_node_id: self.core.self_node_id.clone(), - master_node_id: master, - configured_nodes_count: cluster.configured_nodes_count(), - connected_nodes_count: cluster.connected_nodes_count(), - }, - cluster: cluster.clone(), - key_storage: self.core.key_storage.clone(), - nonce: nonce, - all_nodes_set: cluster.nodes(), - admin_public: admin_public, - migration_id: migration_id, - }, - )?) - } - None => unreachable!("expected to call with non-empty creation data; qed"), - })) - } -} - -impl IntoSessionId for Message { - fn into_session_id(&self) -> Result { - match *self { - Message::Generation(ref message) => Ok(message.session_id().clone()), - Message::Encryption(ref message) => Ok(message.session_id().clone()), - Message::Decryption(_) => Err(Error::InvalidMessage), - Message::SchnorrSigning(_) => Err(Error::InvalidMessage), - Message::EcdsaSigning(_) => Err(Error::InvalidMessage), - Message::ServersSetChange(ref message) => Ok(message.session_id().clone()), - Message::ShareAdd(ref message) => Ok(message.session_id().clone()), - Message::KeyVersionNegotiation(_) => Err(Error::InvalidMessage), - Message::Cluster(_) => Err(Error::InvalidMessage), - } - } -} - -impl IntoSessionId for Message { - fn into_session_id(&self) -> Result { - match *self { - Message::Generation(_) => Err(Error::InvalidMessage), - Message::Encryption(_) => Err(Error::InvalidMessage), - Message::Decryption(ref message) => Ok(SessionIdWithSubSession::new( - message.session_id().clone(), - message.sub_session_id().clone(), - )), - Message::SchnorrSigning(ref message) => Ok(SessionIdWithSubSession::new( - message.session_id().clone(), - message.sub_session_id().clone(), - )), - Message::EcdsaSigning(ref message) => Ok(SessionIdWithSubSession::new( - message.session_id().clone(), - message.sub_session_id().clone(), - )), - Message::ServersSetChange(_) => Err(Error::InvalidMessage), - Message::ShareAdd(_) => Err(Error::InvalidMessage), - Message::KeyVersionNegotiation(ref message) => Ok(SessionIdWithSubSession::new( - message.session_id().clone(), - message.sub_session_id().clone(), - )), - Message::Cluster(_) => Err(Error::InvalidMessage), - } - } -} diff --git a/secret-store/src/key_server_cluster/connection_trigger.rs b/secret-store/src/key_server_cluster/connection_trigger.rs deleted file mode 100644 index fe26ee403d..0000000000 --- a/secret-store/src/key_server_cluster/connection_trigger.rs +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::Public; -use key_server_cluster::{ - cluster::{ClusterConfiguration, ServersSetChangeParams}, - cluster_connections::Connection, - cluster_connections_net::NetConnectionsContainer, - cluster_sessions::AdminSession, - KeyServerSet, KeyServerSetSnapshot, -}; -use std::{ - collections::{btree_map::Entry, BTreeMap, BTreeSet}, - net::SocketAddr, - sync::Arc, -}; -use types::{Error, NodeId}; -use NodeKeyPair; - -#[derive(Debug, Clone, Copy, PartialEq)] -/// Describes which maintain() call is required. -pub enum Maintain { - /// We need to maintain() both connections && session. - SessionAndConnections, - /// Only call maintain_session. - Session, - /// Only call maintain_connections. - Connections, -} - -/// Connection trigger, which executes necessary actions when set of key servers changes. -pub trait ConnectionTrigger: Send + Sync { - /// On maintain interval. - fn on_maintain(&mut self) -> Option; - /// When connection is established. - fn on_connection_established(&mut self, node: &NodeId) -> Option; - /// When connection is closed. - fn on_connection_closed(&mut self, node: &NodeId) -> Option; - /// Maintain active sessions. Returns Some if servers set session creation required. - fn maintain_session(&mut self) -> Option; - /// Maintain active connections. - fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer); - /// Return connector for the servers set change session creator. - fn servers_set_change_creator_connector( - &self, - ) -> Arc; -} - -/// Servers set change session creator connector. -pub trait ServersSetChangeSessionCreatorConnector: Send + Sync { - /// Get actual administrator public key. For manual-migration configuration it is the pre-configured - /// administrator key. For auto-migration configurations it is the key of actual MigrationSession master node. - fn admin_public( - &self, - migration_id: Option<&H256>, - new_server_set: BTreeSet, - ) -> Result; - /// Set active servers set change session. - fn set_key_servers_set_change_session(&self, session: Arc); -} - -/// Simple connection trigger, which only keeps connections to current_set. -pub struct SimpleConnectionTrigger { - /// Key server set cluster. - key_server_set: Arc, - /// Trigger connections. - connections: TriggerConnections, - /// Servers set change session creator connector. - connector: Arc, -} - -/// Simple Servers set change session creator connector, which will just return -/// pre-configured administartor public when asked. -pub struct SimpleServersSetChangeSessionCreatorConnector { - /// Secret store administrator public key. - pub admin_public: Option, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -/// Action with trigger connections. -pub enum ConnectionsAction { - /// Connect to nodes from old set only. - ConnectToCurrentSet, - /// Connect to nodes from migration set. - ConnectToMigrationSet, -} - -/// Trigger connections. -pub struct TriggerConnections { - /// This node key pair. - pub self_key_pair: Arc, -} - -impl SimpleConnectionTrigger { - /// Create new simple from cluster configuration. - pub fn with_config(config: &ClusterConfiguration) -> Self { - Self::new( - config.key_server_set.clone(), - config.self_key_pair.clone(), - config.admin_public, - ) - } - - /// Create new simple connection trigger. - pub fn new( - key_server_set: Arc, - self_key_pair: Arc, - admin_public: Option, - ) -> Self { - SimpleConnectionTrigger { - key_server_set: key_server_set, - connections: TriggerConnections { - self_key_pair: self_key_pair, - }, - connector: Arc::new(SimpleServersSetChangeSessionCreatorConnector { - admin_public: admin_public, - }), - } - } -} - -impl ConnectionTrigger for SimpleConnectionTrigger { - fn on_maintain(&mut self) -> Option { - Some(Maintain::Connections) - } - - fn on_connection_established(&mut self, _node: &NodeId) -> Option { - None - } - - fn on_connection_closed(&mut self, _node: &NodeId) -> Option { - // we do not want to reconnect after every connection close - // because it could be a part of something bigger - None - } - - fn maintain_session(&mut self) -> Option { - None - } - - fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer) { - self.connections.maintain( - ConnectionsAction::ConnectToCurrentSet, - connections, - &self.key_server_set.snapshot(), - ) - } - - fn servers_set_change_creator_connector( - &self, - ) -> Arc { - self.connector.clone() - } -} - -impl ServersSetChangeSessionCreatorConnector for SimpleServersSetChangeSessionCreatorConnector { - fn admin_public( - &self, - _migration_id: Option<&H256>, - _new_server_set: BTreeSet, - ) -> Result { - self.admin_public.clone().ok_or(Error::AccessDenied) - } - - fn set_key_servers_set_change_session(&self, _session: Arc) {} -} - -impl TriggerConnections { - pub fn maintain( - &self, - action: ConnectionsAction, - data: &mut NetConnectionsContainer, - server_set: &KeyServerSetSnapshot, - ) { - match action { - ConnectionsAction::ConnectToCurrentSet => { - adjust_connections(self.self_key_pair.public(), data, &server_set.current_set); - } - ConnectionsAction::ConnectToMigrationSet => { - let migration_set = server_set - .migration - .as_ref() - .map(|s| s.set.clone()) - .unwrap_or_default(); - adjust_connections(self.self_key_pair.public(), data, &migration_set); - } - } - } -} - -fn adjust_connections( - self_node_id: &NodeId, - data: &mut NetConnectionsContainer, - required_set: &BTreeMap, -) { - if !required_set.contains_key(self_node_id) { - if !data.is_isolated { - trace!(target: "secretstore_net", "{}: isolated from cluser", self_node_id); - } - - data.is_isolated = true; - data.connections.clear(); - data.nodes.clear(); - return; - } - - data.is_isolated = false; - for node_to_disconnect in select_nodes_to_disconnect(&data.nodes, required_set) { - if let Entry::Occupied(entry) = data.connections.entry(node_to_disconnect.clone()) { - trace!(target: "secretstore_net", "{}: adjusting connections - removing connection to {} at {}", - self_node_id, entry.get().node_id(), entry.get().node_address()); - entry.remove(); - } - - data.nodes.remove(&node_to_disconnect); - } - - for (node_to_connect, node_addr) in required_set { - if node_to_connect != self_node_id { - data.nodes - .insert(node_to_connect.clone(), node_addr.clone()); - } - } -} - -fn select_nodes_to_disconnect( - current_set: &BTreeMap, - new_set: &BTreeMap, -) -> Vec { - current_set - .iter() - .filter(|&(node_id, node_addr)| match new_set.get(node_id) { - Some(new_node_addr) => node_addr != new_node_addr, - None => true, - }) - .map(|(node_id, _)| node_id.clone()) - .collect() -} - -#[cfg(test)] -mod tests { - use super::{ - adjust_connections, select_nodes_to_disconnect, ConnectionTrigger, ConnectionsAction, - Maintain, SimpleConnectionTrigger, TriggerConnections, - }; - use ethkey::{Generator, Random}; - use key_server_cluster::{ - cluster_connections_net::NetConnectionsContainer, KeyServerSetMigration, - KeyServerSetSnapshot, MapKeyServerSet, PlainNodeKeyPair, - }; - use std::{collections::BTreeSet, sync::Arc}; - - fn default_connection_data() -> NetConnectionsContainer { - NetConnectionsContainer { - is_isolated: false, - nodes: Default::default(), - connections: Default::default(), - } - } - - fn create_connections() -> TriggerConnections { - TriggerConnections { - self_key_pair: Arc::new(PlainNodeKeyPair::new(Random.generate().unwrap())), - } - } - - #[test] - fn do_not_disconnect_if_set_is_not_changed() { - let node_id = Random.generate().unwrap().public().clone(); - assert_eq!( - select_nodes_to_disconnect( - &vec![(node_id, "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - &vec![(node_id, "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect() - ), - vec![] - ); - } - - #[test] - fn disconnect_if_address_has_changed() { - let node_id = Random.generate().unwrap().public().clone(); - assert_eq!( - select_nodes_to_disconnect( - &vec![(node_id.clone(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - &vec![(node_id.clone(), "127.0.0.1:8082".parse().unwrap())] - .into_iter() - .collect() - ), - vec![node_id.clone()] - ); - } - - #[test] - fn disconnect_if_node_has_removed() { - let node_id = Random.generate().unwrap().public().clone(); - assert_eq!( - select_nodes_to_disconnect( - &vec![(node_id.clone(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - &vec![].into_iter().collect() - ), - vec![node_id.clone()] - ); - } - - #[test] - fn does_not_disconnect_if_node_has_added() { - let node_id = Random.generate().unwrap().public().clone(); - assert_eq!( - select_nodes_to_disconnect( - &vec![(node_id.clone(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - &vec![ - (node_id.clone(), "127.0.0.1:8081".parse().unwrap()), - ( - Random.generate().unwrap().public().clone(), - "127.0.0.1:8082".parse().unwrap() - ) - ] - .into_iter() - .collect() - ), - vec![] - ); - } - - #[test] - fn adjust_connections_disconnects_from_all_nodes_if_not_a_part_of_key_server() { - let self_node_id = Random.generate().unwrap().public().clone(); - let other_node_id = Random.generate().unwrap().public().clone(); - let mut connection_data = default_connection_data(); - connection_data - .nodes - .insert(other_node_id.clone(), "127.0.0.1:8081".parse().unwrap()); - - let required_set = connection_data.nodes.clone(); - adjust_connections(&self_node_id, &mut connection_data, &required_set); - assert!(connection_data.nodes.is_empty()); - assert!(connection_data.is_isolated); - } - - #[test] - fn adjust_connections_connects_to_new_nodes() { - let self_node_id = Random.generate().unwrap().public().clone(); - let other_node_id = Random.generate().unwrap().public().clone(); - let mut connection_data = default_connection_data(); - - let required_set = vec![ - (self_node_id.clone(), "127.0.0.1:8081".parse().unwrap()), - (other_node_id.clone(), "127.0.0.1:8082".parse().unwrap()), - ] - .into_iter() - .collect(); - adjust_connections(&self_node_id, &mut connection_data, &required_set); - assert!(connection_data.nodes.contains_key(&other_node_id)); - assert!(!connection_data.is_isolated); - } - - #[test] - fn adjust_connections_reconnects_from_changed_nodes() { - let self_node_id = Random.generate().unwrap().public().clone(); - let other_node_id = Random.generate().unwrap().public().clone(); - let mut connection_data = default_connection_data(); - connection_data - .nodes - .insert(other_node_id.clone(), "127.0.0.1:8082".parse().unwrap()); - - let required_set = vec![ - (self_node_id.clone(), "127.0.0.1:8081".parse().unwrap()), - (other_node_id.clone(), "127.0.0.1:8083".parse().unwrap()), - ] - .into_iter() - .collect(); - adjust_connections(&self_node_id, &mut connection_data, &required_set); - assert_eq!( - connection_data.nodes.get(&other_node_id), - Some(&"127.0.0.1:8083".parse().unwrap()) - ); - assert!(!connection_data.is_isolated); - } - - #[test] - fn adjust_connections_disconnects_from_removed_nodes() { - let self_node_id = Random.generate().unwrap().public().clone(); - let other_node_id = Random.generate().unwrap().public().clone(); - let mut connection_data = default_connection_data(); - connection_data - .nodes - .insert(other_node_id.clone(), "127.0.0.1:8082".parse().unwrap()); - - let required_set = vec![(self_node_id.clone(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(); - adjust_connections(&self_node_id, &mut connection_data, &required_set); - assert!(connection_data.nodes.is_empty()); - assert!(!connection_data.is_isolated); - } - - #[test] - fn adjust_connections_does_not_connects_to_self() { - let self_node_id = Random.generate().unwrap().public().clone(); - let mut connection_data = default_connection_data(); - - let required_set = vec![(self_node_id.clone(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(); - adjust_connections(&self_node_id, &mut connection_data, &required_set); - assert!(connection_data.nodes.is_empty()); - assert!(!connection_data.is_isolated); - } - - #[test] - fn maintain_connects_to_current_set_works() { - let connections = create_connections(); - let self_node_id = connections.self_key_pair.public().clone(); - let current_node_id = Random.generate().unwrap().public().clone(); - let migration_node_id = Random.generate().unwrap().public().clone(); - let new_node_id = Random.generate().unwrap().public().clone(); - - let mut connections_data = default_connection_data(); - connections.maintain( - ConnectionsAction::ConnectToCurrentSet, - &mut connections_data, - &KeyServerSetSnapshot { - current_set: vec![ - (self_node_id.clone(), "127.0.0.1:8081".parse().unwrap()), - (current_node_id.clone(), "127.0.0.1:8082".parse().unwrap()), - ] - .into_iter() - .collect(), - new_set: vec![(new_node_id.clone(), "127.0.0.1:8083".parse().unwrap())] - .into_iter() - .collect(), - migration: Some(KeyServerSetMigration { - set: vec![(migration_node_id.clone(), "127.0.0.1:8084".parse().unwrap())] - .into_iter() - .collect(), - ..Default::default() - }), - }, - ); - - assert_eq!( - vec![current_node_id], - connections_data.nodes.keys().cloned().collect::>() - ); - } - - #[test] - fn maintain_connects_to_migration_set_works() { - let connections = create_connections(); - let self_node_id = connections.self_key_pair.public().clone(); - let current_node_id = Random.generate().unwrap().public().clone(); - let migration_node_id = Random.generate().unwrap().public().clone(); - let new_node_id = Random.generate().unwrap().public().clone(); - - let mut connections_data = default_connection_data(); - connections.maintain( - ConnectionsAction::ConnectToMigrationSet, - &mut connections_data, - &KeyServerSetSnapshot { - current_set: vec![(current_node_id.clone(), "127.0.0.1:8082".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![(new_node_id.clone(), "127.0.0.1:8083".parse().unwrap())] - .into_iter() - .collect(), - migration: Some(KeyServerSetMigration { - set: vec![ - (self_node_id.clone(), "127.0.0.1:8081".parse().unwrap()), - (migration_node_id.clone(), "127.0.0.1:8084".parse().unwrap()), - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - ); - - assert_eq!( - vec![migration_node_id].into_iter().collect::>(), - connections_data - .nodes - .keys() - .cloned() - .collect::>() - ); - } - - #[test] - fn simple_connections_trigger_only_maintains_connections() { - let key_server_set = Arc::new(MapKeyServerSet::new(false, Default::default())); - let self_key_pair = Arc::new(PlainNodeKeyPair::new(Random.generate().unwrap())); - let mut trigger = SimpleConnectionTrigger::new(key_server_set, self_key_pair, None); - assert_eq!(trigger.on_maintain(), Some(Maintain::Connections)); - } -} diff --git a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs b/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs deleted file mode 100644 index 6ce17b348a..0000000000 --- a/secret-store/src/key_server_cluster/connection_trigger_with_migration.rs +++ /dev/null @@ -1,1123 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::Public; -use key_server_cluster::{ - cluster::{ClusterConfiguration, ServersSetChangeParams}, - cluster_connections_net::NetConnectionsContainer, - cluster_sessions::{AdminSession, ClusterSession}, - connection_trigger::{ - ConnectionTrigger, ConnectionsAction, Maintain, ServersSetChangeSessionCreatorConnector, - TriggerConnections, - }, - is_migration_required, - jobs::servers_set_change_access_job::ordered_nodes_hash, - KeyServerSet, KeyServerSetMigration, KeyServerSetSnapshot, -}; -use parking_lot::Mutex; -use std::{ - collections::{BTreeMap, BTreeSet}, - net::SocketAddr, - sync::Arc, -}; -use types::{Error, NodeId}; -use NodeKeyPair; - -/// Key servers set change trigger with automated migration procedure. -pub struct ConnectionTriggerWithMigration { - /// This node key pair. - self_key_pair: Arc, - /// Key server set. - key_server_set: Arc, - /// Last server set state. - snapshot: KeyServerSetSnapshot, - /// Required connections action. - connections_action: Option, - /// Required session action. - session_action: Option, - /// Currenty connected nodes. - connected: BTreeSet, - /// Trigger migration connections. - connections: TriggerConnections, - /// Trigger migration session. - session: TriggerSession, -} - -#[derive(Default)] -/// Key servers set change session creator connector with migration support. -pub struct ServersSetChangeSessionCreatorConnectorWithMigration { - /// This node id. - self_node_id: NodeId, - /// Active migration state to check when servers set change session is started. - migration: Mutex>, - /// Active servers set change session. - session: Mutex>>, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -/// Migration session action. -enum SessionAction { - /// Start migration (confirm migration transaction). - StartMigration(H256), - /// Start migration session. - Start, - /// Confirm migration and forget migration session. - ConfirmAndDrop(H256), - /// Forget migration session. - Drop, - /// Forget migration session and retry. - DropAndRetry, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -/// Migration session state. -enum SessionState { - /// No active session. - Idle, - /// Session is running with given migration id. - Active(Option), - /// Session is completed successfully. - Finished(Option), - /// Session is completed with an error. - Failed(Option), -} - -#[derive(Debug, Clone, Copy, PartialEq)] -/// Migration state. -pub enum MigrationState { - /// No migration required. - Idle, - /// Migration is required. - Required, - /// Migration has started. - Started, -} - -/// Migration session. -struct TriggerSession { - /// Servers set change session creator connector. - connector: Arc, - /// This node key pair. - self_key_pair: Arc, - /// Key server set. - key_server_set: Arc, -} - -impl ConnectionTriggerWithMigration { - /// Create new simple from cluster configuration. - pub fn with_config(config: &ClusterConfiguration) -> Self { - Self::new(config.key_server_set.clone(), config.self_key_pair.clone()) - } - - /// Create new trigge with migration. - pub fn new(key_server_set: Arc, self_key_pair: Arc) -> Self { - let snapshot = key_server_set.snapshot(); - let migration = snapshot.migration.clone(); - - ConnectionTriggerWithMigration { - self_key_pair: self_key_pair.clone(), - key_server_set: key_server_set.clone(), - snapshot: snapshot, - connected: BTreeSet::new(), - connections: TriggerConnections { - self_key_pair: self_key_pair.clone(), - }, - session: TriggerSession { - connector: Arc::new(ServersSetChangeSessionCreatorConnectorWithMigration { - self_node_id: self_key_pair.public().clone(), - migration: Mutex::new(migration), - session: Mutex::new(None), - }), - self_key_pair: self_key_pair, - key_server_set: key_server_set, - }, - connections_action: None, - session_action: None, - } - } - - /// Actually do mainteinance. - fn do_maintain(&mut self) -> Option { - loop { - let session_state = session_state(self.session.connector.session.lock().clone()); - let migration_state = migration_state(self.self_key_pair.public(), &self.snapshot); - - let session_action = maintain_session( - self.self_key_pair.public(), - &self.connected, - &self.snapshot, - migration_state, - session_state, - ); - let session_maintain_required = session_action - .map(|session_action| self.session.process(session_action)) - .unwrap_or_default(); - self.session_action = session_action; - - let connections_action = maintain_connections(migration_state, session_state); - let connections_maintain_required = - connections_action.map(|_| true).unwrap_or_default(); - self.connections_action = connections_action; - - if session_state != SessionState::Idle || migration_state != MigrationState::Idle { - trace!(target: "secretstore_net", "{}: non-idle auto-migration state: {:?} -> {:?}", - self.self_key_pair.public(), (migration_state, session_state), (self.connections_action, self.session_action)); - } - - if session_action != Some(SessionAction::DropAndRetry) { - return match (session_maintain_required, connections_maintain_required) { - (true, true) => Some(Maintain::SessionAndConnections), - (true, false) => Some(Maintain::Session), - (false, true) => Some(Maintain::Connections), - (false, false) => None, - }; - } - } - } -} - -impl ConnectionTrigger for ConnectionTriggerWithMigration { - fn on_maintain(&mut self) -> Option { - self.snapshot = self.key_server_set.snapshot(); - *self.session.connector.migration.lock() = self.snapshot.migration.clone(); - - self.do_maintain() - } - - fn on_connection_established(&mut self, node: &NodeId) -> Option { - self.connected.insert(node.clone()); - self.do_maintain() - } - - fn on_connection_closed(&mut self, node: &NodeId) -> Option { - self.connected.remove(node); - self.do_maintain() - } - - fn maintain_session(&mut self) -> Option { - self.session_action - .and_then(|action| self.session.maintain(action, &self.snapshot)) - } - - fn maintain_connections(&mut self, connections: &mut NetConnectionsContainer) { - if let Some(action) = self.connections_action { - self.connections - .maintain(action, connections, &self.snapshot); - } - } - - fn servers_set_change_creator_connector( - &self, - ) -> Arc { - self.session.connector.clone() - } -} - -impl ServersSetChangeSessionCreatorConnector - for ServersSetChangeSessionCreatorConnectorWithMigration -{ - fn admin_public( - &self, - migration_id: Option<&H256>, - new_server_set: BTreeSet, - ) -> Result { - // the idea is that all nodes are agreed upon a block number and a new set of nodes in this block - // then master node is selected of all nodes set && this master signs the old set && new set - // (signatures are inputs to ServerSetChangeSession) - self.migration.lock().as_ref() - .map(|migration| { - let is_migration_id_same = migration_id.map(|mid| mid == &migration.id).unwrap_or_default(); - let is_migration_set_same = new_server_set == migration.set.keys().cloned().collect(); - if is_migration_id_same && is_migration_set_same { - Ok(migration.master.clone()) - } else { - warn!(target: "secretstore_net", "{}: failed to accept auto-migration session: same_migration_id={}, same_migration_set={}", - self.self_node_id, is_migration_id_same, is_migration_set_same); - - Err(Error::AccessDenied) - } - }) - .unwrap_or_else(|| { - warn!(target: "secretstore_net", "{}: failed to accept non-scheduled auto-migration session", self.self_node_id); - Err(Error::AccessDenied) - }) - } - - fn set_key_servers_set_change_session(&self, session: Arc) { - *self.session.lock() = Some(session); - } -} - -impl TriggerSession { - /// Process session action. - pub fn process(&mut self, action: SessionAction) -> bool { - match action { - SessionAction::ConfirmAndDrop(migration_id) => { - *self.connector.session.lock() = None; - self.key_server_set.confirm_migration(migration_id); - false - } - SessionAction::Drop | SessionAction::DropAndRetry => { - *self.connector.session.lock() = None; - false - } - SessionAction::StartMigration(migration_id) => { - self.key_server_set.start_migration(migration_id); - false - } - SessionAction::Start => true, - } - } - - /// Maintain session. - pub fn maintain( - &mut self, - action: SessionAction, - server_set: &KeyServerSetSnapshot, - ) -> Option { - if action != SessionAction::Start { - // all other actions are processed in maintain - return None; - } - let migration = server_set - .migration - .as_ref() - .expect("action is Start only when migration is started (see maintain_session); qed"); - - // we assume that authorities that are removed from the servers set are either offline, or malicious - // => they're not involved in ServersSetChangeSession - // => both sets are the same - let old_set: BTreeSet<_> = migration.set.keys().cloned().collect(); - let new_set = old_set.clone(); - - let signatures = self - .self_key_pair - .sign(&ordered_nodes_hash(&old_set)) - .and_then(|old_set_signature| { - self.self_key_pair - .sign(&ordered_nodes_hash(&new_set)) - .map(|new_set_signature| (old_set_signature, new_set_signature)) - }); - - match signatures { - Ok((old_set_signature, new_set_signature)) => Some(ServersSetChangeParams { - session_id: None, - migration_id: Some(migration.id), - new_nodes_set: new_set, - old_set_signature, - new_set_signature, - }), - Err(err) => { - trace!( - target: "secretstore_net", - "{}: failed to sign servers set for auto-migrate session with: {}", - self.self_key_pair.public(), err); - None - } - } - } -} - -fn migration_state(self_node_id: &NodeId, snapshot: &KeyServerSetSnapshot) -> MigrationState { - // if this node is not on current && old set => we do not participate in migration - if !snapshot.current_set.contains_key(self_node_id) - && !snapshot - .migration - .as_ref() - .map(|s| s.set.contains_key(self_node_id)) - .unwrap_or_default() - { - return MigrationState::Idle; - } - - // if migration has already started no other states possible - if snapshot.migration.is_some() { - return MigrationState::Started; - } - - // we only require migration if set actually changes - // when only address changes, we could simply adjust connections - if !is_migration_required(&snapshot.current_set, &snapshot.new_set) { - return MigrationState::Idle; - } - - return MigrationState::Required; -} - -fn session_state(session: Option>) -> SessionState { - session - .and_then(|s| match s.as_servers_set_change() { - Some(s) if !s.is_finished() => Some(SessionState::Active(s.migration_id().cloned())), - Some(s) => match s.wait() { - Ok(_) => Some(SessionState::Finished(s.migration_id().cloned())), - Err(_) => Some(SessionState::Failed(s.migration_id().cloned())), - }, - None => None, - }) - .unwrap_or(SessionState::Idle) -} - -fn maintain_session( - self_node_id: &NodeId, - connected: &BTreeSet, - snapshot: &KeyServerSetSnapshot, - migration_state: MigrationState, - session_state: SessionState, -) -> Option { - let migration_data_proof = - "migration_state is Started; migration data available when started; qed"; - - match (migration_state, session_state) { - // === NORMAL combinations === - - // having no session when it is not required => ok - (MigrationState::Idle, SessionState::Idle) => None, - // migration is required && no active session => start migration - (MigrationState::Required, SessionState::Idle) => { - match select_master_node(snapshot) == self_node_id { - true => Some(SessionAction::StartMigration(H256::random())), - // we are not on master node - false => None, - } - }, - // migration is active && there's no active session => start it - (MigrationState::Started, SessionState::Idle) => { - match is_connected_to_all_nodes(self_node_id, &snapshot.migration.as_ref().expect(migration_data_proof).set, connected) && - select_master_node(snapshot) == self_node_id { - true => Some(SessionAction::Start), - // we are not connected to all required nodes yet or we are not on master node => wait for it - false => None, - } - }, - // migration is active && session is not yet started/finished => ok - (MigrationState::Started, SessionState::Active(ref session_migration_id)) - if snapshot.migration.as_ref().expect(migration_data_proof).id == session_migration_id.unwrap_or_default() => - None, - // migration has finished => confirm migration - (MigrationState::Started, SessionState::Finished(ref session_migration_id)) - if snapshot.migration.as_ref().expect(migration_data_proof).id == session_migration_id.unwrap_or_default() => - match snapshot.migration.as_ref().expect(migration_data_proof).set.contains_key(self_node_id) { - true => Some(SessionAction::ConfirmAndDrop( - snapshot.migration.as_ref().expect(migration_data_proof).id.clone() - )), - // we are not on migration set => we do not need to confirm - false => Some(SessionAction::Drop), - }, - // migration has failed => it should be dropped && restarted later - (MigrationState::Started, SessionState::Failed(ref session_migration_id)) - if snapshot.migration.as_ref().expect(migration_data_proof).id == session_migration_id.unwrap_or_default() => - Some(SessionAction::Drop), - - // ABNORMAL combinations, which are still possible when contract misbehaves === - - // having active session when it is not required => drop it && wait for other tasks - (MigrationState::Idle, SessionState::Active(_)) | - // no migration required && there's finished session => drop it && wait for other tasks - (MigrationState::Idle, SessionState::Finished(_)) | - // no migration required && there's failed session => drop it && wait for other tasks - (MigrationState::Idle, SessionState::Failed(_)) | - // migration is required && session is active => drop it && wait for other tasks - (MigrationState::Required, SessionState::Active(_)) | - // migration is required && session has failed => we need to forget this obsolete session and retry - (MigrationState::Required, SessionState::Finished(_)) | - // session for other migration is active => we need to forget this obsolete session and retry - // (the case for same id is checked above) - (MigrationState::Started, SessionState::Active(_)) | - // session for other migration has finished => we need to forget this obsolete session and retry - // (the case for same id is checked above) - (MigrationState::Started, SessionState::Finished(_)) | - // session for other migration has failed => we need to forget this obsolete session and retry - // (the case for same id is checked above) - (MigrationState::Started, SessionState::Failed(_)) | - // migration is required && session has failed => we need to forget this obsolete session and retry - (MigrationState::Required, SessionState::Failed(_)) => { - // some of the cases above could happen because of lags (could actually be a non-abnormal behavior) - // => we ony trace here - trace!(target: "secretstore_net", "{}: suspicious auto-migration state: {:?}", - self_node_id, (migration_state, session_state)); - Some(SessionAction::DropAndRetry) - }, - } -} - -fn maintain_connections( - migration_state: MigrationState, - session_state: SessionState, -) -> Option { - match (migration_state, session_state) { - // session is active => we do not alter connections when session is active - (_, SessionState::Active(_)) => None, - // when no migration required => we just keep us connected to old nodes set - (MigrationState::Idle, _) => Some(ConnectionsAction::ConnectToCurrentSet), - // when migration is either scheduled, or in progress => connect to both old and migration set. - // this could lead to situation when node is not 'officially' a part of KeyServer (i.e. it is not in current_set) - // but it participates in new key generation session - // it is ok, since 'officialy' here means that this node is a owner of all old shares - (MigrationState::Required, _) | (MigrationState::Started, _) => { - Some(ConnectionsAction::ConnectToMigrationSet) - } - } -} - -fn is_connected_to_all_nodes( - self_node_id: &NodeId, - nodes: &BTreeMap, - connected: &BTreeSet, -) -> bool { - nodes - .keys() - .filter(|n| *n != self_node_id) - .all(|n| connected.contains(n)) -} - -fn select_master_node(snapshot: &KeyServerSetSnapshot) -> &NodeId { - // we want to minimize a number of UnknownSession messages => - // try to select a node which was in SS && will be in SS - match snapshot.migration.as_ref() { - Some(migration) => &migration.master, - None => snapshot.current_set.keys() - .filter(|n| snapshot.new_set.contains_key(n)) - .nth(0) - .or_else(|| snapshot.new_set.keys().nth(0)) - .unwrap_or_else(|| snapshot.current_set.keys().nth(0) - .expect("select_master_node is only called when migration is Required or Started;\ - when Started: migration.is_some() && we return migration.master; qed;\ - when Required: current_set != new_set; this means that at least one set is non-empty; we try to take node from each set; qed")) - } -} - -#[cfg(test)] -mod tests { - use super::{ - maintain_connections, maintain_session, migration_state, select_master_node, - MigrationState, SessionAction, SessionState, - }; - use key_server_cluster::{ - connection_trigger::ConnectionsAction, KeyServerSetMigration, KeyServerSetSnapshot, - }; - - #[test] - fn migration_state_is_idle_when_required_but_this_node_is_not_on_the_list() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![(2.into(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![(3.into(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - migration: None, - } - ), - MigrationState::Idle - ); - } - - #[test] - fn migration_state_is_idle_when_sets_are_equal() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![(1.into(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - migration: None, - } - ), - MigrationState::Idle - ); - } - - #[test] - fn migration_state_is_idle_when_only_address_changes() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8080".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![(1.into(), "127.0.0.1:8081".parse().unwrap())] - .into_iter() - .collect(), - migration: None, - } - ), - MigrationState::Idle - ); - } - - #[test] - fn migration_state_is_required_when_node_is_added() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8080".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![ - (1.into(), "127.0.0.1:8080".parse().unwrap()), - (2.into(), "127.0.0.1:8081".parse().unwrap()) - ] - .into_iter() - .collect(), - migration: None, - } - ), - MigrationState::Required - ); - } - - #[test] - fn migration_state_is_required_when_node_is_removed() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![ - (1.into(), "127.0.0.1:8080".parse().unwrap()), - (2.into(), "127.0.0.1:8081".parse().unwrap()) - ] - .into_iter() - .collect(), - new_set: vec![(1.into(), "127.0.0.1:8080".parse().unwrap())] - .into_iter() - .collect(), - migration: None, - } - ), - MigrationState::Required - ); - } - - #[test] - fn migration_state_is_started_when_migration_is_some() { - assert_eq!( - migration_state( - &1.into(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8080".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - id: Default::default(), - set: Default::default(), - master: Default::default(), - is_confirmed: Default::default(), - }), - } - ), - MigrationState::Started - ); - } - - #[test] - fn existing_master_is_selected_when_migration_has_started() { - assert_eq!( - select_master_node(&KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8180".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![(2.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - migration: Some(KeyServerSetMigration { - master: 3.into(), - ..Default::default() - }), - }), - &3.into() - ); - } - - #[test] - fn persistent_master_is_selected_when_migration_has_not_started_yet() { - assert_eq!( - select_master_node(&KeyServerSetSnapshot { - current_set: vec![ - (1.into(), "127.0.0.1:8180".parse().unwrap()), - (2.into(), "127.0.0.1:8180".parse().unwrap()) - ] - .into_iter() - .collect(), - new_set: vec![ - (2.into(), "127.0.0.1:8181".parse().unwrap()), - (4.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - migration: None, - }), - &2.into() - ); - } - - #[test] - fn new_master_is_selected_in_worst_case() { - assert_eq!( - select_master_node(&KeyServerSetSnapshot { - current_set: vec![ - (1.into(), "127.0.0.1:8180".parse().unwrap()), - (2.into(), "127.0.0.1:8180".parse().unwrap()) - ] - .into_iter() - .collect(), - new_set: vec![ - (3.into(), "127.0.0.1:8181".parse().unwrap()), - (4.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - migration: None, - }), - &3.into() - ); - } - - #[test] - fn maintain_connections_returns_none_when_session_is_active() { - assert_eq!( - maintain_connections( - MigrationState::Required, - SessionState::Active(Default::default()) - ), - None - ); - } - - #[test] - fn maintain_connections_connects_to_current_set_when_no_migration() { - assert_eq!( - maintain_connections(MigrationState::Idle, SessionState::Idle), - Some(ConnectionsAction::ConnectToCurrentSet) - ); - } - - #[test] - fn maintain_connections_connects_to_current_and_old_set_when_migration_is_required() { - assert_eq!( - maintain_connections(MigrationState::Required, SessionState::Idle), - Some(ConnectionsAction::ConnectToMigrationSet) - ); - } - - #[test] - fn maintain_connections_connects_to_current_and_old_set_when_migration_is_started() { - assert_eq!( - maintain_connections(MigrationState::Started, SessionState::Idle), - Some(ConnectionsAction::ConnectToMigrationSet) - ); - } - - #[test] - fn maintain_sessions_does_nothing_if_no_session_and_no_migration() { - assert_eq!( - maintain_session( - &1.into(), - &Default::default(), - &Default::default(), - MigrationState::Idle, - SessionState::Idle - ), - None - ); - } - - #[test] - fn maintain_session_does_nothing_when_migration_required_on_slave_node_and_no_session() { - assert_eq!( - maintain_session( - &2.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - migration: None, - }, - MigrationState::Required, - SessionState::Idle - ), - None - ); - } - - #[test] - fn maintain_session_does_nothing_when_migration_started_on_slave_node_and_no_session() { - assert_eq!( - maintain_session( - &2.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Idle - ), - None - ); - } - - #[test] - fn maintain_session_does_nothing_when_migration_started_on_master_node_and_no_session_and_not_connected_to_migration_nodes( - ) { - assert_eq!( - maintain_session( - &1.into(), - &Default::default(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Idle - ), - None - ); - } - - #[test] - fn maintain_session_starts_session_when_migration_started_on_master_node_and_no_session() { - assert_eq!( - maintain_session( - &1.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Idle - ), - Some(SessionAction::Start) - ); - } - - #[test] - fn maintain_session_does_nothing_when_both_migration_and_session_are_started() { - assert_eq!( - maintain_session( - &1.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Active(Default::default()) - ), - None - ); - } - - #[test] - fn maintain_session_confirms_migration_when_active_and_session_has_finished_on_new_node() { - assert_eq!( - maintain_session( - &1.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Finished(Default::default()) - ), - Some(SessionAction::ConfirmAndDrop(Default::default())) - ); - } - - #[test] - fn maintain_session_drops_session_when_active_and_session_has_finished_on_removed_node() { - assert_eq!( - maintain_session( - &1.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 2.into(), - set: vec![(2.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Finished(Default::default()) - ), - Some(SessionAction::Drop) - ); - } - - #[test] - fn maintain_session_drops_session_when_active_and_session_has_failed() { - assert_eq!( - maintain_session( - &1.into(), - &vec![2.into()].into_iter().collect(), - &KeyServerSetSnapshot { - current_set: vec![(1.into(), "127.0.0.1:8181".parse().unwrap())] - .into_iter() - .collect(), - new_set: Default::default(), - migration: Some(KeyServerSetMigration { - master: 1.into(), - set: vec![ - (1.into(), "127.0.0.1:8181".parse().unwrap()), - (2.into(), "127.0.0.1:8181".parse().unwrap()) - ] - .into_iter() - .collect(), - ..Default::default() - }), - }, - MigrationState::Started, - SessionState::Failed(Default::default()) - ), - Some(SessionAction::Drop) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_no_migration_and_active_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Idle, - SessionState::Active(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_no_migration_and_finished_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Idle, - SessionState::Finished(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_no_migration_and_failed_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Idle, - SessionState::Failed(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_required_migration_and_active_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Required, - SessionState::Active(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_required_migration_and_finished_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Required, - SessionState::Finished(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_required_migration_and_failed_session() { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &Default::default(), - MigrationState::Required, - SessionState::Failed(Default::default()) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_active_migration_and_active_session_with_different_id( - ) { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &KeyServerSetSnapshot { - migration: Some(KeyServerSetMigration { - id: 0.into(), - ..Default::default() - }), - ..Default::default() - }, - MigrationState::Started, - SessionState::Active(Some(1.into())) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_active_migration_and_finished_session_with_different_id( - ) { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &KeyServerSetSnapshot { - migration: Some(KeyServerSetMigration { - id: 0.into(), - ..Default::default() - }), - ..Default::default() - }, - MigrationState::Started, - SessionState::Finished(Some(1.into())) - ), - Some(SessionAction::DropAndRetry) - ); - } - - #[test] - fn maintain_session_detects_abnormal_when_active_migration_and_failed_session_with_different_id( - ) { - assert_eq!( - maintain_session( - &Default::default(), - &Default::default(), - &KeyServerSetSnapshot { - migration: Some(KeyServerSetMigration { - id: 0.into(), - ..Default::default() - }), - ..Default::default() - }, - MigrationState::Started, - SessionState::Failed(Some(1.into())) - ), - Some(SessionAction::DropAndRetry) - ); - } -} diff --git a/secret-store/src/key_server_cluster/io/deadline.rs b/secret-store/src/key_server_cluster/io/deadline.rs deleted file mode 100644 index 130c105507..0000000000 --- a/secret-store/src/key_server_cluster/io/deadline.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::{Future, Poll}; -use std::{io, time::Duration}; -use tokio::timer::timeout::{Error as TimeoutError, Timeout}; - -type DeadlineBox = Box< - dyn Future< - Item = DeadlineStatus<::Item>, - Error = TimeoutError<::Error>, - > + Send, ->; - -/// Complete a passed future or fail if it is not completed within timeout. -pub fn deadline(duration: Duration, future: F) -> Result, io::Error> -where - F: Future + Send + 'static, - T: Send + 'static, -{ - let timeout = Box::new(Timeout::new(future, duration).then(|res| match res { - Ok(fut) => Ok(DeadlineStatus::Meet(fut)), - Err(err) => { - if err.is_elapsed() { - Ok(DeadlineStatus::Timeout) - } else { - Err(err) - } - } - })); - let deadline = Deadline { future: timeout }; - Ok(deadline) -} - -/// Deadline future completion status. -#[derive(Debug, PartialEq)] -pub enum DeadlineStatus { - /// Completed a future. - Meet(T), - /// Faled with timeout. - Timeout, -} - -/// Future, which waits for passed future completion within given period, or fails with timeout. -pub struct Deadline -where - F: Future, -{ - future: DeadlineBox, -} - -impl Future for Deadline -where - F: Future, -{ - type Item = DeadlineStatus; - type Error = TimeoutError; - - fn poll(&mut self) -> Poll { - self.future.poll() - } -} - -#[cfg(test)] -mod tests { - use super::{deadline, DeadlineStatus}; - use futures::{done, Future}; - use std::time::Duration; - use tokio::reactor::Reactor; - - #[test] - fn deadline_result_works() { - let mut reactor = Reactor::new().unwrap(); - let deadline = deadline(Duration::from_millis(1000), done(Ok(()))).unwrap(); - reactor.turn(Some(Duration::from_millis(3))).unwrap(); - assert_eq!(deadline.wait().unwrap(), DeadlineStatus::Meet(())); - } -} diff --git a/secret-store/src/key_server_cluster/io/handshake.rs b/secret-store/src/key_server_cluster/io/handshake.rs deleted file mode 100644 index 3952b4c7c9..0000000000 --- a/secret-store/src/key_server_cluster/io/handshake.rs +++ /dev/null @@ -1,533 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{ - crypto::ecdh::agree, recover, sign, verify_public, Generator, KeyPair, Public, Random, - Signature, -}; -use futures::{Async, Future, Poll}; -use key_server_cluster::{ - io::{ - fix_shared_key, read_encrypted_message, read_message, write_encrypted_message, - write_message, ReadMessage, WriteMessage, - }, - message::{ClusterMessage, Message, NodePrivateKeySignature, NodePublicKey}, - Error, NodeId, NodeKeyPair, -}; -///! Given: two nodes each holding its own `self_key_pair`. -///! -///! Handshake process: -///! 1) both nodes are generating random `KeyPair` (`session_key_pair`), which will be used for channel encryption -///! 2) both nodes are generating random H256 (`confirmation_plain`) -///! 3) both nodes are signing `confirmation_plain` using `session_key_pair` to receive `confirmation_signed_session` -///! 4) nodes exchange with `NodePublicKey` messages, containing: `self_key_pair.public`, `confirmation_plain`, `confirmation_signed_session` -///! 5) both nodes are checking that they're configured to communicate to server with received `message.self_key_pair.public`. Connection is closed otherwise -///! 6) both nodes are recovering peer' `session_key_pair.public` from `message.confirmation_plain` and `message.confirmation_signed_session` -///! 7) both nodes are computing shared session key pair using self' `session_key_pair.secret` && peer' `session_key_pair.public`. All following messages are encrypted using this key_pair. -///! 8) both nodes are signing `message.confirmation_plain` with their own `self_key_pair.private` to receive `confirmation_signed` -///! 9) nodes exchange with `NodePrivateKeySignature` messages, containing `confirmation_signed` -///! 10) both nodes are checking that `confirmation_signed` is actually signed with the owner of peer' `self_key_pair.secret` -///! -///! Result of handshake is: -///! 1) belief, that we are connected to the KS from our KS-set -///! 2) session key pair, which is used to enrypt all connection messages -use std::io; -use std::{collections::BTreeSet, sync::Arc}; -use tokio_io::{AsyncRead, AsyncWrite}; - -/// Start handshake procedure with another node from the cluster. -pub fn handshake( - a: A, - self_key_pair: Arc, - trusted_nodes: BTreeSet, -) -> Handshake -where - A: AsyncWrite + AsyncRead, -{ - let init_data = Random - .generate() - .map(|kp| *kp.secret().clone()) - .map_err(Into::into) - .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); - handshake_with_init_data(a, init_data, self_key_pair, trusted_nodes) -} - -/// Start handshake procedure with another node from the cluster and given plain confirmation + session key pair. -pub fn handshake_with_init_data( - a: A, - init_data: Result<(H256, KeyPair), Error>, - self_key_pair: Arc, - trusted_nodes: BTreeSet, -) -> Handshake -where - A: AsyncWrite + AsyncRead, -{ - let handshake_input_data = init_data - .and_then(|(cp, kp)| { - sign(kp.secret(), &cp) - .map(|sp| (cp, kp, sp)) - .map_err(Into::into) - }) - .and_then(|(cp, kp, sp)| { - Handshake::::make_public_key_message(self_key_pair.public().clone(), cp.clone(), sp) - .map(|msg| (cp, kp, msg)) - }); - - let (error, cp, kp, state) = match handshake_input_data { - Ok((cp, kp, msg)) => ( - None, - cp, - Some(kp), - HandshakeState::SendPublicKey(write_message(a, msg)), - ), - Err(err) => ( - Some((a, Err(err))), - Default::default(), - None, - HandshakeState::Finished, - ), - }; - - Handshake { - is_active: true, - error: error, - state: state, - self_key_pair: self_key_pair, - self_session_key_pair: kp, - self_confirmation_plain: cp, - trusted_nodes: Some(trusted_nodes), - peer_node_id: None, - peer_session_public: None, - peer_confirmation_plain: None, - shared_key: None, - } -} - -/// Wait for handshake procedure to be started by another node from the cluster. -pub fn accept_handshake(a: A, self_key_pair: Arc) -> Handshake -where - A: AsyncWrite + AsyncRead, -{ - let self_confirmation_plain = Random - .generate() - .map(|kp| *kp.secret().clone()) - .map_err(Into::into); - let handshake_input_data = self_confirmation_plain - .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); - - let (error, cp, kp, state) = match handshake_input_data { - Ok((cp, kp)) => ( - None, - cp, - Some(kp), - HandshakeState::ReceivePublicKey(read_message(a)), - ), - Err(err) => ( - Some((a, Err(err))), - Default::default(), - None, - HandshakeState::Finished, - ), - }; - - Handshake { - is_active: false, - error: error, - state: state, - self_key_pair: self_key_pair, - self_session_key_pair: kp, - self_confirmation_plain: cp, - trusted_nodes: None, - peer_node_id: None, - peer_session_public: None, - peer_confirmation_plain: None, - shared_key: None, - } -} - -/// Result of handshake procedure. -#[derive(Debug, PartialEq)] -pub struct HandshakeResult { - /// Node id. - pub node_id: NodeId, - /// Shared key. - pub shared_key: KeyPair, -} - -/// Future handshake procedure. -pub struct Handshake { - is_active: bool, - error: Option<(A, Result)>, - state: HandshakeState, - self_key_pair: Arc, - self_session_key_pair: Option, - self_confirmation_plain: H256, - trusted_nodes: Option>, - peer_node_id: Option, - peer_session_public: Option, - peer_confirmation_plain: Option, - shared_key: Option, -} - -/// Active handshake state. -enum HandshakeState { - SendPublicKey(WriteMessage), - ReceivePublicKey(ReadMessage), - SendPrivateKeySignature(WriteMessage), - ReceivePrivateKeySignature(ReadMessage), - Finished, -} - -impl Handshake -where - A: AsyncRead + AsyncWrite, -{ - #[cfg(test)] - pub fn set_self_confirmation_plain(&mut self, self_confirmation_plain: H256) { - self.self_confirmation_plain = self_confirmation_plain; - } - - #[cfg(test)] - pub fn set_self_session_key_pair(&mut self, self_session_key_pair: KeyPair) { - self.self_session_key_pair = Some(self_session_key_pair); - } - - pub fn make_public_key_message( - self_node_id: NodeId, - confirmation_plain: H256, - confirmation_signed_session: Signature, - ) -> Result { - Ok(Message::Cluster(ClusterMessage::NodePublicKey( - NodePublicKey { - node_id: self_node_id.into(), - confirmation_plain: confirmation_plain.into(), - confirmation_signed_session: confirmation_signed_session.into(), - }, - ))) - } - - fn make_private_key_signature_message( - self_key_pair: &dyn NodeKeyPair, - confirmation_plain: &H256, - ) -> Result { - Ok(Message::Cluster(ClusterMessage::NodePrivateKeySignature( - NodePrivateKeySignature { - confirmation_signed: self_key_pair.sign(confirmation_plain)?.into(), - }, - ))) - } - - fn compute_shared_key( - self_session_key_pair: &KeyPair, - peer_session_public: &Public, - ) -> Result { - agree(self_session_key_pair.secret(), peer_session_public) - .map_err(Into::into) - .and_then(|s| fix_shared_key(&s)) - } -} - -impl Future for Handshake -where - A: AsyncRead + AsyncWrite, -{ - type Item = (A, Result); - type Error = io::Error; - - fn poll(&mut self) -> Poll { - if let Some(error_result) = self.error.take() { - return Ok(error_result.into()); - } - - let (next, result) = match self.state { - HandshakeState::SendPublicKey(ref mut future) => { - let (stream, _) = try_ready!(future.poll()); - - if self.is_active { - ( - HandshakeState::ReceivePublicKey(read_message(stream)), - Async::NotReady, - ) - } else { - let shared_key = Self::compute_shared_key( - self.self_session_key_pair.as_ref().expect( - "self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"), - self.peer_session_public.as_ref().expect( - "we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_session_public is filled in ReceivePublicKey; qed"), - ); - - self.shared_key = match shared_key { - Ok(shared_key) => Some(shared_key), - Err(err) => return Ok((stream, Err(err)).into()), - }; - - let peer_confirmation_plain = self.peer_confirmation_plain.as_ref() - .expect("we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_confirmation_plain is filled in ReceivePublicKey; qed"); - let message = match Handshake::::make_private_key_signature_message( - &*self.self_key_pair, - peer_confirmation_plain, - ) { - Ok(message) => message, - Err(err) => return Ok((stream, Err(err)).into()), - }; - - ( - HandshakeState::SendPrivateKeySignature(write_encrypted_message( - stream, - self.shared_key - .as_ref() - .expect("filled couple of lines above; qed"), - message, - )), - Async::NotReady, - ) - } - } - HandshakeState::ReceivePublicKey(ref mut future) => { - let (stream, message) = try_ready!(future.poll()); - - let message = match message { - Ok(message) => match message { - Message::Cluster(ClusterMessage::NodePublicKey(message)) => message, - _ => return Ok((stream, Err(Error::InvalidMessage)).into()), - }, - Err(err) => return Ok((stream, Err(err.into())).into()), - }; - - if !self - .trusted_nodes - .as_ref() - .map(|tn| tn.contains(&*message.node_id)) - .unwrap_or(true) - { - return Ok((stream, Err(Error::InvalidNodeId)).into()); - } - - self.peer_node_id = Some(message.node_id.into()); - self.peer_session_public = Some( - match recover( - &message.confirmation_signed_session, - &message.confirmation_plain, - ) { - Ok(peer_session_public) => peer_session_public, - Err(err) => return Ok((stream, Err(err.into())).into()), - }, - ); - self.peer_confirmation_plain = Some(message.confirmation_plain.into()); - if self.is_active { - let shared_key = Self::compute_shared_key( - self.self_session_key_pair.as_ref().expect( - "self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"), - self.peer_session_public.as_ref().expect( - "we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_session_public is filled in ReceivePublicKey; qed"), - ); - - self.shared_key = match shared_key { - Ok(shared_key) => Some(shared_key), - Err(err) => return Ok((stream, Err(err)).into()), - }; - - let peer_confirmation_plain = self - .peer_confirmation_plain - .as_ref() - .expect("filled couple of lines above; qed"); - let message = match Handshake::::make_private_key_signature_message( - &*self.self_key_pair, - peer_confirmation_plain, - ) { - Ok(message) => message, - Err(err) => return Ok((stream, Err(err)).into()), - }; - - ( - HandshakeState::SendPrivateKeySignature(write_encrypted_message( - stream, - self.shared_key - .as_ref() - .expect("filled couple of lines above; qed"), - message, - )), - Async::NotReady, - ) - } else { - let self_session_key_pair = self.self_session_key_pair.as_ref() - .expect("self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"); - let confirmation_signed_session = match sign( - self_session_key_pair.secret(), - &self.self_confirmation_plain, - ) - .map_err(Into::into) - { - Ok(confirmation_signed_session) => confirmation_signed_session, - Err(err) => return Ok((stream, Err(err)).into()), - }; - - let message = match Handshake::::make_public_key_message( - self.self_key_pair.public().clone(), - self.self_confirmation_plain.clone(), - confirmation_signed_session, - ) { - Ok(message) => message, - Err(err) => return Ok((stream, Err(err)).into()), - }; - ( - HandshakeState::SendPublicKey(write_message(stream, message)), - Async::NotReady, - ) - } - } - HandshakeState::SendPrivateKeySignature(ref mut future) => { - let (stream, _) = try_ready!(future.poll()); - - (HandshakeState::ReceivePrivateKeySignature( - read_encrypted_message(stream, - self.shared_key.as_ref().expect("shared_key is filled in Send/ReceivePublicKey; SendPrivateKeySignature follows Send/ReceivePublicKey; qed").clone() - ) - ), Async::NotReady) - } - HandshakeState::ReceivePrivateKeySignature(ref mut future) => { - let (stream, message) = try_ready!(future.poll()); - - let message = match message { - Ok(message) => match message { - Message::Cluster(ClusterMessage::NodePrivateKeySignature(message)) => { - message - } - _ => return Ok((stream, Err(Error::InvalidMessage)).into()), - }, - Err(err) => return Ok((stream, Err(err.into())).into()), - }; - - let peer_public = self.peer_node_id.as_ref().expect("peer_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"); - if !verify_public( - peer_public, - &*message.confirmation_signed, - &self.self_confirmation_plain, - ) - .unwrap_or(false) - { - return Ok((stream, Err(Error::InvalidMessage)).into()); - } - - (HandshakeState::Finished, Async::Ready((stream, Ok(HandshakeResult { - node_id: self.peer_node_id.expect("peer_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"), - shared_key: self.shared_key.clone().expect("shared_key is filled in Send/ReceivePublicKey; ReceivePrivateKeySignature follows Send/ReceivePublicKey; qed"), - })))) - } - HandshakeState::Finished => panic!("poll Handshake after it's done"), - }; - - self.state = next; - match result { - // by polling again, we register new future - Async::NotReady => self.poll(), - result => Ok(result), - } - } -} - -#[cfg(test)] -mod tests { - use super::{accept_handshake, handshake_with_init_data, HandshakeResult}; - use ethereum_types::H256; - use ethkey::{sign, Generator, Random}; - use futures::Future; - use key_server_cluster::{ - io::message::tests::TestIo, - message::{ClusterMessage, Message, NodePrivateKeySignature, NodePublicKey}, - PlainNodeKeyPair, - }; - use std::{collections::BTreeSet, sync::Arc}; - - fn prepare_test_io() -> (H256, TestIo) { - let mut io = TestIo::new(); - - let self_confirmation_plain = *Random.generate().unwrap().secret().clone(); - let peer_confirmation_plain = *Random.generate().unwrap().secret().clone(); - - let self_confirmation_signed = - sign(io.peer_key_pair().secret(), &self_confirmation_plain).unwrap(); - let peer_confirmation_signed = sign( - io.peer_session_key_pair().secret(), - &peer_confirmation_plain, - ) - .unwrap(); - - let peer_public = io.peer_key_pair().public().clone(); - io.add_input_message(Message::Cluster(ClusterMessage::NodePublicKey( - NodePublicKey { - node_id: peer_public.into(), - confirmation_plain: peer_confirmation_plain.into(), - confirmation_signed_session: peer_confirmation_signed.into(), - }, - ))); - io.add_encrypted_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature( - NodePrivateKeySignature { - confirmation_signed: self_confirmation_signed.into(), - }, - ))); - - (self_confirmation_plain, io) - } - - #[test] - fn active_handshake_works() { - let (self_confirmation_plain, io) = prepare_test_io(); - let trusted_nodes: BTreeSet<_> = vec![io.peer_key_pair().public().clone()] - .into_iter() - .collect(); - let self_session_key_pair = io.self_session_key_pair().clone(); - let self_key_pair = Arc::new(PlainNodeKeyPair::new(io.self_key_pair().clone())); - let shared_key = io.shared_key_pair().clone(); - - let handshake = handshake_with_init_data( - io, - Ok((self_confirmation_plain, self_session_key_pair)), - self_key_pair, - trusted_nodes, - ); - let handshake_result = handshake.wait().unwrap(); - assert_eq!( - handshake_result.1, - Ok(HandshakeResult { - node_id: handshake_result.0.peer_key_pair().public().clone(), - shared_key: shared_key, - }) - ); - } - - #[test] - fn passive_handshake_works() { - let (self_confirmation_plain, io) = prepare_test_io(); - let self_key_pair = Arc::new(PlainNodeKeyPair::new(io.self_key_pair().clone())); - let self_session_key_pair = io.self_session_key_pair().clone(); - let shared_key = io.shared_key_pair().clone(); - - let mut handshake = accept_handshake(io, self_key_pair); - handshake.set_self_confirmation_plain(self_confirmation_plain); - handshake.set_self_session_key_pair(self_session_key_pair); - - let handshake_result = handshake.wait().unwrap(); - assert_eq!( - handshake_result.1, - Ok(HandshakeResult { - node_id: handshake_result.0.peer_key_pair().public().clone(), - shared_key: shared_key, - }) - ); - } -} diff --git a/secret-store/src/key_server_cluster/io/message.rs b/secret-store/src/key_server_cluster/io/message.rs deleted file mode 100644 index c82e3739c8..0000000000 --- a/secret-store/src/key_server_cluster/io/message.rs +++ /dev/null @@ -1,673 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use ethereum_types::{H256, U256}; -use ethkey::{crypto::ecies, math::curve_order, KeyPair, Secret}; -use key_server_cluster::{ - message::{ - ClusterMessage, DecryptionMessage, EcdsaSigningMessage, EncryptionMessage, - GenerationMessage, KeyVersionNegotiationMessage, Message, SchnorrSigningMessage, - ServersSetChangeMessage, ShareAddMessage, - }, - Error, -}; -use serde_json; -use std::{io::Cursor, ops::Deref, u16}; - -/// Size of serialized header. -pub const MESSAGE_HEADER_SIZE: usize = 18; -/// Current header version. -pub const CURRENT_HEADER_VERSION: u64 = 1; - -/// Message header. -#[derive(Debug, PartialEq)] -pub struct MessageHeader { - /// Message/Header version. - pub version: u64, - /// Message kind. - pub kind: u64, - /// Message payload size (without header). - pub size: u16, -} - -/// Serialized message. -#[derive(Debug, Clone, PartialEq)] -pub struct SerializedMessage(Vec); - -impl Deref for SerializedMessage { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - &self.0 - } -} - -impl Into> for SerializedMessage { - fn into(self) -> Vec { - self.0 - } -} - -/// Serialize message. -pub fn serialize_message(message: Message) -> Result { - let (message_kind, payload) = match message { - Message::Cluster(ClusterMessage::NodePublicKey(payload)) => { - (1, serde_json::to_vec(&payload)) - } - Message::Cluster(ClusterMessage::NodePrivateKeySignature(payload)) => { - (2, serde_json::to_vec(&payload)) - } - Message::Cluster(ClusterMessage::KeepAlive(payload)) => (3, serde_json::to_vec(&payload)), - Message::Cluster(ClusterMessage::KeepAliveResponse(payload)) => { - (4, serde_json::to_vec(&payload)) - } - - Message::Generation(GenerationMessage::InitializeSession(payload)) => { - (50, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::ConfirmInitialization(payload)) => { - (51, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::CompleteInitialization(payload)) => { - (52, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::KeysDissemination(payload)) => { - (53, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::PublicKeyShare(payload)) => { - (54, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::SessionError(payload)) => { - (55, serde_json::to_vec(&payload)) - } - Message::Generation(GenerationMessage::SessionCompleted(payload)) => { - (56, serde_json::to_vec(&payload)) - } - - Message::Encryption(EncryptionMessage::InitializeEncryptionSession(payload)) => { - (100, serde_json::to_vec(&payload)) - } - Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization(payload)) => { - (101, serde_json::to_vec(&payload)) - } - Message::Encryption(EncryptionMessage::EncryptionSessionError(payload)) => { - (102, serde_json::to_vec(&payload)) - } - - Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(payload)) => { - (150, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::RequestPartialDecryption(payload)) => { - (151, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::PartialDecryption(payload)) => { - (152, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::DecryptionSessionError(payload)) => { - (153, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::DecryptionSessionCompleted(payload)) => { - (154, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::DecryptionSessionDelegation(payload)) => { - (155, serde_json::to_vec(&payload)) - } - Message::Decryption(DecryptionMessage::DecryptionSessionDelegationCompleted(payload)) => { - (156, serde_json::to_vec(&payload)) - } - - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage(payload)) => { - (200, serde_json::to_vec(&payload)) - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningGenerationMessage( - payload, - )) => (201, serde_json::to_vec(&payload)), - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrRequestPartialSignature(payload)) => { - (202, serde_json::to_vec(&payload)) - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrPartialSignature(payload)) => { - (203, serde_json::to_vec(&payload)) - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionError(payload)) => { - (204, serde_json::to_vec(&payload)) - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionCompleted(payload)) => { - (205, serde_json::to_vec(&payload)) - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionDelegation( - payload, - )) => (206, serde_json::to_vec(&payload)), - Message::SchnorrSigning( - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(payload), - ) => (207, serde_json::to_vec(&payload)), - - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeConsensusMessage( - payload, - )) => (250, serde_json::to_vec(&payload)), - Message::ServersSetChange(ServersSetChangeMessage::UnknownSessionsRequest(payload)) => { - (251, serde_json::to_vec(&payload)) - } - Message::ServersSetChange(ServersSetChangeMessage::UnknownSessions(payload)) => { - (252, serde_json::to_vec(&payload)) - } - Message::ServersSetChange(ServersSetChangeMessage::ShareChangeKeyVersionNegotiation( - payload, - )) => (253, serde_json::to_vec(&payload)), - Message::ServersSetChange(ServersSetChangeMessage::InitializeShareChangeSession( - payload, - )) => (254, serde_json::to_vec(&payload)), - Message::ServersSetChange( - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization(payload), - ) => (255, serde_json::to_vec(&payload)), - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegate(payload)) => { - (256, serde_json::to_vec(&payload)) - } - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegateResponse( - payload, - )) => (257, serde_json::to_vec(&payload)), - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeShareAddMessage( - payload, - )) => (258, serde_json::to_vec(&payload)), - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeError(payload)) => { - (261, serde_json::to_vec(&payload)) - } - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeCompleted(payload)) => { - (262, serde_json::to_vec(&payload)) - } - - Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage(payload)) => { - (300, serde_json::to_vec(&payload)) - } - Message::ShareAdd(ShareAddMessage::KeyShareCommon(payload)) => { - (301, serde_json::to_vec(&payload)) - } - Message::ShareAdd(ShareAddMessage::NewKeysDissemination(payload)) => { - (302, serde_json::to_vec(&payload)) - } - Message::ShareAdd(ShareAddMessage::ShareAddError(payload)) => { - (303, serde_json::to_vec(&payload)) - } - - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::RequestKeyVersions( - payload, - )) => (450, serde_json::to_vec(&payload)), - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersions(payload)) => { - (451, serde_json::to_vec(&payload)) - } - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersionsError(payload)) => { - (452, serde_json::to_vec(&payload)) - } - - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage(payload)) => { - (500, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage( - payload, - )) => (501, serde_json::to_vec(&payload)), - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage( - payload, - )) => (502, serde_json::to_vec(&payload)), - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage( - payload, - )) => (503, serde_json::to_vec(&payload)), - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare( - payload, - )) => (504, serde_json::to_vec(&payload)), - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaRequestPartialSignature(payload)) => { - (505, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaPartialSignature(payload)) => { - (506, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionError(payload)) => { - (507, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionCompleted(payload)) => { - (508, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegation(payload)) => { - (509, serde_json::to_vec(&payload)) - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted( - payload, - )) => (510, serde_json::to_vec(&payload)), - }; - - let payload = payload.map_err(|err| Error::Serde(err.to_string()))?; - build_serialized_message( - MessageHeader { - kind: message_kind, - version: CURRENT_HEADER_VERSION, - size: 0, - }, - payload, - ) -} - -/// Deserialize message. -pub fn deserialize_message(header: &MessageHeader, payload: Vec) -> Result { - Ok(match header.kind { - 1 => Message::Cluster(ClusterMessage::NodePublicKey( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 2 => Message::Cluster(ClusterMessage::NodePrivateKeySignature( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 3 => Message::Cluster(ClusterMessage::KeepAlive( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 4 => Message::Cluster(ClusterMessage::KeepAliveResponse( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 50 => Message::Generation(GenerationMessage::InitializeSession( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 51 => Message::Generation(GenerationMessage::ConfirmInitialization( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 52 => Message::Generation(GenerationMessage::CompleteInitialization( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 53 => Message::Generation(GenerationMessage::KeysDissemination( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 54 => Message::Generation(GenerationMessage::PublicKeyShare( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 55 => Message::Generation(GenerationMessage::SessionError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 56 => Message::Generation(GenerationMessage::SessionCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 100 => Message::Encryption(EncryptionMessage::InitializeEncryptionSession( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 101 => Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 102 => Message::Encryption(EncryptionMessage::EncryptionSessionError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 150 => Message::Decryption(DecryptionMessage::DecryptionConsensusMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 151 => Message::Decryption(DecryptionMessage::RequestPartialDecryption( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 152 => Message::Decryption(DecryptionMessage::PartialDecryption( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 153 => Message::Decryption(DecryptionMessage::DecryptionSessionError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 154 => Message::Decryption(DecryptionMessage::DecryptionSessionCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 155 => Message::Decryption(DecryptionMessage::DecryptionSessionDelegation( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 156 => Message::Decryption(DecryptionMessage::DecryptionSessionDelegationCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 200 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 201 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningGenerationMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 202 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrRequestPartialSignature( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 203 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrPartialSignature( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 204 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 205 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 206 => Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionDelegation( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 207 => Message::SchnorrSigning( - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - ), - ), - - 250 => { - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeConsensusMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )) - } - 251 => Message::ServersSetChange(ServersSetChangeMessage::UnknownSessionsRequest( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 252 => Message::ServersSetChange(ServersSetChangeMessage::UnknownSessions( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 253 => { - Message::ServersSetChange(ServersSetChangeMessage::ShareChangeKeyVersionNegotiation( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )) - } - 254 => Message::ServersSetChange(ServersSetChangeMessage::InitializeShareChangeSession( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 255 => Message::ServersSetChange( - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - ), - ), - 256 => Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegate( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 257 => { - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeDelegateResponse( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )) - } - 258 => Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeShareAddMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 261 => Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 262 => Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 300 => Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 301 => Message::ShareAdd(ShareAddMessage::KeyShareCommon( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 302 => Message::ShareAdd(ShareAddMessage::NewKeysDissemination( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 303 => Message::ShareAdd(ShareAddMessage::ShareAddError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 450 => Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::RequestKeyVersions( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 451 => Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersions( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 452 => Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersionsError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - 500 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 501 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 502 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 503 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 504 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 505 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaRequestPartialSignature( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 506 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaPartialSignature( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 507 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionError( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 508 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 509 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegation( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - 510 => Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted( - serde_json::from_slice(&payload).map_err(|err| Error::Serde(err.to_string()))?, - )), - - _ => { - return Err(Error::Serde(format!( - "unknown message type {}", - header.kind - ))) - } - }) -} - -/// Encrypt serialized message. -pub fn encrypt_message( - key: &KeyPair, - message: SerializedMessage, -) -> Result { - let mut header: Vec<_> = message.into(); - let payload = header.split_off(MESSAGE_HEADER_SIZE); - let encrypted_payload = ecies::encrypt(key.public(), &[], &payload)?; - - let header = deserialize_header(&header)?; - build_serialized_message(header, encrypted_payload) -} - -/// Decrypt serialized message. -pub fn decrypt_message(key: &KeyPair, payload: Vec) -> Result, Error> { - Ok(ecies::decrypt(key.secret(), &[], &payload)?) -} - -/// Fix shared encryption key. -pub fn fix_shared_key(shared_secret: &Secret) -> Result { - // secret key created in agree function is invalid, as it is not calculated mod EC.field.n - // => let's do it manually - let shared_secret: H256 = (**shared_secret).into(); - let shared_secret: U256 = shared_secret.into(); - let shared_secret: H256 = (shared_secret % curve_order()).into(); - let shared_key_pair = KeyPair::from_secret_slice(&*shared_secret)?; - Ok(shared_key_pair) -} - -/// Serialize message header. -fn serialize_header(header: &MessageHeader) -> Result, Error> { - let mut buffer = Vec::with_capacity(MESSAGE_HEADER_SIZE); - buffer.write_u64::(header.version)?; - buffer.write_u64::(header.kind)?; - buffer.write_u16::(header.size)?; - Ok(buffer) -} - -/// Deserialize message header. -pub fn deserialize_header(data: &[u8]) -> Result { - let mut reader = Cursor::new(data); - let version = reader.read_u64::()?; - if version != CURRENT_HEADER_VERSION { - return Err(Error::InvalidMessageVersion); - } - - Ok(MessageHeader { - version: version, - kind: reader.read_u64::()?, - size: reader.read_u16::()?, - }) -} - -/// Build serialized message from header && payload -fn build_serialized_message( - mut header: MessageHeader, - payload: Vec, -) -> Result { - let payload_len = payload.len(); - if payload_len > u16::MAX as usize { - return Err(Error::InvalidMessage); - } - header.size = payload.len() as u16; - - let mut message = serialize_header(&header)?; - message.extend(payload); - Ok(SerializedMessage(message)) -} - -#[cfg(test)] -pub mod tests { - use super::{ - deserialize_header, encrypt_message, fix_shared_key, serialize_header, serialize_message, - MessageHeader, CURRENT_HEADER_VERSION, MESSAGE_HEADER_SIZE, - }; - use ethkey::{crypto::ecdh::agree, Generator, KeyPair, Random}; - use futures::Poll; - use key_server_cluster::{message::Message, Error}; - use std::io; - use tokio_io::{AsyncRead, AsyncWrite}; - - pub struct TestIo { - self_key_pair: KeyPair, - self_session_key_pair: KeyPair, - peer_key_pair: KeyPair, - peer_session_key_pair: KeyPair, - shared_key_pair: KeyPair, - input_buffer: io::Cursor>, - } - - impl TestIo { - pub fn new() -> Self { - let self_session_key_pair = Random.generate().unwrap(); - let peer_session_key_pair = Random.generate().unwrap(); - let self_key_pair = Random.generate().unwrap(); - let peer_key_pair = Random.generate().unwrap(); - let shared_key_pair = fix_shared_key( - &agree( - self_session_key_pair.secret(), - peer_session_key_pair.public(), - ) - .unwrap(), - ) - .unwrap(); - TestIo { - self_key_pair: self_key_pair, - self_session_key_pair: self_session_key_pair, - peer_key_pair: peer_key_pair, - peer_session_key_pair: peer_session_key_pair, - shared_key_pair: shared_key_pair, - input_buffer: io::Cursor::new(Vec::new()), - } - } - - pub fn self_key_pair(&self) -> &KeyPair { - &self.self_key_pair - } - - pub fn self_session_key_pair(&self) -> &KeyPair { - &self.self_session_key_pair - } - - pub fn peer_key_pair(&self) -> &KeyPair { - &self.peer_key_pair - } - - pub fn peer_session_key_pair(&self) -> &KeyPair { - &self.peer_session_key_pair - } - - pub fn shared_key_pair(&self) -> &KeyPair { - &self.shared_key_pair - } - - pub fn add_input_message(&mut self, message: Message) { - let serialized_message = serialize_message(message).unwrap(); - let serialized_message: Vec<_> = serialized_message.into(); - let input_buffer = self.input_buffer.get_mut(); - for b in serialized_message { - input_buffer.push(b); - } - } - - pub fn add_encrypted_input_message(&mut self, message: Message) { - let serialized_message = - encrypt_message(&self.shared_key_pair, serialize_message(message).unwrap()) - .unwrap(); - let serialized_message: Vec<_> = serialized_message.into(); - let input_buffer = self.input_buffer.get_mut(); - for b in serialized_message { - input_buffer.push(b); - } - } - } - - impl AsyncRead for TestIo {} - - impl AsyncWrite for TestIo { - fn shutdown(&mut self) -> Poll<(), io::Error> { - Ok(().into()) - } - } - - impl io::Read for TestIo { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - io::Read::read(&mut self.input_buffer, buf) - } - } - - impl io::Write for TestIo { - fn write(&mut self, buf: &[u8]) -> io::Result { - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - - #[test] - fn header_serialization_works() { - let header = MessageHeader { - kind: 1, - version: CURRENT_HEADER_VERSION, - size: 3, - }; - - let serialized_header = serialize_header(&header).unwrap(); - assert_eq!(serialized_header.len(), MESSAGE_HEADER_SIZE); - - let deserialized_header = deserialize_header(&serialized_header).unwrap(); - assert_eq!(deserialized_header, header); - } - - #[test] - fn deserializing_header_of_wrong_version_fails() { - let header = MessageHeader { - kind: 1, - version: CURRENT_HEADER_VERSION + 1, - size: 3, - }; - - assert_eq!( - deserialize_header(&serialize_header(&header).unwrap()).unwrap_err(), - Error::InvalidMessageVersion - ); - } -} diff --git a/secret-store/src/key_server_cluster/io/mod.rs b/secret-store/src/key_server_cluster/io/mod.rs deleted file mode 100644 index 54b0d963d5..0000000000 --- a/secret-store/src/key_server_cluster/io/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -mod deadline; -mod handshake; -mod message; -mod read_header; -mod read_message; -mod read_payload; -mod shared_tcp_stream; -mod write_message; - -pub use self::{ - deadline::{deadline, Deadline, DeadlineStatus}, - handshake::{accept_handshake, handshake, Handshake, HandshakeResult}, - message::{ - deserialize_message, encrypt_message, fix_shared_key, serialize_message, MessageHeader, - SerializedMessage, - }, - read_header::{read_header, ReadHeader}, - read_message::{read_encrypted_message, read_message, ReadMessage}, - read_payload::{read_encrypted_payload, read_payload, ReadPayload}, - shared_tcp_stream::SharedTcpStream, - write_message::{write_encrypted_message, write_message, WriteMessage}, -}; diff --git a/secret-store/src/key_server_cluster/io/read_header.rs b/secret-store/src/key_server_cluster/io/read_header.rs deleted file mode 100644 index c33b10abe9..0000000000 --- a/secret-store/src/key_server_cluster/io/read_header.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::{Async, Future, Poll}; -use key_server_cluster::{ - io::message::{deserialize_header, MessageHeader, MESSAGE_HEADER_SIZE}, - Error, -}; -use std::io; -use tokio_io::{ - io::{read_exact, ReadExact}, - AsyncRead, -}; - -/// Create future for read single message header from the stream. -pub fn read_header(a: A) -> ReadHeader -where - A: AsyncRead, -{ - ReadHeader { - reader: read_exact(a, [0; MESSAGE_HEADER_SIZE]), - } -} - -/// Future for read single message header from the stream. -pub struct ReadHeader { - reader: ReadExact, -} - -impl Future for ReadHeader -where - A: AsyncRead, -{ - type Item = (A, Result); - type Error = io::Error; - - fn poll(&mut self) -> Poll { - let (read, data) = try_ready!(self.reader.poll()); - let header = deserialize_header(&data); - Ok(Async::Ready((read, header))) - } -} diff --git a/secret-store/src/key_server_cluster/io/read_message.rs b/secret-store/src/key_server_cluster/io/read_message.rs deleted file mode 100644 index 12726ea384..0000000000 --- a/secret-store/src/key_server_cluster/io/read_message.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::KeyPair; -use futures::{Async, Future, Poll}; -use key_server_cluster::{ - io::{read_encrypted_payload, read_header, read_payload, ReadHeader, ReadPayload}, - message::Message, - Error, -}; -use std::io; -use tokio_io::AsyncRead; - -/// Create future for read single message from the stream. -pub fn read_message(a: A) -> ReadMessage -where - A: AsyncRead, -{ - ReadMessage { - key: None, - state: ReadMessageState::ReadHeader(read_header(a)), - } -} - -/// Create future for read single encrypted message from the stream. -pub fn read_encrypted_message(a: A, key: KeyPair) -> ReadMessage -where - A: AsyncRead, -{ - ReadMessage { - key: Some(key), - state: ReadMessageState::ReadHeader(read_header(a)), - } -} - -enum ReadMessageState { - ReadHeader(ReadHeader), - ReadPayload(ReadPayload), - Finished, -} - -/// Future for read single message from the stream. -pub struct ReadMessage { - key: Option, - state: ReadMessageState, -} - -impl Future for ReadMessage -where - A: AsyncRead, -{ - type Item = (A, Result); - type Error = io::Error; - - fn poll(&mut self) -> Poll { - let (next, result) = match self.state { - ReadMessageState::ReadHeader(ref mut future) => { - let (read, header) = try_ready!(future.poll()); - let header = match header { - Ok(header) => header, - Err(err) => return Ok((read, Err(err)).into()), - }; - - let future = match self.key.take() { - Some(key) => read_encrypted_payload(read, header, key), - None => read_payload(read, header), - }; - let next = ReadMessageState::ReadPayload(future); - (next, Async::NotReady) - } - ReadMessageState::ReadPayload(ref mut future) => { - let (read, payload) = try_ready!(future.poll()); - (ReadMessageState::Finished, Async::Ready((read, payload))) - } - ReadMessageState::Finished => panic!("poll ReadMessage after it's done"), - }; - - self.state = next; - match result { - // by polling again, we register new future - Async::NotReady => self.poll(), - result => Ok(result), - } - } -} diff --git a/secret-store/src/key_server_cluster/io/read_payload.rs b/secret-store/src/key_server_cluster/io/read_payload.rs deleted file mode 100644 index 749e9d40e5..0000000000 --- a/secret-store/src/key_server_cluster/io/read_payload.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::KeyPair; -use futures::{Future, Poll}; -use key_server_cluster::{ - io::message::{decrypt_message, deserialize_message, MessageHeader}, - message::Message, - Error, -}; -use std::io; -use tokio_io::{ - io::{read_exact, ReadExact}, - AsyncRead, -}; - -/// Create future for read single message payload from the stream. -pub fn read_payload(a: A, header: MessageHeader) -> ReadPayload -where - A: AsyncRead, -{ - ReadPayload { - reader: read_exact(a, vec![0; header.size as usize]), - header: header, - key: None, - } -} - -/// Create future for read single encrypted message payload from the stream. -pub fn read_encrypted_payload(a: A, header: MessageHeader, key: KeyPair) -> ReadPayload -where - A: AsyncRead, -{ - ReadPayload { - reader: read_exact(a, vec![0; header.size as usize]), - header: header, - key: Some(key), - } -} - -/// Future for read single message payload from the stream. -pub struct ReadPayload { - reader: ReadExact>, - header: MessageHeader, - key: Option, -} - -impl Future for ReadPayload -where - A: AsyncRead, -{ - type Item = (A, Result); - type Error = io::Error; - - fn poll(&mut self) -> Poll { - let (read, data) = try_ready!(self.reader.poll()); - let payload = if let Some(key) = self.key.take() { - decrypt_message(&key, data).and_then(|data| deserialize_message(&self.header, data)) - } else { - deserialize_message(&self.header, data) - }; - Ok((read, payload).into()) - } -} diff --git a/secret-store/src/key_server_cluster/io/shared_tcp_stream.rs b/secret-store/src/key_server_cluster/io/shared_tcp_stream.rs deleted file mode 100644 index 5136088add..0000000000 --- a/secret-store/src/key_server_cluster/io/shared_tcp_stream.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::Poll; -use std::{ - io::{Error, Read, Write}, - net::Shutdown, - sync::Arc, -}; -use tokio::net::TcpStream; -use tokio_io::{AsyncRead, AsyncWrite}; - -/// Read+Write implementation for Arc. -pub struct SharedTcpStream { - io: Arc, -} - -impl SharedTcpStream { - pub fn new(a: Arc) -> Self { - SharedTcpStream { io: a } - } -} - -impl From for SharedTcpStream { - fn from(a: TcpStream) -> Self { - SharedTcpStream::new(Arc::new(a)) - } -} - -impl AsyncRead for SharedTcpStream {} - -impl AsyncWrite for SharedTcpStream { - fn shutdown(&mut self) -> Poll<(), Error> { - self.io.shutdown(Shutdown::Both).map(Into::into) - } -} - -impl Read for SharedTcpStream { - fn read(&mut self, buf: &mut [u8]) -> Result { - Read::read(&mut (&*self.io as &TcpStream), buf) - } -} - -impl Write for SharedTcpStream { - fn write(&mut self, buf: &[u8]) -> Result { - Write::write(&mut (&*self.io as &TcpStream), buf) - } - - fn flush(&mut self) -> Result<(), Error> { - Write::flush(&mut (&*self.io as &TcpStream)) - } -} - -impl Clone for SharedTcpStream { - fn clone(&self) -> Self { - SharedTcpStream::new(self.io.clone()) - } -} diff --git a/secret-store/src/key_server_cluster/io/write_message.rs b/secret-store/src/key_server_cluster/io/write_message.rs deleted file mode 100644 index 79de02b9e0..0000000000 --- a/secret-store/src/key_server_cluster/io/write_message.rs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::KeyPair; -use futures::{Future, Poll}; -use key_server_cluster::{ - io::{encrypt_message, serialize_message}, - message::Message, -}; -use std::io; -use tokio_io::{ - io::{write_all, WriteAll}, - AsyncWrite, -}; - -/// Write plain message to the channel. -pub fn write_message(a: A, message: Message) -> WriteMessage -where - A: AsyncWrite, -{ - let (error, future) = match serialize_message(message) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) - { - Ok(message) => (None, write_all(a, message.into())), - Err(error) => (Some(error), write_all(a, Vec::new())), - }; - WriteMessage { - error: error, - future: future, - } -} - -/// Write encrypted message to the channel. -pub fn write_encrypted_message(a: A, key: &KeyPair, message: Message) -> WriteMessage -where - A: AsyncWrite, -{ - let (error, future) = match serialize_message(message) - .and_then(|message| encrypt_message(key, message)) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string())) - { - Ok(message) => (None, write_all(a, message.into())), - Err(error) => (Some(error), write_all(a, Vec::new())), - }; - - WriteMessage { - error: error, - future: future, - } -} - -/// Future message write. -pub struct WriteMessage { - error: Option, - future: WriteAll>, -} - -impl Future for WriteMessage -where - A: AsyncWrite, -{ - type Item = (A, Vec); - type Error = io::Error; - - fn poll(&mut self) -> Poll { - if let Some(err) = self.error.take() { - return Err(err); - } - - self.future.poll() - } -} diff --git a/secret-store/src/key_server_cluster/jobs/consensus_session.rs b/secret-store/src/key_server_cluster/jobs/consensus_session.rs deleted file mode 100644 index 596b921435..0000000000 --- a/secret-store/src/key_server_cluster/jobs/consensus_session.rs +++ /dev/null @@ -1,1395 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{ - jobs::job_session::{ - JobExecutor, JobPartialRequestAction, JobSession, JobSessionState, JobTransport, - }, - message::ConsensusMessage, - Error, NodeId, Requester, SessionMeta, -}; -use std::collections::BTreeSet; - -/// Consensus session state. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ConsensusSessionState { - /// Every node starts in this state. - WaitingForInitialization, - /// Consensus group is establishing. - EstablishingConsensus, - /// Consensus group is established. - /// Master node can start jobs dissemination. - /// Slave node waits for partial job requests. - ConsensusEstablished, - /// Master node waits for partial jobs responses. - WaitingForPartialResults, - /// Consensus session is completed successfully. - /// Master node can call result() to get computation result. - Finished, - /// Consensus session has failed with error. - Failed, -} - -/// Consensus session consists of following states: -/// 1) consensus group is established -/// 2) master node sends partial job requests to every member of consensus group -/// 3) slave nodes are computing partial responses -/// 4) master node computes result from partial responses -pub struct ConsensusSession< - ConsensusExecutor: JobExecutor, - ConsensusTransport: JobTransport< - PartialJobRequest = ConsensusExecutor::PartialJobRequest, - PartialJobResponse = ConsensusExecutor::PartialJobResponse, - >, - ComputationExecutor: JobExecutor, - ComputationTransport: JobTransport< - PartialJobRequest = ComputationExecutor::PartialJobRequest, - PartialJobResponse = ComputationExecutor::PartialJobResponse, - >, -> { - /// Current session state. - state: ConsensusSessionState, - /// Session metadata. - meta: SessionMeta, - /// Consensus establish job. - consensus_job: JobSession, - /// Consensus group. - consensus_group: BTreeSet, - /// Computation job. - computation_job: Option>, -} - -/// Consensus session creation parameters. -pub struct ConsensusSessionParams< - ConsensusExecutor: JobExecutor, - ConsensusTransport: JobTransport< - PartialJobRequest = ConsensusExecutor::PartialJobRequest, - PartialJobResponse = ConsensusExecutor::PartialJobResponse, - >, -> { - /// Session metadata. - pub meta: SessionMeta, - /// ACL storage for access check. - pub consensus_executor: ConsensusExecutor, - /// Transport for consensus establish job. - pub consensus_transport: ConsensusTransport, -} - -impl - ConsensusSession< - ConsensusExecutor, - ConsensusTransport, - ComputationExecutor, - ComputationTransport, - > -where - ConsensusExecutor: JobExecutor>, - ConsensusTransport: JobTransport< - PartialJobRequest = ConsensusExecutor::PartialJobRequest, - PartialJobResponse = ConsensusExecutor::PartialJobResponse, - >, - ComputationExecutor: JobExecutor, - ComputationTransport: JobTransport< - PartialJobRequest = ComputationExecutor::PartialJobRequest, - PartialJobResponse = ComputationExecutor::PartialJobResponse, - >, -{ - /// Create new consensus session. - pub fn new( - params: ConsensusSessionParams, - ) -> Result { - let consensus_job = JobSession::new( - params.meta.clone(), - params.consensus_executor, - params.consensus_transport, - ); - debug_assert!(consensus_job.state() == JobSessionState::Inactive); - - Ok(ConsensusSession { - state: ConsensusSessionState::WaitingForInitialization, - meta: params.meta, - consensus_job: consensus_job, - consensus_group: BTreeSet::new(), - computation_job: None, - }) - } - - /// Get consensus job reference. - pub fn consensus_job(&self) -> &JobSession { - &self.consensus_job - } - - /// Get mutable consensus job reference. - pub fn consensus_job_mut(&mut self) -> &mut JobSession { - &mut self.consensus_job - } - - /// Get all nodes, which has not rejected consensus request. - pub fn consensus_non_rejected_nodes(&self) -> BTreeSet { - self.consensus_job - .responses() - .iter() - .filter(|r| *r.1) - .map(|r| r.0) - .chain(self.consensus_job.requests()) - .filter(|n| **n != self.meta.self_node_id) - .cloned() - .collect() - } - - /// Get computation job reference. - pub fn computation_job(&self) -> &JobSession { - self.computation_job - .as_ref() - .expect("computation_job must only be called on master nodes") - } - - /// Get consensus session state. - pub fn state(&self) -> ConsensusSessionState { - self.state - } - - /// Get computation result. - pub fn result(&self) -> Result { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - if self.state != ConsensusSessionState::Finished { - return Err(Error::InvalidStateForRequest); - } - - self.computation_job.as_ref() - .expect("we are on master node in finished state; computation_job is set on master node during initialization; qed") - .result() - } - - /// Initialize session on master node. - pub fn initialize(&mut self, nodes: BTreeSet) -> Result<(), Error> { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - let initialization_result = self.consensus_job.initialize(nodes, None, false); - self.state = ConsensusSessionState::EstablishingConsensus; - self.process_result(initialization_result.map(|_| ())) - } - - /// Process consensus request message. - pub fn on_consensus_partial_request( - &mut self, - sender: &NodeId, - request: ConsensusExecutor::PartialJobRequest, - ) -> Result<(), Error> { - let consensus_result = self.consensus_job.on_partial_request(sender, request); - self.process_result(consensus_result.map(|_| ())) - } - - /// Process consensus message response. - pub fn on_consensus_partial_response( - &mut self, - sender: &NodeId, - response: bool, - ) -> Result<(), Error> { - let consensus_result = self.consensus_job.on_partial_response(sender, response); - self.process_result(consensus_result) - } - - /// Select nodes for processing partial requests. - pub fn select_consensus_group(&mut self) -> Result<&BTreeSet, Error> { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - if self.state != ConsensusSessionState::ConsensusEstablished { - return Err(Error::InvalidStateForRequest); - } - - if self.consensus_group.is_empty() { - let consensus_group = self.consensus_job.result()?; - let is_self_in_consensus = consensus_group.contains(&self.meta.self_node_id); - self.consensus_group = consensus_group - .into_iter() - .take(self.meta.threshold + 1) - .collect(); - - if is_self_in_consensus { - self.consensus_group.remove(&self.meta.master_node_id); - self.consensus_group - .insert(self.meta.master_node_id.clone()); - } - } - - Ok(&self.consensus_group) - } - - /// Disseminate jobs from master node. - pub fn disseminate_jobs( - &mut self, - executor: ComputationExecutor, - transport: ComputationTransport, - broadcast_self_response: bool, - ) -> Result, Error> { - let consensus_group = self.select_consensus_group()?.clone(); - self.consensus_group.clear(); - - let mut computation_job = JobSession::new(self.meta.clone(), executor, transport); - let computation_result = - computation_job.initialize(consensus_group, None, broadcast_self_response); - self.computation_job = Some(computation_job); - self.state = ConsensusSessionState::WaitingForPartialResults; - match computation_result { - Ok(computation_result) => self.process_result(Ok(())).map(|_| computation_result), - Err(error) => Err(self.process_result(Err(error)).unwrap_err()), - } - } - - /// Process job request on slave node. - pub fn on_job_request( - &mut self, - node: &NodeId, - request: ComputationExecutor::PartialJobRequest, - executor: ComputationExecutor, - transport: ComputationTransport, - ) -> Result, Error> { - if &self.meta.master_node_id != node { - return Err(Error::InvalidMessage); - } - if self.state != ConsensusSessionState::ConsensusEstablished { - return Err(Error::InvalidStateForRequest); - } - - JobSession::new(self.meta.clone(), executor, transport).on_partial_request(node, request) - } - - /// Process job response on slave node. - pub fn on_job_response( - &mut self, - node: &NodeId, - response: ComputationExecutor::PartialJobResponse, - ) -> Result<(), Error> { - if self.state != ConsensusSessionState::WaitingForPartialResults { - return Err(Error::InvalidStateForRequest); - } - - let computation_result = self - .computation_job - .as_mut() - .expect("WaitingForPartialResults is only set when computation_job is created; qed") - .on_partial_response(node, response); - - self.process_result(computation_result) - } - - /// When session is completed on slave node. - pub fn on_session_completed(&mut self, node: &NodeId) -> Result<(), Error> { - if node != &self.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if self.state != ConsensusSessionState::ConsensusEstablished { - return Err(Error::InvalidStateForRequest); - } - - self.state = ConsensusSessionState::Finished; - - Ok(()) - } - - /// When error is received from node. - pub fn on_node_error(&mut self, node: &NodeId, error: Error) -> Result { - let is_self_master = self.meta.master_node_id == self.meta.self_node_id; - let is_node_master = self.meta.master_node_id == *node; - let (is_restart_needed, timeout_result) = match self.state { - ConsensusSessionState::WaitingForInitialization if is_self_master => { - // it is strange to receive error before session is initialized && slave doesn't know access_key - // => unreachable - self.state = ConsensusSessionState::Failed; - (false, Err(Error::ConsensusUnreachable)) - } - ConsensusSessionState::WaitingForInitialization if is_node_master => { - // error from master node before establishing consensus - // => unreachable - self.state = ConsensusSessionState::Failed; - ( - false, - Err(if !error.is_non_fatal() { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - }), - ) - } - ConsensusSessionState::EstablishingConsensus => { - debug_assert!(is_self_master); - - // consensus still can be established - // => try to live without this node - (false, self.consensus_job.on_node_error(node, error)) - } - ConsensusSessionState::ConsensusEstablished => { - // we could try to continue without this node, if enough nodes left - (false, self.consensus_job.on_node_error(node, error)) - } - ConsensusSessionState::WaitingForPartialResults => { - // check if *current* computation job can continue without this node - let is_computation_node = self.computation_job.as_mut() - .expect("WaitingForPartialResults state is only set when computation_job is created; qed") - .on_node_error(node, error.clone()) - .is_err(); - if !is_computation_node { - // it is not used by current computation job - // => no restart required - (false, Ok(())) - } else { - // it is used by current computation job - // => restart is required if there are still enough nodes - self.consensus_group.clear(); - self.state = ConsensusSessionState::EstablishingConsensus; - - let consensus_result = self.consensus_job.on_node_error(node, error); - let is_consensus_established = - self.consensus_job.state() == JobSessionState::Finished; - (is_consensus_established, consensus_result) - } - } - // in all other cases - just ignore error - ConsensusSessionState::WaitingForInitialization - | ConsensusSessionState::Failed - | ConsensusSessionState::Finished => (false, Ok(())), - }; - self.process_result(timeout_result)?; - Ok(is_restart_needed) - } - - /// When session is timeouted. - pub fn on_session_timeout(&mut self) -> Result { - match self.state { - // if we are waiting for results from slaves, there is a chance to send request to other nodes subset => fall through - ConsensusSessionState::WaitingForPartialResults => (), - // in some states this error is fatal - ConsensusSessionState::WaitingForInitialization - | ConsensusSessionState::EstablishingConsensus - | ConsensusSessionState::ConsensusEstablished => { - let _ = self.consensus_job.on_session_timeout(); - - self.consensus_group.clear(); - self.state = ConsensusSessionState::EstablishingConsensus; - return self - .process_result(Err(Error::ConsensusTemporaryUnreachable)) - .map(|_| unreachable!()); - } - // in all other cases - just ignore error - ConsensusSessionState::Finished | ConsensusSessionState::Failed => return Ok(false), - }; - - let timeouted_nodes = self - .computation_job - .as_ref() - .expect( - "WaitingForPartialResults state is only set when computation_job is created; qed", - ) - .requests() - .clone(); - assert!(!timeouted_nodes.is_empty()); // timeout should not ever happen if no requests are active && we are waiting for responses - - self.consensus_group.clear(); - for timeouted_node in timeouted_nodes { - let timeout_result = self - .consensus_job - .on_node_error(&timeouted_node, Error::NodeDisconnected); - self.state = ConsensusSessionState::EstablishingConsensus; - self.process_result(timeout_result)?; - } - - Ok(self.state == ConsensusSessionState::ConsensusEstablished) - } - - /// Process result of job. - fn process_result(&mut self, result: Result<(), Error>) -> Result<(), Error> { - match self.state { - ConsensusSessionState::WaitingForInitialization | ConsensusSessionState::EstablishingConsensus | ConsensusSessionState::ConsensusEstablished => match self.consensus_job.state() { - JobSessionState::Finished => self.state = ConsensusSessionState::ConsensusEstablished, - JobSessionState::Failed => self.state = ConsensusSessionState::Failed, - _ => (), - }, - ConsensusSessionState::WaitingForPartialResults => match self.computation_job.as_ref() - .expect("WaitingForPartialResults state is only set when computation_job is created; qed") - .state() { - JobSessionState::Finished => self.state = ConsensusSessionState::Finished, - JobSessionState::Failed => self.state = ConsensusSessionState::Failed, - _ => (), - }, - _ => (), - } - - result - } -} - -impl - ConsensusSession< - ConsensusExecutor, - ConsensusTransport, - ComputationExecutor, - ComputationTransport, - > -where - ConsensusExecutor: JobExecutor< - PartialJobRequest = Requester, - PartialJobResponse = bool, - JobResponse = BTreeSet, - >, - ConsensusTransport: JobTransport< - PartialJobRequest = ConsensusExecutor::PartialJobRequest, - PartialJobResponse = ConsensusExecutor::PartialJobResponse, - >, - ComputationExecutor: JobExecutor, - ComputationTransport: JobTransport< - PartialJobRequest = ComputationExecutor::PartialJobRequest, - PartialJobResponse = ComputationExecutor::PartialJobResponse, - >, -{ - /// Process basic consensus message. - pub fn on_consensus_message( - &mut self, - sender: &NodeId, - message: &ConsensusMessage, - ) -> Result<(), Error> { - let consensus_result = match message { - &ConsensusMessage::InitializeConsensusSession(ref message) => self - .consensus_job - .on_partial_request(sender, message.requester.clone().into()) - .map(|_| ()), - &ConsensusMessage::ConfirmConsensusInitialization(ref message) => self - .consensus_job - .on_partial_response(sender, message.is_confirmed), - }; - self.process_result(consensus_result) - } -} - -#[cfg(test)] -mod tests { - use super::{ConsensusSession, ConsensusSessionParams, ConsensusSessionState}; - use ethkey::{public_to_address, sign, Generator, KeyPair, Random}; - use key_server_cluster::{ - jobs::{ - job_session::tests::{ - make_master_session_meta, make_slave_session_meta, DummyJobTransport, - SquaredSumJobExecutor, - }, - key_access_job::KeyAccessJob, - }, - message::{ConfirmConsensusInitialization, ConsensusMessage, InitializeConsensusSession}, - DummyAclStorage, Error, NodeId, Requester, SessionId, - }; - use std::sync::Arc; - - type SquaredSumConsensusSession = ConsensusSession< - KeyAccessJob, - DummyJobTransport, - SquaredSumJobExecutor, - DummyJobTransport, - >; - - fn make_master_consensus_session( - threshold: usize, - requester: Option, - acl_storage: Option, - ) -> SquaredSumConsensusSession { - let secret = requester - .map(|kp| kp.secret().clone()) - .unwrap_or(Random.generate().unwrap().secret().clone()); - SquaredSumConsensusSession::new(ConsensusSessionParams { - meta: make_master_session_meta(threshold), - consensus_executor: KeyAccessJob::new_on_master( - SessionId::default(), - Arc::new(acl_storage.unwrap_or(DummyAclStorage::default())), - sign(&secret, &SessionId::default()).unwrap().into(), - ), - consensus_transport: DummyJobTransport::default(), - }) - .unwrap() - } - - fn make_slave_consensus_session( - threshold: usize, - acl_storage: Option, - ) -> SquaredSumConsensusSession { - SquaredSumConsensusSession::new(ConsensusSessionParams { - meta: make_slave_session_meta(threshold), - consensus_executor: KeyAccessJob::new_on_slave( - SessionId::default(), - Arc::new(acl_storage.unwrap_or(DummyAclStorage::default())), - ), - consensus_transport: DummyJobTransport::default(), - }) - .unwrap() - } - - #[test] - fn consensus_session_consensus_is_not_reached_when_initializes_with_non_zero_threshold() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_consensus_is_reached_when_initializes_with_zero_threshold() { - let mut session = make_master_consensus_session(0, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_consensus_is_not_reached_when_initializes_with_zero_threshold_and_master_rejects( - ) { - let requester = Random.generate().unwrap(); - let acl_storage = DummyAclStorage::default(); - acl_storage.prohibit(public_to_address(requester.public()), SessionId::default()); - - let mut session = make_master_consensus_session(0, Some(requester), Some(acl_storage)); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_consensus_is_failed_by_master_node() { - let requester = Random.generate().unwrap(); - let acl_storage = DummyAclStorage::default(); - acl_storage.prohibit(public_to_address(requester.public()), SessionId::default()); - - let mut session = make_master_consensus_session(1, Some(requester), Some(acl_storage)); - assert_eq!( - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap_err(), - Error::ConsensusUnreachable - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_consensus_is_failed_by_slave_node() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - assert_eq!( - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization( - ConfirmConsensusInitialization { - is_confirmed: false, - } - ) - ) - .unwrap_err(), - Error::ConsensusUnreachable - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_job_dissemination_fails_if_consensus_is_not_reached() { - let mut session = make_master_consensus_session(1, None, None); - assert_eq!( - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn consensus_session_job_dissemination_selects_master_node_if_agreed() { - let mut session = make_master_consensus_session(0, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::Finished); - assert!(session - .computation_job() - .responses() - .contains_key(&NodeId::from(1))); - } - - #[test] - fn consensus_session_job_dissemination_does_not_select_master_node_if_rejected() { - let requester = Random.generate().unwrap(); - let acl_storage = DummyAclStorage::default(); - acl_storage.prohibit(public_to_address(requester.public()), SessionId::default()); - - let mut session = make_master_consensus_session(0, Some(requester), Some(acl_storage)); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - assert!(!session - .computation_job() - .responses() - .contains_key(&NodeId::from(1))); - } - - #[test] - fn consensus_session_computation_request_is_rejected_when_received_by_master_node() { - let mut session = make_master_consensus_session(0, None, None); - assert_eq!( - session - .on_job_request( - &NodeId::from(2), - 2, - SquaredSumJobExecutor, - DummyJobTransport::default() - ) - .unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn consensus_session_computation_request_is_rejected_when_received_before_consensus_is_established( - ) { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session - .on_job_request( - &NodeId::from(1), - 2, - SquaredSumJobExecutor, - DummyJobTransport::default() - ) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn consensus_session_computation_request_is_ignored_when_wrong() { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForInitialization - ); - session - .on_consensus_message( - &NodeId::from(1), - &ConsensusMessage::InitializeConsensusSession(InitializeConsensusSession { - requester: Requester::Signature( - sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - ) - .into(), - version: Default::default(), - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - assert_eq!( - session - .on_job_request( - &NodeId::from(1), - 20, - SquaredSumJobExecutor, - DummyJobTransport::default() - ) - .unwrap_err(), - Error::InvalidMessage - ); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_computation_request_is_processed_when_correct() { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForInitialization - ); - session - .on_consensus_message( - &NodeId::from(1), - &ConsensusMessage::InitializeConsensusSession(InitializeConsensusSession { - requester: Requester::Signature( - sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - ) - .into(), - version: Default::default(), - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .on_job_request( - &NodeId::from(1), - 2, - SquaredSumJobExecutor, - DummyJobTransport::default(), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_computation_response_is_ignored_when_consensus_is_not_reached() { - let mut session = make_master_consensus_session(1, None, None); - assert_eq!( - session.on_job_response(&NodeId::from(2), 4).unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn consessus_session_completion_is_ignored_when_received_from_non_master_node() { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session.on_session_completed(&NodeId::from(3)).unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn consessus_session_completion_is_ignored_when_consensus_is_not_established() { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session.on_session_completed(&NodeId::from(1)).unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn consessus_session_completion_is_accepted() { - let mut session = make_slave_consensus_session(0, None); - session - .on_consensus_message( - &NodeId::from(1), - &ConsensusMessage::InitializeConsensusSession(InitializeConsensusSession { - requester: Requester::Signature( - sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap(), - ) - .into(), - version: Default::default(), - }), - ) - .unwrap(); - session.on_session_completed(&NodeId::from(1)).unwrap(); - assert_eq!(session.state(), ConsensusSessionState::Finished); - } - - #[test] - fn consensus_session_fails_if_node_error_received_by_uninitialized_master() { - let mut session = make_master_consensus_session(0, None, None); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_fails_if_node_error_received_by_uninitialized_slave_from_master() { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session.on_node_error(&NodeId::from(1), Error::AccessDenied), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_sessions_fails_with_temp_error_if_node_error_received_by_uninitialized_slave_from_master( - ) { - let mut session = make_slave_consensus_session(0, None); - assert_eq!( - session - .on_node_error(&NodeId::from(1), Error::NodeDisconnected) - .unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } - - #[test] - fn consensus_session_continues_if_node_error_received_by_master_during_establish_and_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![NodeId::from(1), NodeId::from(2), NodeId::from(3)] - .into_iter() - .collect(), - ) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Ok(false) - ); - } - - #[test] - fn consensus_session_fails_if_node_error_received_by_master_during_establish_and_not_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_continues_if_node2_error_received_by_master_after_consensus_established_and_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![NodeId::from(1), NodeId::from(2), NodeId::from(3)] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Ok(false) - ); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_continues_if_node3_error_received_by_master_after_consensus_established_and_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![NodeId::from(1), NodeId::from(2), NodeId::from(3)] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(3), Error::AccessDenied), - Ok(false) - ); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - } - - #[test] - fn consensus_session_fails_if_node_error_received_by_master_after_consensus_established_and_not_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_continues_if_node_error_received_from_slave_not_participating_in_computation( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![ - NodeId::from(1), - NodeId::from(2), - NodeId::from(3), - NodeId::from(4), - ] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(3), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(3), Error::AccessDenied), - Ok(false) - ); - assert_eq!( - session.on_node_error(&NodeId::from(4), Error::AccessDenied), - Ok(false) - ); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - } - - #[test] - fn consensus_session_restarts_if_node_error_received_from_slave_participating_in_computation_and_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![ - NodeId::from(1), - NodeId::from(2), - NodeId::from(3), - NodeId::from(4), - ] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - session - .on_consensus_message( - &NodeId::from(3), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Ok(true) - ); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - assert_eq!( - session.on_node_error(&NodeId::from(3), Error::AccessDenied), - Ok(false) - ); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - } - - #[test] - fn consensus_session_fails_if_node_error_received_from_slave_participating_in_computation_and_not_enough_nodes_left( - ) { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.on_node_error(&NodeId::from(2), Error::AccessDenied), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn consensus_session_fails_if_uninitialized_session_timeouts() { - let mut session = make_master_consensus_session(1, None, None); - assert_eq!( - session.on_session_timeout(), - Err(Error::ConsensusTemporaryUnreachable) - ); - } - - #[test] - fn consensus_session_continues_if_session_timeouts_and_enough_nodes_left_for_computation() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![ - NodeId::from(1), - NodeId::from(2), - NodeId::from(3), - NodeId::from(4), - ] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - session - .on_consensus_message( - &NodeId::from(3), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.on_session_timeout(), Ok(true)); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - assert_eq!(session.on_session_timeout(), Ok(false)); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - } - - #[test] - fn consensus_session_continues_if_session_timeouts_and_not_enough_nodes_left_for_computation() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize(vec![NodeId::from(1), NodeId::from(2)].into_iter().collect()) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - assert_eq!( - session.on_session_timeout(), - Err(Error::ConsensusUnreachable) - ); - assert_eq!(session.state(), ConsensusSessionState::Failed); - } - - #[test] - fn same_consensus_group_returned_after_second_selection() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![NodeId::from(1), NodeId::from(2), NodeId::from(3)] - .into_iter() - .collect(), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - session - .on_consensus_message( - &NodeId::from(3), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - - let consensus_group1 = session.select_consensus_group().unwrap().clone(); - let consensus_group2 = session.select_consensus_group().unwrap().clone(); - assert_eq!(consensus_group1, consensus_group2); - } - - #[test] - fn consensus_session_complete_2_of_4() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![ - NodeId::from(1), - NodeId::from(2), - NodeId::from(3), - NodeId::from(3), - ] - .into_iter() - .collect(), - ) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - session.on_job_response(&NodeId::from(2), 16).unwrap(); - assert_eq!(session.state(), ConsensusSessionState::Finished); - assert_eq!(session.result(), Ok(20)); - } - - #[test] - fn consensus_session_complete_2_of_4_after_restart() { - let mut session = make_master_consensus_session(1, None, None); - session - .initialize( - vec![ - NodeId::from(1), - NodeId::from(2), - NodeId::from(3), - NodeId::from(4), - ] - .into_iter() - .collect(), - ) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - session - .on_consensus_message( - &NodeId::from(2), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - session - .on_consensus_message( - &NodeId::from(3), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - - assert_eq!( - session - .on_node_error(&NodeId::from(2), Error::AccessDenied) - .unwrap(), - true - ); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - assert_eq!( - session - .on_node_error(&NodeId::from(3), Error::AccessDenied) - .unwrap(), - false - ); - assert_eq!( - session.state(), - ConsensusSessionState::EstablishingConsensus - ); - - session - .on_consensus_message( - &NodeId::from(4), - &ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { - is_confirmed: true, - }), - ) - .unwrap(); - assert_eq!(session.state(), ConsensusSessionState::ConsensusEstablished); - - session - .disseminate_jobs(SquaredSumJobExecutor, DummyJobTransport::default(), false) - .unwrap(); - assert_eq!( - session.state(), - ConsensusSessionState::WaitingForPartialResults - ); - - session.on_job_response(&NodeId::from(4), 16).unwrap(); - assert_eq!(session.state(), ConsensusSessionState::Finished); - assert_eq!(session.result(), Ok(20)); - } -} diff --git a/secret-store/src/key_server_cluster/jobs/decryption_job.rs b/secret-store/src/key_server_cluster/jobs/decryption_job.rs deleted file mode 100644 index 78cce64fb8..0000000000 --- a/secret-store/src/key_server_cluster/jobs/decryption_job.rs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use crypto::DEFAULT_MAC; -use ethereum_types::H256; -use ethkey::{crypto::ecies::encrypt, Public, Secret}; -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - math, DocumentKeyShare, EncryptedDocumentKeyShadow, Error, NodeId, -}; -use std::collections::{BTreeMap, BTreeSet}; - -/// Decryption job. -pub struct DecryptionJob { - /// This node id. - self_node_id: NodeId, - /// Access key. - access_key: Secret, - /// Requester public key. - requester: Public, - /// Key share. - key_share: DocumentKeyShare, - /// Key version. - key_version: H256, - /// Request id. - request_id: Option, - /// Is shadow decryption requested. - is_shadow_decryption: Option, - /// Is broadcast decryption requested. - is_broadcast_session: Option, -} - -/// Decryption job partial request. -#[derive(Debug)] -pub struct PartialDecryptionRequest { - /// Request id. - pub id: Secret, - /// Is shadow decryption requested. - pub is_shadow_decryption: bool, - /// Is broadcast decryption requested. - pub is_broadcast_session: bool, - /// Id of other nodes, participating in decryption. - pub other_nodes_ids: BTreeSet, -} - -/// Decryption job partial response. -#[derive(Clone)] -pub struct PartialDecryptionResponse { - /// Request id. - pub request_id: Secret, - /// Shadow point. - pub shadow_point: Public, - /// Decryption shadow coefficient, if requested. - pub decrypt_shadow: Option>, -} - -impl DecryptionJob { - pub fn new_on_slave( - self_node_id: NodeId, - access_key: Secret, - requester: Public, - key_share: DocumentKeyShare, - key_version: H256, - ) -> Result { - debug_assert!(key_share.common_point.is_some() && key_share.encrypted_point.is_some()); - Ok(DecryptionJob { - self_node_id: self_node_id, - access_key: access_key, - requester: requester, - key_share: key_share, - key_version: key_version, - request_id: None, - is_shadow_decryption: None, - is_broadcast_session: None, - }) - } - - pub fn new_on_master( - self_node_id: NodeId, - access_key: Secret, - requester: Public, - key_share: DocumentKeyShare, - key_version: H256, - is_shadow_decryption: bool, - is_broadcast_session: bool, - ) -> Result { - debug_assert!(key_share.common_point.is_some() && key_share.encrypted_point.is_some()); - Ok(DecryptionJob { - self_node_id: self_node_id, - access_key: access_key, - requester: requester, - key_share: key_share, - key_version: key_version, - request_id: Some(math::generate_random_scalar()?), - is_shadow_decryption: Some(is_shadow_decryption), - is_broadcast_session: Some(is_broadcast_session), - }) - } - - pub fn request_id(&self) -> &Option { - &self.request_id - } - - pub fn set_request_id(&mut self, request_id: Secret) { - self.request_id = Some(request_id); - } -} - -impl JobExecutor for DecryptionJob { - type PartialJobRequest = PartialDecryptionRequest; - type PartialJobResponse = PartialDecryptionResponse; - type JobResponse = EncryptedDocumentKeyShadow; - - fn prepare_partial_request( - &self, - node: &NodeId, - nodes: &BTreeSet, - ) -> Result { - debug_assert!(nodes.len() == self.key_share.threshold + 1); - - let request_id = self.request_id.as_ref() - .expect("prepare_partial_request is only called on master nodes; request_id is filed in constructor on master nodes; qed"); - let is_shadow_decryption = self.is_shadow_decryption - .expect("prepare_partial_request is only called on master nodes; is_shadow_decryption is filed in constructor on master nodes; qed"); - let is_broadcast_session = self.is_broadcast_session - .expect("prepare_partial_request is only called on master nodes; is_broadcast_session is filed in constructor on master nodes; qed"); - let mut other_nodes_ids = nodes.clone(); - other_nodes_ids.remove(node); - - Ok(PartialDecryptionRequest { - id: request_id.clone(), - is_shadow_decryption: is_shadow_decryption, - is_broadcast_session: is_broadcast_session, - other_nodes_ids: other_nodes_ids, - }) - } - - fn process_partial_request( - &mut self, - partial_request: PartialDecryptionRequest, - ) -> Result, Error> { - let key_version = self.key_share.version(&self.key_version)?; - if partial_request.other_nodes_ids.len() != self.key_share.threshold - || partial_request.other_nodes_ids.contains(&self.self_node_id) - || partial_request - .other_nodes_ids - .iter() - .any(|n| !key_version.id_numbers.contains_key(n)) - { - return Err(Error::InvalidMessage); - } - - let self_id_number = &key_version.id_numbers[&self.self_node_id]; - let other_id_numbers = partial_request - .other_nodes_ids - .iter() - .map(|n| &key_version.id_numbers[n]); - let node_shadow = math::compute_node_shadow( - &key_version.secret_share, - &self_id_number, - other_id_numbers, - )?; - let decrypt_shadow = if partial_request.is_shadow_decryption { - Some(math::generate_random_scalar()?) - } else { - None - }; - let common_point = self - .key_share - .common_point - .as_ref() - .expect("DecryptionJob is only created when common_point is known; qed"); - let (shadow_point, decrypt_shadow) = math::compute_node_shadow_point( - &self.access_key, - &common_point, - &node_shadow, - decrypt_shadow, - )?; - - Ok(JobPartialRequestAction::Respond( - PartialDecryptionResponse { - request_id: partial_request.id, - shadow_point: shadow_point, - decrypt_shadow: match decrypt_shadow.clone() { - None => None, - Some(decrypt_shadow) => { - Some(encrypt(&self.requester, &DEFAULT_MAC, &**decrypt_shadow)?) - } - }, - }, - )) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - partial_response: &PartialDecryptionResponse, - ) -> Result { - if Some(&partial_response.request_id) != self.request_id.as_ref() { - return Ok(JobPartialResponseAction::Ignore); - } - if self.is_shadow_decryption != Some(partial_response.decrypt_shadow.is_some()) { - return Ok(JobPartialResponseAction::Reject); - } - Ok(JobPartialResponseAction::Accept) - } - - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result { - let is_shadow_decryption = self.is_shadow_decryption - .expect("compute_response is only called on master nodes; is_shadow_decryption is filed in constructor on master nodes; qed"); - let common_point = self - .key_share - .common_point - .as_ref() - .expect("DecryptionJob is only created when common_point is known; qed"); - let encrypted_point = self - .key_share - .encrypted_point - .as_ref() - .expect("DecryptionJob is only created when encrypted_point is known; qed"); - let joint_shadow_point = - math::compute_joint_shadow_point(partial_responses.values().map(|s| &s.shadow_point))?; - let decrypted_secret = math::decrypt_with_joint_shadow( - self.key_share.threshold, - &self.access_key, - encrypted_point, - &joint_shadow_point, - )?; - Ok(EncryptedDocumentKeyShadow { - decrypted_secret: decrypted_secret, - common_point: if is_shadow_decryption { - Some(math::make_common_shadow_point( - self.key_share.threshold, - common_point.clone(), - )?) - } else { - None - }, - decrypt_shadows: if is_shadow_decryption { - Some(partial_responses.values().map(|r| r.decrypt_shadow.as_ref() - .expect("is_shadow_decryption == true; decrypt_shadow.is_some() is checked in check_partial_response; qed") - .clone()) - .collect()) - } else { - None - }, - }) - } -} diff --git a/secret-store/src/key_server_cluster/jobs/dummy_job.rs b/secret-store/src/key_server_cluster/jobs/dummy_job.rs deleted file mode 100644 index e5f438feeb..0000000000 --- a/secret-store/src/key_server_cluster/jobs/dummy_job.rs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{ - jobs::job_session::{ - JobExecutor, JobPartialRequestAction, JobPartialResponseAction, JobTransport, - }, - Error, NodeId, -}; -use std::collections::{BTreeMap, BTreeSet}; - -/// No-work job to use in generics (TODO [Refac]: create separate ShareChangeConsensusSession && remove this) -pub struct DummyJob; - -impl JobExecutor for DummyJob { - type PartialJobRequest = (); - type PartialJobResponse = (); - type JobResponse = (); - - fn prepare_partial_request(&self, _n: &NodeId, _nodes: &BTreeSet) -> Result<(), Error> { - unreachable!("dummy job methods are never called") - } - - fn process_partial_request(&mut self, _r: ()) -> Result, Error> { - unreachable!("dummy job methods are never called") - } - - fn check_partial_response( - &mut self, - _s: &NodeId, - _r: &(), - ) -> Result { - unreachable!("dummy job methods are never called") - } - - fn compute_response(&self, _r: &BTreeMap) -> Result<(), Error> { - unreachable!("dummy job methods are never called") - } -} - -/// No-work job transport to use in generics (TODO [Refac]: create separate ShareChangeConsensusSession && remove this) -pub struct DummyJobTransport; - -impl JobTransport for DummyJobTransport { - type PartialJobRequest = (); - type PartialJobResponse = (); - - fn send_partial_request(&self, _node: &NodeId, _request: ()) -> Result<(), Error> { - unreachable!("dummy transport methods are never called") - } - - fn send_partial_response(&self, _node: &NodeId, _response: ()) -> Result<(), Error> { - unreachable!("dummy transport methods are never called") - } -} diff --git a/secret-store/src/key_server_cluster/jobs/job_session.rs b/secret-store/src/key_server_cluster/jobs/job_session.rs deleted file mode 100644 index 3a70debb2e..0000000000 --- a/secret-store/src/key_server_cluster/jobs/job_session.rs +++ /dev/null @@ -1,1043 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{Error, NodeId, SessionMeta}; -use std::collections::{BTreeMap, BTreeSet}; - -/// Partial response action. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum JobPartialResponseAction { - /// Ignore this response. - Ignore, - /// Mark this response as reject. - Reject, - /// Accept this response. - Accept, -} - -/// Partial request action. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum JobPartialRequestAction { - /// Respond with reject. - Reject(PartialJobResponse), - /// Respond with this response. - Respond(PartialJobResponse), -} - -/// Job executor. -pub trait JobExecutor { - type PartialJobRequest; - type PartialJobResponse: Clone; - type JobResponse; - - /// Prepare job request for given node. - fn prepare_partial_request( - &self, - node: &NodeId, - nodes: &BTreeSet, - ) -> Result; - /// Process partial request. - fn process_partial_request( - &mut self, - partial_request: Self::PartialJobRequest, - ) -> Result, Error>; - /// Check partial response of given node. - fn check_partial_response( - &mut self, - sender: &NodeId, - partial_response: &Self::PartialJobResponse, - ) -> Result; - /// Compute final job response. - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result; -} - -/// Jobs transport. -pub trait JobTransport { - type PartialJobRequest; - type PartialJobResponse; - - /// Send partial request to given node. - fn send_partial_request( - &self, - node: &NodeId, - request: Self::PartialJobRequest, - ) -> Result<(), Error>; - /// Send partial request to given node. - fn send_partial_response( - &self, - node: &NodeId, - response: Self::PartialJobResponse, - ) -> Result<(), Error>; -} - -/// Current state of job session. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum JobSessionState { - /// Session is inactive. - Inactive, - /// Session is active. - Active, - /// Session is finished. - Finished, - /// Session has failed. - Failed, -} - -/// Basic request-response session on a set of nodes. -pub struct JobSession -where - Transport: JobTransport< - PartialJobRequest = Executor::PartialJobRequest, - PartialJobResponse = Executor::PartialJobResponse, - >, -{ - /// Session meta. - meta: SessionMeta, - /// Job executor. - executor: Executor, - /// Jobs transport. - transport: Transport, - /// Session data. - data: JobSessionData, -} - -/// Data of job session. -struct JobSessionData { - /// Session state. - state: JobSessionState, - /// Mutable session data. - active_data: Option>, -} - -/// Active job session data. -struct ActiveJobSessionData { - /// Active partial requests. - requests: BTreeSet, - /// Rejects to partial requests (maps to true, if reject is fatal). - rejects: BTreeMap, - /// Received partial responses. - responses: BTreeMap, -} - -impl JobSession -where - Executor: JobExecutor, - Transport: JobTransport< - PartialJobRequest = Executor::PartialJobRequest, - PartialJobResponse = Executor::PartialJobResponse, - >, -{ - /// Create new session. - pub fn new(meta: SessionMeta, executor: Executor, transport: Transport) -> Self { - JobSession { - meta: meta, - executor: executor, - transport: transport, - data: JobSessionData { - state: JobSessionState::Inactive, - active_data: None, - }, - } - } - - /// Get transport reference. - #[cfg(test)] - pub fn transport(&self) -> &Transport { - &self.transport - } - - /// Get mutable transport reference. - pub fn transport_mut(&mut self) -> &mut Transport { - &mut self.transport - } - - /// Get executor reference. - pub fn executor(&self) -> &Executor { - &self.executor - } - - /// Get mutable executor reference. - pub fn executor_mut(&mut self) -> &mut Executor { - &mut self.executor - } - - /// Get job state. - pub fn state(&self) -> JobSessionState { - self.data.state - } - - /// Get rejects. - #[cfg(test)] - pub fn rejects(&self) -> &BTreeMap { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - - &self.data.active_data.as_ref() - .expect("rejects is only called on master nodes after initialization; on master nodes active_data is filled during initialization; qed") - .rejects - } - - /// Get active requests. - pub fn requests(&self) -> &BTreeSet { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - - &self.data.active_data.as_ref() - .expect("requests is only called on master nodes after initialization; on master nodes active_data is filled during initialization; qed") - .requests - } - - /// Get responses. - pub fn responses(&self) -> &BTreeMap { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - - &self.data.active_data.as_ref() - .expect("responses is only called on master nodes after initialization; on master nodes active_data is filled during initialization; qed") - .responses - } - - /// Returns true if enough responses are ready to compute result. - pub fn is_result_ready(&self) -> bool { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - self.data.active_data.as_ref() - .expect("is_result_ready is only called on master nodes after initialization; on master nodes active_data is filled during initialization; qed") - .responses.len() >= self.meta.threshold + 1 - } - - /// Get job result. - pub fn result(&self) -> Result { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - - if self.data.state != JobSessionState::Finished { - return Err(Error::InvalidStateForRequest); - } - - self.executor.compute_response(&self.data.active_data.as_ref() - .expect("requests is only called on master nodes; on master nodes active_data is filled during initialization; qed") - .responses) - } - - /// Initialize. - pub fn initialize( - &mut self, - nodes: BTreeSet, - self_response: Option, - broadcast_self_response: bool, - ) -> Result, Error> { - debug_assert!(self.meta.self_node_id == self.meta.master_node_id); - - if nodes.len() < self.meta.threshold + 1 { - return Err( - if self.meta.configured_nodes_count < self.meta.threshold + 1 { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - }, - ); - } - - if self.data.state != JobSessionState::Inactive { - return Err(Error::InvalidStateForRequest); - } - - // result from self - let active_data = ActiveJobSessionData { - requests: nodes.clone(), - rejects: BTreeMap::new(), - responses: BTreeMap::new(), - }; - let waits_for_self = active_data.requests.contains(&self.meta.self_node_id); - let self_response = match self_response { - Some(self_response) => Some(self_response), - None if waits_for_self => { - let partial_request = self - .executor - .prepare_partial_request(&self.meta.self_node_id, &active_data.requests)?; - let self_response = self.executor.process_partial_request(partial_request)?; - Some(self_response.take_response()) - } - None => None, - }; - - // update state - self.data.active_data = Some(active_data); - self.data.state = JobSessionState::Active; - - // if we are waiting for response from self => do it - if let Some(self_response) = self_response.clone() { - let self_node_id = self.meta.self_node_id.clone(); - self.on_partial_response(&self_node_id, self_response)?; - } - - // send requests to save nodes. we only send requests if session is still active. - for node in nodes.iter().filter(|n| **n != self.meta.self_node_id) { - if self.data.state == JobSessionState::Active { - self.transport.send_partial_request( - node, - self.executor.prepare_partial_request(node, &nodes)?, - )?; - } - if broadcast_self_response { - if let Some(self_response) = self_response.clone() { - self.transport.send_partial_response(node, self_response)?; - } - } - } - - Ok(self_response) - } - - /// When partial request is received by slave node. - pub fn on_partial_request( - &mut self, - node: &NodeId, - request: Executor::PartialJobRequest, - ) -> Result, Error> { - if node != &self.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if self.meta.self_node_id == self.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if self.data.state != JobSessionState::Inactive - && self.data.state != JobSessionState::Finished - { - return Err(Error::InvalidStateForRequest); - } - - let partial_request_action = self.executor.process_partial_request(request)?; - let partial_response = match partial_request_action { - JobPartialRequestAction::Respond(ref partial_response) => { - self.data.state = JobSessionState::Finished; - partial_response.clone() - } - JobPartialRequestAction::Reject(ref partial_response) => { - self.data.state = JobSessionState::Failed; - partial_response.clone() - } - }; - self.transport - .send_partial_response(node, partial_response)?; - Ok(partial_request_action) - } - - /// When partial request is received by master node. - pub fn on_partial_response( - &mut self, - node: &NodeId, - response: Executor::PartialJobResponse, - ) -> Result<(), Error> { - if self.meta.self_node_id != self.meta.master_node_id { - return Err(Error::InvalidMessage); - } - if self.data.state != JobSessionState::Active - && self.data.state != JobSessionState::Finished - { - return Err(Error::InvalidStateForRequest); - } - - let active_data = self.data.active_data.as_mut() - .expect("on_partial_response is only called on master nodes; on master nodes active_data is filled during initialization; qed"); - if !active_data.requests.remove(node) { - return Err(Error::InvalidNodeForRequest); - } - - match self.executor.check_partial_response(node, &response)? { - JobPartialResponseAction::Ignore => Ok(()), - JobPartialResponseAction::Reject => { - // direct reject is always considered as fatal - active_data.rejects.insert(node.clone(), true); - if active_data.requests.len() + active_data.responses.len() - >= self.meta.threshold + 1 - { - return Ok(()); - } - - self.data.state = JobSessionState::Failed; - Err(consensus_unreachable(&active_data.rejects)) - } - JobPartialResponseAction::Accept => { - active_data.responses.insert(node.clone(), response); - if active_data.responses.len() < self.meta.threshold + 1 { - return Ok(()); - } - - self.data.state = JobSessionState::Finished; - Ok(()) - } - } - } - - /// When error from node is received. - pub fn on_node_error(&mut self, node: &NodeId, error: Error) -> Result<(), Error> { - if self.meta.self_node_id != self.meta.master_node_id { - if node != &self.meta.master_node_id { - return Ok(()); - } - - self.data.state = JobSessionState::Failed; - return Err(if !error.is_non_fatal() { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - }); - } - - if let Some(active_data) = self.data.active_data.as_mut() { - if active_data.rejects.contains_key(node) { - return Ok(()); - } - if active_data.requests.remove(node) || active_data.responses.remove(node).is_some() { - active_data - .rejects - .insert(node.clone(), !error.is_non_fatal()); - if self.data.state == JobSessionState::Finished - && active_data.responses.len() < self.meta.threshold + 1 - { - self.data.state = JobSessionState::Active; - } - if active_data.requests.len() + active_data.responses.len() - >= self.meta.threshold + 1 - { - return Ok(()); - } - - self.data.state = JobSessionState::Failed; - return Err(consensus_unreachable(&active_data.rejects)); - } - } - - Ok(()) - } - - /// When session timeouted. - pub fn on_session_timeout(&mut self) -> Result<(), Error> { - if self.data.state == JobSessionState::Finished - || self.data.state == JobSessionState::Failed - { - return Ok(()); - } - - self.data.state = JobSessionState::Failed; - // we have started session => consensus is possible in theory, but now it has failed with timeout - Err(Error::ConsensusTemporaryUnreachable) - } -} - -impl JobPartialRequestAction { - /// Take actual response. - pub fn take_response(self) -> PartialJobResponse { - match self { - JobPartialRequestAction::Respond(response) => response, - JobPartialRequestAction::Reject(response) => response, - } - } -} - -/// Returns appropriate 'consensus unreachable' error. -fn consensus_unreachable(rejects: &BTreeMap) -> Error { - // when >= 50% of nodes have responded with fatal reject => ConsensusUnreachable - if rejects.values().filter(|r| **r).count() >= rejects.len() / 2 { - Error::ConsensusUnreachable - } else { - Error::ConsensusTemporaryUnreachable - } -} - -#[cfg(test)] -pub mod tests { - use super::{ - JobExecutor, JobPartialRequestAction, JobPartialResponseAction, JobSession, - JobSessionState, JobTransport, - }; - use ethkey::Public; - use key_server_cluster::{Error, NodeId, SessionId, SessionMeta}; - use parking_lot::Mutex; - use std::collections::{BTreeMap, BTreeSet, VecDeque}; - - pub struct SquaredSumJobExecutor; - - impl JobExecutor for SquaredSumJobExecutor { - type PartialJobRequest = u32; - type PartialJobResponse = u32; - type JobResponse = u32; - - fn prepare_partial_request( - &self, - _n: &NodeId, - _nodes: &BTreeSet, - ) -> Result { - Ok(2) - } - fn process_partial_request( - &mut self, - r: u32, - ) -> Result, Error> { - if r <= 10 { - Ok(JobPartialRequestAction::Respond(r * r)) - } else { - Err(Error::InvalidMessage) - } - } - fn check_partial_response( - &mut self, - _s: &NodeId, - r: &u32, - ) -> Result { - if r % 2 == 0 { - Ok(JobPartialResponseAction::Accept) - } else { - Ok(JobPartialResponseAction::Reject) - } - } - fn compute_response(&self, r: &BTreeMap) -> Result { - Ok(r.values().fold(0, |v1, v2| v1 + v2)) - } - } - - #[derive(Default)] - pub struct DummyJobTransport { - pub requests: Mutex>, - pub responses: Mutex>, - } - - impl DummyJobTransport { - pub fn is_empty_response(&self) -> bool { - self.responses.lock().is_empty() - } - - pub fn response(&self) -> (NodeId, U) { - self.responses.lock().pop_front().unwrap() - } - } - - impl JobTransport for DummyJobTransport { - type PartialJobRequest = T; - type PartialJobResponse = U; - - fn send_partial_request(&self, node: &NodeId, request: T) -> Result<(), Error> { - self.requests.lock().push_back((node.clone(), request)); - Ok(()) - } - fn send_partial_response(&self, node: &NodeId, response: U) -> Result<(), Error> { - self.responses.lock().push_back((node.clone(), response)); - Ok(()) - } - } - - pub fn make_master_session_meta(threshold: usize) -> SessionMeta { - SessionMeta { - id: SessionId::default(), - master_node_id: NodeId::from(1), - self_node_id: NodeId::from(1), - threshold: threshold, - configured_nodes_count: 5, - connected_nodes_count: 5, - } - } - - pub fn make_slave_session_meta(threshold: usize) -> SessionMeta { - SessionMeta { - id: SessionId::default(), - master_node_id: NodeId::from(1), - self_node_id: NodeId::from(2), - threshold: threshold, - configured_nodes_count: 5, - connected_nodes_count: 5, - } - } - - #[test] - fn job_initialize_fails_if_not_enough_nodes_for_threshold_total() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.meta.configured_nodes_count = 1; - assert_eq!( - job.initialize(vec![Public::from(1)].into_iter().collect(), None, false) - .unwrap_err(), - Error::ConsensusUnreachable - ); - } - - #[test] - fn job_initialize_fails_if_not_enough_nodes_for_threshold_connected() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.meta.connected_nodes_count = 3; - assert_eq!( - job.initialize(vec![Public::from(1)].into_iter().collect(), None, false) - .unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } - - #[test] - fn job_initialize_fails_if_not_inactive() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize(vec![Public::from(1)].into_iter().collect(), None, false) - .unwrap(); - assert_eq!( - job.initialize(vec![Public::from(1)].into_iter().collect(), None, false) - .unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn job_initialization_leads_to_finish_if_single_node_is_required() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize(vec![Public::from(1)].into_iter().collect(), None, false) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Finished); - assert!(job.is_result_ready()); - assert_eq!(job.result(), Ok(4)); - } - - #[test] - fn job_initialization_does_not_leads_to_finish_if_single_other_node_is_required() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize(vec![Public::from(2)].into_iter().collect(), None, false) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - } - - #[test] - fn job_request_fails_if_comes_from_non_master_node() { - let mut job = JobSession::new( - make_slave_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!( - job.on_partial_request(&NodeId::from(3), 2).unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn job_request_fails_if_comes_to_master_node() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!( - job.on_partial_request(&NodeId::from(1), 2).unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn job_request_fails_if_comes_to_failed_state() { - let mut job = JobSession::new( - make_slave_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.on_session_timeout().unwrap_err(); - assert_eq!( - job.on_partial_request(&NodeId::from(1), 2).unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn job_request_succeeds_if_comes_to_finished_state() { - let mut job = JobSession::new( - make_slave_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.on_partial_request(&NodeId::from(1), 2).unwrap(); - assert_eq!(job.transport().response(), (NodeId::from(1), 4)); - assert_eq!(job.state(), JobSessionState::Finished); - job.on_partial_request(&NodeId::from(1), 3).unwrap(); - assert_eq!(job.transport().response(), (NodeId::from(1), 9)); - assert_eq!(job.state(), JobSessionState::Finished); - } - - #[test] - fn job_response_fails_if_comes_to_slave_node() { - let mut job = JobSession::new( - make_slave_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!( - job.on_partial_response(&NodeId::from(1), 2).unwrap_err(), - Error::InvalidMessage - ); - } - - #[test] - fn job_response_fails_if_comes_to_failed_state() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize(vec![Public::from(2)].into_iter().collect(), None, false) - .unwrap(); - job.on_session_timeout().unwrap_err(); - assert_eq!( - job.on_partial_response(&NodeId::from(2), 2).unwrap_err(), - Error::InvalidStateForRequest - ); - } - - #[test] - fn job_response_fails_if_comes_from_unknown_node() { - let mut job = JobSession::new( - make_master_session_meta(0), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize(vec![Public::from(2)].into_iter().collect(), None, false) - .unwrap(); - assert_eq!( - job.on_partial_response(&NodeId::from(3), 2).unwrap_err(), - Error::InvalidNodeForRequest - ); - } - - #[test] - fn job_response_leads_to_failure_if_too_few_nodes_left() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert_eq!( - job.on_partial_response(&NodeId::from(2), 3).unwrap_err(), - Error::ConsensusUnreachable - ); - assert_eq!(job.state(), JobSessionState::Failed); - } - - #[test] - fn job_response_succeeds() { - let mut job = JobSession::new( - make_master_session_meta(2), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2), Public::from(3)] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert!(!job.is_result_ready()); - job.on_partial_response(&NodeId::from(2), 2).unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert!(!job.is_result_ready()); - } - - #[test] - fn job_response_leads_to_finish() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - job.on_partial_response(&NodeId::from(2), 2).unwrap(); - assert_eq!(job.state(), JobSessionState::Finished); - } - - #[test] - fn job_node_error_ignored_when_slave_disconnects_from_slave() { - let mut job = JobSession::new( - make_slave_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!(job.state(), JobSessionState::Inactive); - job.on_node_error(&NodeId::from(3), Error::AccessDenied) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Inactive); - } - - #[test] - fn job_node_error_leads_to_fail_when_slave_disconnects_from_master() { - let mut job = JobSession::new( - make_slave_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!(job.state(), JobSessionState::Inactive); - assert_eq!( - job.on_node_error(&NodeId::from(1), Error::AccessDenied) - .unwrap_err(), - Error::ConsensusUnreachable - ); - assert_eq!(job.state(), JobSessionState::Failed); - } - - #[test] - fn job_node_error_ignored_when_disconnects_from_rejected() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2), Public::from(3)] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - job.on_partial_response(&NodeId::from(2), 3).unwrap(); - job.on_node_error(&NodeId::from(2), Error::AccessDenied) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - } - - #[test] - fn job_node_error_ignored_when_disconnects_from_unknown() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - job.on_node_error(&NodeId::from(3), Error::AccessDenied) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - } - - #[test] - fn job_node_error_ignored_when_disconnects_from_requested_and_enough_nodes_left() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2), Public::from(3)] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - job.on_node_error(&NodeId::from(3), Error::AccessDenied) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - } - - #[test] - fn job_node_error_leads_to_fail_when_disconnects_from_requested_and_not_enough_nodes_left() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert_eq!( - job.on_node_error(&NodeId::from(2), Error::AccessDenied) - .unwrap_err(), - Error::ConsensusUnreachable - ); - assert_eq!(job.state(), JobSessionState::Failed); - } - - #[test] - fn job_broadcasts_self_response() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - true, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert_eq!(job.transport().response(), (NodeId::from(2), 4)); - } - - #[test] - fn job_does_not_broadcasts_self_response() { - let mut job = JobSession::new( - make_master_session_meta(1), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![Public::from(1), Public::from(2)].into_iter().collect(), - None, - false, - ) - .unwrap(); - assert_eq!(job.state(), JobSessionState::Active); - assert!(job.transport().is_empty_response()); - } - - #[test] - fn job_fails_with_temp_error_if_more_than_half_nodes_respond_with_temp_error() { - let mut job = JobSession::new( - make_master_session_meta(2), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![ - Public::from(1), - Public::from(2), - Public::from(3), - Public::from(4), - ] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - job.on_node_error(&NodeId::from(2), Error::NodeDisconnected) - .unwrap(); - assert_eq!( - job.on_node_error(&NodeId::from(3), Error::NodeDisconnected) - .unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } - - #[test] - fn job_fails_with_temp_error_if_more_than_half_rejects_are_temp() { - let mut job = JobSession::new( - make_master_session_meta(2), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![ - Public::from(1), - Public::from(2), - Public::from(3), - Public::from(4), - ] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - job.on_node_error(&NodeId::from(2), Error::NodeDisconnected) - .unwrap(); - assert_eq!( - job.on_node_error(&NodeId::from(3), Error::NodeDisconnected) - .unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } - - #[test] - fn job_fails_if_more_than_half_rejects_are_non_temp() { - let mut job = JobSession::new( - make_master_session_meta(2), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - job.initialize( - vec![ - Public::from(1), - Public::from(2), - Public::from(3), - Public::from(4), - ] - .into_iter() - .collect(), - None, - false, - ) - .unwrap(); - job.on_node_error(&NodeId::from(2), Error::AccessDenied) - .unwrap(); - assert_eq!( - job.on_node_error(&NodeId::from(3), Error::AccessDenied) - .unwrap_err(), - Error::ConsensusUnreachable - ); - } - - #[test] - fn job_fails_with_temp_error_when_temp_error_is_reported_by_master_node() { - let mut job = JobSession::new( - make_slave_session_meta(2), - SquaredSumJobExecutor, - DummyJobTransport::default(), - ); - assert_eq!( - job.on_node_error(&NodeId::from(1), Error::NodeDisconnected) - .unwrap_err(), - Error::ConsensusTemporaryUnreachable - ); - } -} diff --git a/secret-store/src/key_server_cluster/jobs/key_access_job.rs b/secret-store/src/key_server_cluster/jobs/key_access_job.rs deleted file mode 100644 index 2c87b329e9..0000000000 --- a/secret-store/src/key_server_cluster/jobs/key_access_job.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - AclStorage, Error, NodeId, Requester, SessionId, -}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Purpose of this job is to construct set of nodes, which have agreed to provide access to the given key for the given requestor. -pub struct KeyAccessJob { - /// Key id. - id: SessionId, - /// Has key share? - has_key_share: bool, - /// ACL storage. - acl_storage: Arc, - /// Requester data. - requester: Option, -} - -impl KeyAccessJob { - pub fn new_on_slave(id: SessionId, acl_storage: Arc) -> Self { - KeyAccessJob { - id: id, - has_key_share: true, - acl_storage: acl_storage, - requester: None, - } - } - - pub fn new_on_master( - id: SessionId, - acl_storage: Arc, - requester: Requester, - ) -> Self { - KeyAccessJob { - id: id, - has_key_share: true, - acl_storage: acl_storage, - requester: Some(requester), - } - } - - pub fn set_has_key_share(&mut self, has_key_share: bool) { - self.has_key_share = has_key_share; - } - - pub fn set_requester(&mut self, requester: Requester) { - self.requester = Some(requester); - } - - pub fn requester(&self) -> Option<&Requester> { - self.requester.as_ref() - } -} - -impl JobExecutor for KeyAccessJob { - type PartialJobRequest = Requester; - type PartialJobResponse = bool; - type JobResponse = BTreeSet; - - fn prepare_partial_request( - &self, - _node: &NodeId, - _nodes: &BTreeSet, - ) -> Result { - Ok(self.requester.as_ref().expect("prepare_partial_request is only called on master nodes; new_on_master fills the signature; qed").clone()) - } - - fn process_partial_request( - &mut self, - partial_request: Requester, - ) -> Result, Error> { - if !self.has_key_share { - return Ok(JobPartialRequestAction::Reject(false)); - } - - self.requester = Some(partial_request.clone()); - self.acl_storage - .check( - partial_request - .address(&self.id) - .map_err(Error::InsufficientRequesterData)?, - &self.id, - ) - .map(|is_confirmed| { - if is_confirmed { - JobPartialRequestAction::Respond(true) - } else { - JobPartialRequestAction::Reject(false) - } - }) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - partial_response: &bool, - ) -> Result { - Ok(if *partial_response { - JobPartialResponseAction::Accept - } else { - JobPartialResponseAction::Reject - }) - } - - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result, Error> { - Ok(partial_responses.keys().cloned().collect()) - } -} diff --git a/secret-store/src/key_server_cluster/jobs/mod.rs b/secret-store/src/key_server_cluster/jobs/mod.rs deleted file mode 100644 index e417580697..0000000000 --- a/secret-store/src/key_server_cluster/jobs/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -pub mod consensus_session; -pub mod decryption_job; -pub mod dummy_job; -pub mod job_session; -pub mod key_access_job; -pub mod servers_set_change_access_job; -pub mod signing_job_ecdsa; -pub mod signing_job_schnorr; -pub mod unknown_sessions_job; diff --git a/secret-store/src/key_server_cluster/jobs/servers_set_change_access_job.rs b/secret-store/src/key_server_cluster/jobs/servers_set_change_access_job.rs deleted file mode 100644 index 76ef847861..0000000000 --- a/secret-store/src/key_server_cluster/jobs/servers_set_change_access_job.rs +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::{recover, Public, Signature}; -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - message::{InitializeConsensusSessionOfShareAdd, InitializeConsensusSessionWithServersSet}, - Error, NodeId, SessionId, -}; -use std::collections::{BTreeMap, BTreeSet}; -use tiny_keccak::Keccak; - -/// Purpose of this job is to check if requestor is administrator of SecretStore (i.e. it have access to change key servers set). -pub struct ServersSetChangeAccessJob { - /// Servers set administrator public key (this could be changed to ACL-based check later). - administrator: Public, - /// Old servers set. - old_servers_set: Option>, - /// New servers set. - new_servers_set: Option>, - /// Old servers set, signed by requester. - old_set_signature: Option, - /// New servers set, signed by requester. - new_set_signature: Option, -} - -/// Servers set change job partial request. -pub struct ServersSetChangeAccessRequest { - /// Old servers set. - pub old_servers_set: BTreeSet, - /// New servers set. - pub new_servers_set: BTreeSet, - /// Hash(old_servers_set), signed by requester. - pub old_set_signature: Signature, - /// Hash(new_servers_set), signed by requester. - pub new_set_signature: Signature, -} - -impl<'a> From<&'a InitializeConsensusSessionWithServersSet> for ServersSetChangeAccessRequest { - fn from(message: &InitializeConsensusSessionWithServersSet) -> Self { - ServersSetChangeAccessRequest { - old_servers_set: message - .old_nodes_set - .iter() - .cloned() - .map(Into::into) - .collect(), - new_servers_set: message - .new_nodes_set - .iter() - .cloned() - .map(Into::into) - .collect(), - old_set_signature: message.old_set_signature.clone().into(), - new_set_signature: message.new_set_signature.clone().into(), - } - } -} - -impl<'a> From<&'a InitializeConsensusSessionOfShareAdd> for ServersSetChangeAccessRequest { - fn from(message: &InitializeConsensusSessionOfShareAdd) -> Self { - ServersSetChangeAccessRequest { - old_servers_set: message - .old_nodes_set - .iter() - .cloned() - .map(Into::into) - .collect(), - new_servers_set: message - .new_nodes_map - .keys() - .cloned() - .map(Into::into) - .collect(), - old_set_signature: message.old_set_signature.clone().into(), - new_set_signature: message.new_set_signature.clone().into(), - } - } -} - -impl ServersSetChangeAccessJob { - pub fn new_on_slave(administrator: Public) -> Self { - ServersSetChangeAccessJob { - administrator: administrator, - old_servers_set: None, - new_servers_set: None, - old_set_signature: None, - new_set_signature: None, - } - } - - pub fn new_on_master( - administrator: Public, - old_servers_set: BTreeSet, - new_servers_set: BTreeSet, - old_set_signature: Signature, - new_set_signature: Signature, - ) -> Self { - ServersSetChangeAccessJob { - administrator: administrator, - old_servers_set: Some(old_servers_set), - new_servers_set: Some(new_servers_set), - old_set_signature: Some(old_set_signature), - new_set_signature: Some(new_set_signature), - } - } - - pub fn new_servers_set(&self) -> Option<&BTreeSet> { - self.new_servers_set.as_ref() - } -} - -impl JobExecutor for ServersSetChangeAccessJob { - type PartialJobRequest = ServersSetChangeAccessRequest; - type PartialJobResponse = bool; - type JobResponse = BTreeSet; - - fn prepare_partial_request( - &self, - _node: &NodeId, - _nodes: &BTreeSet, - ) -> Result { - let explanation = "prepare_partial_request is only called on master nodes; this field is filled on master nodes in constructor; qed"; - Ok(ServersSetChangeAccessRequest { - old_servers_set: self.old_servers_set.clone().expect(explanation), - new_servers_set: self.new_servers_set.clone().expect(explanation), - old_set_signature: self.old_set_signature.clone().expect(explanation), - new_set_signature: self.new_set_signature.clone().expect(explanation), - }) - } - - fn process_partial_request( - &mut self, - partial_request: ServersSetChangeAccessRequest, - ) -> Result, Error> { - let ServersSetChangeAccessRequest { - old_servers_set, - new_servers_set, - old_set_signature, - new_set_signature, - } = partial_request; - - // check old servers set signature - let old_actual_public = recover( - &old_set_signature, - &ordered_nodes_hash(&old_servers_set).into(), - )?; - let new_actual_public = recover( - &new_set_signature, - &ordered_nodes_hash(&new_servers_set).into(), - )?; - let is_administrator = - old_actual_public == self.administrator && new_actual_public == self.administrator; - self.new_servers_set = Some(new_servers_set); - - Ok(if is_administrator { - JobPartialRequestAction::Respond(true) - } else { - JobPartialRequestAction::Reject(false) - }) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - partial_response: &bool, - ) -> Result { - Ok(if *partial_response { - JobPartialResponseAction::Accept - } else { - JobPartialResponseAction::Reject - }) - } - - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result, Error> { - Ok(partial_responses.keys().cloned().collect()) - } -} - -pub fn ordered_nodes_hash(nodes: &BTreeSet) -> SessionId { - let mut nodes_keccak = Keccak::new_keccak256(); - for node in nodes { - nodes_keccak.update(&*node); - } - - let mut nodes_keccak_value = [0u8; 32]; - nodes_keccak.finalize(&mut nodes_keccak_value); - - nodes_keccak_value.into() -} diff --git a/secret-store/src/key_server_cluster/jobs/signing_job_ecdsa.rs b/secret-store/src/key_server_cluster/jobs/signing_job_ecdsa.rs deleted file mode 100644 index d2cfce50f8..0000000000 --- a/secret-store/src/key_server_cluster/jobs/signing_job_ecdsa.rs +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{Public, Secret, Signature}; -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - math, DocumentKeyShare, Error, NodeId, -}; -use std::collections::{BTreeMap, BTreeSet}; - -/// Signing job. -pub struct EcdsaSigningJob { - /// Key share. - key_share: DocumentKeyShare, - /// Key version. - key_version: H256, - /// Share of inv(nonce). - inv_nonce_share: Secret, - /// Nonce public. - nonce_public: Public, - /// Request id. - request_id: Option, - /// - inversed_nonce_coeff: Option, - /// Message hash. - message_hash: Option, -} - -/// Signing job partial request. -pub struct EcdsaPartialSigningRequest { - /// Request id. - pub id: Secret, - /// - pub inversed_nonce_coeff: Secret, - /// Message hash to sign. - pub message_hash: H256, -} - -/// Signing job partial response. -#[derive(Clone)] -pub struct EcdsaPartialSigningResponse { - /// Request id. - pub request_id: Secret, - /// Partial signature' s share. - pub partial_signature_s: Secret, -} - -impl EcdsaSigningJob { - pub fn new_on_slave( - key_share: DocumentKeyShare, - key_version: H256, - nonce_public: Public, - inv_nonce_share: Secret, - ) -> Result { - Ok(EcdsaSigningJob { - key_share: key_share, - key_version: key_version, - nonce_public: nonce_public, - inv_nonce_share: inv_nonce_share, - request_id: None, - inversed_nonce_coeff: None, - message_hash: None, - }) - } - - pub fn new_on_master( - key_share: DocumentKeyShare, - key_version: H256, - nonce_public: Public, - inv_nonce_share: Secret, - inversed_nonce_coeff: Secret, - message_hash: H256, - ) -> Result { - Ok(EcdsaSigningJob { - key_share: key_share, - key_version: key_version, - nonce_public: nonce_public, - inv_nonce_share: inv_nonce_share, - request_id: Some(math::generate_random_scalar()?), - inversed_nonce_coeff: Some(inversed_nonce_coeff), - message_hash: Some(message_hash), - }) - } -} - -impl JobExecutor for EcdsaSigningJob { - type PartialJobRequest = EcdsaPartialSigningRequest; - type PartialJobResponse = EcdsaPartialSigningResponse; - type JobResponse = Signature; - - fn prepare_partial_request( - &self, - _node: &NodeId, - nodes: &BTreeSet, - ) -> Result { - debug_assert!(nodes.len() == self.key_share.threshold * 2 + 1); - - let request_id = self.request_id.as_ref() - .expect("prepare_partial_request is only called on master nodes; request_id is filed in constructor on master nodes; qed"); - let inversed_nonce_coeff = self.inversed_nonce_coeff.as_ref() - .expect("prepare_partial_request is only called on master nodes; inversed_nonce_coeff is filed in constructor on master nodes; qed"); - let message_hash = self.message_hash.as_ref() - .expect("compute_response is only called on master nodes; message_hash is filed in constructor on master nodes; qed"); - - Ok(EcdsaPartialSigningRequest { - id: request_id.clone(), - inversed_nonce_coeff: inversed_nonce_coeff.clone(), - message_hash: message_hash.clone(), - }) - } - - fn process_partial_request( - &mut self, - partial_request: EcdsaPartialSigningRequest, - ) -> Result, Error> { - let inversed_nonce_coeff_mul_nonce = - math::compute_secret_mul(&partial_request.inversed_nonce_coeff, &self.inv_nonce_share)?; - let key_version = self.key_share.version(&self.key_version)?; - let signature_r = math::compute_ecdsa_r(&self.nonce_public)?; - let inv_nonce_mul_secret = - math::compute_secret_mul(&inversed_nonce_coeff_mul_nonce, &key_version.secret_share)?; - let partial_signature_s = math::compute_ecdsa_s_share( - &inversed_nonce_coeff_mul_nonce, - &inv_nonce_mul_secret, - &signature_r, - &math::to_scalar(partial_request.message_hash)?, - )?; - - Ok(JobPartialRequestAction::Respond( - EcdsaPartialSigningResponse { - request_id: partial_request.id, - partial_signature_s: partial_signature_s, - }, - )) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - partial_response: &EcdsaPartialSigningResponse, - ) -> Result { - if Some(&partial_response.request_id) != self.request_id.as_ref() { - return Ok(JobPartialResponseAction::Ignore); - } - // TODO [Trust]: check_ecdsa_signature_share() - - Ok(JobPartialResponseAction::Accept) - } - - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result { - let key_version = self.key_share.version(&self.key_version)?; - if partial_responses - .keys() - .any(|n| !key_version.id_numbers.contains_key(n)) - { - return Err(Error::InvalidMessage); - } - - let id_numbers: Vec<_> = partial_responses - .keys() - .map(|n| key_version.id_numbers[n].clone()) - .collect(); - let signature_s_shares: Vec<_> = partial_responses - .values() - .map(|r| r.partial_signature_s.clone()) - .collect(); - let signature_s = - math::compute_ecdsa_s(self.key_share.threshold, &signature_s_shares, &id_numbers)?; - let signature_r = math::compute_ecdsa_r(&self.nonce_public)?; - - let signature = - math::serialize_ecdsa_signature(&self.nonce_public, signature_r, signature_s); - - Ok(signature) - } -} diff --git a/secret-store/src/key_server_cluster/jobs/signing_job_schnorr.rs b/secret-store/src/key_server_cluster/jobs/signing_job_schnorr.rs deleted file mode 100644 index d5edd89e61..0000000000 --- a/secret-store/src/key_server_cluster/jobs/signing_job_schnorr.rs +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use ethkey::{Public, Secret}; -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - math, DocumentKeyShare, Error, NodeId, -}; -use std::collections::{BTreeMap, BTreeSet}; - -/// Signing job. -pub struct SchnorrSigningJob { - /// This node id. - self_node_id: NodeId, - /// Key share. - key_share: DocumentKeyShare, - /// Key version. - key_version: H256, - /// Session public key. - session_public: Public, - /// Session secret coefficient. - session_secret_coeff: Secret, - /// Request id. - request_id: Option, - /// Message hash. - message_hash: Option, -} - -/// Signing job partial request. -pub struct SchnorrPartialSigningRequest { - /// Request id. - pub id: Secret, - /// Message hash. - pub message_hash: H256, - /// Id of other nodes, participating in signing. - pub other_nodes_ids: BTreeSet, -} - -/// Signing job partial response. -#[derive(Clone)] -pub struct SchnorrPartialSigningResponse { - /// Request id. - pub request_id: Secret, - /// Partial signature. - pub partial_signature: Secret, -} - -impl SchnorrSigningJob { - pub fn new_on_slave( - self_node_id: NodeId, - key_share: DocumentKeyShare, - key_version: H256, - session_public: Public, - session_secret_coeff: Secret, - ) -> Result { - Ok(SchnorrSigningJob { - self_node_id: self_node_id, - key_share: key_share, - key_version: key_version, - session_public: session_public, - session_secret_coeff: session_secret_coeff, - request_id: None, - message_hash: None, - }) - } - - pub fn new_on_master( - self_node_id: NodeId, - key_share: DocumentKeyShare, - key_version: H256, - session_public: Public, - session_secret_coeff: Secret, - message_hash: H256, - ) -> Result { - Ok(SchnorrSigningJob { - self_node_id: self_node_id, - key_share: key_share, - key_version: key_version, - session_public: session_public, - session_secret_coeff: session_secret_coeff, - request_id: Some(math::generate_random_scalar()?), - message_hash: Some(message_hash), - }) - } -} - -impl JobExecutor for SchnorrSigningJob { - type PartialJobRequest = SchnorrPartialSigningRequest; - type PartialJobResponse = SchnorrPartialSigningResponse; - type JobResponse = (Secret, Secret); - - fn prepare_partial_request( - &self, - node: &NodeId, - nodes: &BTreeSet, - ) -> Result { - debug_assert!(nodes.len() == self.key_share.threshold + 1); - - let request_id = self.request_id.as_ref() - .expect("prepare_partial_request is only called on master nodes; request_id is filed in constructor on master nodes; qed"); - let message_hash = self.message_hash.as_ref() - .expect("compute_response is only called on master nodes; message_hash is filed in constructor on master nodes; qed"); - let mut other_nodes_ids = nodes.clone(); - other_nodes_ids.remove(node); - - Ok(SchnorrPartialSigningRequest { - id: request_id.clone(), - message_hash: message_hash.clone(), - other_nodes_ids: other_nodes_ids, - }) - } - - fn process_partial_request( - &mut self, - partial_request: SchnorrPartialSigningRequest, - ) -> Result, Error> { - let key_version = self.key_share.version(&self.key_version)?; - if partial_request.other_nodes_ids.len() != self.key_share.threshold - || partial_request.other_nodes_ids.contains(&self.self_node_id) - || partial_request - .other_nodes_ids - .iter() - .any(|n| !key_version.id_numbers.contains_key(n)) - { - return Err(Error::InvalidMessage); - } - - let self_id_number = &key_version.id_numbers[&self.self_node_id]; - let other_id_numbers = partial_request - .other_nodes_ids - .iter() - .map(|n| &key_version.id_numbers[n]); - let combined_hash = math::combine_message_hash_with_public( - &partial_request.message_hash, - &self.session_public, - )?; - Ok(JobPartialRequestAction::Respond( - SchnorrPartialSigningResponse { - request_id: partial_request.id, - partial_signature: math::compute_schnorr_signature_share( - self.key_share.threshold, - &combined_hash, - &self.session_secret_coeff, - &key_version.secret_share, - self_id_number, - other_id_numbers, - )?, - }, - )) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - partial_response: &SchnorrPartialSigningResponse, - ) -> Result { - if Some(&partial_response.request_id) != self.request_id.as_ref() { - return Ok(JobPartialResponseAction::Ignore); - } - // TODO [Trust]: check_schnorr_signature_share() - - Ok(JobPartialResponseAction::Accept) - } - - fn compute_response( - &self, - partial_responses: &BTreeMap, - ) -> Result<(Secret, Secret), Error> { - let message_hash = self.message_hash.as_ref() - .expect("compute_response is only called on master nodes; message_hash is filed in constructor on master nodes; qed"); - - let signature_c = - math::combine_message_hash_with_public(message_hash, &self.session_public)?; - let signature_s = math::compute_schnorr_signature( - partial_responses.values().map(|r| &r.partial_signature), - )?; - - Ok((signature_c, signature_s)) - } -} diff --git a/secret-store/src/key_server_cluster/jobs/unknown_sessions_job.rs b/secret-store/src/key_server_cluster/jobs/unknown_sessions_job.rs deleted file mode 100644 index 4e7e18e599..0000000000 --- a/secret-store/src/key_server_cluster/jobs/unknown_sessions_job.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use key_server_cluster::{ - jobs::job_session::{JobExecutor, JobPartialRequestAction, JobPartialResponseAction}, - Error, KeyStorage, NodeId, SessionId, -}; -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -/// Unknown sessions report job. -pub struct UnknownSessionsJob { - /// Target node id. - target_node_id: Option, - /// Keys storage. - key_storage: Arc, -} - -impl UnknownSessionsJob { - pub fn new_on_slave(key_storage: Arc) -> Self { - UnknownSessionsJob { - target_node_id: None, - key_storage: key_storage, - } - } - - pub fn new_on_master(key_storage: Arc, self_node_id: NodeId) -> Self { - UnknownSessionsJob { - target_node_id: Some(self_node_id), - key_storage: key_storage, - } - } -} - -impl JobExecutor for UnknownSessionsJob { - type PartialJobRequest = NodeId; - type PartialJobResponse = BTreeSet; - type JobResponse = BTreeMap>; - - fn prepare_partial_request( - &self, - _node: &NodeId, - _nodes: &BTreeSet, - ) -> Result { - Ok(self.target_node_id.clone().expect("prepare_partial_request is only called on master nodes; this field is filled on master nodes in constructor; qed")) - } - - fn process_partial_request( - &mut self, - partial_request: NodeId, - ) -> Result>, Error> { - Ok(JobPartialRequestAction::Respond( - self.key_storage - .iter() - .filter(|&(_, ref key_share)| { - !key_share - .versions - .last() - .map(|v| v.id_numbers.contains_key(&partial_request)) - .unwrap_or(true) - }) - .map(|(id, _)| id.clone()) - .collect(), - )) - } - - fn check_partial_response( - &mut self, - _sender: &NodeId, - _partial_response: &BTreeSet, - ) -> Result { - Ok(JobPartialResponseAction::Accept) - } - - // TODO [Opt]: - // currently ALL unknown sessions are sent at once - it is better to limit messages by size/len => add partial-partial responses - fn compute_response( - &self, - partial_responses: &BTreeMap>, - ) -> Result>, Error> { - let mut result: BTreeMap> = BTreeMap::new(); - for (node_id, node_sessions) in partial_responses { - for node_session in node_sessions { - result - .entry(node_session.clone()) - .or_insert_with(Default::default) - .insert(node_id.clone()); - } - } - - Ok(result) - } -} diff --git a/secret-store/src/key_server_cluster/math.rs b/secret-store/src/key_server_cluster/math.rs deleted file mode 100644 index 7394170aea..0000000000 --- a/secret-store/src/key_server_cluster/math.rs +++ /dev/null @@ -1,1574 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{H256, U256}; -use ethkey::{math, Generator, Public, Random, Secret, Signature}; -use hash::keccak; -use key_server_cluster::Error; - -/// Encryption result. -#[derive(Debug)] -pub struct EncryptedSecret { - /// Common encryption point. - pub common_point: Public, - /// Ecnrypted point. - pub encrypted_point: Public, -} - -/// Create zero scalar. -pub fn zero_scalar() -> Secret { - Secret::zero() -} - -/// Convert hash to EC scalar (modulo curve order). -pub fn to_scalar(hash: H256) -> Result { - let scalar: U256 = hash.into(); - let scalar: H256 = (scalar % math::curve_order()).into(); - let scalar = Secret::from(scalar.0); - scalar.check_validity()?; - Ok(scalar) -} - -/// Generate random scalar. -pub fn generate_random_scalar() -> Result { - Ok(Random.generate()?.secret().clone()) -} - -/// Generate random point. -pub fn generate_random_point() -> Result { - Ok(Random.generate()?.public().clone()) -} - -/// Get X coordinate of point. -fn public_x(public: &Public) -> H256 { - public[0..32].into() -} - -/// Get Y coordinate of point. -fn public_y(public: &Public) -> H256 { - public[32..64].into() -} - -/// Compute publics sum. -pub fn compute_public_sum<'a, I>(mut publics: I) -> Result -where - I: Iterator, -{ - let mut sum = publics - .next() - .expect("compute_public_sum is called when there's at least one public; qed") - .clone(); - while let Some(public) = publics.next() { - math::public_add(&mut sum, &public)?; - } - Ok(sum) -} - -/// Compute secrets sum. -pub fn compute_secret_sum<'a, I>(mut secrets: I) -> Result -where - I: Iterator, -{ - let mut sum = secrets - .next() - .expect("compute_secret_sum is called when there's at least one secret; qed") - .clone(); - while let Some(secret) = secrets.next() { - sum.add(secret)?; - } - Ok(sum) -} - -/// Compute secrets multiplication. -pub fn compute_secret_mul(secret1: &Secret, secret2: &Secret) -> Result { - let mut secret_mul = secret1.clone(); - secret_mul.mul(secret2)?; - Ok(secret_mul) -} - -/// Compute secrets 'shadow' multiplication: coeff * multiplication(s[j] / (s[i] - s[j])) for every i != j -pub fn compute_shadow_mul<'a, I>( - coeff: &Secret, - self_secret: &Secret, - mut other_secrets: I, -) -> Result -where - I: Iterator, -{ - // when there are no other secrets, only coeff is left - let other_secret = match other_secrets.next() { - Some(other_secret) => other_secret, - None => return Ok(coeff.clone()), - }; - - let mut shadow_mul = self_secret.clone(); - shadow_mul.sub(other_secret)?; - shadow_mul.inv()?; - shadow_mul.mul(other_secret)?; - while let Some(other_secret) = other_secrets.next() { - let mut shadow_mul_element = self_secret.clone(); - shadow_mul_element.sub(other_secret)?; - shadow_mul_element.inv()?; - shadow_mul_element.mul(other_secret)?; - shadow_mul.mul(&shadow_mul_element)?; - } - - shadow_mul.mul(coeff)?; - Ok(shadow_mul) -} - -/// Update point by multiplying to random scalar -pub fn update_random_point(point: &mut Public) -> Result<(), Error> { - Ok(math::public_mul_secret(point, &generate_random_scalar()?)?) -} - -/// Generate random polynom of threshold degree -pub fn generate_random_polynom(threshold: usize) -> Result, Error> { - (0..threshold + 1) - .map(|_| generate_random_scalar()) - .collect() -} - -/// Compute value of polynom, using `node_number` as argument -pub fn compute_polynom(polynom: &[Secret], node_number: &Secret) -> Result { - debug_assert!(!polynom.is_empty()); - - let mut result = polynom[0].clone(); - for i in 1..polynom.len() { - // calculate pow(node_number, i) - let mut appendum = node_number.clone(); - appendum.pow(i)?; - - // calculate coeff * pow(point, i) - appendum.mul(&polynom[i])?; - - // calculate result + coeff * pow(point, i) - result.add(&appendum)?; - } - - Ok(result) -} - -/// Generate public keys for other participants. -pub fn public_values_generation( - threshold: usize, - derived_point: &Public, - polynom1: &[Secret], - polynom2: &[Secret], -) -> Result, Error> { - debug_assert_eq!(polynom1.len(), threshold + 1); - debug_assert_eq!(polynom2.len(), threshold + 1); - - // compute t+1 public values - let mut publics = Vec::with_capacity(threshold + 1); - for i in 0..threshold + 1 { - let coeff1 = &polynom1[i]; - - let mut multiplication1 = math::generation_point(); - math::public_mul_secret(&mut multiplication1, &coeff1)?; - - let coeff2 = &polynom2[i]; - let mut multiplication2 = derived_point.clone(); - math::public_mul_secret(&mut multiplication2, &coeff2)?; - - math::public_add(&mut multiplication1, &multiplication2)?; - - publics.push(multiplication1); - } - debug_assert_eq!(publics.len(), threshold + 1); - - Ok(publics) -} - -/// Check keys passed by other participants. -pub fn keys_verification( - threshold: usize, - derived_point: &Public, - number_id: &Secret, - secret1: &Secret, - secret2: &Secret, - publics: &[Public], -) -> Result { - // calculate left part - let mut multiplication1 = math::generation_point(); - math::public_mul_secret(&mut multiplication1, secret1)?; - - let mut multiplication2 = derived_point.clone(); - math::public_mul_secret(&mut multiplication2, secret2)?; - - math::public_add(&mut multiplication1, &multiplication2)?; - let left = multiplication1; - - // calculate right part - let mut right = publics[0].clone(); - for i in 1..threshold + 1 { - let mut secret_pow = number_id.clone(); - secret_pow.pow(i)?; - - let mut public_k = publics[i].clone(); - math::public_mul_secret(&mut public_k, &secret_pow)?; - - math::public_add(&mut right, &public_k)?; - } - - Ok(left == right) -} - -/// Compute secret subshare from passed secret value. -pub fn compute_secret_subshare<'a, I>( - threshold: usize, - secret_value: &Secret, - sender_id_number: &Secret, - other_id_numbers: I, -) -> Result -where - I: Iterator, -{ - let mut subshare = compute_shadow_mul(secret_value, sender_id_number, other_id_numbers)?; - if threshold % 2 != 0 { - subshare.neg()?; - } - - Ok(subshare) -} - -/// Compute secret share. -pub fn compute_secret_share<'a, I>(secret_values: I) -> Result -where - I: Iterator, -{ - compute_secret_sum(secret_values) -} - -/// Compute public key share. -pub fn compute_public_share(self_secret_value: &Secret) -> Result { - let mut public_share = math::generation_point(); - math::public_mul_secret(&mut public_share, self_secret_value)?; - Ok(public_share) -} - -/// Compute joint public key. -pub fn compute_joint_public<'a, I>(public_shares: I) -> Result -where - I: Iterator, -{ - compute_public_sum(public_shares) -} - -/// Compute joint secret key from N secret coefficients. -#[cfg(test)] -pub fn compute_joint_secret<'a, I>(secret_coeffs: I) -> Result -where - I: Iterator, -{ - compute_secret_sum(secret_coeffs) -} - -/// Compute joint secret key from t+1 secret shares. -pub fn compute_joint_secret_from_shares<'a>( - t: usize, - secret_shares: &[&'a Secret], - id_numbers: &[&'a Secret], -) -> Result { - let secret_share_0 = secret_shares[0]; - let id_number_0 = id_numbers[0]; - let other_nodes_numbers = id_numbers.iter().skip(1).cloned(); - let mut result = compute_node_shadow(secret_share_0, id_number_0, other_nodes_numbers)?; - for i in 1..secret_shares.len() { - let secret_share_i = secret_shares[i]; - let id_number_i = id_numbers[i]; - let other_nodes_numbers = id_numbers - .iter() - .enumerate() - .filter(|&(j, _)| j != i) - .map(|(_, n)| n) - .cloned(); - let addendum = compute_node_shadow(secret_share_i, id_number_i, other_nodes_numbers)?; - result.add(&addendum)?; - } - - if t % 2 != 0 { - result.neg()?; - } - - Ok(result) -} - -/// Encrypt secret with joint public key. -pub fn encrypt_secret(secret: &Public, joint_public: &Public) -> Result { - // this is performed by KS-cluster client (or KS master) - let key_pair = Random.generate()?; - - // k * T - let mut common_point = math::generation_point(); - math::public_mul_secret(&mut common_point, key_pair.secret())?; - - // M + k * y - let mut encrypted_point = joint_public.clone(); - math::public_mul_secret(&mut encrypted_point, key_pair.secret())?; - math::public_add(&mut encrypted_point, secret)?; - - Ok(EncryptedSecret { - common_point: common_point, - encrypted_point: encrypted_point, - }) -} - -/// Compute shadow for the node. -pub fn compute_node_shadow<'a, I>( - node_secret_share: &Secret, - node_number: &Secret, - other_nodes_numbers: I, -) -> Result -where - I: Iterator, -{ - compute_shadow_mul(node_secret_share, node_number, other_nodes_numbers) -} - -/// Compute shadow point for the node. -pub fn compute_node_shadow_point( - access_key: &Secret, - common_point: &Public, - node_shadow: &Secret, - decrypt_shadow: Option, -) -> Result<(Public, Option), Error> { - let mut shadow_key = node_shadow.clone(); - let decrypt_shadow = match decrypt_shadow { - None => None, - Some(mut decrypt_shadow) => { - // update shadow key - shadow_key.mul(&decrypt_shadow)?; - // now udate decrypt shadow itself - decrypt_shadow.dec()?; - decrypt_shadow.mul(node_shadow)?; - Some(decrypt_shadow) - } - }; - shadow_key.mul(access_key)?; - - let mut node_shadow_point = common_point.clone(); - math::public_mul_secret(&mut node_shadow_point, &shadow_key)?; - Ok((node_shadow_point, decrypt_shadow)) -} - -/// Compute joint shadow point. -pub fn compute_joint_shadow_point<'a, I>(nodes_shadow_points: I) -> Result -where - I: Iterator, -{ - compute_public_sum(nodes_shadow_points) -} - -/// Compute joint shadow point (version for tests). -#[cfg(test)] -pub fn compute_joint_shadow_point_test<'a, I>( - access_key: &Secret, - common_point: &Public, - nodes_shadows: I, -) -> Result -where - I: Iterator, -{ - let mut joint_shadow = compute_secret_sum(nodes_shadows)?; - joint_shadow.mul(access_key)?; - - let mut joint_shadow_point = common_point.clone(); - math::public_mul_secret(&mut joint_shadow_point, &joint_shadow)?; - Ok(joint_shadow_point) -} - -/// Decrypt data using joint shadow point. -pub fn decrypt_with_joint_shadow( - threshold: usize, - access_key: &Secret, - encrypted_point: &Public, - joint_shadow_point: &Public, -) -> Result { - let mut inv_access_key = access_key.clone(); - inv_access_key.inv()?; - - let mut mul = joint_shadow_point.clone(); - math::public_mul_secret(&mut mul, &inv_access_key)?; - - let mut decrypted_point = encrypted_point.clone(); - if threshold % 2 != 0 { - math::public_add(&mut decrypted_point, &mul)?; - } else { - math::public_sub(&mut decrypted_point, &mul)?; - } - - Ok(decrypted_point) -} - -/// Prepare common point for shadow decryption. -pub fn make_common_shadow_point( - threshold: usize, - mut common_point: Public, -) -> Result { - if threshold % 2 != 1 { - Ok(common_point) - } else { - math::public_negate(&mut common_point)?; - Ok(common_point) - } -} - -/// Decrypt shadow-encrypted secret. -#[cfg(test)] -pub fn decrypt_with_shadow_coefficients( - mut decrypted_shadow: Public, - mut common_shadow_point: Public, - shadow_coefficients: Vec, -) -> Result { - let shadow_coefficients_sum = compute_secret_sum(shadow_coefficients.iter())?; - math::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum)?; - math::public_add(&mut decrypted_shadow, &common_shadow_point)?; - Ok(decrypted_shadow) -} - -/// Decrypt data using joint secret (version for tests). -#[cfg(test)] -pub fn decrypt_with_joint_secret( - encrypted_point: &Public, - common_point: &Public, - joint_secret: &Secret, -) -> Result { - let mut common_point_mul = common_point.clone(); - math::public_mul_secret(&mut common_point_mul, joint_secret)?; - - let mut decrypted_point = encrypted_point.clone(); - math::public_sub(&mut decrypted_point, &common_point_mul)?; - - Ok(decrypted_point) -} - -/// Combine message hash with public key X coordinate. -pub fn combine_message_hash_with_public( - message_hash: &H256, - public: &Public, -) -> Result { - // buffer is just [message_hash | public.x] - let mut buffer = [0; 64]; - buffer[0..32].copy_from_slice(&message_hash[0..32]); - buffer[32..64].copy_from_slice(&public[0..32]); - - // calculate hash of buffer - let hash = keccak(&buffer[..]); - - // map hash to EC finite field value - to_scalar(hash) -} - -/// Compute Schnorr signature share. -pub fn compute_schnorr_signature_share<'a, I>( - threshold: usize, - combined_hash: &Secret, - one_time_secret_coeff: &Secret, - node_secret_share: &Secret, - node_number: &Secret, - other_nodes_numbers: I, -) -> Result -where - I: Iterator, -{ - let mut sum = one_time_secret_coeff.clone(); - let mut subtrahend = compute_shadow_mul(combined_hash, node_number, other_nodes_numbers)?; - subtrahend.mul(node_secret_share)?; - if threshold % 2 == 0 { - sum.sub(&subtrahend)?; - } else { - sum.add(&subtrahend)?; - } - Ok(sum) -} - -/// Check Schnorr signature share. -pub fn _check_schnorr_signature_share<'a, I>( - _combined_hash: &Secret, - _signature_share: &Secret, - _public_share: &Public, - _one_time_public_share: &Public, - _node_numbers: I, -) -> Result -where - I: Iterator, -{ - // TODO [Trust]: in paper partial signature is checked using comparison: - // sig[i] * T = r[i] - c * lagrange_coeff(i) * y[i] - // => (k[i] - c * lagrange_coeff(i) * s[i]) * T = r[i] - c * lagrange_coeff(i) * y[i] - // => k[i] * T - c * lagrange_coeff(i) * s[i] * T = k[i] * T - c * lagrange_coeff(i) * y[i] - // => this means that y[i] = s[i] * T - // but when verifying signature (for t = 1), nonce public (r) is restored using following expression: - // r = (sig[0] + sig[1]) * T - c * y - // r = (k[0] - c * lagrange_coeff(0) * s[0] + k[1] - c * lagrange_coeff(1) * s[1]) * T - c * y - // r = (k[0] + k[1]) * T - c * (lagrange_coeff(0) * s[0] + lagrange_coeff(1) * s[1]) * T - c * y - // r = r - c * (lagrange_coeff(0) * s[0] + lagrange_coeff(1) * s[1]) * T - c * y - // => -c * y = c * (lagrange_coeff(0) * s[0] + lagrange_coeff(1) * s[1]) * T - // => -y = (lagrange_coeff(0) * s[0] + lagrange_coeff(1) * s[1]) * T - // => y[i] != s[i] * T - // => some other way is required - Ok(true) -} - -/// Compute Schnorr signature. -pub fn compute_schnorr_signature<'a, I>(signature_shares: I) -> Result -where - I: Iterator, -{ - compute_secret_sum(signature_shares) -} - -/// Locally compute Schnorr signature as described in https://en.wikipedia.org/wiki/Schnorr_signature#Signing. -#[cfg(test)] -pub fn local_compute_schnorr_signature( - nonce: &Secret, - secret: &Secret, - message_hash: &Secret, -) -> Result<(Secret, Secret), Error> { - let mut nonce_public = math::generation_point(); - math::public_mul_secret(&mut nonce_public, &nonce).unwrap(); - - let combined_hash = combine_message_hash_with_public(message_hash, &nonce_public)?; - - let mut sig_subtrahend = combined_hash.clone(); - sig_subtrahend.mul(secret)?; - let mut sig = nonce.clone(); - sig.sub(&sig_subtrahend)?; - - Ok((combined_hash, sig)) -} - -/// Verify Schnorr signature as described in https://en.wikipedia.org/wiki/Schnorr_signature#Verifying. -#[cfg(test)] -pub fn verify_schnorr_signature( - public: &Public, - signature: &(Secret, Secret), - message_hash: &H256, -) -> Result { - let mut addendum = math::generation_point(); - math::public_mul_secret(&mut addendum, &signature.1)?; - let mut nonce_public = public.clone(); - math::public_mul_secret(&mut nonce_public, &signature.0)?; - math::public_add(&mut nonce_public, &addendum)?; - - let combined_hash = combine_message_hash_with_public(message_hash, &nonce_public)?; - Ok(combined_hash == signature.0) -} - -/// Compute R part of ECDSA signature. -pub fn compute_ecdsa_r(nonce_public: &Public) -> Result { - to_scalar(public_x(nonce_public)) -} - -/// Compute share of S part of ECDSA signature. -pub fn compute_ecdsa_s_share( - inv_nonce_share: &Secret, - inv_nonce_mul_secret: &Secret, - signature_r: &Secret, - message_hash: &Secret, -) -> Result { - let mut nonce_inv_share_mul_message_hash = inv_nonce_share.clone(); - nonce_inv_share_mul_message_hash.mul(&message_hash.clone().into())?; - - let mut nonce_inv_share_mul_secret_share_mul_r = inv_nonce_mul_secret.clone(); - nonce_inv_share_mul_secret_share_mul_r.mul(signature_r)?; - - let mut signature_s_share = nonce_inv_share_mul_message_hash; - signature_s_share.add(&nonce_inv_share_mul_secret_share_mul_r)?; - - Ok(signature_s_share) -} - -/// Compute S part of ECDSA signature from shares. -pub fn compute_ecdsa_s( - t: usize, - signature_s_shares: &[Secret], - id_numbers: &[Secret], -) -> Result { - let double_t = t * 2; - debug_assert!(id_numbers.len() >= double_t + 1); - debug_assert_eq!(signature_s_shares.len(), id_numbers.len()); - - compute_joint_secret_from_shares( - double_t, - &signature_s_shares - .iter() - .take(double_t + 1) - .collect::>(), - &id_numbers.iter().take(double_t + 1).collect::>(), - ) -} - -/// Serialize ECDSA signature to [r][s]v form. -pub fn serialize_ecdsa_signature( - nonce_public: &Public, - signature_r: Secret, - mut signature_s: Secret, -) -> Signature { - // compute recovery param - let mut signature_v = { - let nonce_public_x = public_x(nonce_public); - let nonce_public_y: U256 = public_y(nonce_public).into(); - let nonce_public_y_is_odd = !(nonce_public_y % 2).is_zero(); - let bit0 = if nonce_public_y_is_odd { 1u8 } else { 0u8 }; - let bit1 = if nonce_public_x != *signature_r { - 2u8 - } else { - 0u8 - }; - bit0 | bit1 - }; - - // fix high S - let curve_order = math::curve_order(); - let curve_order_half = curve_order / 2; - let s_numeric: U256 = (*signature_s).into(); - if s_numeric > curve_order_half { - let signature_s_hash: H256 = (curve_order - s_numeric).into(); - signature_s = signature_s_hash.into(); - signature_v ^= 1; - } - - // serialize as [r][s]v - let mut signature = [0u8; 65]; - signature[..32].copy_from_slice(&**signature_r); - signature[32..64].copy_from_slice(&**signature_s); - signature[64] = signature_v; - - signature.into() -} - -/// Compute share of ECDSA reversed-nonce coefficient. Result of this_coeff * secret_share gives us a share of inv(nonce). -pub fn compute_ecdsa_inversed_secret_coeff_share( - secret_share: &Secret, - nonce_share: &Secret, - zero_share: &Secret, -) -> Result { - let mut coeff = secret_share.clone(); - coeff.mul(nonce_share).unwrap(); - coeff.add(zero_share).unwrap(); - Ok(coeff) -} - -/// Compute ECDSA reversed-nonce coefficient from its shares. Result of this_coeff * secret_share gives us a share of inv(nonce). -pub fn compute_ecdsa_inversed_secret_coeff_from_shares( - t: usize, - id_numbers: &[Secret], - shares: &[Secret], -) -> Result { - debug_assert_eq!(shares.len(), 2 * t + 1); - debug_assert_eq!(shares.len(), id_numbers.len()); - - let u_shares = (0..2 * t + 1) - .map(|i| { - compute_shadow_mul( - &shares[i], - &id_numbers[i], - id_numbers - .iter() - .enumerate() - .filter(|&(j, _)| i != j) - .map(|(_, id)| id) - .take(2 * t), - ) - }) - .collect::, _>>()?; - - // compute u - let u = compute_secret_sum(u_shares.iter())?; - - // compute inv(u) - let mut u_inv = u; - u_inv.inv()?; - Ok(u_inv) -} - -#[cfg(test)] -pub mod tests { - use super::*; - use ethkey::{recover, verify_public, KeyPair}; - use std::iter::once; - - #[derive(Clone)] - struct KeyGenerationArtifacts { - id_numbers: Vec, - polynoms1: Vec>, - secrets1: Vec>, - public_shares: Vec, - secret_shares: Vec, - joint_public: Public, - } - - struct ZeroGenerationArtifacts { - polynoms1: Vec>, - secret_shares: Vec, - } - - fn prepare_polynoms1(t: usize, n: usize, secret_required: Option) -> Vec> { - let mut polynoms1: Vec<_> = (0..n) - .map(|_| generate_random_polynom(t).unwrap()) - .collect(); - // if we need specific secret to be shared, update polynoms so that sum of their free terms = required secret - if let Some(mut secret_required) = secret_required { - for polynom1 in polynoms1.iter_mut().take(n - 1) { - let secret_coeff1 = generate_random_scalar().unwrap(); - secret_required.sub(&secret_coeff1).unwrap(); - polynom1[0] = secret_coeff1; - } - - polynoms1[n - 1][0] = secret_required; - } - polynoms1 - } - - fn run_key_generation( - t: usize, - n: usize, - id_numbers: Option>, - secret_required: Option, - ) -> KeyGenerationArtifacts { - // === PART1: DKG === - - // data, gathered during initialization - let derived_point = Random.generate().unwrap().public().clone(); - let id_numbers: Vec<_> = match id_numbers { - Some(id_numbers) => id_numbers, - None => (0..n).map(|_| generate_random_scalar().unwrap()).collect(), - }; - - // data, generated during keys dissemination - let polynoms1 = prepare_polynoms1(t, n, secret_required); - let secrets1: Vec<_> = (0..n) - .map(|i| { - (0..n) - .map(|j| compute_polynom(&polynoms1[i], &id_numbers[j]).unwrap()) - .collect::>() - }) - .collect(); - - // following data is used only on verification step - let polynoms2: Vec<_> = (0..n) - .map(|_| generate_random_polynom(t).unwrap()) - .collect(); - let secrets2: Vec<_> = (0..n) - .map(|i| { - (0..n) - .map(|j| compute_polynom(&polynoms2[i], &id_numbers[j]).unwrap()) - .collect::>() - }) - .collect(); - let publics: Vec<_> = (0..n) - .map(|i| { - public_values_generation(t, &derived_point, &polynoms1[i], &polynoms2[i]).unwrap() - }) - .collect(); - - // keys verification - (0..n).for_each(|i| { - (0..n).filter(|&j| i != j).for_each(|j| { - assert!(keys_verification( - t, - &derived_point, - &id_numbers[i], - &secrets1[j][i], - &secrets2[j][i], - &publics[j] - ) - .unwrap()); - }) - }); - - // data, generated during keys generation - let public_shares: Vec<_> = (0..n) - .map(|i| compute_public_share(&polynoms1[i][0]).unwrap()) - .collect(); - let secret_shares: Vec<_> = (0..n) - .map(|i| compute_secret_share(secrets1.iter().map(|s| &s[i])).unwrap()) - .collect(); - - // joint public key, as a result of DKG - let joint_public = compute_joint_public(public_shares.iter()).unwrap(); - - KeyGenerationArtifacts { - id_numbers: id_numbers, - polynoms1: polynoms1, - secrets1: secrets1, - public_shares: public_shares, - secret_shares: secret_shares, - joint_public: joint_public, - } - } - - fn run_zero_key_generation( - t: usize, - n: usize, - id_numbers: &[Secret], - ) -> ZeroGenerationArtifacts { - // data, generated during keys dissemination - let polynoms1 = prepare_polynoms1(t, n, Some(zero_scalar())); - let secrets1: Vec<_> = (0..n) - .map(|i| { - (0..n) - .map(|j| compute_polynom(&polynoms1[i], &id_numbers[j]).unwrap()) - .collect::>() - }) - .collect(); - - // data, generated during keys generation - let secret_shares: Vec<_> = (0..n) - .map(|i| compute_secret_share(secrets1.iter().map(|s| &s[i])).unwrap()) - .collect(); - - ZeroGenerationArtifacts { - polynoms1: polynoms1, - secret_shares: secret_shares, - } - } - - fn run_key_share_refreshing( - old_t: usize, - new_t: usize, - new_n: usize, - old_artifacts: &KeyGenerationArtifacts, - ) -> KeyGenerationArtifacts { - // === share refreshing protocol from - // === based on "Verifiable Secret Redistribution for Threshold Sharing Schemes" - // === http://www.cs.cmu.edu/~wing/publications/CMU-CS-02-114.pdf - - // generate new id_numbers for new nodes - let new_nodes = new_n.saturating_sub(old_artifacts.id_numbers.len()); - let id_numbers: Vec<_> = old_artifacts - .id_numbers - .iter() - .take(new_n) - .cloned() - .chain((0..new_nodes).map(|_| generate_random_scalar().unwrap())) - .collect(); - - // on every authorized node: generate random polynomial ai(j) = si + ... + ai[new_t - 1] * j^(new_t - 1) - let mut subshare_polynoms = Vec::new(); - for i in 0..old_t + 1 { - let mut subshare_polynom = generate_random_polynom(new_t).unwrap(); - subshare_polynom[0] = old_artifacts.secret_shares[i].clone(); - subshare_polynoms.push(subshare_polynom); - } - - // on every authorized node: calculate subshare for every new node - let mut subshares = Vec::new(); - for j in 0..new_n { - let mut subshares_to_j = Vec::new(); - for i in 0..old_t + 1 { - let subshare_from_i_to_j = - compute_polynom(&subshare_polynoms[i], &id_numbers[j]).unwrap(); - subshares_to_j.push(subshare_from_i_to_j); - } - subshares.push(subshares_to_j); - } - - // on every new node: generate new share using Lagrange interpolation - // on every node: generate new share using Lagrange interpolation - let mut new_secret_shares = Vec::new(); - for j in 0..new_n { - let mut subshares_to_j = Vec::new(); - for i in 0..old_t + 1 { - let subshare_from_i = &subshares[j][i]; - let id_number_i = &id_numbers[i]; - let other_id_numbers = (0usize..old_t + 1) - .filter(|j| *j != i) - .map(|j| &id_numbers[j]); - let mut subshare_from_i = - compute_shadow_mul(subshare_from_i, id_number_i, other_id_numbers).unwrap(); - if old_t % 2 != 0 { - subshare_from_i.neg().unwrap(); - } - subshares_to_j.push(subshare_from_i); - } - new_secret_shares.push(compute_secret_sum(subshares_to_j.iter()).unwrap()); - } - - let mut result = old_artifacts.clone(); - result.id_numbers = id_numbers; - result.secret_shares = new_secret_shares; - result - } - - fn run_multiplication_protocol( - t: usize, - secret_shares1: &[Secret], - secret_shares2: &[Secret], - ) -> Vec { - let n = secret_shares1.len(); - assert!(t * 2 + 1 <= n); - - // shares of secrets multiplication = multiplication of secrets shares - let mul_shares: Vec<_> = (0..n) - .map(|i| { - let share1 = secret_shares1[i].clone(); - let share2 = secret_shares2[i].clone(); - let mut mul_share = share1; - mul_share.mul(&share2).unwrap(); - mul_share - }) - .collect(); - - mul_shares - } - - fn run_reciprocal_protocol(t: usize, artifacts: &KeyGenerationArtifacts) -> Vec { - // === Given a secret x mod r which is shared among n players, it is - // === required to generate shares of inv(x) mod r with out revealing - // === any information about x or inv(x). - // === https://www.researchgate.net/publication/280531698_Robust_Threshold_Elliptic_Curve_Digital_Signature - - // generate shared random secret e for given t - let n = artifacts.id_numbers.len(); - assert!(t * 2 + 1 <= n); - let e_artifacts = run_key_generation(t, n, Some(artifacts.id_numbers.clone()), None); - - // generate shares of zero for 2 * t threshold - let z_artifacts = run_zero_key_generation(2 * t, n, &artifacts.id_numbers); - - // each player computes && broadcast u[i] = x[i] * e[i] + z[i] - let ui: Vec<_> = (0..n) - .map(|i| { - compute_ecdsa_inversed_secret_coeff_share( - &artifacts.secret_shares[i], - &e_artifacts.secret_shares[i], - &z_artifacts.secret_shares[i], - ) - .unwrap() - }) - .collect(); - - // players can interpolate the polynomial of degree 2t and compute u && inv(u): - let u_inv = compute_ecdsa_inversed_secret_coeff_from_shares( - t, - &artifacts - .id_numbers - .iter() - .take(2 * t + 1) - .cloned() - .collect::>(), - &ui.iter().take(2 * t + 1).cloned().collect::>(), - ) - .unwrap(); - - // each player Pi computes his share of inv(x) as e[i] * inv(u) - let x_inv_shares: Vec<_> = (0..n) - .map(|i| { - let mut x_inv_share = e_artifacts.secret_shares[i].clone(); - x_inv_share.mul(&u_inv).unwrap(); - x_inv_share - }) - .collect(); - - x_inv_shares - } - - pub fn do_encryption_and_decryption( - t: usize, - joint_public: &Public, - id_numbers: &[Secret], - secret_shares: &[Secret], - joint_secret: Option<&Secret>, - document_secret_plain: Public, - ) -> (Public, Public) { - // === PART2: encryption using joint public key === - - // the next line is executed on KeyServer-client - let encrypted_secret = encrypt_secret(&document_secret_plain, &joint_public).unwrap(); - - // === PART3: decryption === - - // next line is executed on KeyServer client - let access_key = generate_random_scalar().unwrap(); - - // use t + 1 nodes to compute joint shadow point - let nodes_shadows: Vec<_> = (0..t + 1) - .map(|i| { - compute_node_shadow( - &secret_shares[i], - &id_numbers[i], - id_numbers - .iter() - .enumerate() - .filter(|&(j, _)| j != i) - .take(t) - .map(|(_, id_number)| id_number), - ) - .unwrap() - }) - .collect(); - - let nodes_shadow_points: Vec<_> = nodes_shadows - .iter() - .map(|s| { - compute_node_shadow_point(&access_key, &encrypted_secret.common_point, s, None) - .unwrap() - }) - .map(|sp| sp.0) - .collect(); - - assert_eq!(nodes_shadows.len(), t + 1); - assert_eq!(nodes_shadow_points.len(), t + 1); - - let joint_shadow_point = compute_joint_shadow_point(nodes_shadow_points.iter()).unwrap(); - let joint_shadow_point_test = compute_joint_shadow_point_test( - &access_key, - &encrypted_secret.common_point, - nodes_shadows.iter(), - ) - .unwrap(); - assert_eq!(joint_shadow_point, joint_shadow_point_test); - - // decrypt encrypted secret using joint shadow point - let document_secret_decrypted = decrypt_with_joint_shadow( - t, - &access_key, - &encrypted_secret.encrypted_point, - &joint_shadow_point, - ) - .unwrap(); - - // decrypt encrypted secret using joint secret [just for test] - let document_secret_decrypted_test = match joint_secret { - Some(joint_secret) => decrypt_with_joint_secret( - &encrypted_secret.encrypted_point, - &encrypted_secret.common_point, - joint_secret, - ) - .unwrap(), - None => document_secret_decrypted.clone(), - }; - - (document_secret_decrypted, document_secret_decrypted_test) - } - - #[test] - fn full_encryption_math_session() { - let test_cases = [ - (0, 2), - (1, 2), - (1, 3), - (2, 3), - (1, 4), - (2, 4), - (3, 4), - (1, 5), - (2, 5), - (3, 5), - (4, 5), - (1, 10), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - ]; - for &(t, n) in &test_cases { - let artifacts = run_key_generation(t, n, None, None); - - // compute joint private key [just for test] - let joint_secret = - compute_joint_secret(artifacts.polynoms1.iter().map(|p| &p[0])).unwrap(); - let joint_key_pair = KeyPair::from_secret(joint_secret.clone()).unwrap(); - assert_eq!(&artifacts.joint_public, joint_key_pair.public()); - - // check secret shares computation [just for test] - let secret_shares_polynom: Vec<_> = (0..t + 1) - .map(|k| compute_secret_share(artifacts.polynoms1.iter().map(|p| &p[k])).unwrap()) - .collect(); - let secret_shares_calculated_from_polynom: Vec<_> = artifacts - .id_numbers - .iter() - .map(|id_number| compute_polynom(&*secret_shares_polynom, id_number).unwrap()) - .collect(); - assert_eq!( - artifacts.secret_shares, - secret_shares_calculated_from_polynom - ); - - // now encrypt and decrypt data - let document_secret_plain = generate_random_point().unwrap(); - let (document_secret_decrypted, document_secret_decrypted_test) = - do_encryption_and_decryption( - t, - &artifacts.joint_public, - &artifacts.id_numbers, - &artifacts.secret_shares, - Some(&joint_secret), - document_secret_plain.clone(), - ); - - assert_eq!(document_secret_plain, document_secret_decrypted_test); - assert_eq!(document_secret_plain, document_secret_decrypted); - } - } - - #[test] - fn local_signature_works() { - let key_pair = Random.generate().unwrap(); - let message_hash = "0000000000000000000000000000000000000000000000000000000000000042" - .parse() - .unwrap(); - let nonce = generate_random_scalar().unwrap(); - let signature = - local_compute_schnorr_signature(&nonce, key_pair.secret(), &message_hash).unwrap(); - assert_eq!( - verify_schnorr_signature(key_pair.public(), &signature, &message_hash), - Ok(true) - ); - } - - #[test] - fn full_schnorr_signature_math_session() { - let test_cases = [ - (0, 1), - (0, 2), - (1, 2), - (1, 3), - (2, 3), - (1, 4), - (2, 4), - (3, 4), - (1, 5), - (2, 5), - (3, 5), - (4, 5), - (1, 10), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - ]; - for &(t, n) in &test_cases { - // hash of the message to be signed - let message_hash: Secret = - "0000000000000000000000000000000000000000000000000000000000000042" - .parse() - .unwrap(); - - // === MiDS-S algorithm === - // setup: all nodes share master secret key && every node knows master public key - let artifacts = run_key_generation(t, n, None, None); - - // in this gap (not related to math): - // master node should ask every other node if it is able to do a signing - // if there are < than t+1 nodes, able to sign => error - // select t+1 nodes for signing session - // all steps below are for this subset of nodes - let n = t + 1; - - // step 1: run DKG to generate one-time secret key (nonce) - let id_numbers = artifacts.id_numbers.iter().cloned().take(n).collect(); - let one_time_artifacts = run_key_generation(t, n, Some(id_numbers), None); - - // step 2: message hash && x coordinate of one-time public value are combined - let combined_hash = - combine_message_hash_with_public(&message_hash, &one_time_artifacts.joint_public) - .unwrap(); - - // step 3: compute signature shares - let partial_signatures: Vec<_> = (0..n) - .map(|i| { - compute_schnorr_signature_share( - t, - &combined_hash, - &one_time_artifacts.polynoms1[i][0], - &artifacts.secret_shares[i], - &artifacts.id_numbers[i], - artifacts - .id_numbers - .iter() - .enumerate() - .filter(|&(j, _)| i != j) - .map(|(_, n)| n) - .take(t), - ) - .unwrap() - }) - .collect(); - - // step 4: receive and verify signatures shares from other nodes - let received_signatures: Vec> = (0..n) - .map(|i| { - (0..n) - .filter(|j| i != *j) - .map(|j| { - let signature_share = partial_signatures[j].clone(); - assert!(_check_schnorr_signature_share( - &combined_hash, - &signature_share, - &artifacts.public_shares[j], - &one_time_artifacts.public_shares[j], - artifacts.id_numbers.iter().take(t) - ) - .unwrap_or(false)); - signature_share - }) - .collect() - }) - .collect(); - - // step 5: compute signature - let signatures: Vec<_> = (0..n) - .map(|i| { - ( - combined_hash.clone(), - compute_schnorr_signature( - received_signatures[i] - .iter() - .chain(once(&partial_signatures[i])), - ) - .unwrap(), - ) - }) - .collect(); - - // === verify signature === - let master_secret = - compute_joint_secret(artifacts.polynoms1.iter().map(|p| &p[0])).unwrap(); - let nonce = - compute_joint_secret(one_time_artifacts.polynoms1.iter().map(|p| &p[0])).unwrap(); - let local_signature = - local_compute_schnorr_signature(&nonce, &master_secret, &message_hash).unwrap(); - for signature in &signatures { - assert_eq!(signature, &local_signature); - assert_eq!( - verify_schnorr_signature(&artifacts.joint_public, signature, &message_hash), - Ok(true) - ); - } - } - } - - #[test] - fn full_ecdsa_signature_math_session() { - let test_cases = [(2, 5), (2, 6), (3, 11), (4, 11)]; - for &(t, n) in &test_cases { - // values that can be hardcoded - let joint_secret: Secret = Random.generate().unwrap().secret().clone(); - let joint_nonce: Secret = Random.generate().unwrap().secret().clone(); - let message_hash: H256 = H256::random(); - - // convert message hash to EC scalar - let message_hash_scalar = to_scalar(message_hash.clone()).unwrap(); - - // generate secret key shares - let artifacts = run_key_generation(t, n, None, Some(joint_secret)); - - // generate nonce shares - let nonce_artifacts = - run_key_generation(t, n, Some(artifacts.id_numbers.clone()), Some(joint_nonce)); - - // compute nonce public - // x coordinate (mapped to EC field) of this public is the r-portion of signature - let nonce_public_shares: Vec<_> = (0..n) - .map(|i| compute_public_share(&nonce_artifacts.polynoms1[i][0]).unwrap()) - .collect(); - let nonce_public = compute_joint_public(nonce_public_shares.iter()).unwrap(); - let signature_r = compute_ecdsa_r(&nonce_public).unwrap(); - - // compute shares of inv(nonce) so that both nonce && inv(nonce) are still unknown to all nodes - let nonce_inv_shares = run_reciprocal_protocol(t, &nonce_artifacts); - - // compute multiplication of secret-shares * inv-nonce-shares - let mul_shares = - run_multiplication_protocol(t, &artifacts.secret_shares, &nonce_inv_shares); - - // compute shares for s portion of signature: nonce_inv * (message_hash + secret * signature_r) - // every node broadcasts this share - let double_t = 2 * t; - let signature_s_shares: Vec<_> = (0..double_t + 1) - .map(|i| { - compute_ecdsa_s_share( - &nonce_inv_shares[i], - &mul_shares[i], - &signature_r, - &message_hash_scalar, - ) - .unwrap() - }) - .collect(); - - // compute signature_s from received shares - let signature_s = compute_ecdsa_s( - t, - &signature_s_shares, - &artifacts - .id_numbers - .iter() - .take(double_t + 1) - .cloned() - .collect::>(), - ) - .unwrap(); - - // check signature - let signature_actual = - serialize_ecdsa_signature(&nonce_public, signature_r, signature_s); - let joint_secret = - compute_joint_secret(artifacts.polynoms1.iter().map(|p| &p[0])).unwrap(); - let joint_secret_pair = KeyPair::from_secret(joint_secret).unwrap(); - assert_eq!( - recover(&signature_actual, &message_hash).unwrap(), - *joint_secret_pair.public() - ); - assert!( - verify_public(joint_secret_pair.public(), &signature_actual, &message_hash) - .unwrap() - ); - } - } - - #[test] - fn full_generation_math_session_with_refreshing_shares() { - let test_cases = vec![(1, 4), (6, 10)]; - for (t, n) in test_cases { - // generate key using t-of-n session - let artifacts1 = run_key_generation(t, n, None, None); - let joint_secret1 = - compute_joint_secret(artifacts1.polynoms1.iter().map(|p1| &p1[0])).unwrap(); - - // let's say we want to refresh existing secret shares - // by doing this every T seconds, and assuming that in each T-second period adversary KS is not able to collect t+1 secret shares - // we can be sure that the scheme is secure - let artifacts2 = run_key_share_refreshing(t, t, n, &artifacts1); - let joint_secret2 = compute_joint_secret_from_shares( - t, - &artifacts2 - .secret_shares - .iter() - .take(t + 1) - .collect::>(), - &artifacts2.id_numbers.iter().take(t + 1).collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret2); - - // refresh again - let artifacts3 = run_key_share_refreshing(t, t, n, &artifacts2); - let joint_secret3 = compute_joint_secret_from_shares( - t, - &artifacts3 - .secret_shares - .iter() - .take(t + 1) - .collect::>(), - &artifacts3.id_numbers.iter().take(t + 1).collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret3); - } - } - - #[test] - fn full_generation_math_session_with_adding_new_nodes() { - let test_cases = vec![(1, 3), (1, 4), (6, 10)]; - for (t, n) in test_cases { - // generate key using t-of-n session - let artifacts1 = run_key_generation(t, n, None, None); - let joint_secret1 = - compute_joint_secret(artifacts1.polynoms1.iter().map(|p1| &p1[0])).unwrap(); - - // let's say we want to include additional couple of servers to the set - // so that scheme becames t-of-n+2 - let artifacts2 = run_key_share_refreshing(t, t, n + 2, &artifacts1); - let joint_secret2 = compute_joint_secret_from_shares( - t, - &artifacts2 - .secret_shares - .iter() - .take(t + 1) - .collect::>(), - &artifacts2.id_numbers.iter().take(t + 1).collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret2); - - // include another server (t-of-n+3) - let artifacts3 = run_key_share_refreshing(t, t, n + 3, &artifacts2); - let joint_secret3 = compute_joint_secret_from_shares( - t, - &artifacts3 - .secret_shares - .iter() - .take(t + 1) - .collect::>(), - &artifacts3.id_numbers.iter().take(t + 1).collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret3); - } - } - - #[test] - fn full_generation_math_session_with_decreasing_threshold() { - let (t, n) = (3, 5); - - // generate key using t-of-n session - let artifacts1 = run_key_generation(t, n, None, None); - - let joint_secret1 = - compute_joint_secret(artifacts1.polynoms1.iter().map(|p1| &p1[0])).unwrap(); - - // let's say we want to decrease threshold so that it becames (t-1)-of-n - let new_t = t - 1; - let artifacts2 = run_key_share_refreshing(t, new_t, n, &artifacts1); - let joint_secret2 = compute_joint_secret_from_shares( - new_t, - &artifacts2 - .secret_shares - .iter() - .take(new_t + 1) - .collect::>(), - &artifacts2 - .id_numbers - .iter() - .take(new_t + 1) - .collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret2); - - // let's say we want to decrease threshold once again so that it becames (t-2)-of-n - let t = t - 1; - let new_t = t - 2; - let artifacts3 = run_key_share_refreshing(t, new_t, n, &artifacts2); - let joint_secret3 = compute_joint_secret_from_shares( - new_t, - &artifacts3 - .secret_shares - .iter() - .take(new_t + 1) - .collect::>(), - &artifacts3 - .id_numbers - .iter() - .take(new_t + 1) - .collect::>(), - ) - .unwrap(); - assert_eq!(joint_secret1, joint_secret3); - } - - #[test] - fn full_zero_secret_generation_math_session() { - let test_cases = vec![(1, 4), (2, 4)]; - for (t, n) in test_cases { - // run joint zero generation session - let id_numbers: Vec<_> = (0..n).map(|_| generate_random_scalar().unwrap()).collect(); - let artifacts = run_zero_key_generation(t, n, &id_numbers); - - // check that zero secret is generated - // we can't compute secrets sum here, because result will be zero (invalid secret, unsupported by SECP256k1) - // so just use complement trick: x + (-x) = 0 - // TODO [Refac]: switch to SECP256K1-free scalar EC arithmetic - let partial_joint_secret = - compute_secret_sum(artifacts.polynoms1.iter().take(n - 1).map(|p| &p[0])).unwrap(); - let mut partial_joint_secret_complement = artifacts.polynoms1[n - 1][0].clone(); - partial_joint_secret_complement.neg().unwrap(); - assert_eq!(partial_joint_secret, partial_joint_secret_complement); - } - } - - #[test] - fn full_generation_with_multiplication() { - let test_cases = vec![(1, 3), (2, 5), (2, 7), (3, 8)]; - for (t, n) in test_cases { - // generate two shared secrets - let artifacts1 = run_key_generation(t, n, None, None); - let artifacts2 = run_key_generation(t, n, Some(artifacts1.id_numbers.clone()), None); - - // multiplicate original secrets - let joint_secret1 = - compute_joint_secret(artifacts1.polynoms1.iter().map(|p| &p[0])).unwrap(); - let joint_secret2 = - compute_joint_secret(artifacts2.polynoms1.iter().map(|p| &p[0])).unwrap(); - let mut expected_joint_secret_mul = joint_secret1; - expected_joint_secret_mul.mul(&joint_secret2).unwrap(); - - // run multiplication protocol - let joint_secret_mul_shares = run_multiplication_protocol( - t, - &artifacts1.secret_shares, - &artifacts2.secret_shares, - ); - - // calculate actual secrets multiplication - let double_t = t * 2; - let actual_joint_secret_mul = compute_joint_secret_from_shares( - double_t, - &joint_secret_mul_shares - .iter() - .take(double_t + 1) - .collect::>(), - &artifacts1 - .id_numbers - .iter() - .take(double_t + 1) - .collect::>(), - ) - .unwrap(); - - assert_eq!(actual_joint_secret_mul, expected_joint_secret_mul); - } - } - - #[test] - fn full_generation_with_reciprocal() { - let test_cases = vec![(1, 3), (2, 5), (2, 7), (2, 7), (3, 8)]; - for (t, n) in test_cases { - // generate shared secret - let artifacts = run_key_generation(t, n, None, None); - - // calculate inversion of original shared secret - let joint_secret = - compute_joint_secret(artifacts.polynoms1.iter().map(|p| &p[0])).unwrap(); - let mut expected_joint_secret_inv = joint_secret.clone(); - expected_joint_secret_inv.inv().unwrap(); - - // run inversion protocol - let reciprocal_shares = run_reciprocal_protocol(t, &artifacts); - - // calculate actual secret inversion - let double_t = t * 2; - let actual_joint_secret_inv = compute_joint_secret_from_shares( - double_t, - &reciprocal_shares - .iter() - .take(double_t + 1) - .collect::>(), - &artifacts - .id_numbers - .iter() - .take(double_t + 1) - .collect::>(), - ) - .unwrap(); - - assert_eq!(actual_joint_secret_inv, expected_joint_secret_inv); - } - } -} diff --git a/secret-store/src/key_server_cluster/message.rs b/secret-store/src/key_server_cluster/message.rs deleted file mode 100644 index 8e05ff3809..0000000000 --- a/secret-store/src/key_server_cluster/message.rs +++ /dev/null @@ -1,1675 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::{ - Error, SerializableAddress, SerializableH256, SerializableMessageHash, SerializablePublic, - SerializableRequester, SerializableSecret, SerializableSignature, -}; -use ethkey::Secret; -use key_server_cluster::SessionId; -use std::{ - collections::{BTreeMap, BTreeSet}, - fmt, -}; - -pub type MessageSessionId = SerializableH256; -pub type MessageNodeId = SerializablePublic; - -/// All possible messages that can be sent during encryption/decryption sessions. -#[derive(Clone, Debug)] -pub enum Message { - /// Cluster message. - Cluster(ClusterMessage), - /// Key generation message. - Generation(GenerationMessage), - /// Encryption message. - Encryption(EncryptionMessage), - /// Decryption message. - Decryption(DecryptionMessage), - /// Schnorr signing message. - SchnorrSigning(SchnorrSigningMessage), - /// ECDSA signing message. - EcdsaSigning(EcdsaSigningMessage), - /// Key version negotiation message. - KeyVersionNegotiation(KeyVersionNegotiationMessage), - /// Share add message. - ShareAdd(ShareAddMessage), - /// Servers set change message. - ServersSetChange(ServersSetChangeMessage), -} - -/// All possible cluster-level messages. -#[derive(Clone, Debug)] -pub enum ClusterMessage { - /// Introduce node public key. - NodePublicKey(NodePublicKey), - /// Confirm that node owns its private key. - NodePrivateKeySignature(NodePrivateKeySignature), - /// Keep alive message. - KeepAlive(KeepAlive), - /// Keep alive message response. - KeepAliveResponse(KeepAliveResponse), -} - -/// All possible messages that can be sent during key generation session. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum GenerationMessage { - /// Initialize new DKG session. - InitializeSession(InitializeSession), - /// Confirm DKG session initialization. - ConfirmInitialization(ConfirmInitialization), - /// Broadcast data, calculated during session initialization phase. - CompleteInitialization(CompleteInitialization), - /// Generated keys are sent to every node. - KeysDissemination(KeysDissemination), - /// Broadcast self public key portion. - PublicKeyShare(PublicKeyShare), - /// When session error has occured. - SessionError(SessionError), - /// When session is completed. - SessionCompleted(SessionCompleted), -} - -/// All possible messages that can be sent during encryption session. -#[derive(Clone, Debug)] -pub enum EncryptionMessage { - /// Initialize encryption session. - InitializeEncryptionSession(InitializeEncryptionSession), - /// Confirm/reject encryption session initialization. - ConfirmEncryptionInitialization(ConfirmEncryptionInitialization), - /// When encryption session error has occured. - EncryptionSessionError(EncryptionSessionError), -} - -/// All possible messages that can be sent during consensus establishing. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ConsensusMessage { - /// Initialize consensus session. - InitializeConsensusSession(InitializeConsensusSession), - /// Confirm/reject consensus session initialization. - ConfirmConsensusInitialization(ConfirmConsensusInitialization), -} - -/// All possible messages that can be sent during servers-set consensus establishing. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ConsensusMessageWithServersSet { - /// Initialize consensus session. - InitializeConsensusSession(InitializeConsensusSessionWithServersSet), - /// Confirm/reject consensus session initialization. - ConfirmConsensusInitialization(ConfirmConsensusInitialization), -} - -/// All possible messages that can be sent during share add consensus establishing. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ConsensusMessageOfShareAdd { - /// Initialize consensus session. - InitializeConsensusSession(InitializeConsensusSessionOfShareAdd), - /// Confirm/reject consensus session initialization. - ConfirmConsensusInitialization(ConfirmConsensusInitialization), -} - -/// All possible messages that can be sent during decryption session. -#[derive(Clone, Debug)] -pub enum DecryptionMessage { - /// Consensus establishing message. - DecryptionConsensusMessage(DecryptionConsensusMessage), - /// Request partial decryption from node. - RequestPartialDecryption(RequestPartialDecryption), - /// Partial decryption is completed. - PartialDecryption(PartialDecryption), - /// When decryption session error has occured. - DecryptionSessionError(DecryptionSessionError), - /// When decryption session is completed. - DecryptionSessionCompleted(DecryptionSessionCompleted), - /// When decryption session is delegated to another node. - DecryptionSessionDelegation(DecryptionSessionDelegation), - /// When delegated decryption session is completed. - DecryptionSessionDelegationCompleted(DecryptionSessionDelegationCompleted), -} - -/// All possible messages that can be sent during Schnorr signing session. -#[derive(Clone, Debug)] -pub enum SchnorrSigningMessage { - /// Consensus establishing message. - SchnorrSigningConsensusMessage(SchnorrSigningConsensusMessage), - /// Session key generation message. - SchnorrSigningGenerationMessage(SchnorrSigningGenerationMessage), - /// Request partial signature from node. - SchnorrRequestPartialSignature(SchnorrRequestPartialSignature), - /// Partial signature is generated. - SchnorrPartialSignature(SchnorrPartialSignature), - /// Signing error occured. - SchnorrSigningSessionError(SchnorrSigningSessionError), - /// Signing session completed. - SchnorrSigningSessionCompleted(SchnorrSigningSessionCompleted), - /// When signing session is delegated to another node. - SchnorrSigningSessionDelegation(SchnorrSigningSessionDelegation), - /// When delegated signing session is completed. - SchnorrSigningSessionDelegationCompleted(SchnorrSigningSessionDelegationCompleted), -} - -/// All possible messages that can be sent during ECDSA signing session. -#[derive(Clone, Debug)] -pub enum EcdsaSigningMessage { - /// Consensus establishing message. - EcdsaSigningConsensusMessage(EcdsaSigningConsensusMessage), - /// Signature nonce generation message. - EcdsaSignatureNonceGenerationMessage(EcdsaSignatureNonceGenerationMessage), - /// Inversion nonce generation message. - EcdsaInversionNonceGenerationMessage(EcdsaInversionNonceGenerationMessage), - /// Inversion zero generation message. - EcdsaInversionZeroGenerationMessage(EcdsaInversionZeroGenerationMessage), - /// Inversed nonce coefficient share. - EcdsaSigningInversedNonceCoeffShare(EcdsaSigningInversedNonceCoeffShare), - /// Request partial signature from node. - EcdsaRequestPartialSignature(EcdsaRequestPartialSignature), - /// Partial signature is generated. - EcdsaPartialSignature(EcdsaPartialSignature), - /// Signing error occured. - EcdsaSigningSessionError(EcdsaSigningSessionError), - /// Signing session completed. - EcdsaSigningSessionCompleted(EcdsaSigningSessionCompleted), - /// When signing session is delegated to another node. - EcdsaSigningSessionDelegation(EcdsaSigningSessionDelegation), - /// When delegated signing session is completed. - EcdsaSigningSessionDelegationCompleted(EcdsaSigningSessionDelegationCompleted), -} - -/// All possible messages that can be sent during servers set change session. -#[derive(Clone, Debug)] -pub enum ServersSetChangeMessage { - /// Consensus establishing message. - ServersSetChangeConsensusMessage(ServersSetChangeConsensusMessage), - /// Unknown sessions ids request. - UnknownSessionsRequest(UnknownSessionsRequest), - /// Unknown sessions ids. - UnknownSessions(UnknownSessions), - /// Negotiating key version to use as a base for ShareAdd session. - ShareChangeKeyVersionNegotiation(ShareChangeKeyVersionNegotiation), - /// Initialize share change session(s). - InitializeShareChangeSession(InitializeShareChangeSession), - /// Confirm share change session(s) initialization. - ConfirmShareChangeSessionInitialization(ConfirmShareChangeSessionInitialization), - /// Share change session delegation. - ServersSetChangeDelegate(ServersSetChangeDelegate), - /// Share change session delegation response. - ServersSetChangeDelegateResponse(ServersSetChangeDelegateResponse), - /// Share add message. - ServersSetChangeShareAddMessage(ServersSetChangeShareAddMessage), - /// Servers set change session completed. - ServersSetChangeError(ServersSetChangeError), - /// Servers set change session completed. - ServersSetChangeCompleted(ServersSetChangeCompleted), -} - -/// All possible messages that can be sent during share add session. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ShareAddMessage { - /// Consensus establishing message. - ShareAddConsensusMessage(ShareAddConsensusMessage), - /// Common key share data is sent to new node. - KeyShareCommon(KeyShareCommon), - /// Generated keys are sent to every node. - NewKeysDissemination(NewKeysDissemination), - /// When session error has occured. - ShareAddError(ShareAddError), -} - -/// All possible messages that can be sent during key version negotiation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum KeyVersionNegotiationMessage { - /// Request key versions. - RequestKeyVersions(RequestKeyVersions), - /// Key versions. - KeyVersions(KeyVersions), - /// When session error has occured. - KeyVersionsError(KeyVersionsError), -} - -/// Introduce node public key. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct NodePublicKey { - /// Node identifier (aka node public key). - pub node_id: MessageNodeId, - /// Random data, which must be signed by peer to prove that he owns the corresponding private key. - pub confirmation_plain: SerializableH256, - /// The same random `confirmation_plain`, signed with one-time session key. - pub confirmation_signed_session: SerializableSignature, -} - -/// Confirm that node owns the private key of previously passed public key (aka node id). -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct NodePrivateKeySignature { - /// Previously passed `confirmation_plain`, signed with node private key. - pub confirmation_signed: SerializableSignature, -} - -/// Ask if the node is still alive. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeepAlive {} - -/// Confirm that the node is still alive. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeepAliveResponse { - /// Session id, if used for session-level keep alive. - pub session_id: Option, -} - -/// Initialize new DKG session. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeSession { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Session origin address (if any). - pub origin: Option, - /// Session author. - pub author: SerializableAddress, - /// All session participants along with their identification numbers. - pub nodes: BTreeMap, - /// Is zero secret generation session? - pub is_zero: bool, - /// Decryption threshold. During decryption threshold-of-route.len() nodes must came to - /// consensus to successfully decrypt message. - pub threshold: usize, - /// Derived generation point. Starting from originator, every node must multiply this - /// point by random scalar (unknown by other nodes). At the end of initialization - /// `point` will be some (k1 * k2 * ... * kn) * G = `point` where `(k1 * k2 * ... * kn)` - /// is unknown for every node. - pub derived_point: SerializablePublic, -} - -/// Confirm DKG session initialization. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ConfirmInitialization { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Derived generation point. - pub derived_point: SerializablePublic, -} - -/// Broadcast generated point to every other node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct CompleteInitialization { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Derived generation point. - pub derived_point: SerializablePublic, -} - -/// Generated keys are sent to every node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeysDissemination { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Secret 1. - pub secret1: SerializableSecret, - /// Secret 2. - pub secret2: SerializableSecret, - /// Public values. - pub publics: Vec, -} - -/// Node is sharing its public key share. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct PublicKeyShare { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Public key share. - pub public_share: SerializablePublic, -} - -/// When session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SessionError { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// When session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SessionCompleted { - /// Session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// Node is requested to prepare for saving encrypted data. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeEncryptionSession { - /// Encryption session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Requester. - pub requester: SerializableRequester, - /// Common point. - pub common_point: SerializablePublic, - /// Encrypted data. - pub encrypted_point: SerializablePublic, -} - -/// Node is responding to encryption initialization request. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ConfirmEncryptionInitialization { - /// Encryption session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// When encryption session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EncryptionSessionError { - /// Encryption session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// Node is asked to be part of consensus group. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeConsensusSession { - /// Requester. - pub requester: SerializableRequester, - /// Key version. - pub version: SerializableH256, -} - -/// Node is responding to consensus initialization request. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ConfirmConsensusInitialization { - /// Is node confirmed consensus participation. - pub is_confirmed: bool, -} - -/// Node is asked to be part of servers-set consensus group. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeConsensusSessionWithServersSet { - /// Migration id (if any). - pub migration_id: Option, - /// Old nodes set. - pub old_nodes_set: BTreeSet, - /// New nodes set. - pub new_nodes_set: BTreeSet, - /// Old server set, signed by requester. - pub old_set_signature: SerializableSignature, - /// New server set, signed by requester. - pub new_set_signature: SerializableSignature, -} - -/// Node is asked to be part of servers-set consensus group. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeConsensusSessionOfShareAdd { - /// Key version. - pub version: SerializableH256, - /// Nodes that have reported version ownership. - pub version_holders: BTreeSet, - /// threshold+1 nodes from old_nodes_set selected for shares redistribution. - pub consensus_group: BTreeSet, - /// Old nodes set: all non-isolated owners of selected key share version. - pub old_nodes_set: BTreeSet, - /// New nodes map: node id => node id number. - pub new_nodes_map: BTreeMap, - /// Old server set, signed by requester. - pub old_set_signature: SerializableSignature, - /// New server set, signed by requester. - pub new_set_signature: SerializableSignature, -} - -/// Consensus-related Schnorr signing message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningConsensusMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Consensus message. - pub message: ConsensusMessage, -} - -/// Session key generation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningGenerationMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Generation message. - pub message: GenerationMessage, -} - -/// Request partial Schnorr signature. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrRequestPartialSignature { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// Message hash. - pub message_hash: SerializableMessageHash, - /// Selected nodes. - pub nodes: BTreeSet, -} - -/// Partial Schnorr signature. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrPartialSignature { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// S part of signature. - pub partial_signature: SerializableSecret, -} - -/// When Schnorr signing session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningSessionError { - /// Encryption session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// Schnorr signing session completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningSessionCompleted { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// When Schnorr signing session is delegated to another node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningSessionDelegation { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Requester. - pub requester: SerializableRequester, - /// Key version. - pub version: SerializableH256, - /// Message hash. - pub message_hash: SerializableH256, -} - -/// When delegated Schnorr signing session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SchnorrSigningSessionDelegationCompleted { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// S-portion of signature. - pub signature_s: SerializableSecret, - /// C-portion of signature. - pub signature_c: SerializableSecret, -} - -/// Consensus-related ECDSA signing message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningConsensusMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Consensus message. - pub message: ConsensusMessage, -} - -/// ECDSA signature nonce generation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSignatureNonceGenerationMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Generation message. - pub message: GenerationMessage, -} - -/// ECDSA inversion nonce generation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaInversionNonceGenerationMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Generation message. - pub message: GenerationMessage, -} - -/// ECDSA inversed nonce share message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningInversedNonceCoeffShare { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Inversed nonce coefficient share. - pub inversed_nonce_coeff_share: SerializableSecret, -} - -/// ECDSA inversion zero generation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaInversionZeroGenerationMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Generation message. - pub message: GenerationMessage, -} - -/// Request partial ECDSA signature. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaRequestPartialSignature { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// - pub inversed_nonce_coeff: SerializableSecret, - /// Message hash. - pub message_hash: SerializableMessageHash, -} - -/// Partial ECDSA signature. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaPartialSignature { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// Partial S part of signature. - pub partial_signature_s: SerializableSecret, -} - -/// When ECDSA signing session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningSessionError { - /// Encryption session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// ECDSA signing session completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningSessionCompleted { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// When ECDSA signing session is delegated to another node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningSessionDelegation { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Requestor signature. - pub requester: SerializableRequester, - /// Key version. - pub version: SerializableH256, - /// Message hash. - pub message_hash: SerializableH256, -} - -/// When delegated ECDSA signing session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct EcdsaSigningSessionDelegationCompleted { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Signature. - pub signature: SerializableSignature, -} - -/// Consensus-related decryption message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DecryptionConsensusMessage { - /// Generation session Id. - pub session: MessageSessionId, - /// Signing session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Session origin (in consensus initialization message). - pub origin: Option, - /// Consensus message. - pub message: ConsensusMessage, -} - -/// Node is requested to do a partial decryption. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RequestPartialDecryption { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// Is shadow decryption requested? When true, decryption result - /// will be visible to the owner of requestor public key only. - pub is_shadow_decryption: bool, - /// Decryption result must be reconstructed on all participating nodes. This is useful - /// for service contract API so that all nodes from consensus group can confirm decryption. - pub is_broadcast_session: bool, - /// Nodes that are agreed to do a decryption. - pub nodes: BTreeSet, -} - -/// Node has partially decrypted the secret. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct PartialDecryption { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Request id. - pub request_id: SerializableSecret, - /// Partially decrypted secret. - pub shadow_point: SerializablePublic, - /// Decrypt shadow coefficient (if requested), encrypted with requestor public. - pub decrypt_shadow: Option>, -} - -/// When decryption session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DecryptionSessionError { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// When decryption session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DecryptionSessionCompleted { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// When decryption session is delegated to another node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DecryptionSessionDelegation { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Session origin. - pub origin: Option, - /// Requester. - pub requester: SerializableRequester, - /// Key version. - pub version: SerializableH256, - /// Is shadow decryption requested? When true, decryption result - /// will be visible to the owner of requestor public key only. - pub is_shadow_decryption: bool, - /// Decryption result must be reconstructed on all participating nodes. This is useful - /// for service contract API so that all nodes from consensus group can confirm decryption. - pub is_broadcast_session: bool, -} - -/// When delegated decryption session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct DecryptionSessionDelegationCompleted { - /// Encryption session Id. - pub session: MessageSessionId, - /// Decryption session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested. - pub decrypted_secret: SerializablePublic, - /// Shared common point. - pub common_point: Option, - /// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public. - pub decrypt_shadows: Option>>, -} - -/// Consensus-related servers set change message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeConsensusMessage { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Consensus message. - pub message: ConsensusMessageWithServersSet, -} - -/// Unknown sessions ids request. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct UnknownSessionsRequest { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// Unknown session ids. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct UnknownSessions { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Unknown session id. - pub unknown_sessions: BTreeSet, -} - -/// Key version negotiation message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ShareChangeKeyVersionNegotiation { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Key version negotiation message. - pub message: KeyVersionNegotiationMessage, -} - -/// Master node opens share initialize session on other nodes. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct InitializeShareChangeSession { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Key id. - pub key_id: MessageSessionId, - /// Key vesion to use in ShareAdd session. - pub version: SerializableH256, - /// Nodes that have confirmed version ownership. - pub version_holders: BTreeSet, - /// Master node. - pub master_node_id: MessageNodeId, - /// Consensus group to use in ShareAdd session. - pub consensus_group: BTreeSet, - /// Shares to add. Values are filled for new nodes only. - pub new_nodes_map: BTreeMap>, -} - -/// Slave node confirms session initialization. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ConfirmShareChangeSessionInitialization { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Sessions that are confirmed. - pub key_id: MessageSessionId, -} - -/// Share change is requested. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeDelegate { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Key id. - pub key_id: MessageSessionId, -} - -/// Share change is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeDelegateResponse { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Key id. - pub key_id: MessageSessionId, -} - -/// Servers set change share add message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeShareAddMessage { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Unknown session id. - pub message: ShareAddMessage, -} - -/// When servers set change session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeError { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// When servers set change session is completed. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ServersSetChangeCompleted { - /// Servers set change session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// Consensus-related share add session message. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ShareAddConsensusMessage { - /// Share add session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Consensus message. - pub message: ConsensusMessageOfShareAdd, -} - -/// Key share common data is passed to new node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeyShareCommon { - /// Generation session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Common key data. - pub key_common: CommonKeyData, - /// Common (shared) encryption point. - pub common_point: Option, - /// Encrypted point. - pub encrypted_point: Option, - /// Selected version id numbers. - pub id_numbers: BTreeMap, -} - -/// Generated keys are sent to every node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct NewKeysDissemination { - /// Generation session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Sub share of rcevier' secret share. - pub secret_subshare: SerializableSecret, -} - -/// When share add session error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct ShareAddError { - /// Generation session Id. - pub session: MessageSessionId, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, -} - -/// Key versions are requested. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct RequestKeyVersions { - /// Generation session id. - pub session: MessageSessionId, - /// Version negotiation session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, -} - -/// Key versions are sent. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeyVersions { - /// Generation session id. - pub session: MessageSessionId, - /// Version negotiation session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Common key data, shared by all versions. - pub key_common: Option, - /// Key versions. - pub versions: Vec, -} - -/// Common key data. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct CommonKeyData { - /// Key threshold. - pub threshold: usize, - /// Author of the key entry. - pub author: SerializableAddress, - /// Joint public. - pub public: SerializablePublic, -} - -/// When key versions error has occured. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct KeyVersionsError { - /// Generation session id. - pub session: MessageSessionId, - /// Version negotiation session Id. - pub sub_session: SerializableSecret, - /// Session-level nonce. - pub session_nonce: u64, - /// Error message. - pub error: Error, - /// Continue action from failed node (if any). This field is oly filled - /// when error has occured when trying to compute result on master node. - pub continue_with: Option, -} - -/// Key version continue action from failed node. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum FailedKeyVersionContinueAction { - /// Decryption session: origin + requester. - Decrypt(Option, SerializableAddress), -} - -impl Message { - pub fn is_initialization_message(&self) -> bool { - match *self { - Message::Generation(GenerationMessage::InitializeSession(_)) => true, - Message::Encryption(EncryptionMessage::InitializeEncryptionSession(_)) => true, - Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(ref msg)) => { - match msg.message { - ConsensusMessage::InitializeConsensusSession(_) => true, - _ => false, - } - } - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningConsensusMessage( - ref msg, - )) => match msg.message { - ConsensusMessage::InitializeConsensusSession(_) => true, - _ => false, - }, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref msg)) => { - match msg.message { - ConsensusMessage::InitializeConsensusSession(_) => true, - _ => false, - } - } - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::RequestKeyVersions(_)) => { - true - } - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersionsError( - ref msg, - )) if msg.continue_with.is_some() => true, - Message::ShareAdd(ShareAddMessage::ShareAddConsensusMessage(ref msg)) => { - match msg.message { - ConsensusMessageOfShareAdd::InitializeConsensusSession(_) => true, - _ => false, - } - } - Message::ServersSetChange( - ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref msg), - ) => match msg.message { - ConsensusMessageWithServersSet::InitializeConsensusSession(_) => true, - _ => false, - }, - _ => false, - } - } - - pub fn is_delegation_message(&self) -> bool { - match *self { - Message::Decryption(DecryptionMessage::DecryptionSessionDelegation(_)) => true, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionDelegation(_)) => { - true - } - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionDelegation(_)) => true, - _ => false, - } - } - - pub fn is_error_message(&self) -> bool { - match *self { - Message::Generation(GenerationMessage::SessionError(_)) => true, - Message::Encryption(EncryptionMessage::EncryptionSessionError(_)) => true, - Message::Decryption(DecryptionMessage::DecryptionSessionError(_)) => true, - Message::SchnorrSigning(SchnorrSigningMessage::SchnorrSigningSessionError(_)) => true, - Message::EcdsaSigning(EcdsaSigningMessage::EcdsaSigningSessionError(_)) => true, - Message::KeyVersionNegotiation(KeyVersionNegotiationMessage::KeyVersionsError(_)) => { - true - } - Message::ShareAdd(ShareAddMessage::ShareAddError(_)) => true, - Message::ServersSetChange(ServersSetChangeMessage::ServersSetChangeError(_)) => true, - _ => false, - } - } - - pub fn is_exclusive_session_message(&self) -> bool { - match *self { - Message::ServersSetChange(_) => true, - _ => false, - } - } - - pub fn session_nonce(&self) -> Option { - match *self { - Message::Cluster(_) => None, - Message::Generation(ref message) => Some(message.session_nonce()), - Message::Encryption(ref message) => Some(message.session_nonce()), - Message::Decryption(ref message) => Some(message.session_nonce()), - Message::SchnorrSigning(ref message) => Some(message.session_nonce()), - Message::EcdsaSigning(ref message) => Some(message.session_nonce()), - Message::ShareAdd(ref message) => Some(message.session_nonce()), - Message::ServersSetChange(ref message) => Some(message.session_nonce()), - Message::KeyVersionNegotiation(ref message) => Some(message.session_nonce()), - } - } -} - -impl GenerationMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - GenerationMessage::InitializeSession(ref msg) => &msg.session, - GenerationMessage::ConfirmInitialization(ref msg) => &msg.session, - GenerationMessage::CompleteInitialization(ref msg) => &msg.session, - GenerationMessage::KeysDissemination(ref msg) => &msg.session, - GenerationMessage::PublicKeyShare(ref msg) => &msg.session, - GenerationMessage::SessionError(ref msg) => &msg.session, - GenerationMessage::SessionCompleted(ref msg) => &msg.session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - GenerationMessage::InitializeSession(ref msg) => msg.session_nonce, - GenerationMessage::ConfirmInitialization(ref msg) => msg.session_nonce, - GenerationMessage::CompleteInitialization(ref msg) => msg.session_nonce, - GenerationMessage::KeysDissemination(ref msg) => msg.session_nonce, - GenerationMessage::PublicKeyShare(ref msg) => msg.session_nonce, - GenerationMessage::SessionError(ref msg) => msg.session_nonce, - GenerationMessage::SessionCompleted(ref msg) => msg.session_nonce, - } - } -} - -impl EncryptionMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - EncryptionMessage::InitializeEncryptionSession(ref msg) => &msg.session, - EncryptionMessage::ConfirmEncryptionInitialization(ref msg) => &msg.session, - EncryptionMessage::EncryptionSessionError(ref msg) => &msg.session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - EncryptionMessage::InitializeEncryptionSession(ref msg) => msg.session_nonce, - EncryptionMessage::ConfirmEncryptionInitialization(ref msg) => msg.session_nonce, - EncryptionMessage::EncryptionSessionError(ref msg) => msg.session_nonce, - } - } -} - -impl DecryptionMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - DecryptionMessage::DecryptionConsensusMessage(ref msg) => &msg.session, - DecryptionMessage::RequestPartialDecryption(ref msg) => &msg.session, - DecryptionMessage::PartialDecryption(ref msg) => &msg.session, - DecryptionMessage::DecryptionSessionError(ref msg) => &msg.session, - DecryptionMessage::DecryptionSessionCompleted(ref msg) => &msg.session, - DecryptionMessage::DecryptionSessionDelegation(ref msg) => &msg.session, - DecryptionMessage::DecryptionSessionDelegationCompleted(ref msg) => &msg.session, - } - } - - pub fn sub_session_id(&self) -> &Secret { - match *self { - DecryptionMessage::DecryptionConsensusMessage(ref msg) => &msg.sub_session, - DecryptionMessage::RequestPartialDecryption(ref msg) => &msg.sub_session, - DecryptionMessage::PartialDecryption(ref msg) => &msg.sub_session, - DecryptionMessage::DecryptionSessionError(ref msg) => &msg.sub_session, - DecryptionMessage::DecryptionSessionCompleted(ref msg) => &msg.sub_session, - DecryptionMessage::DecryptionSessionDelegation(ref msg) => &msg.sub_session, - DecryptionMessage::DecryptionSessionDelegationCompleted(ref msg) => &msg.sub_session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - DecryptionMessage::DecryptionConsensusMessage(ref msg) => msg.session_nonce, - DecryptionMessage::RequestPartialDecryption(ref msg) => msg.session_nonce, - DecryptionMessage::PartialDecryption(ref msg) => msg.session_nonce, - DecryptionMessage::DecryptionSessionError(ref msg) => msg.session_nonce, - DecryptionMessage::DecryptionSessionCompleted(ref msg) => msg.session_nonce, - DecryptionMessage::DecryptionSessionDelegation(ref msg) => msg.session_nonce, - DecryptionMessage::DecryptionSessionDelegationCompleted(ref msg) => msg.session_nonce, - } - } -} - -impl SchnorrSigningMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - SchnorrSigningMessage::SchnorrSigningConsensusMessage(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrSigningGenerationMessage(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrRequestPartialSignature(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrPartialSignature(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrSigningSessionError(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrSigningSessionCompleted(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrSigningSessionDelegation(ref msg) => &msg.session, - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(ref msg) => { - &msg.session - } - } - } - - pub fn sub_session_id(&self) -> &Secret { - match *self { - SchnorrSigningMessage::SchnorrSigningConsensusMessage(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrSigningGenerationMessage(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrRequestPartialSignature(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrPartialSignature(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrSigningSessionError(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrSigningSessionCompleted(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrSigningSessionDelegation(ref msg) => &msg.sub_session, - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(ref msg) => { - &msg.sub_session - } - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - SchnorrSigningMessage::SchnorrSigningConsensusMessage(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrSigningGenerationMessage(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrRequestPartialSignature(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrPartialSignature(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrSigningSessionError(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrSigningSessionCompleted(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrSigningSessionDelegation(ref msg) => msg.session_nonce, - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(ref msg) => { - msg.session_nonce - } - } - } -} - -impl EcdsaSigningMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaRequestPartialSignature(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaPartialSignature(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSigningSessionError(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSigningSessionCompleted(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSigningSessionDelegation(ref msg) => &msg.session, - EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted(ref msg) => &msg.session, - } - } - - pub fn sub_session_id(&self) -> &Secret { - match *self { - EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaRequestPartialSignature(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaPartialSignature(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSigningSessionError(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSigningSessionCompleted(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSigningSessionDelegation(ref msg) => &msg.sub_session, - EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted(ref msg) => { - &msg.sub_session - } - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaRequestPartialSignature(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaPartialSignature(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSigningSessionError(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSigningSessionCompleted(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSigningSessionDelegation(ref msg) => msg.session_nonce, - EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted(ref msg) => { - msg.session_nonce - } - } - } -} - -impl ServersSetChangeMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref msg) => &msg.session, - ServersSetChangeMessage::UnknownSessionsRequest(ref msg) => &msg.session, - ServersSetChangeMessage::UnknownSessions(ref msg) => &msg.session, - ServersSetChangeMessage::ShareChangeKeyVersionNegotiation(ref msg) => &msg.session, - ServersSetChangeMessage::InitializeShareChangeSession(ref msg) => &msg.session, - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization(ref msg) => { - &msg.session - } - ServersSetChangeMessage::ServersSetChangeDelegate(ref msg) => &msg.session, - ServersSetChangeMessage::ServersSetChangeDelegateResponse(ref msg) => &msg.session, - ServersSetChangeMessage::ServersSetChangeShareAddMessage(ref msg) => &msg.session, - ServersSetChangeMessage::ServersSetChangeError(ref msg) => &msg.session, - ServersSetChangeMessage::ServersSetChangeCompleted(ref msg) => &msg.session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref msg) => msg.session_nonce, - ServersSetChangeMessage::UnknownSessionsRequest(ref msg) => msg.session_nonce, - ServersSetChangeMessage::UnknownSessions(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ShareChangeKeyVersionNegotiation(ref msg) => msg.session_nonce, - ServersSetChangeMessage::InitializeShareChangeSession(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization(ref msg) => { - msg.session_nonce - } - ServersSetChangeMessage::ServersSetChangeDelegate(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ServersSetChangeDelegateResponse(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ServersSetChangeShareAddMessage(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ServersSetChangeError(ref msg) => msg.session_nonce, - ServersSetChangeMessage::ServersSetChangeCompleted(ref msg) => msg.session_nonce, - } - } -} - -impl ShareAddMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - ShareAddMessage::ShareAddConsensusMessage(ref msg) => &msg.session, - ShareAddMessage::KeyShareCommon(ref msg) => &msg.session, - ShareAddMessage::NewKeysDissemination(ref msg) => &msg.session, - ShareAddMessage::ShareAddError(ref msg) => &msg.session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - ShareAddMessage::ShareAddConsensusMessage(ref msg) => msg.session_nonce, - ShareAddMessage::KeyShareCommon(ref msg) => msg.session_nonce, - ShareAddMessage::NewKeysDissemination(ref msg) => msg.session_nonce, - ShareAddMessage::ShareAddError(ref msg) => msg.session_nonce, - } - } -} - -impl KeyVersionNegotiationMessage { - pub fn session_id(&self) -> &SessionId { - match *self { - KeyVersionNegotiationMessage::RequestKeyVersions(ref msg) => &msg.session, - KeyVersionNegotiationMessage::KeyVersions(ref msg) => &msg.session, - KeyVersionNegotiationMessage::KeyVersionsError(ref msg) => &msg.session, - } - } - - pub fn sub_session_id(&self) -> &Secret { - match *self { - KeyVersionNegotiationMessage::RequestKeyVersions(ref msg) => &msg.sub_session, - KeyVersionNegotiationMessage::KeyVersions(ref msg) => &msg.sub_session, - KeyVersionNegotiationMessage::KeyVersionsError(ref msg) => &msg.sub_session, - } - } - - pub fn session_nonce(&self) -> u64 { - match *self { - KeyVersionNegotiationMessage::RequestKeyVersions(ref msg) => msg.session_nonce, - KeyVersionNegotiationMessage::KeyVersions(ref msg) => msg.session_nonce, - KeyVersionNegotiationMessage::KeyVersionsError(ref msg) => msg.session_nonce, - } - } -} - -impl fmt::Display for Message { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Message::Cluster(ref message) => write!(f, "Cluster.{}", message), - Message::Generation(ref message) => write!(f, "Generation.{}", message), - Message::Encryption(ref message) => write!(f, "Encryption.{}", message), - Message::Decryption(ref message) => write!(f, "Decryption.{}", message), - Message::SchnorrSigning(ref message) => write!(f, "SchnorrSigning.{}", message), - Message::EcdsaSigning(ref message) => write!(f, "EcdsaSigning.{}", message), - Message::ServersSetChange(ref message) => write!(f, "ServersSetChange.{}", message), - Message::ShareAdd(ref message) => write!(f, "ShareAdd.{}", message), - Message::KeyVersionNegotiation(ref message) => { - write!(f, "KeyVersionNegotiation.{}", message) - } - } - } -} - -impl fmt::Display for ClusterMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ClusterMessage::NodePublicKey(_) => write!(f, "NodePublicKey"), - ClusterMessage::NodePrivateKeySignature(_) => write!(f, "NodePrivateKeySignature"), - ClusterMessage::KeepAlive(_) => write!(f, "KeepAlive"), - ClusterMessage::KeepAliveResponse(_) => write!(f, "KeepAliveResponse"), - } - } -} - -impl fmt::Display for GenerationMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - GenerationMessage::InitializeSession(_) => write!(f, "InitializeSession"), - GenerationMessage::ConfirmInitialization(_) => write!(f, "ConfirmInitialization"), - GenerationMessage::CompleteInitialization(_) => write!(f, "CompleteInitialization"), - GenerationMessage::KeysDissemination(_) => write!(f, "KeysDissemination"), - GenerationMessage::PublicKeyShare(_) => write!(f, "PublicKeyShare"), - GenerationMessage::SessionError(ref msg) => write!(f, "SessionError({})", msg.error), - GenerationMessage::SessionCompleted(_) => write!(f, "SessionCompleted"), - } - } -} - -impl fmt::Display for EncryptionMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - EncryptionMessage::InitializeEncryptionSession(_) => { - write!(f, "InitializeEncryptionSession") - } - EncryptionMessage::ConfirmEncryptionInitialization(_) => { - write!(f, "ConfirmEncryptionInitialization") - } - EncryptionMessage::EncryptionSessionError(ref msg) => { - write!(f, "EncryptionSessionError({})", msg.error) - } - } - } -} - -impl fmt::Display for ConsensusMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConsensusMessage::InitializeConsensusSession(_) => { - write!(f, "InitializeConsensusSession") - } - ConsensusMessage::ConfirmConsensusInitialization(ref msg) => { - write!(f, "ConfirmConsensusInitialization({})", msg.is_confirmed) - } - } - } -} - -impl fmt::Display for ConsensusMessageWithServersSet { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConsensusMessageWithServersSet::InitializeConsensusSession(_) => { - write!(f, "InitializeConsensusSession") - } - ConsensusMessageWithServersSet::ConfirmConsensusInitialization(ref msg) => { - write!(f, "ConfirmConsensusInitialization({})", msg.is_confirmed) - } - } - } -} - -impl fmt::Display for ConsensusMessageOfShareAdd { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ConsensusMessageOfShareAdd::InitializeConsensusSession(_) => { - write!(f, "InitializeConsensusSession") - } - ConsensusMessageOfShareAdd::ConfirmConsensusInitialization(ref msg) => { - write!(f, "ConfirmConsensusInitialization({})", msg.is_confirmed) - } - } - } -} - -impl fmt::Display for DecryptionMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - DecryptionMessage::DecryptionConsensusMessage(ref m) => { - write!(f, "DecryptionConsensusMessage.{}", m.message) - } - DecryptionMessage::RequestPartialDecryption(_) => write!(f, "RequestPartialDecryption"), - DecryptionMessage::PartialDecryption(_) => write!(f, "PartialDecryption"), - DecryptionMessage::DecryptionSessionError(_) => write!(f, "DecryptionSessionError"), - DecryptionMessage::DecryptionSessionCompleted(_) => { - write!(f, "DecryptionSessionCompleted") - } - DecryptionMessage::DecryptionSessionDelegation(_) => { - write!(f, "DecryptionSessionDelegation") - } - DecryptionMessage::DecryptionSessionDelegationCompleted(_) => { - write!(f, "DecryptionSessionDelegationCompleted") - } - } - } -} - -impl fmt::Display for SchnorrSigningMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - SchnorrSigningMessage::SchnorrSigningConsensusMessage(ref m) => { - write!(f, "SchnorrSigningConsensusMessage.{}", m.message) - } - SchnorrSigningMessage::SchnorrSigningGenerationMessage(ref m) => { - write!(f, "SchnorrSigningGenerationMessage.{}", m.message) - } - SchnorrSigningMessage::SchnorrRequestPartialSignature(_) => { - write!(f, "SchnorrRequestPartialSignature") - } - SchnorrSigningMessage::SchnorrPartialSignature(_) => { - write!(f, "SchnorrPartialSignature") - } - SchnorrSigningMessage::SchnorrSigningSessionError(_) => { - write!(f, "SchnorrSigningSessionError") - } - SchnorrSigningMessage::SchnorrSigningSessionCompleted(_) => { - write!(f, "SchnorrSigningSessionCompleted") - } - SchnorrSigningMessage::SchnorrSigningSessionDelegation(_) => { - write!(f, "SchnorrSigningSessionDelegation") - } - SchnorrSigningMessage::SchnorrSigningSessionDelegationCompleted(_) => { - write!(f, "SchnorrSigningSessionDelegationCompleted") - } - } - } -} - -impl fmt::Display for EcdsaSigningMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - EcdsaSigningMessage::EcdsaSigningConsensusMessage(ref m) => { - write!(f, "EcdsaSigningConsensusMessage.{}", m.message) - } - EcdsaSigningMessage::EcdsaSignatureNonceGenerationMessage(ref m) => { - write!(f, "EcdsaSignatureNonceGenerationMessage.{}", m.message) - } - EcdsaSigningMessage::EcdsaInversionNonceGenerationMessage(ref m) => { - write!(f, "EcdsaInversionNonceGenerationMessage.{}", m.message) - } - EcdsaSigningMessage::EcdsaInversionZeroGenerationMessage(ref m) => { - write!(f, "EcdsaInversionZeroGenerationMessage.{}", m.message) - } - EcdsaSigningMessage::EcdsaSigningInversedNonceCoeffShare(_) => { - write!(f, "EcdsaSigningInversedNonceCoeffShare") - } - EcdsaSigningMessage::EcdsaRequestPartialSignature(_) => { - write!(f, "EcdsaRequestPartialSignature") - } - EcdsaSigningMessage::EcdsaPartialSignature(_) => write!(f, "EcdsaPartialSignature"), - EcdsaSigningMessage::EcdsaSigningSessionError(_) => { - write!(f, "EcdsaSigningSessionError") - } - EcdsaSigningMessage::EcdsaSigningSessionCompleted(_) => { - write!(f, "EcdsaSigningSessionCompleted") - } - EcdsaSigningMessage::EcdsaSigningSessionDelegation(_) => { - write!(f, "EcdsaSigningSessionDelegation") - } - EcdsaSigningMessage::EcdsaSigningSessionDelegationCompleted(_) => { - write!(f, "EcdsaSigningSessionDelegationCompleted") - } - } - } -} - -impl fmt::Display for ServersSetChangeMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ServersSetChangeMessage::ServersSetChangeConsensusMessage(ref m) => { - write!(f, "ServersSetChangeConsensusMessage.{}", m.message) - } - ServersSetChangeMessage::UnknownSessionsRequest(_) => { - write!(f, "UnknownSessionsRequest") - } - ServersSetChangeMessage::UnknownSessions(_) => write!(f, "UnknownSessions"), - ServersSetChangeMessage::ShareChangeKeyVersionNegotiation(ref m) => { - write!(f, "ShareChangeKeyVersionNegotiation.{}", m.message) - } - ServersSetChangeMessage::InitializeShareChangeSession(_) => { - write!(f, "InitializeShareChangeSession") - } - ServersSetChangeMessage::ConfirmShareChangeSessionInitialization(_) => { - write!(f, "ConfirmShareChangeSessionInitialization") - } - ServersSetChangeMessage::ServersSetChangeDelegate(_) => { - write!(f, "ServersSetChangeDelegate") - } - ServersSetChangeMessage::ServersSetChangeDelegateResponse(_) => { - write!(f, "ServersSetChangeDelegateResponse") - } - ServersSetChangeMessage::ServersSetChangeShareAddMessage(ref m) => { - write!(f, "ServersSetChangeShareAddMessage.{}", m.message) - } - ServersSetChangeMessage::ServersSetChangeError(_) => write!(f, "ServersSetChangeError"), - ServersSetChangeMessage::ServersSetChangeCompleted(_) => { - write!(f, "ServersSetChangeCompleted") - } - } - } -} - -impl fmt::Display for ShareAddMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ShareAddMessage::ShareAddConsensusMessage(ref m) => { - write!(f, "ShareAddConsensusMessage.{}", m.message) - } - ShareAddMessage::KeyShareCommon(_) => write!(f, "KeyShareCommon"), - ShareAddMessage::NewKeysDissemination(_) => write!(f, "NewKeysDissemination"), - ShareAddMessage::ShareAddError(_) => write!(f, "ShareAddError"), - } - } -} - -impl fmt::Display for KeyVersionNegotiationMessage { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - KeyVersionNegotiationMessage::RequestKeyVersions(_) => write!(f, "RequestKeyVersions"), - KeyVersionNegotiationMessage::KeyVersions(_) => write!(f, "KeyVersions"), - KeyVersionNegotiationMessage::KeyVersionsError(_) => write!(f, "KeyVersionsError"), - } - } -} diff --git a/secret-store/src/key_server_cluster/mod.rs b/secret-store/src/key_server_cluster/mod.rs deleted file mode 100644 index a98cdf2ce3..0000000000 --- a/secret-store/src/key_server_cluster/mod.rs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::types::ServerKeyId; - -#[cfg(test)] -pub use self::cluster::tests::DummyClusterClient; -pub use self::{ - cluster::{new_network_cluster, ClusterClient, ClusterConfiguration, ClusterCore}, - cluster_connections_net::NetConnectionsManagerConfig, - cluster_sessions::{ClusterSession, ClusterSessionsListener}, -}; -pub use super::{ - acl_storage::AclStorage, - key_server_set::{ - is_migration_required, KeyServerSet, KeyServerSetMigration, KeyServerSetSnapshot, - }, - key_storage::{DocumentKeyShare, DocumentKeyShareVersion, KeyStorage}, - serialization::{ - SerializableAddress, SerializableH256, SerializableMessageHash, SerializablePublic, - SerializableRequester, SerializableSecret, SerializableSignature, - }, - traits::NodeKeyPair, - types::{EncryptedDocumentKeyShadow, Error, NodeId, Requester}, -}; - -pub use super::acl_storage::DummyAclStorage; -#[cfg(test)] -pub use super::key_server_set::tests::MapKeyServerSet; -#[cfg(test)] -pub use super::key_storage::tests::DummyKeyStorage; -#[cfg(test)] -pub use super::node_key_pair::PlainNodeKeyPair; - -pub type SessionId = ServerKeyId; - -/// Session metadata. -#[derive(Debug, Clone)] -pub struct SessionMeta { - /// Key id. - pub id: SessionId, - /// Id of node, which has started this session. - pub master_node_id: NodeId, - /// Id of node, on which this session is running. - pub self_node_id: NodeId, - /// Session threshold. - pub threshold: usize, - /// Count of all configured key server nodes (valid at session start time). - pub configured_nodes_count: usize, - /// Count of all connected key server nodes (valid at session start time). - pub connected_nodes_count: usize, -} - -mod admin_sessions; -mod client_sessions; - -pub use self::admin_sessions::{ - key_version_negotiation_session, servers_set_change_session, share_add_session, - share_change_session, -}; - -pub use self::client_sessions::{ - decryption_session, encryption_session, generation_session, signing_session_ecdsa, - signing_session_schnorr, -}; - -mod cluster; -mod cluster_connections; -mod cluster_connections_net; -mod cluster_message_processor; -mod cluster_sessions; -mod cluster_sessions_creator; -mod connection_trigger; -mod connection_trigger_with_migration; -mod io; -mod jobs; -pub mod math; -mod message; -mod net; diff --git a/secret-store/src/key_server_cluster/net/accept_connection.rs b/secret-store/src/key_server_cluster/net/accept_connection.rs deleted file mode 100644 index 82f91f2699..0000000000 --- a/secret-store/src/key_server_cluster/net/accept_connection.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::{Future, Poll}; -use key_server_cluster::{ - io::{accept_handshake, deadline, Deadline, Handshake}, - net::Connection, - Error, NodeKeyPair, -}; -use std::{io, net::SocketAddr, sync::Arc, time::Duration}; -use tokio::net::TcpStream; - -/// Create future for accepting incoming connection. -pub fn accept_connection( - stream: TcpStream, - self_key_pair: Arc, -) -> Deadline { - // TODO: This could fail so it would be better either to accept the - // address as a separate argument or return a result. - let address = stream - .peer_addr() - .expect("Unable to determine tcp peer address"); - - let accept = AcceptConnection { - handshake: accept_handshake(stream, self_key_pair), - address: address, - }; - - deadline(Duration::new(5, 0), accept).expect("Failed to create timeout") -} - -/// Future for accepting incoming connection. -pub struct AcceptConnection { - handshake: Handshake, - address: SocketAddr, -} - -impl Future for AcceptConnection { - type Item = Result; - type Error = io::Error; - - fn poll(&mut self) -> Poll { - let (stream, result) = try_ready!(self.handshake.poll()); - let result = match result { - Ok(result) => result, - Err(err) => return Ok(Err(err).into()), - }; - let connection = Connection { - stream: stream.into(), - address: self.address, - node_id: result.node_id, - key: result.shared_key, - }; - Ok(Ok(connection).into()) - } -} diff --git a/secret-store/src/key_server_cluster/net/connect.rs b/secret-store/src/key_server_cluster/net/connect.rs deleted file mode 100644 index 40c25e414e..0000000000 --- a/secret-store/src/key_server_cluster/net/connect.rs +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::{Async, Future, Poll}; -use key_server_cluster::{ - io::{deadline, handshake, Deadline, Handshake}, - net::Connection, - Error, NodeId, NodeKeyPair, -}; -use std::{collections::BTreeSet, io, net::SocketAddr, sync::Arc, time::Duration}; -use tokio::net::{tcp::ConnectFuture, TcpStream}; - -/// Create future for connecting to other node. -pub fn connect( - address: &SocketAddr, - self_key_pair: Arc, - trusted_nodes: BTreeSet, -) -> Deadline { - let connect = Connect { - state: ConnectState::TcpConnect(TcpStream::connect(address)), - address: address.clone(), - self_key_pair: self_key_pair, - trusted_nodes: trusted_nodes, - }; - - deadline(Duration::new(5, 0), connect).expect("Failed to create timeout") -} - -enum ConnectState { - TcpConnect(ConnectFuture), - Handshake(Handshake), - Connected, -} - -/// Future for connecting to other node. -pub struct Connect { - state: ConnectState, - address: SocketAddr, - self_key_pair: Arc, - trusted_nodes: BTreeSet, -} - -impl Future for Connect { - type Item = Result; - type Error = io::Error; - - fn poll(&mut self) -> Poll { - let (next, result) = match self.state { - ConnectState::TcpConnect(ref mut future) => { - let stream = try_ready!(future.poll()); - let handshake = handshake( - stream, - self.self_key_pair.clone(), - self.trusted_nodes.clone(), - ); - (ConnectState::Handshake(handshake), Async::NotReady) - } - ConnectState::Handshake(ref mut future) => { - let (stream, result) = try_ready!(future.poll()); - let result = match result { - Ok(result) => result, - Err(err) => return Ok(Async::Ready(Err(err))), - }; - let connection = Connection { - stream: stream.into(), - address: self.address, - node_id: result.node_id, - key: result.shared_key, - }; - (ConnectState::Connected, Async::Ready(Ok(connection))) - } - ConnectState::Connected => panic!("poll Connect after it's done"), - }; - - self.state = next; - match result { - // by polling again, we register new future - Async::NotReady => self.poll(), - result => Ok(result), - } - } -} diff --git a/secret-store/src/key_server_cluster/net/connection.rs b/secret-store/src/key_server_cluster/net/connection.rs deleted file mode 100644 index 769d15ef97..0000000000 --- a/secret-store/src/key_server_cluster/net/connection.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethkey::KeyPair; -use key_server_cluster::{io::SharedTcpStream, NodeId}; -use std::net; - -/// Established connection data -pub struct Connection { - /// Peer address. - pub address: net::SocketAddr, - /// Connection stream. - pub stream: SharedTcpStream, - /// Peer node id. - pub node_id: NodeId, - /// Encryption key. - pub key: KeyPair, -} diff --git a/secret-store/src/key_server_cluster/net/mod.rs b/secret-store/src/key_server_cluster/net/mod.rs deleted file mode 100644 index 43874b0c61..0000000000 --- a/secret-store/src/key_server_cluster/net/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -mod accept_connection; -mod connect; -mod connection; - -pub use self::{ - accept_connection::{accept_connection, AcceptConnection}, - connect::{connect, Connect}, - connection::Connection, -}; diff --git a/secret-store/src/key_server_set.rs b/secret-store/src/key_server_set.rs deleted file mode 100644 index 137e1b0dd9..0000000000 --- a/secret-store/src/key_server_set.rs +++ /dev/null @@ -1,982 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use bytes::Bytes; -use call_contract::CallContract; -use ethabi::FunctionOutputDecoder; -use ethcore::client::{BlockChainClient, BlockId, ChainNotify, Client, NewBlocks}; -use ethereum_types::{Address, H256}; -use ethkey::public_to_address; -use parking_lot::Mutex; -use std::{ - collections::{BTreeMap, HashSet}, - net::SocketAddr, - sync::Arc, -}; -use trusted_client::TrustedClient; -use types::{Error, NodeAddress, NodeId, Public}; -use ContractAddress; -use NodeKeyPair; - -use_contract!(key_server, "res/key_server_set.json"); - -/// Name of KeyServerSet contract in registry. -const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set"; -/// Number of blocks (since latest new_set change) required before actually starting migration. -const MIGRATION_CONFIRMATIONS_REQUIRED: u64 = 5; -/// Number of blocks before the same-migration transaction (be it start or confirmation) will be retried. -const TRANSACTION_RETRY_INTERVAL_BLOCKS: u64 = 30; - -#[derive(Default, Debug, Clone, PartialEq)] -/// Key Server Set state. -pub struct KeyServerSetSnapshot { - /// Current set of key servers. - pub current_set: BTreeMap, - /// New set of key servers. - pub new_set: BTreeMap, - /// Current migration data. - pub migration: Option, -} - -#[derive(Default, Debug, Clone, PartialEq)] -/// Key server set migration. -pub struct KeyServerSetMigration { - /// Migration id. - pub id: H256, - /// Migration set of key servers. It is the new_set at the moment of migration start. - pub set: BTreeMap, - /// Master node of the migration process. - pub master: NodeId, - /// Is migration confirmed by this node? - pub is_confirmed: bool, -} - -/// Key Server Set -pub trait KeyServerSet: Send + Sync { - /// Is this node currently isolated from the set? - fn is_isolated(&self) -> bool; - /// Get server set state. - fn snapshot(&self) -> KeyServerSetSnapshot; - /// Start migration. - fn start_migration(&self, migration_id: H256); - /// Confirm migration. - fn confirm_migration(&self, migration_id: H256); -} - -/// On-chain Key Server set implementation. -pub struct OnChainKeyServerSet { - /// Cached on-chain contract. - contract: Mutex, -} - -#[derive(Default, Debug, Clone, PartialEq)] -/// Non-finalized new_set. -struct FutureNewSet { - /// New servers set. - pub new_set: BTreeMap, - /// Hash of block, when this set has appeared for first time. - pub block: H256, -} - -#[derive(Default, Debug, Clone, PartialEq)] -/// Migration-related transaction information. -struct PreviousMigrationTransaction { - /// Migration id. - pub migration_id: H256, - /// Latest actual block number at the time this transaction has been sent. - pub block: u64, -} - -/// Cached on-chain Key Server set contract. -struct CachedContract { - /// Blockchain client. - client: TrustedClient, - /// Contract address source. - contract_address_source: Option, - /// Current contract address. - contract_address: Option
, - /// Is auto-migrate enabled? - auto_migrate_enabled: bool, - /// Current contract state. - snapshot: KeyServerSetSnapshot, - /// Scheduled contract state (if any). - future_new_set: Option, - /// Previous start migration transaction. - start_migration_tx: Option, - /// Previous confirm migration transaction. - confirm_migration_tx: Option, - /// This node key pair. - self_key_pair: Arc, -} - -impl OnChainKeyServerSet { - pub fn new( - trusted_client: TrustedClient, - contract_address_source: Option, - self_key_pair: Arc, - auto_migrate_enabled: bool, - key_servers: BTreeMap, - ) -> Result, Error> { - let client = trusted_client.get_untrusted(); - let key_server_set = Arc::new(OnChainKeyServerSet { - contract: Mutex::new(CachedContract::new( - trusted_client, - contract_address_source, - self_key_pair, - auto_migrate_enabled, - key_servers, - )?), - }); - client - .ok_or_else(|| { - Error::Internal("Constructing OnChainKeyServerSet without active Client".into()) - })? - .add_notify(key_server_set.clone()); - Ok(key_server_set) - } -} - -impl KeyServerSet for OnChainKeyServerSet { - fn is_isolated(&self) -> bool { - self.contract.lock().is_isolated() - } - - fn snapshot(&self) -> KeyServerSetSnapshot { - self.contract.lock().snapshot() - } - - fn start_migration(&self, migration_id: H256) { - self.contract.lock().start_migration(migration_id) - } - - fn confirm_migration(&self, migration_id: H256) { - self.contract.lock().confirm_migration(migration_id); - } -} - -impl ChainNotify for OnChainKeyServerSet { - // t_nb 11.6 SecretStore OnChainKeyServerSet. - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { - return; - } - let (enacted, retracted) = new_blocks.route.into_enacted_retracted(); - - if !enacted.is_empty() || !retracted.is_empty() { - self.contract.lock().update(enacted, retracted) - } - } -} - -trait KeyServerSubset) -> Result, String>> { - fn read_list(&self, f: &F) -> Result, String>; - - fn read_public(&self, address: Address, f: &F) -> Result; - - fn read_address(&self, address: Address, f: &F) -> Result; -} - -struct CurrentKeyServerSubset; - -impl) -> Result, String>> KeyServerSubset for CurrentKeyServerSubset { - fn read_list(&self, f: &F) -> Result, String> { - let (encoded, decoder) = key_server::functions::get_current_key_servers::call(); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_public(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = - key_server::functions::get_current_key_server_public::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_address(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = - key_server::functions::get_current_key_server_address::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } -} - -struct MigrationKeyServerSubset; - -impl) -> Result, String>> KeyServerSubset for MigrationKeyServerSubset { - fn read_list(&self, f: &F) -> Result, String> { - let (encoded, decoder) = key_server::functions::get_migration_key_servers::call(); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_public(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = - key_server::functions::get_migration_key_server_public::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_address(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = - key_server::functions::get_migration_key_server_address::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } -} - -struct NewKeyServerSubset; - -impl) -> Result, String>> KeyServerSubset for NewKeyServerSubset { - fn read_list(&self, f: &F) -> Result, String> { - let (encoded, decoder) = key_server::functions::get_new_key_servers::call(); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_public(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = key_server::functions::get_new_key_server_public::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } - - fn read_address(&self, address: Address, f: &F) -> Result { - let (encoded, decoder) = key_server::functions::get_new_key_server_address::call(address); - decoder.decode(&f(encoded)?).map_err(|e| e.to_string()) - } -} - -impl CachedContract { - pub fn new( - client: TrustedClient, - contract_address_source: Option, - self_key_pair: Arc, - auto_migrate_enabled: bool, - key_servers: BTreeMap, - ) -> Result { - let server_set = match contract_address_source.is_none() { - true => key_servers - .into_iter() - .map(|(p, addr)| { - let addr = - format!("{}:{}", addr.address, addr.port) - .parse() - .map_err(|err| { - Error::Internal(format!("error parsing node address: {}", err)) - })?; - Ok((p, addr)) - }) - .collect::, Error>>()?, - false => Default::default(), - }; - - let mut contract = CachedContract { - client: client, - contract_address_source: contract_address_source, - contract_address: None, - auto_migrate_enabled: auto_migrate_enabled, - future_new_set: None, - confirm_migration_tx: None, - start_migration_tx: None, - snapshot: KeyServerSetSnapshot { - current_set: server_set.clone(), - new_set: server_set, - ..Default::default() - }, - self_key_pair: self_key_pair, - }; - contract.update_contract_address(); - - Ok(contract) - } - - pub fn update_contract_address(&mut self) { - if let Some(ref contract_address_source) = self.contract_address_source { - let contract_address = self.client.read_contract_address( - KEY_SERVER_SET_CONTRACT_REGISTRY_NAME.into(), - contract_address_source, - ); - if contract_address != self.contract_address { - trace!(target: "secretstore", "{}: Configuring for key server set contract from address {:?}", - self.self_key_pair.public(), contract_address); - - self.contract_address = contract_address; - } - } - } - - pub fn update(&mut self, enacted: Vec, retracted: Vec) { - // no need to update when servers set is hardcoded - if self.contract_address_source.is_none() { - return; - } - - if let Some(client) = self.client.get() { - // read new snapshot from reqistry (if something has chnaged) - if !enacted.is_empty() || !retracted.is_empty() { - self.update_contract_address(); - self.read_from_registry(&*client); - } - - // update number of confirmations (if there's future new set) - self.update_number_of_confirmations_if_required(&*client); - } - } - - fn is_isolated(&self) -> bool { - !self - .snapshot - .current_set - .contains_key(self.self_key_pair.public()) - } - - fn snapshot(&self) -> KeyServerSetSnapshot { - self.snapshot.clone() - } - - fn start_migration(&mut self, migration_id: H256) { - // trust is not needed here, because it is the reaction to the read of the trusted client - if let (Some(client), Some(contract_address)) = - (self.client.get_untrusted(), self.contract_address.as_ref()) - { - // check if we need to send start migration transaction - if !update_last_transaction_block(&*client, &migration_id, &mut self.start_migration_tx) - { - return; - } - - // prepare transaction data - let transaction_data = - key_server::functions::start_migration::encode_input(migration_id); - - // send transaction - match self - .client - .transact_contract(*contract_address, transaction_data) - { - Ok(_) => { - trace!(target: "secretstore_net", "{}: sent auto-migration start transaction", - self.self_key_pair.public()) - } - Err(error) => { - warn!(target: "secretstore_net", "{}: failed to submit auto-migration start transaction: {}", - self.self_key_pair.public(), error) - } - } - } - } - - fn confirm_migration(&mut self, migration_id: H256) { - // trust is not needed here, because we have already completed the action - if let (Some(client), Some(contract_address)) = (self.client.get(), self.contract_address) { - // check if we need to send start migration transaction - if !update_last_transaction_block( - &*client, - &migration_id, - &mut self.confirm_migration_tx, - ) { - return; - } - - // prepare transaction data - let transaction_data = - key_server::functions::confirm_migration::encode_input(migration_id); - - // send transaction - match self - .client - .transact_contract(contract_address, transaction_data) - { - Ok(_) => { - trace!(target: "secretstore_net", "{}: sent auto-migration confirm transaction", - self.self_key_pair.public()) - } - Err(error) => { - warn!(target: "secretstore_net", "{}: failed to submit auto-migration confirmation transaction: {}", - self.self_key_pair.public(), error) - } - } - } - } - - fn read_from_registry(&mut self, client: &Client) { - let contract_address = match self.contract_address { - Some(contract_address) => contract_address, - None => { - // no contract installed => empty snapshot - // WARNING: after restart current_set will be reset to the set from configuration file - // even though we have reset to empty set here. We are not considering this as an issue - // because it is actually the issue of administrator. - self.snapshot = Default::default(); - self.future_new_set = None; - return; - } - }; - - let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); - - let current_set = Self::read_key_server_set(CurrentKeyServerSubset, &do_call); - - // read migration-related data if auto migration is enabled - let (new_set, migration) = match self.auto_migrate_enabled { - true => { - let new_set = Self::read_key_server_set(NewKeyServerSubset, &do_call); - let migration_set = Self::read_key_server_set(MigrationKeyServerSubset, &do_call); - - let migration_id = match migration_set.is_empty() { - false => { - let (encoded, decoder) = key_server::functions::get_migration_id::call(); - do_call(encoded) - .map_err(|e| e.to_string()) - .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) - .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err }) - .ok() - } - true => None, - }; - - let migration_master = match migration_set.is_empty() { - false => { - let (encoded, decoder) = - key_server::functions::get_migration_master::call(); - do_call(encoded) - .map_err(|e| e.to_string()) - .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) - .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration master from contract", err); err }) - .ok() - .and_then(|address| current_set.keys().chain(migration_set.keys()) - .find(|public| public_to_address(public) == address) - .cloned()) - } - true => None, - }; - - let is_migration_confirmed = match migration_set.is_empty() { - false - if current_set.contains_key(self.self_key_pair.public()) - || migration_set.contains_key(self.self_key_pair.public()) => - { - let (encoded, decoder) = - key_server::functions::is_migration_confirmed::call( - self.self_key_pair.address(), - ); - do_call(encoded) - .map_err(|e| e.to_string()) - .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string())) - .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration confirmation from contract", err); err }) - .ok() - } - _ => None, - }; - - let migration = match ( - migration_set.is_empty(), - migration_id, - migration_master, - is_migration_confirmed, - ) { - ( - false, - Some(migration_id), - Some(migration_master), - Some(is_migration_confirmed), - ) => Some(KeyServerSetMigration { - id: migration_id, - master: migration_master, - set: migration_set, - is_confirmed: is_migration_confirmed, - }), - _ => None, - }; - - (new_set, migration) - } - false => (current_set.clone(), None), - }; - - let mut new_snapshot = KeyServerSetSnapshot { - current_set: current_set, - new_set: new_set, - migration: migration, - }; - - // we might want to adjust new_set if auto migration is enabled - if self.auto_migrate_enabled { - let block = client.block_hash(BlockId::Latest).unwrap_or_default(); - update_future_set(&mut self.future_new_set, &mut new_snapshot, block); - } - - self.snapshot = new_snapshot; - } - - fn read_key_server_set(subset: T, do_call: F) -> BTreeMap - where - T: KeyServerSubset, - F: Fn(Vec) -> Result, String>, - { - let mut key_servers = BTreeMap::new(); - let mut key_servers_addresses = HashSet::new(); - let key_servers_list = subset.read_list(&do_call) - .map_err(|err| { warn!(target: "secretstore_net", "error {} reading list of key servers from contract", err); err }) - .unwrap_or_default(); - for key_server in key_servers_list { - let key_server_public = subset.read_public(key_server, &do_call).and_then(|p| { - if p.len() == 64 { - Ok(Public::from_slice(&p)) - } else { - Err(format!("Invalid public length {}", p.len())) - } - }); - let key_server_address: Result = subset - .read_address(key_server, &do_call) - .and_then(|a| a.parse().map_err(|e| format!("Invalid ip address: {}", e))); - - // only add successfully parsed nodes - match (key_server_public, key_server_address) { - (Ok(key_server_public), Ok(key_server_address)) => { - if !key_servers_addresses.insert(key_server_address.clone()) { - warn!(target: "secretstore_net", "the same address ({}) specified twice in list of contracts. Ignoring server {}", - key_server_address, key_server_public); - continue; - } - - key_servers.insert(key_server_public, key_server_address); - } - (Err(public_err), _) => { - warn!(target: "secretstore_net", "received invalid public from key server set contract: {}", public_err) - } - (_, Err(ip_err)) => { - warn!(target: "secretstore_net", "received invalid IP from key server set contract: {}", ip_err) - } - } - } - key_servers - } - - fn update_number_of_confirmations_if_required(&mut self, client: &dyn BlockChainClient) { - if !self.auto_migrate_enabled { - return; - } - - update_number_of_confirmations( - &|| latest_block_hash(&*client), - &|block| block_confirmations(&*client, block), - &mut self.future_new_set, - &mut self.snapshot, - ); - } -} - -/// Check if two sets are equal (in terms of migration requirements). We do not need migration if only -/// addresses are changed - simply adjusting connections is enough in this case. -pub fn is_migration_required( - current_set: &BTreeMap, - new_set: &BTreeMap, -) -> bool { - let no_nodes_removed = current_set.keys().all(|n| new_set.contains_key(n)); - let no_nodes_added = new_set.keys().all(|n| current_set.contains_key(n)); - !no_nodes_removed || !no_nodes_added -} - -fn update_future_set( - future_new_set: &mut Option, - new_snapshot: &mut KeyServerSetSnapshot, - block: H256, -) { - // migration has already started => no need to delay visibility - if new_snapshot.migration.is_some() { - *future_new_set = None; - return; - } - - // no migration is required => no need to delay visibility - if !is_migration_required(&new_snapshot.current_set, &new_snapshot.new_set) { - *future_new_set = None; - return; - } - - // when auto-migrate is enabled, we do not want to start migration right after new_set is changed, because of: - // 1) there could be a fork && we could start migration to forked version (and potentially lose secrets) - // 2) there must be some period for new_set changes finalization (i.e. adding/removing more servers) - let mut new_set = new_snapshot.current_set.clone(); - ::std::mem::swap(&mut new_set, &mut new_snapshot.new_set); - - // if nothing has changed in future_new_set, then we want to preserve previous block hash - let block = match Some(&new_set) == future_new_set.as_ref().map(|f| &f.new_set) { - true => future_new_set - .as_ref() - .map(|f| &f.block) - .cloned() - .unwrap_or_else(|| block), - false => block, - }; - - *future_new_set = Some(FutureNewSet { - new_set: new_set, - block: block, - }); -} - -fn update_number_of_confirmations H256, F2: Fn(H256) -> Option>( - latest_block: &F1, - confirmations: &F2, - future_new_set: &mut Option, - snapshot: &mut KeyServerSetSnapshot, -) { - match future_new_set.as_mut() { - // no future new set is scheduled => do nothing, - None => return, - // else we should calculate number of confirmations for future new set - Some(future_new_set) => match confirmations(future_new_set.block.clone()) { - // we have enough confirmations => should move new_set from future to snapshot - Some(confirmations) if confirmations >= MIGRATION_CONFIRMATIONS_REQUIRED => (), - // not enough confirmations => do nothing - Some(_) => return, - // if number of confirmations is None, then reorg has happened && we need to reset block - // (some more intelligent strategy is possible, but let's stick to simplest one) - None => { - future_new_set.block = latest_block(); - return; - } - }, - } - - let future_new_set = future_new_set - .take() - .expect("we only pass through match above when future_new_set is some; qed"); - snapshot.new_set = future_new_set.new_set; -} - -fn update_last_transaction_block( - client: &Client, - migration_id: &H256, - previous_transaction: &mut Option, -) -> bool { - let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); - match previous_transaction.as_ref() { - // no previous transaction => send immediately - None => (), - // previous transaction has been sent for other migration process => send immediately - Some(tx) if tx.migration_id != *migration_id => (), - // if we have sent the same type of transaction recently => do nothing (hope it will be mined eventually) - // if we have sent the same transaction some time ago => - // assume that our tx queue was full - // or we didn't have enough eth fot this tx - // or the transaction has been removed from the queue (and never reached any miner node) - // if we have restarted after sending tx => assume we have never sent it - Some(tx) => { - if tx.block > last_block || last_block - tx.block < TRANSACTION_RETRY_INTERVAL_BLOCKS { - return false; - } - } - } - - *previous_transaction = Some(PreviousMigrationTransaction { - migration_id: migration_id.clone(), - block: last_block, - }); - - true -} - -fn latest_block_hash(client: &dyn BlockChainClient) -> H256 { - client.block_hash(BlockId::Latest).unwrap_or_default() -} - -fn block_confirmations(client: &dyn BlockChainClient, block: H256) -> Option { - client - .block_number(BlockId::Hash(block)) - .and_then(|block| { - client - .block_number(BlockId::Latest) - .map(|last_block| (block, last_block)) - }) - .map(|(block, last_block)| last_block - block) -} - -#[cfg(test)] -pub mod tests { - use super::{ - update_future_set, update_number_of_confirmations, FutureNewSet, KeyServerSet, - KeyServerSetSnapshot, MIGRATION_CONFIRMATIONS_REQUIRED, - }; - use ethereum_types::H256; - use ethkey::Public; - use std::{collections::BTreeMap, net::SocketAddr}; - - #[derive(Default)] - pub struct MapKeyServerSet { - is_isolated: bool, - nodes: BTreeMap, - } - - impl MapKeyServerSet { - pub fn new(is_isolated: bool, nodes: BTreeMap) -> Self { - MapKeyServerSet { - is_isolated: is_isolated, - nodes: nodes, - } - } - } - - impl KeyServerSet for MapKeyServerSet { - fn is_isolated(&self) -> bool { - self.is_isolated - } - - fn snapshot(&self) -> KeyServerSetSnapshot { - KeyServerSetSnapshot { - current_set: self.nodes.clone(), - new_set: self.nodes.clone(), - ..Default::default() - } - } - - fn start_migration(&self, _migration_id: H256) { - unimplemented!("test-only") - } - - fn confirm_migration(&self, _migration_id: H256) { - unimplemented!("test-only") - } - } - - #[test] - fn future_set_is_updated_to_none_when_migration_has_already_started() { - let mut future_new_set = Some(Default::default()); - let mut new_snapshot = KeyServerSetSnapshot { - migration: Some(Default::default()), - ..Default::default() - }; - let new_snapshot_copy = new_snapshot.clone(); - update_future_set(&mut future_new_set, &mut new_snapshot, Default::default()); - assert_eq!(future_new_set, None); - assert_eq!(new_snapshot, new_snapshot_copy); - } - - #[test] - fn future_set_is_updated_to_none_when_no_migration_is_required() { - let node_id = Default::default(); - let address1 = "127.0.0.1:12000".parse().unwrap(); - let address2 = "127.0.0.1:12001".parse().unwrap(); - - // addresses are different, but node set is the same => no migration is required - let mut future_new_set = Some(Default::default()); - let mut new_snapshot = KeyServerSetSnapshot { - current_set: vec![(node_id, address1)].into_iter().collect(), - new_set: vec![(node_id, address2)].into_iter().collect(), - ..Default::default() - }; - let new_snapshot_copy = new_snapshot.clone(); - update_future_set(&mut future_new_set, &mut new_snapshot, Default::default()); - assert_eq!(future_new_set, None); - assert_eq!(new_snapshot, new_snapshot_copy); - - // everything is the same => no migration is required - let mut future_new_set = Some(Default::default()); - let mut new_snapshot = KeyServerSetSnapshot { - current_set: vec![(node_id, address1)].into_iter().collect(), - new_set: vec![(node_id, address1)].into_iter().collect(), - ..Default::default() - }; - let new_snapshot_copy = new_snapshot.clone(); - update_future_set(&mut future_new_set, &mut new_snapshot, Default::default()); - assert_eq!(future_new_set, None); - assert_eq!(new_snapshot, new_snapshot_copy); - } - - #[test] - fn future_set_is_initialized() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = None; - let mut new_snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(2.into(), address)].into_iter().collect(), - ..Default::default() - }; - update_future_set(&mut future_new_set, &mut new_snapshot, Default::default()); - assert_eq!( - future_new_set, - Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }) - ); - assert_eq!( - new_snapshot, - KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - } - ); - } - - #[test] - fn future_set_is_updated_when_set_differs() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }); - let mut new_snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(3.into(), address)].into_iter().collect(), - ..Default::default() - }; - update_future_set(&mut future_new_set, &mut new_snapshot, 1.into()); - assert_eq!( - future_new_set, - Some(FutureNewSet { - new_set: vec![(3.into(), address)].into_iter().collect(), - block: 1.into(), - }) - ); - assert_eq!( - new_snapshot, - KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - } - ); - } - - #[test] - fn future_set_is_not_updated_when_set_is_the_same() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }); - let mut new_snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(2.into(), address)].into_iter().collect(), - ..Default::default() - }; - update_future_set(&mut future_new_set, &mut new_snapshot, 1.into()); - assert_eq!( - future_new_set, - Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }) - ); - assert_eq!( - new_snapshot, - KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - } - ); - } - - #[test] - fn when_updating_confirmations_nothing_is_changed_if_no_future_set() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = None; - let mut snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - }; - let snapshot_copy = snapshot.clone(); - update_number_of_confirmations( - &|| 1.into(), - &|_| Some(MIGRATION_CONFIRMATIONS_REQUIRED), - &mut future_new_set, - &mut snapshot, - ); - assert_eq!(future_new_set, None); - assert_eq!(snapshot, snapshot_copy); - } - - #[test] - fn when_updating_confirmations_migration_is_scheduled() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }); - let mut snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - }; - update_number_of_confirmations( - &|| 1.into(), - &|_| Some(MIGRATION_CONFIRMATIONS_REQUIRED), - &mut future_new_set, - &mut snapshot, - ); - assert_eq!(future_new_set, None); - assert_eq!( - snapshot, - KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(2.into(), address)].into_iter().collect(), - ..Default::default() - } - ); - } - - #[test] - fn when_updating_confirmations_migration_is_not_scheduled_when_not_enough_confirmations() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: Default::default(), - }); - let mut snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - }; - let future_new_set_copy = future_new_set.clone(); - let snapshot_copy = snapshot.clone(); - update_number_of_confirmations( - &|| 1.into(), - &|_| Some(MIGRATION_CONFIRMATIONS_REQUIRED - 1), - &mut future_new_set, - &mut snapshot, - ); - assert_eq!(future_new_set, future_new_set_copy); - assert_eq!(snapshot, snapshot_copy); - } - - #[test] - fn when_updating_confirmations_migration_is_reset_when_reorganized() { - let address = "127.0.0.1:12000".parse().unwrap(); - - let mut future_new_set = Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: 1.into(), - }); - let mut snapshot = KeyServerSetSnapshot { - current_set: vec![(1.into(), address)].into_iter().collect(), - new_set: vec![(1.into(), address)].into_iter().collect(), - ..Default::default() - }; - let snapshot_copy = snapshot.clone(); - update_number_of_confirmations(&|| 2.into(), &|_| None, &mut future_new_set, &mut snapshot); - assert_eq!( - future_new_set, - Some(FutureNewSet { - new_set: vec![(2.into(), address)].into_iter().collect(), - block: 2.into(), - }) - ); - assert_eq!(snapshot, snapshot_copy); - } -} diff --git a/secret-store/src/key_storage.rs b/secret-store/src/key_storage.rs deleted file mode 100644 index 8fcbfec28b..0000000000 --- a/secret-store/src/key_storage.rs +++ /dev/null @@ -1,738 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::{public_to_address, Public, Secret}; -use kvdb::KeyValueDB; -use serde_json; -use serialization::{ - SerializableAddress, SerializableH256, SerializablePublic, SerializableSecret, -}; -use std::{collections::BTreeMap, sync::Arc}; -use tiny_keccak::Keccak; -use types::{Error, NodeId, ServerKeyId}; - -/// Key of version value. -const DB_META_KEY_VERSION: &'static [u8; 7] = b"version"; -/// Current db version. -const CURRENT_VERSION: u8 = 3; -/// Current type of serialized key shares. -type CurrentSerializableDocumentKeyShare = SerializableDocumentKeyShareV3; -/// Current type of serialized key shares versions. -type CurrentSerializableDocumentKeyVersion = SerializableDocumentKeyShareVersionV3; - -/// Encrypted key share, stored by key storage on the single key server. -#[derive(Debug, Default, Clone, PartialEq)] -pub struct DocumentKeyShare { - /// Author of the entry. - pub author: Address, - /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). - pub threshold: usize, - /// Server public key. - pub public: Public, - /// Common (shared) encryption point. - pub common_point: Option, - /// Encrypted point. - pub encrypted_point: Option, - /// Key share versions. - pub versions: Vec, -} - -/// Versioned portion of document key share. -#[derive(Debug, Clone, PartialEq)] -pub struct DocumentKeyShareVersion { - /// Version hash (Keccak(time + id_numbers)). - pub hash: H256, - /// Nodes ids numbers. - pub id_numbers: BTreeMap, - /// Node secret share. - pub secret_share: Secret, -} - -/// Document encryption keys storage -pub trait KeyStorage: Send + Sync { - /// Insert document encryption key - fn insert(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error>; - /// Update document encryption key - fn update(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error>; - /// Get document encryption key - fn get(&self, document: &ServerKeyId) -> Result, Error>; - /// Remove document encryption key - fn remove(&self, document: &ServerKeyId) -> Result<(), Error>; - /// Clears the database - fn clear(&self) -> Result<(), Error>; - /// Check if storage contains document encryption key - fn contains(&self, document: &ServerKeyId) -> bool; - /// Iterate through storage - fn iter<'a>(&'a self) -> Box + 'a>; -} - -/// Persistent document encryption keys storage -pub struct PersistentKeyStorage { - db: Arc, -} - -/// Persistent document encryption keys storage iterator -pub struct PersistentKeyStorageIterator<'a> { - iter: Box, Box<[u8]>)> + 'a>, -} - -/// V0 of encrypted key share, as it is stored by key storage on the single key server. -#[derive(Serialize, Deserialize)] -pub struct SerializableDocumentKeyShareV0 { - /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). - pub threshold: usize, - /// Nodes ids numbers. - pub id_numbers: BTreeMap, - /// Node secret share. - pub secret_share: SerializableSecret, - /// Common (shared) encryption point. - pub common_point: SerializablePublic, - /// Encrypted point. - pub encrypted_point: SerializablePublic, -} - -/// V1 of encrypted key share, as it is stored by key storage on the single key server. -#[derive(Serialize, Deserialize)] -struct SerializableDocumentKeyShareV1 { - /// Author of the entry. - pub author: SerializablePublic, - /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). - pub threshold: usize, - /// Nodes ids numbers. - pub id_numbers: BTreeMap, - /// Node secret share. - pub secret_share: SerializableSecret, - /// Common (shared) encryption point. - pub common_point: Option, - /// Encrypted point. - pub encrypted_point: Option, -} - -/// V2 of encrypted key share, as it is stored by key storage on the single key server. -#[derive(Serialize, Deserialize)] -struct SerializableDocumentKeyShareV2 { - /// Author of the entry. - pub author: SerializablePublic, - /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). - pub threshold: usize, - /// Server public. - pub public: SerializablePublic, - /// Common (shared) encryption point. - pub common_point: Option, - /// Encrypted point. - pub encrypted_point: Option, - /// Versions. - pub versions: Vec, -} - -/// V2 of encrypted key share version, as it is stored by key storage on the single key server. -#[derive(Serialize, Deserialize)] -struct SerializableDocumentKeyShareVersionV2 { - /// Version hash. - pub hash: SerializableH256, - /// Nodes ids numbers. - pub id_numbers: BTreeMap, - /// Node secret share. - pub secret_share: SerializableSecret, -} - -/// V3 of encrypted key share, as it is stored by key storage on the single key server. -#[derive(Serialize, Deserialize)] -struct SerializableDocumentKeyShareV3 { - /// Author of the entry. - pub author: SerializableAddress, - /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). - pub threshold: usize, - /// Server public. - pub public: SerializablePublic, - /// Common (shared) encryption point. - pub common_point: Option, - /// Encrypted point. - pub encrypted_point: Option, - /// Versions. - pub versions: Vec, -} - -/// V3 of encrypted key share version, as it is stored by key storage on the single key server. -type SerializableDocumentKeyShareVersionV3 = SerializableDocumentKeyShareVersionV2; - -impl PersistentKeyStorage { - /// Create new persistent document encryption keys storage - pub fn new(db: Arc) -> Result { - let db = upgrade_db(db)?; - - Ok(PersistentKeyStorage { db: db }) - } -} - -fn upgrade_db(db: Arc) -> Result, Error> { - let version = db.get(None, DB_META_KEY_VERSION)?; - let version = version.and_then(|v| v.get(0).cloned()).unwrap_or(0); - match version { - 0 => { - let mut batch = db.transaction(); - batch.put(None, DB_META_KEY_VERSION, &[CURRENT_VERSION]); - for (db_key, db_value) in db - .iter(None) - .into_iter() - .filter(|&(ref k, _)| **k != *DB_META_KEY_VERSION) - { - let v0_key = serde_json::from_slice::(&db_value) - .map_err(|e| Error::Database(e.to_string()))?; - let current_key = CurrentSerializableDocumentKeyShare { - // author is used in separate generation + encrypt sessions. - // in v0 there have been only simultaneous GenEnc sessions. - author: Address::default().into(), // added in v1 - threshold: v0_key.threshold, - public: Public::default().into(), // addded in v2 - common_point: Some(v0_key.common_point), - encrypted_point: Some(v0_key.encrypted_point), - versions: vec![CurrentSerializableDocumentKeyVersion { - hash: DocumentKeyShareVersion::data_hash( - v0_key.id_numbers.iter().map(|(k, v)| (&***k, &****v)), - ) - .into(), - id_numbers: v0_key.id_numbers, - secret_share: v0_key.secret_share, - }], - }; - let db_value = - serde_json::to_vec(¤t_key).map_err(|e| Error::Database(e.to_string()))?; - batch.put(None, &*db_key, &*db_value); - } - db.write(batch)?; - Ok(db) - } - 1 => { - let mut batch = db.transaction(); - batch.put(None, DB_META_KEY_VERSION, &[CURRENT_VERSION]); - for (db_key, db_value) in db - .iter(None) - .into_iter() - .filter(|&(ref k, _)| **k != *DB_META_KEY_VERSION) - { - let v1_key = serde_json::from_slice::(&db_value) - .map_err(|e| Error::Database(e.to_string()))?; - let current_key = CurrentSerializableDocumentKeyShare { - author: public_to_address(&v1_key.author).into(), // added in v1 + changed in v3 - threshold: v1_key.threshold, - public: Public::default().into(), // addded in v2 - common_point: v1_key.common_point, - encrypted_point: v1_key.encrypted_point, - versions: vec![CurrentSerializableDocumentKeyVersion { - hash: DocumentKeyShareVersion::data_hash( - v1_key.id_numbers.iter().map(|(k, v)| (&***k, &****v)), - ) - .into(), - id_numbers: v1_key.id_numbers, - secret_share: v1_key.secret_share, - }], - }; - let db_value = - serde_json::to_vec(¤t_key).map_err(|e| Error::Database(e.to_string()))?; - batch.put(None, &*db_key, &*db_value); - } - db.write(batch)?; - Ok(db) - } - 2 => { - let mut batch = db.transaction(); - batch.put(None, DB_META_KEY_VERSION, &[CURRENT_VERSION]); - for (db_key, db_value) in db - .iter(None) - .into_iter() - .filter(|&(ref k, _)| **k != *DB_META_KEY_VERSION) - { - let v2_key = serde_json::from_slice::(&db_value) - .map_err(|e| Error::Database(e.to_string()))?; - let current_key = CurrentSerializableDocumentKeyShare { - author: public_to_address(&v2_key.author).into(), // changed in v3 - threshold: v2_key.threshold, - public: v2_key.public, - common_point: v2_key.common_point, - encrypted_point: v2_key.encrypted_point, - versions: v2_key.versions, - }; - let db_value = - serde_json::to_vec(¤t_key).map_err(|e| Error::Database(e.to_string()))?; - batch.put(None, &*db_key, &*db_value); - } - db.write(batch)?; - Ok(db) - } - 3 => Ok(db), - _ => Err(Error::Database(format!( - "unsupported SecretStore database version: {}", - version - ))), - } -} - -impl KeyStorage for PersistentKeyStorage { - fn insert(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error> { - let key: CurrentSerializableDocumentKeyShare = key.into(); - let key = serde_json::to_vec(&key).map_err(|e| Error::Database(e.to_string()))?; - let mut batch = self.db.transaction(); - batch.put(None, &document, &key); - self.db.write(batch).map_err(Into::into) - } - - fn update(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error> { - self.insert(document, key) - } - - fn get(&self, document: &ServerKeyId) -> Result, Error> { - self.db - .get(None, document) - .map_err(|e| Error::Database(e.to_string())) - .and_then(|key| match key { - None => Ok(None), - Some(key) => serde_json::from_slice::(&key) - .map_err(|e| Error::Database(e.to_string())) - .map(Into::into) - .map(Some), - }) - } - - fn remove(&self, document: &ServerKeyId) -> Result<(), Error> { - let mut batch = self.db.transaction(); - batch.delete(None, &document); - self.db.write(batch).map_err(Into::into) - } - - fn clear(&self) -> Result<(), Error> { - let mut batch = self.db.transaction(); - for (key, _) in self.iter() { - batch.delete(None, &key); - } - self.db - .write(batch) - .map_err(|e| Error::Database(e.to_string())) - } - - fn contains(&self, document: &ServerKeyId) -> bool { - self.db - .get(None, document) - .map(|k| k.is_some()) - .unwrap_or(false) - } - - fn iter<'a>(&'a self) -> Box + 'a> { - Box::new(PersistentKeyStorageIterator { - iter: self.db.iter(None), - }) - } -} - -impl<'a> Iterator for PersistentKeyStorageIterator<'a> { - type Item = (ServerKeyId, DocumentKeyShare); - - fn next(&mut self) -> Option<(ServerKeyId, DocumentKeyShare)> { - self.iter.as_mut().next().and_then(|(db_key, db_val)| { - serde_json::from_slice::(&db_val) - .ok() - .map(|key| ((*db_key).into(), key.into())) - }) - } -} - -impl DocumentKeyShare { - /// Get last version reference. - #[cfg(test)] - pub fn last_version(&self) -> Result<&DocumentKeyShareVersion, Error> { - self.versions - .iter() - .rev() - .nth(0) - .ok_or_else(|| Error::Database("key version is not found".into())) - } - - /// Get given version reference. - pub fn version(&self, version: &H256) -> Result<&DocumentKeyShareVersion, Error> { - self.versions - .iter() - .rev() - .find(|v| &v.hash == version) - .ok_or_else(|| Error::Database("key version is not found".into())) - } -} - -impl DocumentKeyShareVersion { - /// Create new version - pub fn new(id_numbers: BTreeMap, secret_share: Secret) -> Self { - DocumentKeyShareVersion { - hash: Self::data_hash(id_numbers.iter().map(|(k, v)| (&**k, &***v))), - id_numbers: id_numbers, - secret_share: secret_share, - } - } - - /// Calculate hash of given version data. - pub fn data_hash<'a, I>(id_numbers: I) -> H256 - where - I: Iterator, - { - let mut nodes_keccak = Keccak::new_keccak256(); - - for (node, node_number) in id_numbers { - nodes_keccak.update(node); - nodes_keccak.update(node_number); - } - - let mut nodes_keccak_value = [0u8; 32]; - nodes_keccak.finalize(&mut nodes_keccak_value); - - nodes_keccak_value.into() - } -} - -impl From for SerializableDocumentKeyShareV3 { - fn from(key: DocumentKeyShare) -> Self { - SerializableDocumentKeyShareV3 { - author: key.author.into(), - threshold: key.threshold, - public: key.public.into(), - common_point: key.common_point.map(Into::into), - encrypted_point: key.encrypted_point.map(Into::into), - versions: key.versions.into_iter().map(Into::into).collect(), - } - } -} - -impl From for SerializableDocumentKeyShareVersionV3 { - fn from(version: DocumentKeyShareVersion) -> Self { - SerializableDocumentKeyShareVersionV3 { - hash: version.hash.into(), - id_numbers: version - .id_numbers - .into_iter() - .map(|(k, v)| (k.into(), v.into())) - .collect(), - secret_share: version.secret_share.into(), - } - } -} - -impl From for DocumentKeyShare { - fn from(key: SerializableDocumentKeyShareV3) -> Self { - DocumentKeyShare { - author: key.author.into(), - threshold: key.threshold, - public: key.public.into(), - common_point: key.common_point.map(Into::into), - encrypted_point: key.encrypted_point.map(Into::into), - versions: key - .versions - .into_iter() - .map(|v| DocumentKeyShareVersion { - hash: v.hash.into(), - id_numbers: v - .id_numbers - .into_iter() - .map(|(k, v)| (k.into(), v.into())) - .collect(), - secret_share: v.secret_share.into(), - }) - .collect(), - } - } -} - -#[cfg(test)] -pub mod tests { - extern crate tempdir; - - use self::tempdir::TempDir; - use super::{ - upgrade_db, CurrentSerializableDocumentKeyShare, DocumentKeyShare, DocumentKeyShareVersion, - KeyStorage, PersistentKeyStorage, SerializableDocumentKeyShareV0, - SerializableDocumentKeyShareV1, SerializableDocumentKeyShareV2, - SerializableDocumentKeyShareVersionV2, CURRENT_VERSION, DB_META_KEY_VERSION, - }; - use ethereum_types::{Address, H256}; - use ethkey::{public_to_address, Generator, Public, Random, Secret}; - use kvdb_rocksdb::Database; - use parking_lot::RwLock; - use serde_json; - use std::{collections::HashMap, sync::Arc}; - use types::{Error, ServerKeyId}; - - /// In-memory document encryption keys storage - #[derive(Default)] - pub struct DummyKeyStorage { - keys: RwLock>, - } - - impl KeyStorage for DummyKeyStorage { - fn insert(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error> { - self.keys.write().insert(document, key); - Ok(()) - } - - fn update(&self, document: ServerKeyId, key: DocumentKeyShare) -> Result<(), Error> { - self.keys.write().insert(document, key); - Ok(()) - } - - fn get(&self, document: &ServerKeyId) -> Result, Error> { - Ok(self.keys.read().get(document).cloned()) - } - - fn remove(&self, document: &ServerKeyId) -> Result<(), Error> { - self.keys.write().remove(document); - Ok(()) - } - - fn clear(&self) -> Result<(), Error> { - self.keys.write().clear(); - Ok(()) - } - - fn contains(&self, document: &ServerKeyId) -> bool { - self.keys.read().contains_key(document) - } - - fn iter<'a>(&'a self) -> Box + 'a> { - Box::new(self.keys.read().clone().into_iter()) - } - } - - #[test] - fn persistent_key_storage() { - let tempdir = TempDir::new("").unwrap(); - let key1 = ServerKeyId::from(1); - let value1 = DocumentKeyShare { - author: Default::default(), - threshold: 100, - public: Public::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: vec![( - Random.generate().unwrap().public().clone(), - Random.generate().unwrap().secret().clone(), - )] - .into_iter() - .collect(), - secret_share: Random.generate().unwrap().secret().clone(), - }], - }; - let key2 = ServerKeyId::from(2); - let value2 = DocumentKeyShare { - author: Default::default(), - threshold: 200, - public: Public::default(), - common_point: Some(Random.generate().unwrap().public().clone()), - encrypted_point: Some(Random.generate().unwrap().public().clone()), - versions: vec![DocumentKeyShareVersion { - hash: Default::default(), - id_numbers: vec![( - Random.generate().unwrap().public().clone(), - Random.generate().unwrap().secret().clone(), - )] - .into_iter() - .collect(), - secret_share: Random.generate().unwrap().secret().clone(), - }], - }; - let key3 = ServerKeyId::from(3); - - let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); - - let key_storage = PersistentKeyStorage::new(Arc::new(db)).unwrap(); - key_storage.insert(key1.clone(), value1.clone()).unwrap(); - key_storage.insert(key2.clone(), value2.clone()).unwrap(); - assert_eq!(key_storage.get(&key1), Ok(Some(value1.clone()))); - assert_eq!(key_storage.get(&key2), Ok(Some(value2.clone()))); - assert_eq!(key_storage.get(&key3), Ok(None)); - drop(key_storage); - - let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); - - let key_storage = PersistentKeyStorage::new(Arc::new(db)).unwrap(); - assert_eq!(key_storage.get(&key1), Ok(Some(value1))); - assert_eq!(key_storage.get(&key2), Ok(Some(value2))); - assert_eq!(key_storage.get(&key3), Ok(None)); - } - - #[test] - fn upgrade_db_from_0() { - let tempdir = TempDir::new("").unwrap(); - let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); - - // prepare v0 database - { - let key = serde_json::to_vec(&SerializableDocumentKeyShareV0 { - threshold: 777, - id_numbers: vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), - )].into_iter().collect(), - secret_share: "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::().unwrap().into(), - common_point: "99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into(), - encrypted_point: "7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into(), - }).unwrap(); - let mut batch = db.transaction(); - batch.put(None, &[7], &key); - db.write(batch).unwrap(); - } - - // upgrade database - let db = upgrade_db(Arc::new(db)).unwrap(); - - // check upgrade - assert_eq!( - db.get(None, DB_META_KEY_VERSION).unwrap().unwrap()[0], - CURRENT_VERSION - ); - let key = serde_json::from_slice::( - &db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap(), - ) - .unwrap(); - assert_eq!(Address::default(), key.author.clone().into()); - assert_eq!(777, key.threshold); - assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); - assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); - - assert_eq!(key.versions.len(), 1); - assert_eq!(vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse::().unwrap(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap(), - )], key.versions[0].id_numbers.clone().into_iter().map(|(k, v)| (k.into(), v.into())).collect::>()); - assert_eq!( - "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b" - .parse::() - .unwrap(), - key.versions[0].secret_share.clone().into() - ); - } - - #[test] - fn upgrade_db_from_1() { - let tempdir = TempDir::new("").unwrap(); - let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); - - // prepare v1 database - { - let key = serde_json::to_vec(&SerializableDocumentKeyShareV1 { - author: "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - threshold: 777, - id_numbers: vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), - )].into_iter().collect(), - secret_share: "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::().unwrap().into(), - common_point: Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into()), - encrypted_point: Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into()), - }).unwrap(); - let mut batch = db.transaction(); - batch.put(None, DB_META_KEY_VERSION, &[1]); - batch.put(None, &[7], &key); - db.write(batch).unwrap(); - } - - // upgrade database - let db = upgrade_db(Arc::new(db)).unwrap(); - - // check upgrade - assert_eq!( - db.get(None, DB_META_KEY_VERSION).unwrap().unwrap()[0], - CURRENT_VERSION - ); - let key = serde_json::from_slice::( - &db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap(), - ) - .unwrap(); - assert_eq!(777, key.threshold); - assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); - assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); - assert_eq!(key.author.0, public_to_address(&"b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into())); - - assert_eq!(key.versions.len(), 1); - assert_eq!(vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse::().unwrap(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap(), - )], key.versions[0].id_numbers.clone().into_iter().map(|(k, v)| (k.into(), v.into())).collect::>()); - - assert_eq!( - "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b" - .parse::() - .unwrap(), - key.versions[0].secret_share.clone().into() - ); - } - - #[test] - fn upgrade_db_from_2() { - let tempdir = TempDir::new("").unwrap(); - let db = Database::open_default(&tempdir.path().display().to_string()).unwrap(); - - // prepare v2 database - { - let key = serde_json::to_vec(&SerializableDocumentKeyShareV2 { - author: "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - threshold: 777, - common_point: Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".into()), - encrypted_point: Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".into()), - public: "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - versions: vec![SerializableDocumentKeyShareVersionV2 { - hash: "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), - id_numbers: vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".into(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap().into(), - )].into_iter().collect(), - secret_share: "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b".parse::().unwrap().into(), - }], - }).unwrap(); - let mut batch = db.transaction(); - batch.put(None, DB_META_KEY_VERSION, &[2]); - batch.put(None, &[7], &key); - db.write(batch).unwrap(); - } - - // upgrade database - let db = upgrade_db(Arc::new(db)).unwrap(); - - // check upgrade - assert_eq!( - db.get(None, DB_META_KEY_VERSION).unwrap().unwrap()[0], - CURRENT_VERSION - ); - let key = serde_json::from_slice::( - &db.get(None, &[7]).unwrap().map(|key| key.to_vec()).unwrap(), - ) - .unwrap(); - assert_eq!(777, key.threshold); - assert_eq!(Some("99e82b163b062d55a64085bacfd407bb55f194ba5fb7a1af9c34b84435455520f1372e0e650a4f91aed0058cb823f62146ccb5599c8d13372c300dea866b69fc".parse::().unwrap()), key.common_point.clone().map(Into::into)); - assert_eq!(Some("7e05df9dd077ec21ed4bc45c9fe9e0a43d65fa4be540630de615ced5e95cf5c3003035eb713317237d7667feeeb64335525158f5f7411f67aca9645169ea554c".parse::().unwrap()), key.encrypted_point.clone().map(Into::into)); - assert_eq!(key.author.0, public_to_address(&"b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse().unwrap())); - - assert_eq!(key.versions.len(), 1); - assert_eq!(vec![( - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse::().unwrap(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse::().unwrap(), - )], key.versions[0].id_numbers.clone().into_iter().map(|(k, v)| (k.into(), v.into())).collect::>()); - - assert_eq!( - "00125d85a05e5e63e214cb60fe63f132eec8a103aa29266b7e6e6c5b7597230b" - .parse::() - .unwrap(), - key.versions[0].secret_share.clone().into() - ); - } -} diff --git a/secret-store/src/lib.rs b/secret-store/src/lib.rs deleted file mode 100644 index 51342346e2..0000000000 --- a/secret-store/src/lib.rs +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -extern crate byteorder; -extern crate common_types; -extern crate ethabi; -extern crate ethcore; -extern crate ethcore_call_contract as call_contract; -extern crate ethcore_sync as sync; -extern crate ethereum_types; -extern crate ethkey; -extern crate hyper; -extern crate keccak_hash as hash; -extern crate kvdb; -extern crate parity_bytes as bytes; -extern crate parity_crypto as crypto; -extern crate parity_runtime; -extern crate parking_lot; -extern crate percent_encoding; -extern crate rustc_hex; -extern crate serde; -extern crate serde_json; -extern crate tiny_keccak; -extern crate tokio; -extern crate tokio_io; -extern crate tokio_service; -extern crate url; - -#[macro_use] -extern crate ethabi_derive; -#[macro_use] -extern crate ethabi_contract; -#[macro_use] -extern crate futures; -#[macro_use] -extern crate serde_derive; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; - -#[cfg(test)] -extern crate env_logger; -#[cfg(test)] -extern crate kvdb_rocksdb; - -#[cfg(feature = "accounts")] -extern crate ethcore_accounts as accounts; - -mod helpers; -mod key_server_cluster; -mod types; - -mod acl_storage; -mod key_server; -mod key_server_set; -mod key_storage; -mod listener; -mod node_key_pair; -mod serialization; -mod traits; -mod trusted_client; - -use ethcore::{client::Client, miner::Miner}; -use kvdb::KeyValueDB; -use parity_runtime::Executor; -use std::sync::Arc; -use sync::SyncProvider; - -#[cfg(feature = "accounts")] -pub use self::node_key_pair::KeyStoreNodeKeyPair; -pub use self::node_key_pair::PlainNodeKeyPair; -pub use traits::{KeyServer, NodeKeyPair}; -pub use types::{ - ClusterConfiguration, ContractAddress, EncryptedDocumentKey, Error, NodeAddress, Public, - RequestSignature, ServerKeyId, ServiceConfiguration, -}; - -/// Start new key server instance -pub fn start( - client: Arc, - sync: Arc, - miner: Arc, - self_key_pair: Arc, - mut config: ServiceConfiguration, - db: Arc, - executor: Executor, -) -> Result, Error> { - let trusted_client = - trusted_client::TrustedClient::new(self_key_pair.clone(), client.clone(), sync, miner); - let acl_storage: Arc = - match config.acl_check_contract_address.take() { - Some(acl_check_contract_address) => acl_storage::OnChainAclStorage::new( - trusted_client.clone(), - acl_check_contract_address, - )?, - None => Arc::new(acl_storage::DummyAclStorage::default()), - }; - - let key_server_set = key_server_set::OnChainKeyServerSet::new( - trusted_client.clone(), - config.cluster_config.key_server_set_contract_address.take(), - self_key_pair.clone(), - config.cluster_config.auto_migrate_enabled, - config.cluster_config.nodes.clone(), - )?; - let key_storage = Arc::new(key_storage::PersistentKeyStorage::new(db)?); - let key_server = Arc::new(key_server::KeyServerImpl::new( - &config.cluster_config, - key_server_set.clone(), - self_key_pair.clone(), - acl_storage.clone(), - key_storage.clone(), - executor.clone(), - )?); - let cluster = key_server.cluster(); - let key_server: Arc = key_server; - - // prepare HTTP listener - let http_listener = match config.listener_address { - Some(listener_address) => Some(listener::http_listener::KeyServerHttpListener::start( - listener_address, - Arc::downgrade(&key_server), - executor, - )?), - None => None, - }; - - // prepare service contract listeners - let create_service_contract = |address, name, api_mask| { - Arc::new(listener::service_contract::OnChainServiceContract::new( - api_mask, - trusted_client.clone(), - name, - address, - self_key_pair.clone(), - )) - }; - - let mut contracts: Vec> = Vec::new(); - config - .service_contract_address - .map(|address| { - create_service_contract( - address, - listener::service_contract::SERVICE_CONTRACT_REGISTRY_NAME.to_owned(), - listener::ApiMask::all(), - ) - }) - .map(|l| contracts.push(l)); - config - .service_contract_srv_gen_address - .map(|address| { - create_service_contract( - address, - listener::service_contract::SRV_KEY_GEN_SERVICE_CONTRACT_REGISTRY_NAME.to_owned(), - listener::ApiMask { - server_key_generation_requests: true, - ..Default::default() - }, - ) - }) - .map(|l| contracts.push(l)); - config - .service_contract_srv_retr_address - .map(|address| { - create_service_contract( - address, - listener::service_contract::SRV_KEY_RETR_SERVICE_CONTRACT_REGISTRY_NAME.to_owned(), - listener::ApiMask { - server_key_retrieval_requests: true, - ..Default::default() - }, - ) - }) - .map(|l| contracts.push(l)); - config - .service_contract_doc_store_address - .map(|address| { - create_service_contract( - address, - listener::service_contract::DOC_KEY_STORE_SERVICE_CONTRACT_REGISTRY_NAME.to_owned(), - listener::ApiMask { - document_key_store_requests: true, - ..Default::default() - }, - ) - }) - .map(|l| contracts.push(l)); - config - .service_contract_doc_sretr_address - .map(|address| { - create_service_contract( - address, - listener::service_contract::DOC_KEY_SRETR_SERVICE_CONTRACT_REGISTRY_NAME.to_owned(), - listener::ApiMask { - document_key_shadow_retrieval_requests: true, - ..Default::default() - }, - ) - }) - .map(|l| contracts.push(l)); - - let contract: Option> = match contracts - .len() - { - 0 => None, - 1 => Some(contracts.pop().expect("contract.len() is 1; qed")), - _ => Some(Arc::new( - listener::service_contract_aggregate::OnChainServiceContractAggregate::new(contracts), - )), - }; - - let contract_listener = match contract { - Some(contract) => Some({ - let listener = listener::service_contract_listener::ServiceContractListener::new( - listener::service_contract_listener::ServiceContractListenerParams { - contract: contract, - self_key_pair: self_key_pair.clone(), - key_server_set: key_server_set, - acl_storage: acl_storage, - cluster: cluster, - key_storage: key_storage, - }, - )?; - client.add_notify(listener.clone()); - listener - }), - None => None, - }; - - Ok(Box::new(listener::Listener::new( - key_server, - http_listener, - contract_listener, - ))) -} diff --git a/secret-store/src/listener/http_listener.rs b/secret-store/src/listener/http_listener.rs deleted file mode 100644 index 71821162a3..0000000000 --- a/secret-store/src/listener/http_listener.rs +++ /dev/null @@ -1,634 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use futures::{future, Future, Stream}; -use hyper::{ - self, - header::{self, HeaderValue}, - server::conn::Http, - service::Service, - Body, Method as HttpMethod, Request as HttpRequest, Response as HttpResponse, - StatusCode as HttpStatusCode, Uri, -}; -use parity_runtime::Executor; -use percent_encoding::percent_decode; -use serde::Serialize; -use serde_json; -use std::{ - collections::BTreeSet, - sync::{Arc, Weak}, -}; -use tokio::{self, net::TcpListener}; - -use serialization::{ - SerializableBytes, SerializableEncryptedDocumentKeyShadow, SerializablePublic, -}; -use traits::KeyServer; -use types::{ - EncryptedDocumentKey, EncryptedDocumentKeyShadow, Error, MessageHash, NodeAddress, NodeId, - Public, RequestSignature, ServerKeyId, -}; - -/// Key server http-requests listener. Available requests: -/// To generate server key: POST /shadow/{server_key_id}/{signature}/{threshold} -/// To store pregenerated encrypted document key: POST /shadow/{server_key_id}/{signature}/{common_point}/{encrypted_key} -/// To generate server && document key: POST /{server_key_id}/{signature}/{threshold} -/// To get public portion of server key: GET /server/{server_key_id}/{signature} -/// To get document key: GET /{server_key_id}/{signature} -/// To get document key shadow: GET /shadow/{server_key_id}/{signature} -/// To generate Schnorr signature with server key: GET /schnorr/{server_key_id}/{signature}/{message_hash} -/// To generate ECDSA signature with server key: GET /ecdsa/{server_key_id}/{signature}/{message_hash} -/// To change servers set: POST /admin/servers_set_change/{old_signature}/{new_signature} + BODY: json array of hex-encoded nodes ids - -pub struct KeyServerHttpListener { - _executor: Executor, - _handler: Arc, -} - -/// Parsed http request -#[derive(Debug, Clone, PartialEq)] -enum Request { - /// Invalid request - Invalid, - /// Generate server key. - GenerateServerKey(ServerKeyId, RequestSignature, usize), - /// Store document key. - StoreDocumentKey(ServerKeyId, RequestSignature, Public, Public), - /// Generate encryption key. - GenerateDocumentKey(ServerKeyId, RequestSignature, usize), - /// Request public portion of server key. - GetServerKey(ServerKeyId, RequestSignature), - /// Request encryption key of given document for given requestor. - GetDocumentKey(ServerKeyId, RequestSignature), - /// Request shadow of encryption key of given document for given requestor. - GetDocumentKeyShadow(ServerKeyId, RequestSignature), - /// Generate Schnorr signature for the message. - SchnorrSignMessage(ServerKeyId, RequestSignature, MessageHash), - /// Generate ECDSA signature for the message. - EcdsaSignMessage(ServerKeyId, RequestSignature, MessageHash), - /// Change servers set. - ChangeServersSet(RequestSignature, RequestSignature, BTreeSet), -} - -/// Cloneable http handler -#[derive(Clone)] -struct KeyServerHttpHandler { - handler: Arc, -} - -/// Shared http handler -struct KeyServerSharedHttpHandler { - key_server: Weak, -} - -impl KeyServerHttpListener { - /// Start KeyServer http listener - pub fn start( - listener_address: NodeAddress, - key_server: Weak, - executor: Executor, - ) -> Result { - let shared_handler = Arc::new(KeyServerSharedHttpHandler { - key_server: key_server, - }); - - let listener_address = - format!("{}:{}", listener_address.address, listener_address.port).parse()?; - let listener = TcpListener::bind(&listener_address)?; - - let shared_handler2 = shared_handler.clone(); - - let server = listener - .incoming() - .map_err(|e| warn!("Key server listener error: {:?}", e)) - .for_each(move |socket| { - let http = Http::new(); - let serve = http - .serve_connection( - socket, - KeyServerHttpHandler { - handler: shared_handler2.clone(), - }, - ) - .map(|_| ()) - .map_err(|e| { - warn!("Key server handler error: {:?}", e); - }); - - tokio::spawn(serve) - }); - - executor.spawn(server); - - let listener = KeyServerHttpListener { - _executor: executor, - _handler: shared_handler, - }; - - Ok(listener) - } -} - -impl KeyServerHttpHandler { - fn process( - self, - req_method: HttpMethod, - req_uri: Uri, - path: &str, - req_body: &[u8], - ) -> HttpResponse { - match parse_request(&req_method, &path, &req_body) { - Request::GenerateServerKey(document, signature, threshold) => { - return_server_public_key(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.generate_key(&document, &signature.into(), threshold)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GenerateServerKey request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::StoreDocumentKey(document, signature, common_point, encrypted_document_key) => { - return_empty(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.store_document_key(&document, &signature.into(), common_point, encrypted_document_key)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "StoreDocumentKey request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::GenerateDocumentKey(document, signature, threshold) => { - return_document_key(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.generate_document_key(&document, &signature.into(), threshold)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GenerateDocumentKey request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::GetServerKey(document, signature) => { - return_server_public_key(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.restore_key_public(&document, &signature.into())) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GetServerKey request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::GetDocumentKey(document, signature) => { - return_document_key(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.restore_document_key(&document, &signature.into())) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GetDocumentKey request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::GetDocumentKeyShadow(document, signature) => { - return_document_key_shadow(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.restore_document_key_shadow(&document, &signature.into())) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "GetDocumentKeyShadow request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::SchnorrSignMessage(document, signature, message_hash) => { - return_message_signature(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.sign_message_schnorr(&document, &signature.into(), message_hash)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "SchnorrSignMessage request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::EcdsaSignMessage(document, signature, message_hash) => { - return_message_signature(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.sign_message_ecdsa(&document, &signature.into(), message_hash)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "EcdsaSignMessage request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::ChangeServersSet(old_set_signature, new_set_signature, new_servers_set) => { - return_empty(&req_uri, self.handler.key_server.upgrade() - .map(|key_server| key_server.change_servers_set(old_set_signature, new_set_signature, new_servers_set)) - .unwrap_or(Err(Error::Internal("KeyServer is already destroyed".into()))) - .map_err(|err| { - warn!(target: "secretstore", "ChangeServersSet request {} has failed with: {}", req_uri, err); - err - })) - }, - Request::Invalid => { - warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); - HttpResponse::builder() - .status(HttpStatusCode::BAD_REQUEST) - .body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed") - }, - } - } -} - -impl Service for KeyServerHttpHandler { - type ReqBody = Body; - type ResBody = Body; - type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; - - fn call(&mut self, req: HttpRequest) -> Self::Future { - if req.headers().contains_key(header::ORIGIN) { - warn!(target: "secretstore", "Ignoring {}-request {} with Origin header", req.method(), req.uri()); - return Box::new(future::ok( - HttpResponse::builder() - .status(HttpStatusCode::NOT_FOUND) - .body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed"), - )); - } - - let req_method = req.method().clone(); - let req_uri = req.uri().clone(); - // We cannot consume Self because of the Service trait requirement. - let this = self.clone(); - - Box::new(req.into_body().concat2().map(move |body| { - let path = req_uri.path().to_string(); - if path.starts_with("/") { - this.process(req_method, req_uri, &path, &body) - } else { - warn!(target: "secretstore", "Ignoring invalid {}-request {}", req_method, req_uri); - HttpResponse::builder() - .status(HttpStatusCode::NOT_FOUND) - .body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed") - } - })) - } -} - -fn return_empty(req_uri: &Uri, empty: Result<(), Error>) -> HttpResponse { - return_bytes::(req_uri, empty.map(|_| None)) -} - -fn return_server_public_key( - req_uri: &Uri, - server_public: Result, -) -> HttpResponse { - return_bytes(req_uri, server_public.map(|k| Some(SerializablePublic(k)))) -} - -fn return_message_signature( - req_uri: &Uri, - signature: Result, -) -> HttpResponse { - return_bytes(req_uri, signature.map(|s| Some(SerializableBytes(s)))) -} - -fn return_document_key( - req_uri: &Uri, - document_key: Result, -) -> HttpResponse { - return_bytes(req_uri, document_key.map(|k| Some(SerializableBytes(k)))) -} - -fn return_document_key_shadow( - req_uri: &Uri, - document_key_shadow: Result, -) -> HttpResponse { - return_bytes( - req_uri, - document_key_shadow.map(|k| { - Some(SerializableEncryptedDocumentKeyShadow { - decrypted_secret: k.decrypted_secret.into(), - common_point: k - .common_point - .expect("always filled when requesting document_key_shadow; qed") - .into(), - decrypt_shadows: k - .decrypt_shadows - .expect("always filled when requesting document_key_shadow; qed") - .into_iter() - .map(Into::into) - .collect(), - }) - }), - ) -} - -fn return_bytes( - req_uri: &Uri, - result: Result, Error>, -) -> HttpResponse { - match result { - Ok(Some(result)) => match serde_json::to_vec(&result) { - Ok(result) => { - let body: Body = result.into(); - HttpResponse::builder() - .header( - header::CONTENT_TYPE, - HeaderValue::from_static("application/json; charset=utf-8"), - ) - .body(body) - .expect("Error creating http response") - } - Err(err) => { - warn!(target: "secretstore", "response to request {} has failed with: {}", req_uri, err); - HttpResponse::builder() - .status(HttpStatusCode::INTERNAL_SERVER_ERROR) - .body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed") - } - }, - Ok(None) => HttpResponse::builder() - .status(HttpStatusCode::OK) - .body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed"), - Err(err) => return_error(err), - } -} - -fn return_error(err: Error) -> HttpResponse { - let status = match err { - Error::AccessDenied - | Error::ConsensusUnreachable - | Error::ConsensusTemporaryUnreachable => HttpStatusCode::FORBIDDEN, - Error::ServerKeyIsNotFound | Error::DocumentKeyIsNotFound => HttpStatusCode::NOT_FOUND, - Error::InsufficientRequesterData(_) - | Error::Hyper(_) - | Error::Serde(_) - | Error::DocumentKeyAlreadyStored - | Error::ServerKeyAlreadyGenerated => HttpStatusCode::BAD_REQUEST, - _ => HttpStatusCode::INTERNAL_SERVER_ERROR, - }; - - let mut res = HttpResponse::builder(); - res.status(status); - - // return error text. ignore errors when returning error - let error_text = format!("\"{}\"", err); - if let Ok(error_text) = serde_json::to_vec(&error_text) { - res.header( - header::CONTENT_TYPE, - HeaderValue::from_static("application/json; charset=utf-8"), - ); - res.body(error_text.into()) - .expect("`error_text` is a formatted string, parsing cannot fail; qed") - } else { - res.body(Body::empty()) - .expect("Nothing to parse, cannot fail; qed") - } -} - -fn parse_request(method: &HttpMethod, uri_path: &str, body: &[u8]) -> Request { - let uri_path = match percent_decode(uri_path.as_bytes()).decode_utf8() { - Ok(path) => path, - Err(_) => return Request::Invalid, - }; - - let path: Vec = uri_path - .trim_start_matches('/') - .split('/') - .map(Into::into) - .collect(); - if path.len() == 0 { - return Request::Invalid; - } - - if path[0] == "admin" { - return parse_admin_request(method, path, body); - } - - let is_known_prefix = &path[0] == "shadow" - || &path[0] == "schnorr" - || &path[0] == "ecdsa" - || &path[0] == "server"; - let (prefix, args_offset) = if is_known_prefix { - (&*path[0], 1) - } else { - ("", 0) - }; - let args_count = path.len() - args_offset; - if args_count < 2 || path[args_offset].is_empty() || path[args_offset + 1].is_empty() { - return Request::Invalid; - } - - let document = match path[args_offset].parse() { - Ok(document) => document, - _ => return Request::Invalid, - }; - let signature = match path[args_offset + 1].parse() { - Ok(signature) => signature, - _ => return Request::Invalid, - }; - - let threshold = path.get(args_offset + 2).map(|v| v.parse()); - let message_hash = path.get(args_offset + 2).map(|v| v.parse()); - let common_point = path.get(args_offset + 2).map(|v| v.parse()); - let encrypted_key = path.get(args_offset + 3).map(|v| v.parse()); - match ( - prefix, - args_count, - method, - threshold, - message_hash, - common_point, - encrypted_key, - ) { - ("shadow", 3, &HttpMethod::POST, Some(Ok(threshold)), _, _, _) => { - Request::GenerateServerKey(document, signature, threshold) - } - ("shadow", 4, &HttpMethod::POST, _, _, Some(Ok(common_point)), Some(Ok(encrypted_key))) => { - Request::StoreDocumentKey(document, signature, common_point, encrypted_key) - } - ("", 3, &HttpMethod::POST, Some(Ok(threshold)), _, _, _) => { - Request::GenerateDocumentKey(document, signature, threshold) - } - ("server", 2, &HttpMethod::GET, _, _, _, _) => Request::GetServerKey(document, signature), - ("", 2, &HttpMethod::GET, _, _, _, _) => Request::GetDocumentKey(document, signature), - ("shadow", 2, &HttpMethod::GET, _, _, _, _) => { - Request::GetDocumentKeyShadow(document, signature) - } - ("schnorr", 3, &HttpMethod::GET, _, Some(Ok(message_hash)), _, _) => { - Request::SchnorrSignMessage(document, signature, message_hash) - } - ("ecdsa", 3, &HttpMethod::GET, _, Some(Ok(message_hash)), _, _) => { - Request::EcdsaSignMessage(document, signature, message_hash) - } - _ => Request::Invalid, - } -} - -fn parse_admin_request(method: &HttpMethod, path: Vec, body: &[u8]) -> Request { - let args_count = path.len(); - if *method != HttpMethod::POST || args_count != 4 || path[1] != "servers_set_change" { - return Request::Invalid; - } - - let old_set_signature = match path[2].parse() { - Ok(signature) => signature, - _ => return Request::Invalid, - }; - - let new_set_signature = match path[3].parse() { - Ok(signature) => signature, - _ => return Request::Invalid, - }; - - let new_servers_set: BTreeSet = match serde_json::from_slice(body) { - Ok(new_servers_set) => new_servers_set, - _ => return Request::Invalid, - }; - - Request::ChangeServersSet( - old_set_signature, - new_set_signature, - new_servers_set.into_iter().map(Into::into).collect(), - ) -} - -#[cfg(test)] -mod tests { - use std::{str::FromStr, sync::Arc}; - - use super::{parse_request, KeyServerHttpListener, Request}; - use ethereum_types::H256; - use ethkey::Public; - use hyper::Method as HttpMethod; - use key_server::tests::DummyKeyServer; - use parity_runtime::Runtime; - use traits::KeyServer; - use types::NodeAddress; - - #[test] - fn http_listener_successfully_drops() { - let key_server: Arc = Arc::new(DummyKeyServer::default()); - let address = NodeAddress { - address: "127.0.0.1".into(), - port: 9000, - }; - let runtime = Runtime::with_thread_count(1); - let listener = - KeyServerHttpListener::start(address, Arc::downgrade(&key_server), runtime.executor()) - .unwrap(); - drop(listener); - } - - #[test] - fn parse_request_successful() { - // POST /shadow/{server_key_id}/{signature}/{threshold} => generate server key - assert_eq!(parse_request(&HttpMethod::POST, "/shadow/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/2", Default::default()), - Request::GenerateServerKey("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - 2)); - // POST /shadow/{server_key_id}/{signature}/{common_point}/{encrypted_key} => store encrypted document key - assert_eq!(parse_request(&HttpMethod::POST, "/shadow/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8/1395568277679f7f583ab7c0992da35f26cde57149ee70e524e49bdae62db3e18eb96122501e7cbb798b784395d7bb5a499edead0706638ad056d886e56cf8fb", Default::default()), - Request::StoreDocumentKey("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - "b486d3840218837b035c66196ecb15e6b067ca20101e11bd5e626288ab6806ecc70b8307012626bd512bad1559112d11d21025cef48cc7a1d2f3976da08f36c8".parse().unwrap(), - "1395568277679f7f583ab7c0992da35f26cde57149ee70e524e49bdae62db3e18eb96122501e7cbb798b784395d7bb5a499edead0706638ad056d886e56cf8fb".parse().unwrap())); - // POST /{server_key_id}/{signature}/{threshold} => generate server && document key - assert_eq!(parse_request(&HttpMethod::POST, "/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/2", Default::default()), - Request::GenerateDocumentKey("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - 2)); - // GET /server/{server_key_id}/{signature} => get public portion of server key - assert_eq!(parse_request(&HttpMethod::GET, "/server/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", Default::default()), - Request::GetServerKey(H256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap())); - // GET /{server_key_id}/{signature} => get document key - assert_eq!(parse_request(&HttpMethod::GET, "/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", Default::default()), - Request::GetDocumentKey("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap())); - assert_eq!(parse_request(&HttpMethod::GET, "/%30000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", Default::default()), - Request::GetDocumentKey("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap())); - // GET /shadow/{server_key_id}/{signature} => get document key shadow - assert_eq!(parse_request(&HttpMethod::GET, "/shadow/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", Default::default()), - Request::GetDocumentKeyShadow("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap())); - // GET /schnorr/{server_key_id}/{signature}/{message_hash} => schnorr-sign message with server key - assert_eq!(parse_request(&HttpMethod::GET, "/schnorr/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c", Default::default()), - Request::SchnorrSignMessage("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse().unwrap())); - // GET /ecdsa/{server_key_id}/{signature}/{message_hash} => ecdsa-sign message with server key - assert_eq!(parse_request(&HttpMethod::GET, "/ecdsa/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c", Default::default()), - Request::EcdsaSignMessage("0000000000000000000000000000000000000000000000000000000000000001".into(), - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - "281b6bf43cb86d0dc7b98e1b7def4a80f3ce16d28d2308f934f116767306f06c".parse().unwrap())); - // POST /admin/servers_set_change/{old_set_signature}/{new_set_signature} + body - let node1: Public = "843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91".parse().unwrap(); - let node2: Public = "07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3".parse().unwrap(); - let nodes = vec![node1, node2].into_iter().collect(); - assert_eq!(parse_request(&HttpMethod::POST, "/admin/servers_set_change/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/b199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", - &r#"["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91", - "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#.as_bytes()), - Request::ChangeServersSet( - "a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - "b199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01".parse().unwrap(), - nodes, - )); - } - - #[test] - fn parse_request_failed() { - assert_eq!( - parse_request(&HttpMethod::GET, "", Default::default()), - Request::Invalid - ); - assert_eq!( - parse_request(&HttpMethod::GET, "/shadow", Default::default()), - Request::Invalid - ); - assert_eq!( - parse_request(&HttpMethod::GET, "///2", Default::default()), - Request::Invalid - ); - assert_eq!( - parse_request(&HttpMethod::GET, "/shadow///2", Default::default()), - Request::Invalid - ); - assert_eq!( - parse_request( - &HttpMethod::GET, - "/0000000000000000000000000000000000000000000000000000000000000001", - Default::default() - ), - Request::Invalid - ); - assert_eq!( - parse_request( - &HttpMethod::GET, - "/0000000000000000000000000000000000000000000000000000000000000001/", - Default::default() - ), - Request::Invalid - ); - assert_eq!( - parse_request(&HttpMethod::GET, "/a/b", Default::default()), - Request::Invalid - ); - assert_eq!(parse_request(&HttpMethod::GET, "/schnorr/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/0000000000000000000000000000000000000000000000000000000000000002/0000000000000000000000000000000000000000000000000000000000000002", Default::default()), Request::Invalid); - assert_eq!(parse_request(&HttpMethod::GET, "/ecdsa/0000000000000000000000000000000000000000000000000000000000000001/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/0000000000000000000000000000000000000000000000000000000000000002/0000000000000000000000000000000000000000000000000000000000000002", Default::default()), Request::Invalid); - assert_eq!(parse_request(&HttpMethod::POST, "/admin/servers_set_change/xxx/yyy", - &r#"["0x843645726384530ffb0c52f175278143b5a93959af7864460f5a4fec9afd1450cfb8aef63dec90657f43f55b13e0a73c7524d4e9a13c051b4e5f1e53f39ecd91", - "0x07230e34ebfe41337d3ed53b186b3861751f2401ee74b988bba55694e2a6f60c757677e194be2e53c3523cc8548694e636e6acb35c4e8fdc5e29d28679b9b2f3"]"#.as_bytes()), - Request::Invalid); - assert_eq!(parse_request(&HttpMethod::POST, "/admin/servers_set_change/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01/a199fb39e11eefb61c78a4074a53c0d4424600a3e74aad4fb9d93a26c30d067e1d4d29936de0c73f19827394a1dd049480a0d581aee7ae7546968da7d3d1c2fd01", "".as_bytes()), - Request::Invalid); - } -} diff --git a/secret-store/src/listener/mod.rs b/secret-store/src/listener/mod.rs deleted file mode 100644 index 4e30e266eb..0000000000 --- a/secret-store/src/listener/mod.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -pub mod http_listener; -pub mod service_contract; -pub mod service_contract_aggregate; -pub mod service_contract_listener; -mod tasks_queue; - -use std::{collections::BTreeSet, sync::Arc}; -use traits::{ - AdminSessionsServer, DocumentKeyServer, KeyServer, MessageSigner, ServerKeyGenerator, -}; -use types::{ - EncryptedDocumentKey, EncryptedDocumentKeyShadow, EncryptedMessageSignature, Error, - MessageHash, NodeId, Public, RequestSignature, Requester, ServerKeyId, -}; - -/// Available API mask. -#[derive(Debug, Default)] -pub struct ApiMask { - /// Accept server key generation requests. - pub server_key_generation_requests: bool, - /// Accept server key retrieval requests. - pub server_key_retrieval_requests: bool, - /// Accept document key store requests. - pub document_key_store_requests: bool, - /// Accept document key shadow retrieval requests. - pub document_key_shadow_retrieval_requests: bool, -} - -/// Combined HTTP + service contract listener. -pub struct Listener { - key_server: Arc, - _http: Option, - _contract: Option>, -} - -impl ApiMask { - /// Create mask that accepts all requests. - pub fn all() -> Self { - ApiMask { - server_key_generation_requests: true, - server_key_retrieval_requests: true, - document_key_store_requests: true, - document_key_shadow_retrieval_requests: true, - } - } -} - -impl Listener { - /// Create new listener. - pub fn new( - key_server: Arc, - http: Option, - contract: Option>, - ) -> Self { - Self { - key_server: key_server, - _http: http, - _contract: contract, - } - } -} - -impl KeyServer for Listener {} - -impl ServerKeyGenerator for Listener { - fn generate_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result { - self.key_server.generate_key(key_id, author, threshold) - } - - fn restore_key_public( - &self, - key_id: &ServerKeyId, - author: &Requester, - ) -> Result { - self.key_server.restore_key_public(key_id, author) - } -} - -impl DocumentKeyServer for Listener { - fn store_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - common_point: Public, - encrypted_document_key: Public, - ) -> Result<(), Error> { - self.key_server - .store_document_key(key_id, author, common_point, encrypted_document_key) - } - - fn generate_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result { - self.key_server - .generate_document_key(key_id, author, threshold) - } - - fn restore_document_key( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result { - self.key_server.restore_document_key(key_id, requester) - } - - fn restore_document_key_shadow( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result { - self.key_server - .restore_document_key_shadow(key_id, requester) - } -} - -impl MessageSigner for Listener { - fn sign_message_schnorr( - &self, - key_id: &ServerKeyId, - requester: &Requester, - message: MessageHash, - ) -> Result { - self.key_server - .sign_message_schnorr(key_id, requester, message) - } - - fn sign_message_ecdsa( - &self, - key_id: &ServerKeyId, - requester: &Requester, - message: MessageHash, - ) -> Result { - self.key_server - .sign_message_ecdsa(key_id, requester, message) - } -} - -impl AdminSessionsServer for Listener { - fn change_servers_set( - &self, - old_set_signature: RequestSignature, - new_set_signature: RequestSignature, - new_servers_set: BTreeSet, - ) -> Result<(), Error> { - self.key_server - .change_servers_set(old_set_signature, new_set_signature, new_servers_set) - } -} diff --git a/secret-store/src/listener/service_contract.rs b/secret-store/src/listener/service_contract.rs deleted file mode 100644 index 23e29cb034..0000000000 --- a/secret-store/src/listener/service_contract.rs +++ /dev/null @@ -1,1365 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use bytes::Bytes; -use call_contract::CallContract; -use common_types::filter::Filter; -use ethabi::{FunctionOutputDecoder, RawLog}; -use ethcore::client::{BlockChainClient, BlockId, Client}; -use ethereum_types::{Address, H256, U256}; -use ethkey::{public_to_address, Public}; -use hash::keccak; -use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; -use listener::{service_contract_listener::ServiceTask, ApiMask}; -use parking_lot::RwLock; -use std::sync::Arc; -use trusted_client::TrustedClient; -use ContractAddress; -use NodeKeyPair; -use ServerKeyId; - -use_contract!(service, "res/service.json"); - -/// Name of the general SecretStore contract in the registry. -pub const SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service"; -/// Name of the server key generation SecretStore contract in the registry. -pub const SRV_KEY_GEN_SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service_srv_gen"; -/// Name of the server key retrieval SecretStore contract in the registry. -pub const SRV_KEY_RETR_SERVICE_CONTRACT_REGISTRY_NAME: &'static str = - "secretstore_service_srv_retr"; -/// Name of the document key store SecretStore contract in the registry. -pub const DOC_KEY_STORE_SERVICE_CONTRACT_REGISTRY_NAME: &'static str = - "secretstore_service_doc_store"; -/// Name of the document key retrieval SecretStore contract in the registry. -pub const DOC_KEY_SRETR_SERVICE_CONTRACT_REGISTRY_NAME: &'static str = - "secretstore_service_doc_sretr"; - -/// Server key generation has been requested. -const SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME: &'static [u8] = - &*b"ServerKeyGenerationRequested(bytes32,address,uint8)"; -/// Server key retrieval has been requested. -const SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME: &'static [u8] = - &*b"ServerKeyRetrievalRequested(bytes32)"; -/// Document key store has been requested. -const DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME: &'static [u8] = - &*b"DocumentKeyStoreRequested(bytes32,address,bytes,bytes)"; -/// Document key common part retrieval has been requested. -const DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME: &'static [u8] = - &*b"DocumentKeyCommonRetrievalRequested(bytes32,address)"; -/// Document key personal part retrieval has been requested. -const DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME: &'static [u8] = - &*b"DocumentKeyPersonalRetrievalRequested(bytes32,bytes)"; - -lazy_static! { - pub static ref SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH: H256 = - keccak(SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME); - pub static ref SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH: H256 = - keccak(SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME); - pub static ref DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH: H256 = - keccak(DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME); - pub static ref DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH: H256 = - keccak(DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME); - pub static ref DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH: H256 = - keccak(DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME); -} - -/// Service contract trait. -pub trait ServiceContract: Send + Sync { - /// Update contract when new blocks are enacted. Returns true if contract is installed && up-to-date (i.e. chain is synced). - fn update(&self) -> bool; - /// Read recent contract logs. Returns topics of every entry. - fn read_logs(&self) -> Box>; - /// Publish generated key. - fn read_pending_requests(&self) -> Box>; - /// Publish generated server key. - fn publish_generated_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - ) -> Result<(), String>; - /// Publish server key generation error. - fn publish_server_key_generation_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String>; - /// Publish retrieved server key. - fn publish_retrieved_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - threshold: usize, - ) -> Result<(), String>; - /// Publish server key retrieval error. - fn publish_server_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String>; - /// Publish stored document key. - fn publish_stored_document_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String>; - /// Publish document key store error. - fn publish_document_key_store_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String>; - /// Publish retrieved document key common. - fn publish_retrieved_document_key_common( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - common_point: Public, - threshold: usize, - ) -> Result<(), String>; - /// Publish retrieved document key personal. - fn publish_retrieved_document_key_personal( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - participants: &[Address], - decrypted_secret: Public, - shadow: Bytes, - ) -> Result<(), String>; - /// Publish document key store error. - fn publish_document_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - ) -> Result<(), String>; -} - -/// On-chain service contract. -pub struct OnChainServiceContract { - /// Requests mask. - mask: ApiMask, - /// Blockchain client. - client: TrustedClient, - /// This node key pair. - self_key_pair: Arc, - /// Contract registry name (if any). - name: String, - /// Contract address source. - address_source: ContractAddress, - /// Contract. - data: RwLock, -} - -/// On-chain service contract data. -struct ServiceData { - /// Current contract address. - pub contract_address: Option
, - /// Last block we have read logs from. - pub last_log_block: Option, -} - -/// Pending requests iterator. -struct PendingRequestsIterator Option<(bool, ServiceTask)>> { - /// Pending request read function. - read_request: F, - /// Current request index. - index: U256, - /// Requests length. - length: U256, -} - -/// Server key generation related functions. -struct ServerKeyGenerationService; -/// Server key retrieval related functions. -struct ServerKeyRetrievalService; -/// Document key store related functions. -struct DocumentKeyStoreService; -/// Document key shadow retrievalrelated functions. -struct DocumentKeyShadowRetrievalService; - -impl OnChainServiceContract { - /// Create new on-chain service contract. - pub fn new( - mask: ApiMask, - client: TrustedClient, - name: String, - address_source: ContractAddress, - self_key_pair: Arc, - ) -> Self { - let contract = OnChainServiceContract { - mask: mask, - client: client, - self_key_pair: self_key_pair, - name: name, - address_source: address_source, - data: RwLock::new(ServiceData { - contract_address: None, - last_log_block: None, - }), - }; - - contract.update_contract_address(); - contract - } - - /// Send transaction to the service contract. - fn send_contract_transaction( - &self, - tx_name: &str, - origin: &Address, - server_key_id: &ServerKeyId, - is_response_required: C, - prepare_tx: P, - ) -> Result<(), String> - where - C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool, - P: FnOnce(&Client, &Address) -> Result, - { - // only publish if contract address is set && client is online - let client = match self.client.get() { - Some(client) => client, - None => return Err("trusted client is required to publish key".into()), - }; - - // only publish key if contract waits for publication - // failing is ok here - it could be that enough confirmations have been recevied - // or key has been requested using HTTP API - let self_address = public_to_address(self.self_key_pair.public()); - if !is_response_required(&*client, origin, server_key_id, &self_address) { - return Ok(()); - } - - // prepare transaction data - let transaction_data = prepare_tx(&*client, origin)?; - - // send transaction - self.client - .transact_contract(origin.clone(), transaction_data) - .map_err(|e| format!("{}", e))?; - - trace!(target: "secretstore", "{}: transaction {} sent to service contract", - self.self_key_pair.public(), tx_name); - - Ok(()) - } - - /// Create task-specific pending requests iterator. - fn create_pending_requests_iterator< - C: 'static + Fn(&Client, &Address, &BlockId) -> Result, - R: 'static - + Fn( - &dyn NodeKeyPair, - &Client, - &Address, - &BlockId, - U256, - ) -> Result<(bool, ServiceTask), String>, - >( - &self, - client: Arc, - contract_address: &Address, - block: &BlockId, - get_count: C, - read_item: R, - ) -> Box> { - get_count(&*client, contract_address, block) - .map(|count| { - let client = client.clone(); - let self_key_pair = self.self_key_pair.clone(); - let contract_address = contract_address.clone(); - let block = block.clone(); - Box::new(PendingRequestsIterator { - read_request: move |index| { - read_item(&*self_key_pair, &*client, &contract_address, &block, index) - .map_err(|error| { - warn!(target: "secretstore", "{}: reading pending request failed: {}", - self_key_pair.public(), error); - error - }) - .ok() - }, - index: 0.into(), - length: count, - }) as Box> - }) - .map_err(|error| { - warn!(target: "secretstore", "{}: creating pending requests iterator failed: {}", - self.self_key_pair.public(), error); - error - }) - .ok() - .unwrap_or_else(|| Box::new(::std::iter::empty())) - } - - /// Update service contract address. - fn update_contract_address(&self) -> bool { - let contract_address = self - .client - .read_contract_address(self.name.clone(), &self.address_source); - let mut data = self.data.write(); - if contract_address != data.contract_address { - trace!(target: "secretstore", "{}: installing {} service contract from address {:?}", - self.self_key_pair.public(), self.name, contract_address); - - data.contract_address = contract_address; - } - - data.contract_address.is_some() - } -} - -impl ServiceContract for OnChainServiceContract { - fn update(&self) -> bool { - self.update_contract_address() && self.client.get().is_some() - } - - fn read_logs(&self) -> Box> { - let client = match self.client.get() { - Some(client) => client, - None => { - warn!(target: "secretstore", "{}: client is offline during read_logs call", - self.self_key_pair.public()); - return Box::new(::std::iter::empty()); - } - }; - - // prepare range of blocks to read logs from - let (address, first_block, last_block) = { - let mut data = self.data.write(); - let address = match data.contract_address { - Some(address) => address, - None => return Box::new(::std::iter::empty()), // no contract installed - }; - let confirmed_block = - match get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED) { - Some(confirmed_block) => confirmed_block, - None => return Box::new(::std::iter::empty()), // no block with enough confirmations - }; - let first_block = match data - .last_log_block - .take() - .and_then(|b| client.tree_route(&b, &confirmed_block)) - { - // if we have a route from last_log_block to confirmed_block => search for logs on this route - // - // potentially this could lead us to reading same logs twice when reorganizing to the fork, which - // already has been canonical previosuly - // the worst thing that can happen in this case is spending some time reading unneeded data from SS db - Some(ref route) if route.index < route.blocks.len() => route.blocks[route.index], - // else we care only about confirmed block - _ => confirmed_block.clone(), - }; - - data.last_log_block = Some(confirmed_block.clone()); - (address, first_block, confirmed_block) - }; - - // read server key generation requests - let request_logs = client - .logs(Filter { - from_block: BlockId::Hash(first_block), - to_block: BlockId::Hash(last_block), - address: Some(vec![address]), - topics: vec![Some(mask_topics(&self.mask))], - limit: None, - }) - .unwrap_or_default(); - - Box::new( - request_logs - .into_iter() - .filter_map(|log| { - let raw_log: RawLog = ( - log.entry.topics.into_iter().map(|t| t.0.into()).collect(), - log.entry.data, - ) - .into(); - if raw_log.topics[0] == *SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH { - ServerKeyGenerationService::parse_log(&address, raw_log) - } else if raw_log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - ServerKeyRetrievalService::parse_log(&address, raw_log) - } else if raw_log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH { - DocumentKeyStoreService::parse_log(&address, raw_log) - } else if raw_log.topics[0] == *DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - DocumentKeyShadowRetrievalService::parse_common_request_log(&address, raw_log) - } else if raw_log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { - DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, raw_log) - } else { - Err("unknown type of log entry".into()) - } - .map_err(|error| { - warn!(target: "secretstore", "{}: error parsing log entry from service contract: {}", - self.self_key_pair.public(), error); - error - }) - .ok() - }) - .collect::>() - .into_iter(), - ) - } - - fn read_pending_requests(&self) -> Box> { - let client = match self.client.get() { - Some(client) => client, - None => return Box::new(::std::iter::empty()), - }; - - // we only need requests that are here for more than REQUEST_CONFIRMATIONS_REQUIRED blocks - // => we're reading from Latest - (REQUEST_CONFIRMATIONS_REQUIRED + 1) block - let data = self.data.read(); - match data.contract_address { - None => Box::new(::std::iter::empty()), - Some(contract_address) => { - get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED + 1) - .map(|b| { - let block = BlockId::Hash(b); - let iter = match self.mask.server_key_generation_requests { - true => Box::new(self.create_pending_requests_iterator( - client.clone(), - &contract_address, - &block, - &ServerKeyGenerationService::read_pending_requests_count, - &ServerKeyGenerationService::read_pending_request, - )) - as Box>, - false => Box::new(::std::iter::empty()), - }; - let iter = match self.mask.server_key_retrieval_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator( - client.clone(), - &contract_address, - &block, - &ServerKeyRetrievalService::read_pending_requests_count, - &ServerKeyRetrievalService::read_pending_request, - ))), - false => iter, - }; - let iter = match self.mask.document_key_store_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator( - client.clone(), - &contract_address, - &block, - &DocumentKeyStoreService::read_pending_requests_count, - &DocumentKeyStoreService::read_pending_request, - ))), - false => iter, - }; - let iter = match self.mask.document_key_shadow_retrieval_requests { - true => Box::new(iter.chain(self.create_pending_requests_iterator( - client, - &contract_address, - &block, - &DocumentKeyShadowRetrievalService::read_pending_requests_count, - &DocumentKeyShadowRetrievalService::read_pending_request, - ))), - false => iter, - }; - - iter - }) - .unwrap_or_else(|| Box::new(::std::iter::empty())) - } - } - } - - fn publish_generated_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_generated_server_key", - origin, - server_key_id, - ServerKeyGenerationService::is_response_required, - |_, _| { - Ok(ServerKeyGenerationService::prepare_pubish_tx_data( - server_key_id, - &server_key, - )) - }, - ) - } - - fn publish_server_key_generation_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_server_key_generation_error", - origin, - server_key_id, - ServerKeyGenerationService::is_response_required, - |_, _| { - Ok(ServerKeyGenerationService::prepare_error_tx_data( - server_key_id, - )) - }, - ) - } - - fn publish_retrieved_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - threshold: usize, - ) -> Result<(), String> { - let threshold = serialize_threshold(threshold)?; - self.send_contract_transaction( - "publish_retrieved_server_key", - origin, - server_key_id, - ServerKeyRetrievalService::is_response_required, - |_, _| { - Ok(ServerKeyRetrievalService::prepare_pubish_tx_data( - server_key_id, - server_key, - threshold, - )) - }, - ) - } - - fn publish_server_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_server_key_retrieval_error", - origin, - server_key_id, - ServerKeyRetrievalService::is_response_required, - |_, _| { - Ok(ServerKeyRetrievalService::prepare_error_tx_data( - server_key_id, - )) - }, - ) - } - - fn publish_stored_document_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_stored_document_key", - origin, - server_key_id, - DocumentKeyStoreService::is_response_required, - |_, _| { - Ok(DocumentKeyStoreService::prepare_pubish_tx_data( - server_key_id, - )) - }, - ) - } - - fn publish_document_key_store_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_document_key_store_error", - origin, - server_key_id, - DocumentKeyStoreService::is_response_required, - |_, _| { - Ok(DocumentKeyStoreService::prepare_error_tx_data( - server_key_id, - )) - }, - ) - } - - fn publish_retrieved_document_key_common( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - common_point: Public, - threshold: usize, - ) -> Result<(), String> { - let threshold = serialize_threshold(threshold)?; - self.send_contract_transaction( - "publish_retrieved_document_key_common", - origin, - server_key_id, - |client, contract_address, server_key_id, key_server| { - DocumentKeyShadowRetrievalService::is_response_required( - client, - contract_address, - server_key_id, - requester, - key_server, - ) - }, - |_, _| { - Ok( - DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data( - server_key_id, - requester, - common_point, - threshold, - ), - ) - }, - ) - } - - fn publish_retrieved_document_key_personal( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - participants: &[Address], - decrypted_secret: Public, - shadow: Bytes, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_retrieved_document_key_personal", - origin, - server_key_id, - |_, _, _, _| true, - move |client, address| { - DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data( - client, - address, - server_key_id, - requester, - participants, - decrypted_secret, - shadow, - ) - }, - ) - } - - fn publish_document_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - ) -> Result<(), String> { - self.send_contract_transaction( - "publish_document_key_retrieval_error", - origin, - server_key_id, - |client, contract_address, server_key_id, key_server| { - DocumentKeyShadowRetrievalService::is_response_required( - client, - contract_address, - server_key_id, - requester, - key_server, - ) - }, - |_, _| { - Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data( - server_key_id, - requester, - )) - }, - ) - } -} - -impl Iterator for PendingRequestsIterator -where - F: Fn(U256) -> Option<(bool, ServiceTask)>, -{ - type Item = (bool, ServiceTask); - - fn next(&mut self) -> Option<(bool, ServiceTask)> { - if self.index >= self.length { - return None; - } - - let index = self.index.clone(); - self.index = self.index + 1; - - (self.read_request)(index) - } -} - -/// Returns vector of logs topics to listen to. -pub fn mask_topics(mask: &ApiMask) -> Vec { - let mut topics = Vec::new(); - if mask.server_key_generation_requests { - topics.push(*SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH); - } - if mask.server_key_retrieval_requests { - topics.push(*SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH); - } - if mask.document_key_store_requests { - topics.push(*DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH); - } - if mask.document_key_shadow_retrieval_requests { - topics.push(*DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH); - topics.push(*DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH); - } - topics -} - -impl ServerKeyGenerationService { - /// Parse request log entry. - pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { - match service::events::server_key_generation_requested::parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::GenerateServerKey( - origin.clone(), - l.server_key_id, - l.author, - parse_threshold(l.threshold)?, - )), - Err(e) => Err(format!("{}", e)), - } - } - - /// Check if response from key server is required. - pub fn is_response_required( - client: &Client, - contract_address: &Address, - server_key_id: &ServerKeyId, - key_server: &Address, - ) -> bool { - // we're checking confirmation in Latest block, because we're interested in latest contract state here - let (encoded, decoder) = - service::functions::is_server_key_generation_response_required::call( - *server_key_id, - *key_server, - ); - match client.call_contract(BlockId::Latest, *contract_address, encoded) { - Err(_) => true, - Ok(data) => decoder.decode(&data).unwrap_or(true), - } - } - - /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data( - server_key_id: &ServerKeyId, - server_key_public: &Public, - ) -> Bytes { - service::functions::server_key_generated::encode_input( - *server_key_id, - server_key_public.to_vec(), - ) - } - - /// Prepare error transaction data. - pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { - service::functions::server_key_generation_error::encode_input(*server_key_id) - } - - /// Read pending requests count. - fn read_pending_requests_count( - client: &Client, - contract_address: &Address, - block: &BlockId, - ) -> Result { - let (encoded, decoder) = service::functions::server_key_generation_requests_count::call(); - decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string()) - } - - /// Read pending request. - fn read_pending_request( - self_key_pair: &dyn NodeKeyPair, - client: &Client, - contract_address: &Address, - block: &BlockId, - index: U256, - ) -> Result<(bool, ServiceTask), String> { - let self_address = public_to_address(self_key_pair.public()); - - let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index); - let (server_key_id, author, threshold) = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - let threshold = parse_threshold(threshold)?; - - let (encoded, decoder) = - service::functions::is_server_key_generation_response_required::call( - server_key_id, - self_address, - ); - let not_confirmed = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let task = ServiceTask::GenerateServerKey( - contract_address.clone(), - server_key_id, - author, - threshold, - ); - - Ok((not_confirmed, task)) - } -} - -impl ServerKeyRetrievalService { - /// Parse request log entry. - pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { - match service::events::server_key_retrieval_requested::parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::RetrieveServerKey(*origin, l.server_key_id)), - Err(e) => Err(e.to_string()), - } - } - - /// Check if response from key server is required. - pub fn is_response_required( - client: &Client, - contract_address: &Address, - server_key_id: &ServerKeyId, - key_server: &Address, - ) -> bool { - // we're checking confirmation in Latest block, because we're interested in latest contract state here - let (encoded, decoder) = - service::functions::is_server_key_retrieval_response_required::call( - *server_key_id, - *key_server, - ); - match client.call_contract(BlockId::Latest, *contract_address, encoded) { - Err(_) => true, - Ok(data) => decoder.decode(&data).unwrap_or(true), - } - } - - /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data( - server_key_id: &ServerKeyId, - server_key_public: Public, - threshold: U256, - ) -> Bytes { - service::functions::server_key_retrieved::encode_input( - *server_key_id, - server_key_public.to_vec(), - threshold, - ) - } - - /// Prepare error transaction data. - pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { - service::functions::server_key_retrieval_error::encode_input(*server_key_id) - } - - /// Read pending requests count. - fn read_pending_requests_count( - client: &Client, - contract_address: &Address, - block: &BlockId, - ) -> Result { - let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call(); - decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string()) - } - - /// Read pending request. - fn read_pending_request( - self_key_pair: &dyn NodeKeyPair, - client: &Client, - contract_address: &Address, - block: &BlockId, - index: U256, - ) -> Result<(bool, ServiceTask), String> { - let self_address = public_to_address(self_key_pair.public()); - - let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index); - let server_key_id = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let (encoded, decoder) = - service::functions::is_server_key_retrieval_response_required::call( - server_key_id, - self_address, - ); - let not_confirmed = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let task = ServiceTask::RetrieveServerKey(*contract_address, server_key_id); - - Ok((not_confirmed, task)) - } -} - -impl DocumentKeyStoreService { - /// Parse request log entry. - pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result { - match service::events::document_key_store_requested::parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::StoreDocumentKey( - origin.clone(), - l.server_key_id, - l.author, - (*l.common_point).into(), - (*l.encrypted_point).into(), - )), - Err(e) => Err(format!("{}", e)), - } - } - - /// Check if response from key server is required. - pub fn is_response_required( - client: &Client, - contract_address: &Address, - server_key_id: &ServerKeyId, - key_server: &Address, - ) -> bool { - // we're checking confirmation in Latest block, because we're interested in latest contract state here - let (encoded, decoder) = service::functions::is_document_key_store_response_required::call( - *server_key_id, - *key_server, - ); - match client.call_contract(BlockId::Latest, *contract_address, encoded) { - Err(_) => true, - Ok(data) => decoder.decode(&data).unwrap_or(true), - } - } - - /// Prepare publish key transaction data. - pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId) -> Bytes { - service::functions::document_key_stored::encode_input(*server_key_id) - } - - /// Prepare error transaction data. - pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes { - service::functions::document_key_store_error::encode_input(*server_key_id) - } - - /// Read pending requests count. - fn read_pending_requests_count( - client: &Client, - contract_address: &Address, - block: &BlockId, - ) -> Result { - let (encoded, decoder) = service::functions::document_key_store_requests_count::call(); - decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string()) - } - - /// Read pending request. - fn read_pending_request( - self_key_pair: &dyn NodeKeyPair, - client: &Client, - contract_address: &Address, - block: &BlockId, - index: U256, - ) -> Result<(bool, ServiceTask), String> { - let self_address = public_to_address(self_key_pair.public()); - let (encoded, decoder) = service::functions::get_document_key_store_request::call(index); - let (server_key_id, author, common_point, encrypted_point) = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let (encoded, decoder) = service::functions::is_document_key_store_response_required::call( - server_key_id, - self_address, - ); - let not_confirmed = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let task = ServiceTask::StoreDocumentKey( - *contract_address, - server_key_id, - author, - Public::from_slice(&common_point), - Public::from_slice(&encrypted_point), - ); - - Ok((not_confirmed, task)) - } -} - -impl DocumentKeyShadowRetrievalService { - /// Parse common request log entry. - pub fn parse_common_request_log( - origin: &Address, - raw_log: RawLog, - ) -> Result { - match service::events::document_key_common_retrieval_requested::parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyCommon( - origin.clone(), - l.server_key_id, - l.requester, - )), - Err(e) => Err(e.to_string()), - } - } - - /// Parse personal request log entry. - pub fn parse_personal_request_log( - origin: &Address, - raw_log: RawLog, - ) -> Result { - match service::events::document_key_personal_retrieval_requested::parse_log(raw_log) { - Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyPersonal( - origin.clone(), - l.server_key_id, - (*l.requester_public).into(), - )), - Err(e) => Err(e.to_string()), - } - } - - /// Check if response from key server is required. - pub fn is_response_required( - client: &Client, - contract_address: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - key_server: &Address, - ) -> bool { - // we're checking confirmation in Latest block, because we're interested in latest contract state here - let (encoded, decoder) = - service::functions::is_document_key_shadow_retrieval_response_required::call( - *server_key_id, - *requester, - *key_server, - ); - match client.call_contract(BlockId::Latest, *contract_address, encoded) { - Err(_) => true, - Ok(data) => decoder.decode(&data).unwrap_or(true), - } - } - - /// Prepare publish common key transaction data. - pub fn prepare_pubish_common_tx_data( - server_key_id: &ServerKeyId, - requester: &Address, - common_point: Public, - threshold: U256, - ) -> Bytes { - service::functions::document_key_common_retrieved::encode_input( - *server_key_id, - *requester, - common_point.to_vec(), - threshold, - ) - } - - /// Prepare publish personal key transaction data. - pub fn prepare_pubish_personal_tx_data( - client: &Client, - contract_address: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - participants: &[Address], - decrypted_secret: Public, - shadow: Bytes, - ) -> Result { - let mut participants_mask = U256::default(); - for participant in participants { - let participant_index = - Self::map_key_server_address(client, contract_address, participant.clone()) - .map_err(|e| { - format!("Error searching for {} participant: {}", participant, e) - })?; - participants_mask = participants_mask | (U256::one() << participant_index); - } - Ok( - service::functions::document_key_personal_retrieved::encode_input( - *server_key_id, - *requester, - participants_mask, - decrypted_secret.to_vec(), - shadow, - ), - ) - } - - /// Prepare error transaction data. - pub fn prepare_error_tx_data(server_key_id: &ServerKeyId, requester: &Address) -> Bytes { - service::functions::document_key_shadow_retrieval_error::encode_input( - *server_key_id, - *requester, - ) - } - - /// Read pending requests count. - fn read_pending_requests_count( - client: &Client, - contract_address: &Address, - block: &BlockId, - ) -> Result { - let (encoded, decoder) = - service::functions::document_key_shadow_retrieval_requests_count::call(); - decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string()) - } - - /// Read pending request. - fn read_pending_request( - self_key_pair: &dyn NodeKeyPair, - client: &Client, - contract_address: &Address, - block: &BlockId, - index: U256, - ) -> Result<(bool, ServiceTask), String> { - let self_address = public_to_address(self_key_pair.public()); - - let (encoded, decoder) = - service::functions::get_document_key_shadow_retrieval_request::call(index); - let (server_key_id, requester, is_common_retrieval_completed) = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let requester = Public::from_slice(&requester); - let (encoded, decoder) = - service::functions::is_document_key_shadow_retrieval_response_required::call( - server_key_id, - public_to_address(&requester), - self_address, - ); - let not_confirmed = decoder - .decode(&client.call_contract(*block, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - let task = match is_common_retrieval_completed { - true => ServiceTask::RetrieveShadowDocumentKeyPersonal( - *contract_address, - server_key_id, - requester, - ), - false => ServiceTask::RetrieveShadowDocumentKeyCommon( - *contract_address, - server_key_id, - public_to_address(&requester), - ), - }; - - Ok((not_confirmed, task)) - } - - /// Map from key server address to key server index. - fn map_key_server_address( - client: &Client, - contract_address: &Address, - key_server: Address, - ) -> Result { - // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state - let (encoded, decoder) = service::functions::require_key_server::call(key_server); - let index = decoder - .decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?) - .map_err(|e| e.to_string())?; - - if index > u8::max_value().into() { - Err(format!("key server index is too big: {}", index)) - } else { - let index: u32 = index.into(); - Ok(index as u8) - } - } -} - -/// Parse threshold (we only supposrt 256 KS at max). -fn parse_threshold(threshold: U256) -> Result { - let threshold_num = threshold.low_u64(); - if threshold != threshold_num.into() || threshold_num >= ::std::u8::MAX as u64 { - return Err(format!( - "invalid threshold to use in service contract: {}", - threshold - )); - } - - Ok(threshold_num as usize) -} - -/// Serialize threshold (we only support 256 KS at max). -fn serialize_threshold(threshold: usize) -> Result { - if threshold > ::std::u8::MAX as usize { - return Err(format!( - "invalid threshold to use in service contract: {}", - threshold - )); - } - Ok(threshold.into()) -} - -#[cfg(test)] -pub mod tests { - use super::ServiceContract; - use bytes::Bytes; - use ethereum_types::Address; - use ethkey::Public; - use listener::service_contract_listener::ServiceTask; - use parking_lot::Mutex; - use ServerKeyId; - - #[derive(Default)] - pub struct DummyServiceContract { - pub is_actual: bool, - pub logs: Vec, - pub pending_requests: Vec<(bool, ServiceTask)>, - pub generated_server_keys: Mutex>, - pub server_keys_generation_failures: Mutex>, - pub retrieved_server_keys: Mutex>, - pub server_keys_retrieval_failures: Mutex>, - pub stored_document_keys: Mutex>, - pub document_keys_store_failures: Mutex>, - pub common_shadow_retrieved_document_keys: - Mutex>, - pub personal_shadow_retrieved_document_keys: - Mutex, Public, Bytes)>>, - pub document_keys_shadow_retrieval_failures: Mutex>, - } - - impl ServiceContract for DummyServiceContract { - fn update(&self) -> bool { - true - } - - fn read_logs(&self) -> Box> { - Box::new(self.logs.clone().into_iter()) - } - - fn read_pending_requests(&self) -> Box> { - Box::new(self.pending_requests.clone().into_iter()) - } - - fn publish_generated_server_key( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - ) -> Result<(), String> { - self.generated_server_keys - .lock() - .push((server_key_id.clone(), server_key.clone())); - Ok(()) - } - - fn publish_server_key_generation_error( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.server_keys_generation_failures - .lock() - .push(server_key_id.clone()); - Ok(()) - } - - fn publish_retrieved_server_key( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - threshold: usize, - ) -> Result<(), String> { - self.retrieved_server_keys.lock().push(( - server_key_id.clone(), - server_key.clone(), - threshold, - )); - Ok(()) - } - - fn publish_server_key_retrieval_error( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.server_keys_retrieval_failures - .lock() - .push(server_key_id.clone()); - Ok(()) - } - - fn publish_stored_document_key( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.stored_document_keys.lock().push(server_key_id.clone()); - Ok(()) - } - - fn publish_document_key_store_error( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.document_keys_store_failures - .lock() - .push(server_key_id.clone()); - Ok(()) - } - - fn publish_retrieved_document_key_common( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - common_point: Public, - threshold: usize, - ) -> Result<(), String> { - self.common_shadow_retrieved_document_keys.lock().push(( - server_key_id.clone(), - requester.clone(), - common_point.clone(), - threshold, - )); - Ok(()) - } - - fn publish_retrieved_document_key_personal( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - participants: &[Address], - decrypted_secret: Public, - shadow: Bytes, - ) -> Result<(), String> { - self.personal_shadow_retrieved_document_keys.lock().push(( - server_key_id.clone(), - requester.clone(), - participants.iter().cloned().collect(), - decrypted_secret, - shadow, - )); - Ok(()) - } - - fn publish_document_key_retrieval_error( - &self, - _origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - ) -> Result<(), String> { - self.document_keys_shadow_retrieval_failures - .lock() - .push((server_key_id.clone(), requester.clone())); - Ok(()) - } - } -} diff --git a/secret-store/src/listener/service_contract_aggregate.rs b/secret-store/src/listener/service_contract_aggregate.rs deleted file mode 100644 index 1558a17dae..0000000000 --- a/secret-store/src/listener/service_contract_aggregate.rs +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use bytes::Bytes; -use ethereum_types::Address; -use ethkey::Public; -use listener::{service_contract::ServiceContract, service_contract_listener::ServiceTask}; -use std::sync::Arc; -use ServerKeyId; - -/// Aggregated on-chain service contract. -pub struct OnChainServiceContractAggregate { - /// All hosted service contracts. - contracts: Vec>, -} - -impl OnChainServiceContractAggregate { - /// Create new aggregated service contract listener. - pub fn new(contracts: Vec>) -> Self { - debug_assert!(contracts.len() > 1); - OnChainServiceContractAggregate { - contracts: contracts, - } - } -} - -impl ServiceContract for OnChainServiceContractAggregate { - fn update(&self) -> bool { - let mut result = false; - for contract in &self.contracts { - result = contract.update() || result; - } - result - } - - fn read_logs(&self) -> Box> { - self.contracts.iter().fold( - Box::new(::std::iter::empty()) as Box>, - |i, c| Box::new(i.chain(c.read_logs())), - ) - } - - fn read_pending_requests(&self) -> Box> { - self.contracts.iter().fold( - Box::new(::std::iter::empty()) as Box>, - |i, c| Box::new(i.chain(c.read_pending_requests())), - ) - } - - // in current implementation all publish methods are independent of actual contract adddress - // (tx is sent to origin) => we do not care which contract to use for publish data in methods below - - fn publish_generated_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - ) -> Result<(), String> { - self.contracts[0].publish_generated_server_key(origin, server_key_id, server_key) - } - - fn publish_server_key_generation_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.contracts[0].publish_server_key_generation_error(origin, server_key_id) - } - - fn publish_retrieved_server_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - server_key: Public, - threshold: usize, - ) -> Result<(), String> { - self.contracts[0].publish_retrieved_server_key(origin, server_key_id, server_key, threshold) - } - - fn publish_server_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.contracts[0].publish_server_key_retrieval_error(origin, server_key_id) - } - - fn publish_stored_document_key( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.contracts[0].publish_stored_document_key(origin, server_key_id) - } - - fn publish_document_key_store_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - self.contracts[0].publish_document_key_store_error(origin, server_key_id) - } - - fn publish_retrieved_document_key_common( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - common_point: Public, - threshold: usize, - ) -> Result<(), String> { - self.contracts[0].publish_retrieved_document_key_common( - origin, - server_key_id, - requester, - common_point, - threshold, - ) - } - - fn publish_retrieved_document_key_personal( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - participants: &[Address], - decrypted_secret: Public, - shadow: Bytes, - ) -> Result<(), String> { - self.contracts[0].publish_retrieved_document_key_personal( - origin, - server_key_id, - requester, - participants, - decrypted_secret, - shadow, - ) - } - - fn publish_document_key_retrieval_error( - &self, - origin: &Address, - server_key_id: &ServerKeyId, - requester: &Address, - ) -> Result<(), String> { - self.contracts[0].publish_document_key_retrieval_error(origin, server_key_id, requester) - } -} diff --git a/secret-store/src/listener/service_contract_listener.rs b/secret-store/src/listener/service_contract_listener.rs deleted file mode 100644 index 8b6490d9a0..0000000000 --- a/secret-store/src/listener/service_contract_listener.rs +++ /dev/null @@ -1,1971 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use acl_storage::AclStorage; -use bytes::Bytes; -use ethcore::client::{ChainNotify, NewBlocks}; -use ethereum_types::{Address, H256, U256}; -use ethkey::{public_to_address, Public}; -use key_server_cluster::{ - decryption_session::SessionImpl as DecryptionSession, - encryption_session::{check_encrypted_data, update_encrypted_data}, - generation_session::SessionImpl as GenerationSession, - key_version_negotiation_session::{ - FailedContinueAction, IsolatedSessionTransport as KeyVersionNegotiationTransport, - SessionImpl as KeyVersionNegotiationSession, - }, - math, ClusterClient, ClusterSession, ClusterSessionsListener, NodeId, -}; -use key_server_set::KeyServerSet; -use key_storage::KeyStorage; -use listener::{service_contract::ServiceContract, tasks_queue::TasksQueue}; -use parking_lot::Mutex; -use std::{ - collections::HashSet, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, - thread, -}; -use Error; -use NodeKeyPair; -use ServerKeyId; - -/// Retry interval (in blocks). Every RETRY_INTERVAL_BLOCKS blocks each KeyServer reads pending requests from -/// service contract && tries to re-execute. The reason to have this mechanism is primarily because keys -/// servers set change takes a lot of time + there could be some races, when blocks are coming to different -/// KS at different times. This isn't intended to fix && respond to general session errors! -const RETRY_INTERVAL_BLOCKS: usize = 30; - -/// Max failed retry requests (in single retry interval). The reason behind this constant is that if several -/// pending requests have failed, then most probably other will fail too. -const MAX_FAILED_RETRY_REQUESTS: usize = 1; - -/// SecretStore <-> Authority connector responsible for: -/// 1. listening for new requests on SecretStore contract -/// 2. redirecting requests to key server -/// 3. publishing response on SecretStore contract -pub struct ServiceContractListener { - /// Service contract listener data. - data: Arc, - /// Service thread handle. - service_handle: Option>, -} - -/// Service contract listener parameters. -pub struct ServiceContractListenerParams { - /// Service contract. - pub contract: Arc, - /// This node key pair. - pub self_key_pair: Arc, - /// Key servers set. - pub key_server_set: Arc, - /// ACL storage reference. - pub acl_storage: Arc, - /// Cluster reference. - pub cluster: Arc, - /// Key storage reference. - pub key_storage: Arc, -} - -/// Service contract listener data. -struct ServiceContractListenerData { - /// Blocks since last retry. - pub last_retry: AtomicUsize, - /// Retry-related data. - pub retry_data: Mutex, - /// Service tasks queue. - pub tasks_queue: Arc>, - /// Service contract. - pub contract: Arc, - /// ACL storage reference. - pub acl_storage: Arc, - /// Cluster client reference. - pub cluster: Arc, - /// This node key pair. - pub self_key_pair: Arc, - /// Key servers set. - pub key_server_set: Arc, - /// Key storage reference. - pub key_storage: Arc, -} - -/// Retry-related data. -#[derive(Default)] -struct ServiceContractRetryData { - /// Server keys, which we have 'touched' since last retry. - pub affected_server_keys: HashSet, - /// Document keys + requesters, which we have 'touched' since last retry. - pub affected_document_keys: HashSet<(ServerKeyId, Address)>, -} - -/// Service task. -#[derive(Debug, Clone, PartialEq)] -pub enum ServiceTask { - /// Retry all 'stalled' tasks. - Retry, - /// Generate server key (origin, server_key_id, author, threshold). - GenerateServerKey(Address, ServerKeyId, Address, usize), - /// Retrieve server key (origin, server_key_id). - RetrieveServerKey(Address, ServerKeyId), - /// Store document key (origin, server_key_id, author, common_point, encrypted_point). - StoreDocumentKey(Address, ServerKeyId, Address, Public, Public), - /// Retrieve common data of document key (origin, server_key_id, requester). - RetrieveShadowDocumentKeyCommon(Address, ServerKeyId, Address), - /// Retrieve personal data of document key (origin, server_key_id, requester). - RetrieveShadowDocumentKeyPersonal(Address, ServerKeyId, Public), - /// Shutdown listener. - Shutdown, -} - -impl ServiceContractListener { - /// Create new service contract listener. - pub fn new( - params: ServiceContractListenerParams, - ) -> Result, Error> { - let data = Arc::new(ServiceContractListenerData { - last_retry: AtomicUsize::new(0), - retry_data: Default::default(), - tasks_queue: Arc::new(TasksQueue::new()), - contract: params.contract, - acl_storage: params.acl_storage, - cluster: params.cluster, - self_key_pair: params.self_key_pair, - key_server_set: params.key_server_set, - key_storage: params.key_storage, - }); - - // we are not starting thread when in test mode - let service_handle = if cfg!(test) { - None - } else { - let service_thread_data = data.clone(); - Some( - thread::Builder::new() - .name("ServiceContractListener".into()) - .spawn(move || Self::run_service_thread(service_thread_data)) - .map_err(|e| Error::Internal(format!("{}", e)))?, - ) - }; - let contract = Arc::new(ServiceContractListener { - data: data, - service_handle: service_handle, - }); - contract - .data - .cluster - .add_generation_listener(contract.clone()); - contract - .data - .cluster - .add_decryption_listener(contract.clone()); - contract - .data - .cluster - .add_key_version_negotiation_listener(contract.clone()); - Ok(contract) - } - - /// Process incoming events of service contract. - fn process_service_contract_events(&self) { - // shortcut: do not process events if we're isolated from the cluster - if self.data.key_server_set.is_isolated() { - return; - } - - self.data.tasks_queue.push_many( - self.data - .contract - .read_logs() - .filter_map(|task| Self::filter_task(&self.data, task)), - ); - } - - /// Filter service task. Only returns Some if task must be executed by this server. - fn filter_task( - data: &Arc, - task: ServiceTask, - ) -> Option { - match task { - // when this node should be master of this server key generation session - ServiceTask::GenerateServerKey(origin, server_key_id, author, threshold) - if is_processed_by_this_key_server( - &*data.key_server_set, - data.self_key_pair.public(), - &server_key_id, - ) => - { - Some(ServiceTask::GenerateServerKey( - origin, - server_key_id, - author, - threshold, - )) - } - // when server key is not yet generated and generation must be initiated by other node - ServiceTask::GenerateServerKey(_, _, _, _) => None, - - // when server key retrieval is requested - ServiceTask::RetrieveServerKey(origin, server_key_id) => { - Some(ServiceTask::RetrieveServerKey(origin, server_key_id)) - } - - // when document key store is requested - ServiceTask::StoreDocumentKey( - origin, - server_key_id, - author, - common_point, - encrypted_point, - ) => Some(ServiceTask::StoreDocumentKey( - origin, - server_key_id, - author, - common_point, - encrypted_point, - )), - - // when common document key data retrieval is requested - ServiceTask::RetrieveShadowDocumentKeyCommon(origin, server_key_id, requester) => Some( - ServiceTask::RetrieveShadowDocumentKeyCommon(origin, server_key_id, requester), - ), - - // when this node should be master of this document key decryption session - ServiceTask::RetrieveShadowDocumentKeyPersonal(origin, server_key_id, requester) - if is_processed_by_this_key_server( - &*data.key_server_set, - data.self_key_pair.public(), - &server_key_id, - ) => - { - Some(ServiceTask::RetrieveShadowDocumentKeyPersonal( - origin, - server_key_id, - requester, - )) - } - // when server key is not yet generated and generation must be initiated by other node - ServiceTask::RetrieveShadowDocumentKeyPersonal(_, _, _) => None, - - ServiceTask::Retry | ServiceTask::Shutdown => unreachable!("must be filtered outside"), - } - } - - /// Service thread procedure. - fn run_service_thread(data: Arc) { - loop { - let task = data.tasks_queue.wait(); - trace!(target: "secretstore", "{}: processing {:?} task", data.self_key_pair.public(), task); - - match task { - ServiceTask::Shutdown => break, - task => { - // the only possible reaction to an error is a tx+trace && it is already happened - let _ = Self::process_service_task(&data, task); - } - }; - } - - trace!(target: "secretstore", "{}: ServiceContractListener thread stopped", data.self_key_pair.public()); - } - - /// Process single service task. - fn process_service_task( - data: &Arc, - task: ServiceTask, - ) -> Result<(), String> { - match &task { - &ServiceTask::GenerateServerKey(origin, server_key_id, author, threshold) => { - data.retry_data.lock().affected_server_keys.insert(server_key_id.clone()); - log_service_task_result(&task, data.self_key_pair.public(), - Self::generate_server_key(&data, origin, &server_key_id, author, threshold)) - }, - &ServiceTask::RetrieveServerKey(origin, server_key_id) => { - data.retry_data.lock().affected_server_keys.insert(server_key_id.clone()); - log_service_task_result(&task, data.self_key_pair.public(), - Self::retrieve_server_key(&data, origin, &server_key_id)) - }, - &ServiceTask::StoreDocumentKey(origin, server_key_id, author, common_point, encrypted_point) => { - data.retry_data.lock().affected_document_keys.insert((server_key_id.clone(), author.clone())); - log_service_task_result(&task, data.self_key_pair.public(), - Self::store_document_key(&data, origin, &server_key_id, &author, &common_point, &encrypted_point)) - }, - &ServiceTask::RetrieveShadowDocumentKeyCommon(origin, server_key_id, requester) => { - data.retry_data.lock().affected_document_keys.insert((server_key_id.clone(), requester.clone())); - log_service_task_result(&task, data.self_key_pair.public(), - Self::retrieve_document_key_common(&data, origin, &server_key_id, &requester)) - }, - &ServiceTask::RetrieveShadowDocumentKeyPersonal(origin, server_key_id, requester) => { - data.retry_data.lock().affected_server_keys.insert(server_key_id.clone()); - log_service_task_result(&task, data.self_key_pair.public(), - Self::retrieve_document_key_personal(&data, origin, &server_key_id, requester)) - }, - &ServiceTask::Retry => { - Self::retry_pending_requests(&data) - .map(|processed_requests| { - if processed_requests != 0 { - trace!(target: "secretstore", "{}: successfully retried {} pending requests", - data.self_key_pair.public(), processed_requests); - } - () - }) - .map_err(|error| { - warn!(target: "secretstore", "{}: retrying pending requests has failed with: {}", - data.self_key_pair.public(), error); - error - }) - }, - &ServiceTask::Shutdown => unreachable!("must be filtered outside"), - } - } - - /// Retry processing pending requests. - fn retry_pending_requests(data: &Arc) -> Result { - let mut failed_requests = 0; - let mut processed_requests = 0; - let retry_data = ::std::mem::replace(&mut *data.retry_data.lock(), Default::default()); - let pending_tasks = - data.contract - .read_pending_requests() - .filter_map(|(is_confirmed, task)| { - Self::filter_task(data, task).map(|t| (is_confirmed, t)) - }); - for (is_response_required, task) in pending_tasks { - // only process requests, which we haven't confirmed yet - if !is_response_required { - continue; - } - - match task { - ServiceTask::GenerateServerKey(_, ref key, _, _) - | ServiceTask::RetrieveServerKey(_, ref key) - if retry_data.affected_server_keys.contains(key) => - { - continue - } - ServiceTask::StoreDocumentKey(_, ref key, ref author, _, _) - | ServiceTask::RetrieveShadowDocumentKeyCommon(_, ref key, ref author) - if retry_data - .affected_document_keys - .contains(&(key.clone(), author.clone())) => - { - continue - } - ServiceTask::RetrieveShadowDocumentKeyPersonal(_, ref key, ref requester) - if retry_data - .affected_document_keys - .contains(&(key.clone(), public_to_address(requester))) => - { - continue - } - _ => (), - } - - // process request result - let request_result = Self::process_service_task(data, task); - match request_result { - Ok(_) => processed_requests += 1, - Err(_) => { - failed_requests += 1; - if failed_requests > MAX_FAILED_RETRY_REQUESTS { - return Err("too many failed requests".into()); - } - } - } - } - - Ok(processed_requests) - } - - /// Generate server key (start generation session). - fn generate_server_key( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - author: Address, - threshold: usize, - ) -> Result<(), String> { - Self::process_server_key_generation_result( - data, - origin, - server_key_id, - data.cluster - .new_generation_session(server_key_id.clone(), Some(origin), author, threshold) - .map(|_| None) - .map_err(Into::into), - ) - } - - /// Process server key generation result. - fn process_server_key_generation_result( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - result: Result, Error>, - ) -> Result<(), String> { - match result { - Ok(None) => Ok(()), - Ok(Some(server_key)) => { - data.contract - .publish_generated_server_key(&origin, server_key_id, server_key) - } - Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), - Err(ref error) => { - // ignore error as we're already processing an error - let _ = data.contract.publish_server_key_generation_error(&origin, server_key_id) - .map_err(|error| warn!(target: "secretstore", "{}: failed to publish GenerateServerKey({}) error: {}", - data.self_key_pair.public(), server_key_id, error)); - Err(format!("{}", error)) - } - } - } - - /// Retrieve server key. - fn retrieve_server_key( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - ) -> Result<(), String> { - match data.key_storage.get(server_key_id) { - Ok(Some(server_key_share)) => data.contract.publish_retrieved_server_key( - &origin, - server_key_id, - server_key_share.public, - server_key_share.threshold, - ), - Ok(None) => data - .contract - .publish_server_key_retrieval_error(&origin, server_key_id), - Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), - Err(ref error) => { - // ignore error as we're already processing an error - let _ = data.contract.publish_server_key_retrieval_error(&origin, server_key_id) - .map_err(|error| warn!(target: "secretstore", "{}: failed to publish RetrieveServerKey({}) error: {}", - data.self_key_pair.public(), server_key_id, error)); - Err(format!("{}", error)) - } - } - } - - /// Store document key. - fn store_document_key( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - author: &Address, - common_point: &Public, - encrypted_point: &Public, - ) -> Result<(), String> { - let store_result = data - .key_storage - .get(server_key_id) - .and_then(|key_share| key_share.ok_or(Error::ServerKeyIsNotFound)) - .and_then(|key_share| { - check_encrypted_data(Some(&key_share)) - .map(|_| key_share) - .map_err(Into::into) - }) - .and_then(|key_share| { - update_encrypted_data( - &data.key_storage, - server_key_id.clone(), - key_share, - author.clone(), - common_point.clone(), - encrypted_point.clone(), - ) - .map_err(Into::into) - }); - match store_result { - Ok(()) => data - .contract - .publish_stored_document_key(&origin, server_key_id), - Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), - Err(ref error) => { - // ignore error as we're already processing an error - let _ = data.contract.publish_document_key_store_error(&origin, server_key_id) - .map_err(|error| warn!(target: "secretstore", "{}: failed to publish StoreDocumentKey({}) error: {}", - data.self_key_pair.public(), server_key_id, error)); - Err(format!("{}", error)) - } - } - } - - /// Retrieve common part of document key. - fn retrieve_document_key_common( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - requester: &Address, - ) -> Result<(), String> { - let retrieval_result = data - .acl_storage - .check(requester.clone(), server_key_id) - .and_then(|is_allowed| { - if !is_allowed { - Err(Error::AccessDenied) - } else { - Ok(()) - } - }) - .and_then(|_| { - data.key_storage - .get(server_key_id) - .and_then(|key_share| key_share.ok_or(Error::ServerKeyIsNotFound)) - }) - .and_then(|key_share| { - key_share - .common_point - .ok_or(Error::DocumentKeyIsNotFound) - .and_then(|common_point| { - math::make_common_shadow_point(key_share.threshold, common_point) - }) - .map(|common_point| (common_point, key_share.threshold)) - }); - match retrieval_result { - Ok((common_point, threshold)) => data.contract.publish_retrieved_document_key_common( - &origin, - server_key_id, - requester, - common_point, - threshold, - ), - Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), - Err(ref error) => { - // ignore error as we're already processing an error - let _ = data.contract.publish_document_key_retrieval_error(&origin, server_key_id, requester) - .map_err(|error| warn!(target: "secretstore", "{}: failed to publish RetrieveDocumentKey({}) error: {}", - data.self_key_pair.public(), server_key_id, error)); - Err(format!("{}", error)) - } - } - } - - /// Retrieve personal part of document key (start decryption session). - fn retrieve_document_key_personal( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - requester: Public, - ) -> Result<(), String> { - Self::process_document_key_retrieval_result( - data, - origin, - server_key_id, - &public_to_address(&requester), - data.cluster - .new_decryption_session( - server_key_id.clone(), - Some(origin), - requester.clone().into(), - None, - true, - true, - ) - .map(|_| None) - .map_err(Into::into), - ) - } - - /// Process document key retrieval result. - fn process_document_key_retrieval_result( - data: &Arc, - origin: Address, - server_key_id: &ServerKeyId, - requester: &Address, - result: Result, Public, Bytes)>, Error>, - ) -> Result<(), String> { - match result { - Ok(None) => Ok(()), - Ok(Some((participants, decrypted_secret, shadow))) => { - data.contract.publish_retrieved_document_key_personal( - &origin, - server_key_id, - &requester, - &participants, - decrypted_secret, - shadow, - ) - } - Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), - Err(ref error) => { - // ignore error as we're already processing an error - let _ = data.contract.publish_document_key_retrieval_error(&origin, server_key_id, &requester) - .map_err(|error| warn!(target: "secretstore", "{}: failed to publish RetrieveDocumentKey({}) error: {}", - data.self_key_pair.public(), server_key_id, error)); - Err(format!("{}", error)) - } - } - } -} - -impl Drop for ServiceContractListener { - fn drop(&mut self) { - if let Some(service_handle) = self.service_handle.take() { - self.data.tasks_queue.push_front(ServiceTask::Shutdown); - // ignore error as we are already closing - let _ = service_handle.join(); - } - } -} - -impl ChainNotify for ServiceContractListener { - // t_nb 11.7 SecretStore ServiceContractListener - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { - return; - } - let enacted_len = new_blocks.route.enacted().len(); - if enacted_len == 0 && new_blocks.route.retracted().is_empty() { - return; - } - - if !self.data.contract.update() { - return; - } - - self.process_service_contract_events(); - - // schedule retry if received enough blocks since last retry - // it maybe inaccurate when switching syncing/synced states, but that's ok - if self - .data - .last_retry - .fetch_add(enacted_len, Ordering::Relaxed) - >= RETRY_INTERVAL_BLOCKS - { - // shortcut: do not retry if we're isolated from the cluster - if !self.data.key_server_set.is_isolated() { - self.data.tasks_queue.push(ServiceTask::Retry); - self.data.last_retry.store(0, Ordering::Relaxed); - } - } - } -} - -impl ClusterSessionsListener for ServiceContractListener { - fn on_session_removed(&self, session: Arc) { - // by this time sesion must already be completed - either successfully, or not - assert!(session.is_finished()); - - // ignore result - the only thing that we can do is to log the error - let server_key_id = session.id(); - if let Some(origin) = session.origin() { - if let Some(generation_result) = session.wait(Some(Default::default())) { - let generation_result = generation_result.map(Some).map_err(Into::into); - let _ = Self::process_server_key_generation_result( - &self.data, - origin, - &server_key_id, - generation_result, - ); - } - } - } -} - -impl ClusterSessionsListener for ServiceContractListener { - fn on_session_removed(&self, session: Arc) { - // by this time sesion must already be completed - either successfully, or not - assert!(session.is_finished()); - - // ignore result - the only thing that we can do is to log the error - let session_id = session.id(); - let server_key_id = session_id.id; - if let (Some(requester), Some(origin)) = ( - session - .requester() - .and_then(|r| r.address(&server_key_id).ok()), - session.origin(), - ) { - if let Some(retrieval_result) = session.wait(Some(Default::default())) { - let retrieval_result = retrieval_result - .map(|key_shadow| { - session.broadcast_shadows().and_then(|broadcast_shadows| { - broadcast_shadows.get(self.data.self_key_pair.public()).map( - |self_shadow| { - ( - broadcast_shadows.keys().map(public_to_address).collect(), - key_shadow.decrypted_secret, - self_shadow.clone(), - ) - }, - ) - }) - }) - .map_err(Into::into); - let _ = Self::process_document_key_retrieval_result( - &self.data, - origin, - &server_key_id, - &requester, - retrieval_result, - ); - } - } - } -} - -impl ClusterSessionsListener> - for ServiceContractListener -{ - fn on_session_removed( - &self, - session: Arc>, - ) { - // by this time sesion must already be completed - either successfully, or not - assert!(session.is_finished()); - - // we're interested in: - // 1) sessions failed with fatal error - // 2) with decryption continue action - let error = match session.wait() { - Err(ref error) if !error.is_non_fatal() => error.clone(), - _ => return, - }; - - let (origin, requester) = match session.take_failed_continue_action() { - Some(FailedContinueAction::Decrypt(Some(origin), requester)) => (origin, requester), - _ => return, - }; - - // check if master node is responsible for processing key requests - let meta = session.meta(); - if !is_processed_by_this_key_server( - &*self.data.key_server_set, - &meta.master_node_id, - &meta.id, - ) { - return; - } - - // ignore result as we're already processing an error - let _ = Self::process_document_key_retrieval_result( - &self.data, - origin, - &meta.id, - &requester, - Err(error), - ); - } -} - -impl ::std::fmt::Display for ServiceTask { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - match *self { - ServiceTask::Retry => write!(f, "Retry"), - ServiceTask::GenerateServerKey(_, ref server_key_id, ref author, ref threshold) => { - write!( - f, - "GenerateServerKey({}, {}, {})", - server_key_id, author, threshold - ) - } - ServiceTask::RetrieveServerKey(_, ref server_key_id) => { - write!(f, "RetrieveServerKey({})", server_key_id) - } - ServiceTask::StoreDocumentKey(_, ref server_key_id, ref author, _, _) => { - write!(f, "StoreDocumentKey({}, {})", server_key_id, author) - } - ServiceTask::RetrieveShadowDocumentKeyCommon(_, ref server_key_id, ref requester) => { - write!( - f, - "RetrieveShadowDocumentKeyCommon({}, {})", - server_key_id, requester - ) - } - ServiceTask::RetrieveShadowDocumentKeyPersonal(_, ref server_key_id, ref requester) => { - write!( - f, - "RetrieveShadowDocumentKeyPersonal({}, {})", - server_key_id, - public_to_address(requester) - ) - } - ServiceTask::Shutdown => write!(f, "Shutdown"), - } - } -} - -/// Log service task result. -fn log_service_task_result( - task: &ServiceTask, - self_id: &Public, - result: Result<(), String>, -) -> Result<(), String> { - match result { - Ok(_) => trace!(target: "secretstore", "{}: processed {} request", self_id, task), - Err(ref error) => { - warn!(target: "secretstore", "{}: failed to process {} request with: {}", self_id, task, error) - } - } - - result -} - -/// Returns true when session, related to `server_key_id` must be started on `node`. -fn is_processed_by_this_key_server( - key_server_set: &dyn KeyServerSet, - node: &NodeId, - server_key_id: &H256, -) -> bool { - let servers = key_server_set.snapshot().current_set; - let total_servers_count = servers.len(); - match total_servers_count { - 0 => return false, - 1 => return true, - _ => (), - } - - let this_server_index = match servers.keys().enumerate().find(|&(_, s)| s == node) { - Some((index, _)) => index, - None => return false, - }; - - let server_key_id_value: U256 = server_key_id.into(); - let range_interval = U256::max_value() / total_servers_count; - let range_begin = (range_interval + 1) * this_server_index as u32; - let range_end = range_begin.saturating_add(range_interval); - - server_key_id_value >= range_begin && server_key_id_value <= range_end -} - -#[cfg(test)] -mod tests { - use super::{ - is_processed_by_this_key_server, ServiceContractListener, ServiceContractListenerParams, - ServiceTask, - }; - use acl_storage::{AclStorage, DummyAclStorage}; - use ethkey::{Generator, KeyPair, Random}; - use key_server_cluster::DummyClusterClient; - use key_server_set::{tests::MapKeyServerSet, KeyServerSet}; - use key_storage::{tests::DummyKeyStorage, DocumentKeyShare, KeyStorage}; - use listener::service_contract::{tests::DummyServiceContract, ServiceContract}; - use std::sync::{atomic::Ordering, Arc}; - use NodeKeyPair; - use PlainNodeKeyPair; - use ServerKeyId; - - fn create_non_empty_key_storage(has_doc_key: bool) -> Arc { - let key_storage = Arc::new(DummyKeyStorage::default()); - let mut key_share = DocumentKeyShare::default(); - key_share.public = KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000001" - .parse() - .unwrap(), - ) - .unwrap() - .public() - .clone(); - if has_doc_key { - key_share.common_point = Some(Default::default()); - key_share.encrypted_point = Some(Default::default()); - } - key_storage - .insert(Default::default(), key_share.clone()) - .unwrap(); - key_storage - } - - fn make_servers_set(is_isolated: bool) -> Arc { - Arc::new(MapKeyServerSet::new(is_isolated, vec![ - ("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - ("c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - ("f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - ].into_iter().collect())) - } - - fn make_service_contract_listener( - contract: Option>, - cluster: Option>, - key_storage: Option>, - acl_storage: Option>, - servers_set: Option>, - ) -> Arc { - let contract = contract.unwrap_or_else(|| Arc::new(DummyServiceContract::default())); - let cluster = cluster.unwrap_or_else(|| Arc::new(DummyClusterClient::default())); - let key_storage = key_storage.unwrap_or_else(|| Arc::new(DummyKeyStorage::default())); - let acl_storage = acl_storage.unwrap_or_else(|| Arc::new(DummyAclStorage::default())); - let servers_set = servers_set.unwrap_or_else(|| make_servers_set(false)); - let self_key_pair = Arc::new(PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000001" - .parse() - .unwrap(), - ) - .unwrap(), - )); - ServiceContractListener::new(ServiceContractListenerParams { - contract: contract, - self_key_pair: self_key_pair, - key_server_set: servers_set, - acl_storage: acl_storage, - cluster: cluster, - key_storage: key_storage, - }) - .unwrap() - } - - #[test] - fn is_not_processed_by_this_key_server_with_zero_servers() { - assert_eq!( - is_processed_by_this_key_server( - &MapKeyServerSet::default(), - Random.generate().unwrap().public(), - &Default::default() - ), - false - ); - } - - #[test] - fn is_processed_by_this_key_server_with_single_server() { - let self_key_pair = Random.generate().unwrap(); - assert_eq!( - is_processed_by_this_key_server( - &MapKeyServerSet::new( - false, - vec![( - self_key_pair.public().clone(), - "127.0.0.1:8080".parse().unwrap() - )] - .into_iter() - .collect() - ), - self_key_pair.public(), - &Default::default() - ), - true - ); - } - - #[test] - fn is_not_processed_by_this_key_server_when_not_a_part_of_servers_set() { - assert!(is_processed_by_this_key_server( - &MapKeyServerSet::new( - false, - vec![( - Random.generate().unwrap().public().clone(), - "127.0.0.1:8080".parse().unwrap() - )] - .into_iter() - .collect() - ), - Random.generate().unwrap().public(), - &Default::default() - )); - } - - #[test] - fn is_processed_by_this_key_server_in_set_of_3() { - // servers set is ordered && server range depends on index of this server - let servers_set = MapKeyServerSet::new(false, vec![ - // secret: 0000000000000000000000000000000000000000000000000000000000000001 - ("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - // secret: 0000000000000000000000000000000000000000000000000000000000000002 - ("c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - // secret: 0000000000000000000000000000000000000000000000000000000000000003 - ("f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - ].into_iter().collect()); - - // 1st server: process hashes [0x0; 0x555...555] - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000001" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"0000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"3000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"5555555555555555555555555555555555555555555555555555555555555555" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"5555555555555555555555555555555555555555555555555555555555555556" - .parse() - .unwrap() - ), - false - ); - - // 2nd server: process hashes from 0x555...556 to 0xaaa...aab - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000002" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"5555555555555555555555555555555555555555555555555555555555555555" - .parse() - .unwrap() - ), - false - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"5555555555555555555555555555555555555555555555555555555555555556" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"7555555555555555555555555555555555555555555555555555555555555555" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac" - .parse() - .unwrap() - ), - false - ); - - // 3rd server: process hashes from 0x800...000 to 0xbff...ff - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000003" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab" - .parse() - .unwrap() - ), - false - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - true - ); - } - - #[test] - fn is_processed_by_this_key_server_in_set_of_4() { - // servers set is ordered && server range depends on index of this server - let servers_set = MapKeyServerSet::new(false, vec![ - // secret: 0000000000000000000000000000000000000000000000000000000000000001 - ("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - // secret: 0000000000000000000000000000000000000000000000000000000000000002 - ("c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - // secret: 0000000000000000000000000000000000000000000000000000000000000004 - ("e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd1351ed993ea0d455b75642e2098ea51448d967ae33bfbdfe40cfe97bdc47739922".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - // secret: 0000000000000000000000000000000000000000000000000000000000000003 - ("f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672".parse().unwrap(), - "127.0.0.1:8080".parse().unwrap()), - ].into_iter().collect()); - - // 1st server: process hashes [0x0; 0x3ff...ff] - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000001" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"0000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"2000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"4000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - false - ); - - // 2nd server: process hashes from 0x400...000 to 0x7ff...ff - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000002" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - false - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"4000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"6000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"8000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - false - ); - - // 3rd server: process hashes from 0x800...000 to 0xbff...ff - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000004" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - false - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"8000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"a000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"c000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - false - ); - - // 4th server: process hashes from 0xc00...000 to 0xfff...ff - let key_pair = PlainNodeKeyPair::new( - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000003" - .parse() - .unwrap(), - ) - .unwrap(), - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - false - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"c000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"e000000000000000000000000000000000000000000000000000000000000000" - .parse() - .unwrap() - ), - true - ); - assert_eq!( - is_processed_by_this_key_server( - &servers_set, - key_pair.public(), - &"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap() - ), - true - ); - } - - #[test] - fn no_tasks_scheduled_when_no_contract_events() { - let listener = make_service_contract_listener(None, None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - } - - #[test] - fn tasks_are_not_scheduled_on_isolated_node() { - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::GenerateServerKey( - Default::default(), - Default::default(), - Default::default(), - 0, - )); - let listener = make_service_contract_listener( - Some(Arc::new(contract)), - None, - None, - None, - Some(make_servers_set(true)), - ); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - } - - // server key generation tests - - #[test] - fn server_key_generation_is_scheduled_when_requested() { - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::GenerateServerKey( - Default::default(), - Default::default(), - Default::default(), - 0, - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::GenerateServerKey( - Default::default(), - Default::default(), - Default::default(), - 0 - )) - ); - } - - #[test] - fn no_new_tasks_scheduled_when_server_key_generation_requested_and_request_belongs_to_other_key_server( - ) { - let server_key_id = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap(); - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::GenerateServerKey( - Default::default(), - server_key_id, - Default::default(), - 0, - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - } - - #[test] - fn generation_session_is_created_when_processing_generate_server_key_task() { - let cluster = Arc::new(DummyClusterClient::default()); - let listener = - make_service_contract_listener(None, Some(cluster.clone()), None, None, None); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::GenerateServerKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!(cluster.generation_requests_count.load(Ordering::Relaxed), 1); - } - - #[test] - fn server_key_generation_is_not_retried_if_tried_in_the_same_cycle() { - let mut contract = DummyServiceContract::default(); - contract.pending_requests.push(( - false, - ServiceTask::GenerateServerKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - )); - let cluster = Arc::new(DummyClusterClient::default()); - let listener = make_service_contract_listener( - Some(Arc::new(contract)), - Some(cluster.clone()), - None, - None, - None, - ); - listener - .data - .retry_data - .lock() - .affected_server_keys - .insert(Default::default()); - ServiceContractListener::retry_pending_requests(&listener.data).unwrap(); - assert_eq!(cluster.generation_requests_count.load(Ordering::Relaxed), 0); - } - - // server key retrieval tests - - #[test] - fn server_key_retrieval_is_scheduled_when_requested() { - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::RetrieveServerKey( - Default::default(), - Default::default(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::RetrieveServerKey( - Default::default(), - Default::default() - )) - ); - } - - #[test] - fn server_key_retrieval_is_scheduled_when_requested_and_request_belongs_to_other_key_server() { - let server_key_id: ServerKeyId = - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap(); - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::RetrieveServerKey( - Default::default(), - server_key_id.clone(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::RetrieveServerKey( - Default::default(), - server_key_id - )) - ); - } - - #[test] - fn server_key_is_retrieved_when_processing_retrieve_server_key_task() { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(false); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveServerKey(Default::default(), Default::default()), - ) - .unwrap(); - assert_eq!( - *contract.retrieved_server_keys.lock(), - vec![( - Default::default(), - KeyPair::from_secret( - "0000000000000000000000000000000000000000000000000000000000000001" - .parse() - .unwrap() - ) - .unwrap() - .public() - .clone(), - 0 - )] - ); - } - - #[test] - fn server_key_retrieval_failure_is_reported_when_processing_retrieve_server_key_task_and_key_is_unknown( - ) { - let contract = Arc::new(DummyServiceContract::default()); - let listener = - make_service_contract_listener(Some(contract.clone()), None, None, None, None); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveServerKey(Default::default(), Default::default()), - ) - .unwrap(); - assert_eq!( - *contract.server_keys_retrieval_failures.lock(), - vec![Default::default()] - ); - } - - #[test] - fn server_key_retrieval_is_not_retried_if_tried_in_the_same_cycle() { - let mut contract = DummyServiceContract::default(); - contract.pending_requests.push(( - false, - ServiceTask::RetrieveServerKey(Default::default(), Default::default()), - )); - let cluster = Arc::new(DummyClusterClient::default()); - let listener = make_service_contract_listener( - Some(Arc::new(contract)), - Some(cluster.clone()), - None, - None, - None, - ); - listener - .data - .retry_data - .lock() - .affected_server_keys - .insert(Default::default()); - ServiceContractListener::retry_pending_requests(&listener.data).unwrap(); - assert_eq!(cluster.generation_requests_count.load(Ordering::Relaxed), 0); - } - - // document key store tests - - #[test] - fn document_key_store_is_scheduled_when_requested() { - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default() - )) - ); - } - - #[test] - fn document_key_store_is_scheduled_when_requested_and_request_belongs_to_other_key_server() { - let server_key_id: ServerKeyId = - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap(); - let mut contract = DummyServiceContract::default(); - contract.logs.push(ServiceTask::StoreDocumentKey( - Default::default(), - server_key_id.clone(), - Default::default(), - Default::default(), - Default::default(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::StoreDocumentKey( - Default::default(), - server_key_id, - Default::default(), - Default::default(), - Default::default() - )) - ); - } - - #[test] - fn document_key_is_stored_when_processing_store_document_key_task() { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(false); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage.clone()), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap(); - assert_eq!( - *contract.stored_document_keys.lock(), - vec![Default::default()] - ); - - let key_share = key_storage.get(&Default::default()).unwrap().unwrap(); - assert_eq!(key_share.common_point, Some(Default::default())); - assert_eq!(key_share.encrypted_point, Some(Default::default())); - } - - #[test] - fn document_key_store_failure_reported_when_no_server_key() { - let contract = Arc::new(DummyServiceContract::default()); - let listener = - make_service_contract_listener(Some(contract.clone()), None, None, None, None); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_store_failures.lock(), - vec![Default::default()] - ); - } - - #[test] - fn document_key_store_failure_reported_when_document_key_already_set() { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(true); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_store_failures.lock(), - vec![Default::default()] - ); - } - - #[test] - fn document_key_store_failure_reported_when_author_differs() { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(false); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::StoreDocumentKey( - Default::default(), - Default::default(), - 1.into(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_store_failures.lock(), - vec![Default::default()] - ); - } - - // document key shadow common retrieval tests - - #[test] - fn document_key_shadow_common_retrieval_is_scheduled_when_requested() { - let mut contract = DummyServiceContract::default(); - contract - .logs - .push(ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default() - )) - ); - } - - #[test] - fn document_key_shadow_common_retrieval_is_scheduled_when_requested_and_request_belongs_to_other_key_server( - ) { - let server_key_id: ServerKeyId = - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - .parse() - .unwrap(); - let mut contract = DummyServiceContract::default(); - contract - .logs - .push(ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - server_key_id.clone(), - Default::default(), - )); - let listener = - make_service_contract_listener(Some(Arc::new(contract)), None, None, None, None); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 0); - listener.process_service_contract_events(); - assert_eq!(listener.data.tasks_queue.snapshot().len(), 1); - assert_eq!( - listener.data.tasks_queue.snapshot().pop_back(), - Some(ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - server_key_id, - Default::default() - )) - ); - } - - #[test] - fn document_key_shadow_common_is_retrieved_when_processing_document_key_shadow_common_retrieval_task( - ) { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(true); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage.clone()), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap(); - assert_eq!( - *contract.common_shadow_retrieved_document_keys.lock(), - vec![( - Default::default(), - Default::default(), - Default::default(), - 0 - )] - ); - } - - #[test] - fn document_key_shadow_common_retrieval_failure_reported_when_access_denied() { - let acl_storage = DummyAclStorage::default(); - acl_storage.prohibit(Default::default(), Default::default()); - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(true); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage.clone()), - Some(Arc::new(acl_storage)), - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_shadow_retrieval_failures.lock(), - vec![(Default::default(), Default::default())] - ); - } - - #[test] - fn document_key_shadow_common_retrieval_failure_reported_when_no_server_key() { - let contract = Arc::new(DummyServiceContract::default()); - let listener = - make_service_contract_listener(Some(contract.clone()), None, None, None, None); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_shadow_retrieval_failures.lock(), - vec![(Default::default(), Default::default())] - ); - } - - #[test] - fn document_key_shadow_common_retrieval_failure_reported_when_no_document_key() { - let contract = Arc::new(DummyServiceContract::default()); - let key_storage = create_non_empty_key_storage(false); - let listener = make_service_contract_listener( - Some(contract.clone()), - None, - Some(key_storage.clone()), - None, - None, - ); - ServiceContractListener::process_service_task( - &listener.data, - ServiceTask::RetrieveShadowDocumentKeyCommon( - Default::default(), - Default::default(), - Default::default(), - ), - ) - .unwrap_err(); - assert_eq!( - *contract.document_keys_shadow_retrieval_failures.lock(), - vec![(Default::default(), Default::default())] - ); - } -} diff --git a/secret-store/src/listener/tasks_queue.rs b/secret-store/src/listener/tasks_queue.rs deleted file mode 100644 index cfff85e094..0000000000 --- a/secret-store/src/listener/tasks_queue.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use parking_lot::{Condvar, Mutex}; -use std::collections::VecDeque; - -#[derive(Default)] -/// General deque-based tasks queue. -pub struct TasksQueue { - /// Service event. - service_event: Condvar, - /// Service tasks queue. - service_tasks: Mutex>, -} - -impl TasksQueue -where - Task: Clone, -{ - /// Create new tasks queue. - pub fn new() -> Self { - TasksQueue { - service_event: Condvar::new(), - service_tasks: Mutex::new(VecDeque::new()), - } - } - - #[cfg(test)] - /// Get current tasks snapshot. - pub fn snapshot(&self) -> VecDeque { - self.service_tasks.lock().clone() - } - - /// Push task to the front of queue. - pub fn push_front(&self, task: Task) { - let mut service_tasks = self.service_tasks.lock(); - service_tasks.push_front(task); - self.service_event.notify_all(); - } - - /// Push task to the back of queue. - pub fn push(&self, task: Task) { - let mut service_tasks = self.service_tasks.lock(); - service_tasks.push_back(task); - self.service_event.notify_all(); - } - - /// Push task to the back of queue. - pub fn push_many>(&self, tasks: I) { - let mut service_tasks = self.service_tasks.lock(); - let previous_len = service_tasks.len(); - service_tasks.extend(tasks); - if service_tasks.len() != previous_len { - self.service_event.notify_all(); - } - } - - /// Wait for new task (task is removed from the front of queue). - pub fn wait(&self) -> Task { - let mut service_tasks = self.service_tasks.lock(); - if service_tasks.is_empty() { - self.service_event.wait(&mut service_tasks); - } - - service_tasks - .pop_front() - .expect("service_event is only fired when there are new tasks; qed") - } -} diff --git a/secret-store/src/node_key_pair.rs b/secret-store/src/node_key_pair.rs deleted file mode 100644 index 9d0e7724fe..0000000000 --- a/secret-store/src/node_key_pair.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::{ - crypto::ecdh::agree, public_to_address, sign, Error as EthKeyError, KeyPair, Public, Signature, -}; -use traits::NodeKeyPair; - -pub struct PlainNodeKeyPair { - key_pair: KeyPair, -} - -impl PlainNodeKeyPair { - pub fn new(key_pair: KeyPair) -> Self { - PlainNodeKeyPair { key_pair: key_pair } - } - - #[cfg(test)] - pub fn key_pair(&self) -> &KeyPair { - &self.key_pair - } -} - -impl NodeKeyPair for PlainNodeKeyPair { - fn public(&self) -> &Public { - self.key_pair.public() - } - - fn address(&self) -> Address { - public_to_address(self.key_pair.public()) - } - - fn sign(&self, data: &H256) -> Result { - sign(self.key_pair.secret(), data) - } - - fn compute_shared_key(&self, peer_public: &Public) -> Result { - agree(self.key_pair.secret(), peer_public) - .map_err(|e| EthKeyError::Custom(e.to_string())) - .and_then(KeyPair::from_secret) - } -} - -#[cfg(feature = "accounts")] -mod accounts { - use super::*; - use accounts::AccountProvider; - use ethkey::Password; - use std::sync::Arc; - - pub struct KeyStoreNodeKeyPair { - account_provider: Arc, - address: Address, - public: Public, - password: Password, - } - - impl KeyStoreNodeKeyPair { - pub fn new( - account_provider: Arc, - address: Address, - password: Password, - ) -> Result { - let public = account_provider - .account_public(address.clone(), &password) - .map_err(|e| EthKeyError::Custom(format!("{}", e)))?; - Ok(KeyStoreNodeKeyPair { - account_provider: account_provider, - address: address, - public: public, - password: password, - }) - } - } - - impl NodeKeyPair for KeyStoreNodeKeyPair { - fn public(&self) -> &Public { - &self.public - } - - fn address(&self) -> Address { - public_to_address(&self.public) - } - - fn sign(&self, data: &H256) -> Result { - self.account_provider - .sign( - self.address.clone(), - Some(self.password.clone()), - data.clone(), - ) - .map_err(|e| EthKeyError::Custom(format!("{}", e))) - } - - fn compute_shared_key(&self, peer_public: &Public) -> Result { - KeyPair::from_secret( - self.account_provider - .agree( - self.address.clone(), - Some(self.password.clone()), - peer_public, - ) - .map_err(|e| EthKeyError::Custom(format!("{}", e)))?, - ) - } - } -} - -#[cfg(feature = "accounts")] -pub use self::accounts::KeyStoreNodeKeyPair; diff --git a/secret-store/src/serialization.rs b/secret-store/src/serialization.rs deleted file mode 100644 index e6b18353bd..0000000000 --- a/secret-store/src/serialization.rs +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use bytes::Bytes; -use ethereum_types::{H160, H256}; -use ethkey::{Public, Secret, Signature}; -use rustc_hex::{FromHex, ToHex}; -use serde::{ - de::{Error as SerdeError, Visitor}, - Deserialize, Deserializer, Serialize, Serializer, -}; -use std::{fmt, ops::Deref}; -use types::Requester; - -macro_rules! impl_bytes_deserialize { - ($name: ident, $value: expr, true) => { - $value[2..] - .from_hex() - .map($name) - .map_err(SerdeError::custom) - }; - ($name: ident, $value: expr, false) => { - $value[2..].parse().map($name).map_err(SerdeError::custom) - }; -} - -macro_rules! impl_bytes { - ($name: ident, $other: ident, $from_hex: ident, ($($trait: ident),*)) => { - #[derive(Clone, Debug, PartialEq, Eq, $($trait,)*)] - pub struct $name(pub $other); - - impl From for $name where $other: From { - fn from(s: T) -> $name { - $name(s.into()) - } - } - - impl Into<$other> for $name { - fn into(self) -> $other { - self.0 - } - } - - impl Deref for $name { - type Target = $other; - - fn deref(&self) -> &$other { - &self.0 - } - } - - impl Serialize for $name { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut serialized = "0x".to_owned(); - serialized.push_str(self.0.to_hex().as_ref()); - serializer.serialize_str(serialized.as_ref()) - } - } - - impl<'a> Deserialize<'a> for $name { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'a> { - struct HexBytesVisitor; - - impl<'b> Visitor<'b> for HexBytesVisitor { - type Value = $name; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a hex-encoded bytes string") - } - - fn visit_str(self, value: &str) -> Result where E: SerdeError { - if value.len() >= 2 && &value[0..2] == "0x" && value.len() & 1 == 0 { - impl_bytes_deserialize!($name, value, $from_hex) - } else { - Err(SerdeError::custom("invalid format")) - } - } - - fn visit_string(self, value: String) -> Result where E: SerdeError { - self.visit_str(value.as_ref()) - } - } - - deserializer.deserialize_any(HexBytesVisitor) - } - } - } -} - -/// Serializable message hash. -pub type SerializableMessageHash = SerializableH256; -/// Serializable address; -pub type SerializableAddress = SerializableH160; - -// Serializable Bytes. -impl_bytes!(SerializableBytes, Bytes, true, (Default)); -// Serializable H256. -impl_bytes!(SerializableH256, H256, false, (Default, PartialOrd, Ord)); -// Serializable H160. -impl_bytes!(SerializableH160, H160, false, (Default)); -// Serializable H512 (aka Public). -impl_bytes!( - SerializablePublic, - Public, - false, - (Default, PartialOrd, Ord) -); -// Serializable Secret. -impl_bytes!(SerializableSecret, Secret, false, ()); -// Serializable Signature. -impl_bytes!(SerializableSignature, Signature, false, ()); - -/// Serializable shadow decryption result. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct SerializableEncryptedDocumentKeyShadow { - /// Decrypted secret point. It is partially decrypted if shadow decryption was requested. - pub decrypted_secret: SerializablePublic, - /// Shared common point. - pub common_point: SerializablePublic, - /// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public. - pub decrypt_shadows: Vec, -} - -/// Serializable requester identification data. -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum SerializableRequester { - /// Requested with server key id signature. - Signature(SerializableSignature), - /// Requested with public key. - Public(SerializablePublic), - /// Requested with verified address. - Address(SerializableAddress), -} - -impl From for Requester { - fn from(requester: SerializableRequester) -> Requester { - match requester { - SerializableRequester::Signature(signature) => Requester::Signature(signature.into()), - SerializableRequester::Public(public) => Requester::Public(public.into()), - SerializableRequester::Address(address) => Requester::Address(address.into()), - } - } -} - -impl From for SerializableRequester { - fn from(requester: Requester) -> SerializableRequester { - match requester { - Requester::Signature(signature) => SerializableRequester::Signature(signature.into()), - Requester::Public(public) => SerializableRequester::Public(public.into()), - Requester::Address(address) => SerializableRequester::Address(address.into()), - } - } -} - -#[cfg(test)] -mod tests { - use super::{SerializableBytes, SerializablePublic}; - use serde_json; - - #[test] - fn serialize_and_deserialize_bytes() { - let bytes = SerializableBytes(vec![1, 2, 3, 4]); - let bytes_serialized = serde_json::to_string(&bytes).unwrap(); - assert_eq!(&bytes_serialized, r#""0x01020304""#); - let bytes_deserialized: SerializableBytes = - serde_json::from_str(&bytes_serialized).unwrap(); - assert_eq!(bytes_deserialized, bytes); - } - - #[test] - fn serialize_and_deserialize_public() { - let public = SerializablePublic("cac6c205eb06c8308d65156ff6c862c62b000b8ead121a4455a8ddeff7248128d895692136f240d5d1614dc7cc4147b1bd584bd617e30560bb872064d09ea325".parse().unwrap()); - let public_serialized = serde_json::to_string(&public).unwrap(); - assert_eq!( - &public_serialized, - r#""0xcac6c205eb06c8308d65156ff6c862c62b000b8ead121a4455a8ddeff7248128d895692136f240d5d1614dc7cc4147b1bd584bd617e30560bb872064d09ea325""# - ); - let public_deserialized: SerializablePublic = - serde_json::from_str(&public_serialized).unwrap(); - assert_eq!(public_deserialized, public); - } -} diff --git a/secret-store/src/traits.rs b/secret-store/src/traits.rs deleted file mode 100644 index acec864744..0000000000 --- a/secret-store/src/traits.rs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{Address, H256}; -use ethkey::{Error as EthKeyError, KeyPair, Signature}; -use std::collections::BTreeSet; -use types::{ - EncryptedDocumentKey, EncryptedDocumentKeyShadow, EncryptedMessageSignature, Error, - MessageHash, NodeId, Public, RequestSignature, Requester, ServerKeyId, -}; - -/// Node key pair. -pub trait NodeKeyPair: Send + Sync { - /// Public portion of key. - fn public(&self) -> &Public; - /// Address of key owner. - fn address(&self) -> Address; - /// Sign data with node key. - fn sign(&self, data: &H256) -> Result; - /// Compute shared key to encrypt channel between two nodes. - fn compute_shared_key(&self, peer_public: &Public) -> Result; -} - -/// Server key (SK) generator. -pub trait ServerKeyGenerator { - /// Generate new SK. - /// `key_id` is the caller-provided identifier of generated SK. - /// `author` is the author of key entry. - /// `threshold + 1` is the minimal number of nodes, required to restore private key. - /// Result is a public portion of SK. - fn generate_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result; - /// Retrieve public portion of previously generated SK. - /// `key_id` is identifier of previously generated SK. - /// `author` is the same author, that has created the server key. - fn restore_key_public(&self, key_id: &ServerKeyId, author: &Requester) - -> Result; -} - -/// Document key (DK) server. -pub trait DocumentKeyServer: ServerKeyGenerator { - /// Store externally generated DK. - /// `key_id` is identifier of previously generated SK. - /// `author` is the same author, that has created the server key. - /// `common_point` is a result of `k * T` expression, where `T` is generation point and `k` is random scalar in EC field. - /// `encrypted_document_key` is a result of `M + k * y` expression, where `M` is unencrypted document key (point on EC), - /// `k` is the same scalar used in `common_point` calculation and `y` is previously generated public part of SK. - fn store_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - common_point: Public, - encrypted_document_key: Public, - ) -> Result<(), Error>; - /// Generate and store both SK and DK. This is a shortcut for consequent calls of `generate_key` and `store_document_key`. - /// The only difference is that DK is generated by DocumentKeyServer (which might be considered unsafe). - /// `key_id` is the caller-provided identifier of generated SK. - /// `author` is the author of server && document key entry. - /// `threshold + 1` is the minimal number of nodes, required to restore private key. - /// Result is a DK, encrypted with caller public key. - fn generate_document_key( - &self, - key_id: &ServerKeyId, - author: &Requester, - threshold: usize, - ) -> Result; - /// Restore previously stored DK. - /// DK is decrypted on the key server (which might be considered unsafe), and then encrypted with caller public key. - /// `key_id` is identifier of previously generated SK. - /// `requester` is the one who requests access to document key. Caller must be on ACL for this function to succeed. - /// Result is a DK, encrypted with caller public key. - fn restore_document_key( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result; - /// Restore previously stored DK. - /// To decrypt DK on client: - /// 1) use requestor secret key to decrypt secret coefficients from result.decrypt_shadows - /// 2) calculate decrypt_shadows_sum = sum of all secrets from (1) - /// 3) calculate decrypt_shadow_point: decrypt_shadows_sum * result.common_point - /// 4) calculate decrypted_secret: result.decrypted_secret + decrypt_shadow_point - /// Result is a DK shadow. - fn restore_document_key_shadow( - &self, - key_id: &ServerKeyId, - requester: &Requester, - ) -> Result; -} - -/// Message signer. -pub trait MessageSigner: ServerKeyGenerator { - /// Generate Schnorr signature for message with previously generated SK. - /// `key_id` is the caller-provided identifier of generated SK. - /// `requester` is the one who requests access to server key private. - /// `message` is the message to be signed. - /// Result is a signed message, encrypted with caller public key. - fn sign_message_schnorr( - &self, - key_id: &ServerKeyId, - requester: &Requester, - message: MessageHash, - ) -> Result; - /// Generate ECDSA signature for message with previously generated SK. - /// WARNING: only possible when SK was generated using t <= 2 * N. - /// `key_id` is the caller-provided identifier of generated SK. - /// `signature` is `key_id`, signed with caller public key. - /// `message` is the message to be signed. - /// Result is a signed message, encrypted with caller public key. - fn sign_message_ecdsa( - &self, - key_id: &ServerKeyId, - signature: &Requester, - message: MessageHash, - ) -> Result; -} - -/// Administrative sessions server. -pub trait AdminSessionsServer { - /// Change servers set so that nodes in new_servers_set became owners of shares for all keys. - /// And old nodes (i.e. cluster nodes except new_servers_set) have clear databases. - /// WARNING: newly generated keys will be distributed among all cluster nodes. So this session - /// must be followed with cluster nodes change (either via contract, or config files). - fn change_servers_set( - &self, - old_set_signature: RequestSignature, - new_set_signature: RequestSignature, - new_servers_set: BTreeSet, - ) -> Result<(), Error>; -} - -/// Key server. -pub trait KeyServer: AdminSessionsServer + DocumentKeyServer + MessageSigner + Send + Sync {} diff --git a/secret-store/src/trusted_client.rs b/secret-store/src/trusted_client.rs deleted file mode 100644 index 4aa2c6771d..0000000000 --- a/secret-store/src/trusted_client.rs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use bytes::Bytes; -use call_contract::RegistryInfo; -use common_types::transaction::{Action, SignedTransaction, Transaction, TypedTransaction}; -use ethcore::{ - client::{BlockChainClient, BlockId, ChainInfo, Client, Nonce}, - miner::{Miner, MinerService}, -}; -use ethereum_types::Address; -use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; -use std::sync::{Arc, Weak}; -use sync::SyncProvider; -use ContractAddress; -use Error; -use NodeKeyPair; - -#[derive(Clone)] -/// 'Trusted' client weak reference. -pub struct TrustedClient { - /// This key server node key pair. - self_key_pair: Arc, - /// Blockchain client. - client: Weak, - /// Sync provider. - sync: Weak, - /// Miner service. - miner: Weak, -} - -impl TrustedClient { - /// Create new trusted client. - pub fn new( - self_key_pair: Arc, - client: Arc, - sync: Arc, - miner: Arc, - ) -> Self { - TrustedClient { - self_key_pair: self_key_pair, - client: Arc::downgrade(&client), - sync: Arc::downgrade(&sync), - miner: Arc::downgrade(&miner), - } - } - - /// Get 'trusted' `Client` reference only if it is synchronized && trusted. - pub fn get(&self) -> Option> { - self.client - .upgrade() - .and_then(|client| self.sync.upgrade().map(|sync| (client, sync))) - .and_then(|(client, sync)| { - let is_synced = !sync.status().is_syncing(client.queue_info()); - let is_trusted = client.chain_info().security_level().is_full(); - match is_synced && is_trusted { - true => Some(client), - false => None, - } - }) - } - - /// Get untrusted `Client` reference. - pub fn get_untrusted(&self) -> Option> { - self.client.upgrade() - } - - /// Transact contract. - pub fn transact_contract(&self, contract: Address, tx_data: Bytes) -> Result<(), Error> { - let client = self - .client - .upgrade() - .ok_or_else(|| Error::Internal("cannot submit tx when client is offline".into()))?; - let miner = self - .miner - .upgrade() - .ok_or_else(|| Error::Internal("cannot submit tx when miner is offline".into()))?; - let engine = client.engine(); - let transaction = TypedTransaction::Legacy(Transaction { - nonce: client.latest_nonce(&self.self_key_pair.address()), - action: Action::Call(contract), - gas: miner.authoring_params().gas_range_target.0, - gas_price: miner.sensible_gas_price(), - value: Default::default(), - data: tx_data, - }); - let chain_id = engine.signing_chain_id(&client.latest_env_info()); - let signature = self - .self_key_pair - .sign(&transaction.signature_hash(chain_id))?; - let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; - miner - .import_own_transaction(&*client, signed.into()) - .map_err(|e| Error::Internal(format!("failed to import tx: {}", e))) - } - - /// Read contract address. If address source is registry, address only returned if current client state is - /// trusted. Address from registry is read from registry from block latest block with - /// REQUEST_CONFIRMATIONS_REQUIRED confirmations. - pub fn read_contract_address( - &self, - registry_name: String, - address: &ContractAddress, - ) -> Option
{ - match *address { - ContractAddress::Address(ref address) => Some(address.clone()), - ContractAddress::Registry => self.get().and_then(|client| { - get_confirmed_block_hash(&*client, REQUEST_CONFIRMATIONS_REQUIRED) - .and_then(|block| client.registry_address(registry_name, BlockId::Hash(block))) - }), - } - } -} diff --git a/secret-store/src/types/all.rs b/secret-store/src/types/all.rs deleted file mode 100644 index c3b5fe5d15..0000000000 --- a/secret-store/src/types/all.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::collections::BTreeMap; - -use bytes; -use ethereum_types; -use ethkey; - -/// Node id. -pub type NodeId = ethkey::Public; -/// Server key id. When key is used to encrypt document, it could be document contents hash. -pub type ServerKeyId = ethereum_types::H256; -/// Encrypted document key type. -pub type EncryptedDocumentKey = bytes::Bytes; -/// Message hash. -pub type MessageHash = ethereum_types::H256; -/// Message signature. -pub type EncryptedMessageSignature = bytes::Bytes; -/// Request signature type. -pub type RequestSignature = ethkey::Signature; -/// Public key type. -pub use ethkey::Public; - -/// Secret store configuration -#[derive(Debug, Clone)] -pub struct NodeAddress { - /// IP address. - pub address: String, - /// IP port. - pub port: u16, -} - -/// Contract address. -#[derive(Debug, Clone)] -pub enum ContractAddress { - /// Address is read from registry. - Registry, - /// Address is specified. - Address(ethkey::Address), -} - -/// Secret store configuration -#[derive(Debug)] -pub struct ServiceConfiguration { - /// HTTP listener address. If None, HTTP API is disabled. - pub listener_address: Option, - /// Service contract address. - pub service_contract_address: Option, - /// Server key generation service contract address. - pub service_contract_srv_gen_address: Option, - /// Server key retrieval service contract address. - pub service_contract_srv_retr_address: Option, - /// Document key store service contract address. - pub service_contract_doc_store_address: Option, - /// Document key shadow retrieval service contract address. - pub service_contract_doc_sretr_address: Option, - /// ACL check contract address. If None, everyone has access to all keys. Useful for tests only. - pub acl_check_contract_address: Option, - /// Cluster configuration. - pub cluster_config: ClusterConfiguration, -} - -/// Key server cluster configuration -#[derive(Debug)] -pub struct ClusterConfiguration { - /// This node address. - pub listener_address: NodeAddress, - /// All cluster nodes addresses. - pub nodes: BTreeMap, - /// Key Server Set contract address. If None, servers from 'nodes' map are used. - pub key_server_set_contract_address: Option, - /// Allow outbound connections to 'higher' nodes. - /// This is useful for tests, but slower a bit for production. - pub allow_connecting_to_higher_nodes: bool, - /// Administrator public key. - pub admin_public: Option, - /// Should key servers set change session should be started when servers set changes. - /// This will only work when servers set is configured using KeyServerSet contract. - pub auto_migrate_enabled: bool, -} - -/// Shadow decryption result. -#[derive(Clone, Debug, PartialEq)] -pub struct EncryptedDocumentKeyShadow { - /// Decrypted secret point. It is partially decrypted if shadow decryption was requested. - pub decrypted_secret: ethkey::Public, - /// Shared common point. - pub common_point: Option, - /// If shadow decryption was requested: shadow decryption coefficients, encrypted with requestor public. - pub decrypt_shadows: Option>>, -} - -/// Requester identification data. -#[derive(Debug, Clone)] -pub enum Requester { - /// Requested with server key id signature. - Signature(ethkey::Signature), - /// Requested with public key. - Public(ethkey::Public), - /// Requested with verified address. - Address(ethereum_types::Address), -} - -impl Default for Requester { - fn default() -> Self { - Requester::Signature(Default::default()) - } -} - -impl Requester { - pub fn public(&self, server_key_id: &ServerKeyId) -> Result { - match *self { - Requester::Signature(ref signature) => ethkey::recover(signature, server_key_id) - .map_err(|e| format!("bad signature: {}", e)), - Requester::Public(ref public) => Ok(public.clone()), - Requester::Address(_) => Err("cannot recover public from address".into()), - } - } - - pub fn address(&self, server_key_id: &ServerKeyId) -> Result { - self.public(server_key_id) - .map(|p| ethkey::public_to_address(&p)) - } -} - -impl From for Requester { - fn from(signature: ethkey::Signature) -> Requester { - Requester::Signature(signature) - } -} - -impl From for Requester { - fn from(public: ethereum_types::Public) -> Requester { - Requester::Public(public) - } -} - -impl From for Requester { - fn from(address: ethereum_types::Address) -> Requester { - Requester::Address(address) - } -} diff --git a/secret-store/src/types/error.rs b/secret-store/src/types/error.rs deleted file mode 100644 index 8c0eeef9fa..0000000000 --- a/secret-store/src/types/error.rs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::{fmt, io::Error as IoError, net}; - -use crypto; -use ethkey; - -/// Secret store error. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum Error { - /// Invalid node address has been passed. - InvalidNodeAddress, - /// Invalid node id has been passed. - InvalidNodeId, - /// Session with the given id already exists. - DuplicateSessionId, - /// No active session with given id. - NoActiveSessionWithId, - /// Invalid threshold value has been passed. - /// Threshold value must be in [0; n - 1], where n is a number of nodes participating in the encryption. - NotEnoughNodesForThreshold, - /// Current state of encryption/decryption session does not allow to proceed request. - /// Reschedule this request for later processing. - TooEarlyForRequest, - /// Current state of encryption/decryption session does not allow to proceed request. - /// This means that either there is some comm-failure or node is misbehaving/cheating. - InvalidStateForRequest, - /// Request cannot be sent/received from this node. - InvalidNodeForRequest, - /// Message or some data in the message was recognized as invalid. - /// This means that node is misbehaving/cheating. - InvalidMessage, - /// Message version is not supported. - InvalidMessageVersion, - /// Message is invalid because of replay-attack protection. - ReplayProtection, - /// Connection to node, required for this session is not established. - NodeDisconnected, - /// Server key with this ID is already generated. - ServerKeyAlreadyGenerated, - /// Server key with this ID is not yet generated. - ServerKeyIsNotFound, - /// Document key with this ID is already stored. - DocumentKeyAlreadyStored, - /// Document key with this ID is not yet stored. - DocumentKeyIsNotFound, - /// Consensus is temporary unreachable. Means that something is currently blocking us from either forming - /// consensus group (like disconnecting from too many nodes, which are AGREE to participate in consensus) - /// or from rejecting request (disconnecting from AccessDenied-nodes). - ConsensusTemporaryUnreachable, - /// Consensus is unreachable. It doesn't mean that it will ALWAYS remain unreachable, but right NOW we have - /// enough nodes confirmed that they do not want to be a part of consensus. Example: we're connected to 10 - /// of 100 nodes. Key threshold is 6 (i.e. 7 nodes are required for consensus). 4 nodes are responding with - /// reject => consensus is considered unreachable, even though another 90 nodes still can respond with OK. - ConsensusUnreachable, - /// Acl storage error. - AccessDenied, - /// Can't start session, because exclusive session is active. - ExclusiveSessionActive, - /// Can't start exclusive session, because there are other active sessions. - HasActiveSessions, - /// Insufficient requester data. - InsufficientRequesterData(String), - /// Cryptographic error. - EthKey(String), - /// I/O error has occurred. - Io(String), - /// Deserialization error has occurred. - Serde(String), - /// Hyper error. - Hyper(String), - /// Database-related error. - Database(String), - /// Internal error. - Internal(String), -} - -impl Error { - /// Is this a fatal error? Non-fatal means that it is possible to replay the same request with a non-zero - /// chance to success. I.e. the error is not about request itself (or current environment factors that - /// are affecting request processing), but about current SecretStore state. - pub fn is_non_fatal(&self) -> bool { - match *self { - // non-fatal errors: - - // session start errors => restarting session is a solution - Error::DuplicateSessionId | Error::NoActiveSessionWithId | - // unexpected message errors => restarting session/excluding node is a solution - Error::TooEarlyForRequest | Error::InvalidStateForRequest | Error::InvalidNodeForRequest | - // invalid message errors => restarting/updating/excluding node is a solution - Error::InvalidMessage | Error::InvalidMessageVersion | Error::ReplayProtection | - // connectivity problems => waiting for reconnect && restarting session is a solution - Error::NodeDisconnected | - // temporary (?) consensus problems, related to other non-fatal errors => restarting is probably (!) a solution - Error::ConsensusTemporaryUnreachable | - // exclusive session errors => waiting && restarting is a solution - Error::ExclusiveSessionActive | Error::HasActiveSessions => true, - - // fatal errors: - - // config-related errors - Error::InvalidNodeAddress | Error::InvalidNodeId | - // wrong session input params errors - Error::NotEnoughNodesForThreshold | Error::ServerKeyAlreadyGenerated | Error::ServerKeyIsNotFound | - Error::DocumentKeyAlreadyStored | Error::DocumentKeyIsNotFound | Error::InsufficientRequesterData(_) | - // access denied/consensus error - Error::AccessDenied | Error::ConsensusUnreachable | - // indeterminate internal errors, which could be either fatal (db failure, invalid request), or not (network error), - // but we still consider these errors as fatal - Error::EthKey(_) | Error::Serde(_) | Error::Hyper(_) | Error::Database(_) | Error::Internal(_) | Error::Io(_) => false, - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Error::InvalidNodeAddress => write!(f, "invalid node address has been passed"), - Error::InvalidNodeId => write!(f, "invalid node id has been passed"), - Error::DuplicateSessionId => { - write!(f, "session with the same id is already registered") - } - Error::NoActiveSessionWithId => write!(f, "no active session with given id"), - Error::NotEnoughNodesForThreshold => write!(f, "not enough nodes for passed threshold"), - Error::TooEarlyForRequest => { - write!(f, "session is not yet ready to process this request") - } - Error::InvalidStateForRequest => { - write!(f, "session is in invalid state for processing this request") - } - Error::InvalidNodeForRequest => write!(f, "invalid node for this request"), - Error::InvalidMessage => write!(f, "invalid message is received"), - Error::InvalidMessageVersion => write!(f, "unsupported message is received"), - Error::ReplayProtection => write!(f, "replay message is received"), - Error::NodeDisconnected => write!( - f, - "node required for this operation is currently disconnected" - ), - Error::ServerKeyAlreadyGenerated => { - write!(f, "Server key with this ID is already generated") - } - Error::ServerKeyIsNotFound => write!(f, "Server key with this ID is not found"), - Error::DocumentKeyAlreadyStored => { - write!(f, "Document key with this ID is already stored") - } - Error::DocumentKeyIsNotFound => write!(f, "Document key with this ID is not found"), - Error::ConsensusUnreachable => write!(f, "Consensus unreachable"), - Error::ConsensusTemporaryUnreachable => write!(f, "Consensus temporary unreachable"), - Error::AccessDenied => write!(f, "Access denied"), - Error::ExclusiveSessionActive => write!(f, "Exclusive session active"), - Error::HasActiveSessions => write!(f, "Unable to start exclusive session"), - Error::InsufficientRequesterData(ref e) => { - write!(f, "Insufficient requester data: {}", e) - } - Error::EthKey(ref e) => write!(f, "cryptographic error {}", e), - Error::Hyper(ref msg) => write!(f, "Hyper error: {}", msg), - Error::Serde(ref msg) => write!(f, "Serialization error: {}", msg), - Error::Database(ref msg) => write!(f, "Database error: {}", msg), - Error::Internal(ref msg) => write!(f, "Internal error: {}", msg), - Error::Io(ref msg) => write!(f, "IO error: {}", msg), - } - } -} - -impl From for Error { - fn from(err: ethkey::Error) -> Self { - Error::EthKey(err.into()) - } -} - -impl From for Error { - fn from(err: ethkey::crypto::Error) -> Self { - Error::EthKey(err.to_string()) - } -} - -impl From for Error { - fn from(err: crypto::Error) -> Self { - Error::EthKey(err.to_string()) - } -} - -impl From for Error { - fn from(err: IoError) -> Self { - Error::Io(err.to_string()) - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } -} - -impl From for Error { - fn from(err: net::AddrParseError) -> Error { - Error::Internal(err.to_string()) - } -} diff --git a/secret-store/src/types/mod.rs b/secret-store/src/types/mod.rs deleted file mode 100644 index d78d42ad20..0000000000 --- a/secret-store/src/types/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -//! Types used in the public api - -mod all; -mod error; - -pub use self::{all::*, error::*}; diff --git a/secret_store/src/key_server_cluster/cluster_connections.rs b/secret_store/src/key_server_cluster/cluster_connections.rs deleted file mode 100644 index 1d6f577979..0000000000 --- a/secret_store/src/key_server_cluster/cluster_connections.rs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::collections::BTreeSet; -use std::sync::Arc; -use key_server_cluster::{Error, NodeId}; -use key_server_cluster::message::Message; - -/// Connection to the single node. Provides basic information about connected node and -/// allows sending messages to this node. -pub trait Connection: Send + Sync { - /// Is this inbound connection? This only matters when both nodes are simultaneously establishing - /// two connections to each other. The agreement is that the inbound connection from the node with - /// lower NodeId is used and the other connection is closed. - fn is_inbound(&self) -> bool; - /// Returns id of the connected node. - fn node_id(&self) -> &NodeId; - /// Returns 'address' of the node to use in traces. - fn node_address(&self) -> String; - /// Send message to the connected node. - fn send_message(&self, message: Message); -} - -/// Connections manager. Responsible for keeping us connected to all required nodes. -pub trait ConnectionManager: 'static + Send + Sync { - /// Returns shared reference to connections provider. - fn provider(&self) -> Arc; - /// Try to reach all disconnected nodes immediately. This method is exposed mostly for - /// tests, where all 'nodes' are starting listening for incoming connections first and - /// only after this, they're actually start connecting to each other. - fn connect(&self); -} - -/// Connections provider. Holds all active connections and the set of nodes that we need to -/// connect to. At any moment connection could be lost and the set of connected/disconnected -/// nodes could change (at behalf of the connection manager). -/// Clone operation should be cheap (Arc). -pub trait ConnectionProvider: Send + Sync { - /// Returns the set of currently connected nodes. Error is returned when our node is - /// not a part of the cluster ('isolated' node). - fn connected_nodes(&self) -> Result, Error>; - /// Returns the set of currently disconnected nodes. - fn disconnected_nodes(&self) -> BTreeSet; - /// Returns the reference to the active node connection or None if the node is not connected. - fn connection(&self, node: &NodeId) -> Option>; -} - -#[cfg(test)] -pub mod tests { - use std::collections::{BTreeSet, VecDeque}; - use std::sync::Arc; - use std::sync::atomic::{AtomicBool, Ordering}; - use parking_lot::Mutex; - use key_server_cluster::{Error, NodeId}; - use key_server_cluster::message::Message; - use super::{ConnectionManager, Connection, ConnectionProvider}; - - /// Shared messages queue. - pub type MessagesQueue = Arc>>; - - /// Single node connections. - pub struct TestConnections { - node: NodeId, - is_isolated: AtomicBool, - connected_nodes: Mutex>, - disconnected_nodes: Mutex>, - messages: MessagesQueue, - } - - /// Single connection. - pub struct TestConnection { - from: NodeId, - to: NodeId, - messages: MessagesQueue, - } - - impl TestConnections { - pub fn isolate(&self) { - let connected_nodes = ::std::mem::replace(&mut *self.connected_nodes.lock(), Default::default()); - self.is_isolated.store(true, Ordering::Relaxed); - self.disconnected_nodes.lock().extend(connected_nodes) - } - - pub fn disconnect(&self, node: NodeId) { - self.connected_nodes.lock().remove(&node); - self.disconnected_nodes.lock().insert(node); - } - - pub fn exclude(&self, node: NodeId) { - self.connected_nodes.lock().remove(&node); - self.disconnected_nodes.lock().remove(&node); - } - - pub fn include(&self, node: NodeId) { - self.connected_nodes.lock().insert(node); - } - } - - impl ConnectionManager for Arc { - fn provider(&self) -> Arc { - self.clone() - } - - fn connect(&self) {} - } - - impl ConnectionProvider for TestConnections { - fn connected_nodes(&self) -> Result, Error> { - match self.is_isolated.load(Ordering::Relaxed) { - false => Ok(self.connected_nodes.lock().clone()), - true => Err(Error::NodeDisconnected), - } - } - - fn disconnected_nodes(&self) -> BTreeSet { - self.disconnected_nodes.lock().clone() - } - - fn connection(&self, node: &NodeId) -> Option> { - match self.connected_nodes.lock().contains(node) { - true => Some(Arc::new(TestConnection { - from: self.node, - to: *node, - messages: self.messages.clone(), - })), - false => None, - } - } - } - - impl Connection for TestConnection { - fn is_inbound(&self) -> bool { - false - } - - fn node_id(&self) -> &NodeId { - &self.to - } - - fn node_address(&self) -> String { - format!("{}", self.to) - } - - fn send_message(&self, message: Message) { - self.messages.lock().push_back((self.from, self.to, message)) - } - } - - pub fn new_test_connections( - messages: MessagesQueue, - node: NodeId, - mut nodes: BTreeSet - ) -> Arc { - let is_isolated = !nodes.remove(&node); - Arc::new(TestConnections { - node, - is_isolated: AtomicBool::new(is_isolated), - connected_nodes: Mutex::new(nodes), - disconnected_nodes: Default::default(), - messages, - }) - } -} diff --git a/secret_store/src/key_server_cluster/cluster_connections_net.rs b/secret_store/src/key_server_cluster/cluster_connections_net.rs deleted file mode 100644 index c78b9bbfd5..0000000000 --- a/secret_store/src/key_server_cluster/cluster_connections_net.rs +++ /dev/null @@ -1,539 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::collections::{BTreeMap, BTreeSet}; -use std::collections::btree_map::Entry; -use std::io; -use std::net::{SocketAddr, IpAddr}; -use std::sync::Arc; -use std::time::{Duration, Instant}; -use futures::{future, Future, Stream}; -use parking_lot::{Mutex, RwLock}; -use tokio::net::{TcpListener, TcpStream}; -use tokio::timer::{Interval, timeout::Error as TimeoutError}; -use tokio_io::IoFuture; -use ethkey::KeyPair; -use parity_runtime::Executor; -use key_server_cluster::{Error, NodeId, ClusterConfiguration, NodeKeyPair}; -use key_server_cluster::cluster_connections::{ConnectionProvider, Connection, ConnectionManager}; -use key_server_cluster::connection_trigger::{Maintain, ConnectionTrigger}; -use key_server_cluster::cluster_message_processor::MessageProcessor; -use key_server_cluster::io::{DeadlineStatus, ReadMessage, SharedTcpStream, - read_encrypted_message, WriteMessage, write_encrypted_message}; -use key_server_cluster::message::{self, ClusterMessage, Message}; -use key_server_cluster::net::{accept_connection as io_accept_connection, - connect as io_connect, Connection as IoConnection}; - -/// Empty future. -pub type BoxedEmptyFuture = Box + Send>; - -/// Maintain interval (seconds). Every MAINTAIN_INTERVAL seconds node: -/// 1) checks if connected nodes are responding to KeepAlive messages -/// 2) tries to connect to disconnected nodes -/// 3) checks if enc/dec sessions are time-outed -const MAINTAIN_INTERVAL: u64 = 10; - -/// When no messages have been received from node within KEEP_ALIVE_SEND_INTERVAL seconds, -/// we must send KeepAlive message to the node to check if it still responds to messages. -const KEEP_ALIVE_SEND_INTERVAL: Duration = Duration::from_secs(30); -/// When no messages have been received from node within KEEP_ALIVE_DISCONNECT_INTERVAL seconds, -/// we must treat this node as non-responding && disconnect from it. -const KEEP_ALIVE_DISCONNECT_INTERVAL: Duration = Duration::from_secs(60); - -/// Network connection manager configuration. -pub struct NetConnectionsManagerConfig { - /// Allow connecting to 'higher' nodes. - pub allow_connecting_to_higher_nodes: bool, - /// Interface to listen to. - pub listen_address: (String, u16), - /// True if we should autostart key servers set change session when servers set changes? - /// This will only work when servers set is configured using KeyServerSet contract. - pub auto_migrate_enabled: bool, -} - -/// Network connections manager. -pub struct NetConnectionsManager { - /// Address we're listening for incoming connections. - listen_address: SocketAddr, - /// Shared cluster connections data reference. - data: Arc, -} - -/// Network connections data. Shared among NetConnectionsManager and spawned futures. -struct NetConnectionsData { - /// Allow connecting to 'higher' nodes. - allow_connecting_to_higher_nodes: bool, - /// Reference to tokio task executor. - executor: Executor, - /// Key pair of this node. - self_key_pair: Arc, - /// Network messages processor. - message_processor: Arc, - /// Connections trigger. - trigger: Mutex>, - /// Mutable connection data. - container: Arc>, -} - -/// Network connections container. This is the only mutable data of NetConnectionsManager. -/// The set of nodes is mutated by the connection trigger and the connections set is also -/// mutated by spawned futures. -pub struct NetConnectionsContainer { - /// Is this node isolated from cluster? - pub is_isolated: bool, - /// Current key servers set. - pub nodes: BTreeMap, - /// Active connections to key servers. - pub connections: BTreeMap>, -} - -/// Network connection to single key server node. -pub struct NetConnection { - executor: Executor, - /// Id of the peer node. - node_id: NodeId, - /// Address of the peer node. - node_address: SocketAddr, - /// Is this inbound (true) or outbound (false) connection? - is_inbound: bool, - /// Key pair that is used to encrypt connection' messages. - key: KeyPair, - /// Last message time. - last_message_time: RwLock, - /// Underlying TCP stream. - stream: SharedTcpStream, -} - -impl NetConnectionsManager { - /// Create new network connections manager. - pub fn new( - executor: Executor, - message_processor: Arc, - trigger: Box, - container: Arc>, - config: &ClusterConfiguration, - net_config: NetConnectionsManagerConfig, - ) -> Result { - let listen_address = make_socket_address( - &net_config.listen_address.0, - net_config.listen_address.1)?; - - Ok(NetConnectionsManager { - listen_address, - data: Arc::new(NetConnectionsData { - allow_connecting_to_higher_nodes: net_config.allow_connecting_to_higher_nodes, - executor, - message_processor, - self_key_pair: config.self_key_pair.clone(), - trigger: Mutex::new(trigger), - container, - }), - }) - } - - /// Start listening for connections and schedule connections maintenance. - pub fn start(&self) -> Result<(), Error> { - net_listen(&self.listen_address, self.data.clone())?; - net_schedule_maintain(self.data.clone()); - Ok(()) - } -} - -impl ConnectionManager for NetConnectionsManager { - fn provider(&self) -> Arc { - self.data.container.clone() - } - - fn connect(&self) { - net_connect_disconnected(self.data.clone()); - } -} - -impl ConnectionProvider for RwLock { - fn connected_nodes(&self) -> Result, Error> { - let connections = self.read(); - if connections.is_isolated { - return Err(Error::NodeDisconnected); - } - - Ok(connections.connections.keys().cloned().collect()) - } - - fn disconnected_nodes(&self) -> BTreeSet { - let connections = self.read(); - connections.nodes.keys() - .filter(|node_id| !connections.connections.contains_key(node_id)) - .cloned() - .collect() - } - - fn connection(&self, node: &NodeId) -> Option> { - match self.read().connections.get(node).cloned() { - Some(connection) => Some(connection), - None => None, - } - } -} - -impl NetConnection { - /// Create new connection. - pub fn new(executor: Executor, is_inbound: bool, connection: IoConnection) -> NetConnection { - NetConnection { - executor, - node_id: connection.node_id, - node_address: connection.address, - is_inbound: is_inbound, - stream: connection.stream, - key: connection.key, - last_message_time: RwLock::new(Instant::now()), - } - } - - /// Get last message time. - pub fn last_message_time(&self) -> Instant { - *self.last_message_time.read() - } - - /// Update last message time - pub fn set_last_message_time(&self, last_message_time: Instant) { - *self.last_message_time.write() = last_message_time - } - - /// Returns future that sends encrypted message over this connection. - pub fn send_message_future(&self, message: Message) -> WriteMessage { - write_encrypted_message(self.stream.clone(), &self.key, message) - } - - /// Returns future that reads encrypted message from this connection. - pub fn read_message_future(&self) -> ReadMessage { - read_encrypted_message(self.stream.clone(), self.key.clone()) - } -} - -impl Connection for NetConnection { - fn is_inbound(&self) -> bool { - self.is_inbound - } - - fn node_id(&self) -> &NodeId { - &self.node_id - } - - fn node_address(&self) -> String { - format!("{}", self.node_address) - } - - fn send_message(&self, message: Message) { - execute(&self.executor, self.send_message_future(message).then(|_| Ok(()))); - } -} - -impl NetConnectionsData { - /// Executes closure for each active connection. - pub fn active_connections(&self) -> Vec> { - self.container.read().connections.values().cloned().collect() - } - - /// Executes closure for each disconnected node. - pub fn disconnected_nodes(&self) -> Vec<(NodeId, SocketAddr)> { - let container = self.container.read(); - container.nodes.iter() - .filter(|(node_id, _)| !container.connections.contains_key(node_id)) - .map(|(node_id, addr)| (*node_id, *addr)) - .collect() - } - - /// Try to insert new connection. Returns true if connection has been inserted. - /// Returns false (and ignores connections) if: - /// - we do not expect connection from this node - /// - we are already connected to the node and existing connection 'supersede' - /// new connection by agreement - pub fn insert(&self, connection: Arc) -> bool { - let node = *connection.node_id(); - let mut container = self.container.write(); - if !container.nodes.contains_key(&node) { - trace!(target: "secretstore_net", "{}: ignoring unknown connection from {} at {}", - self.self_key_pair.public(), node, connection.node_address()); - return false; - } - - if container.connections.contains_key(&node) { - // we have already connected to the same node - // the agreement is that node with lower id must establish connection to node with higher id - if (*self.self_key_pair.public() < node && connection.is_inbound()) - || (*self.self_key_pair.public() > node && !connection.is_inbound()) { - return false; - } - } - - trace!(target: "secretstore_net", - "{}: inserting connection to {} at {}. Connected to {} of {} nodes", - self.self_key_pair.public(), node, connection.node_address(), - container.connections.len() + 1, container.nodes.len()); - container.connections.insert(node, connection); - - true - } - - /// Tries to remove connection. Returns true if connection has been removed. - /// Returns false if we do not know this connection. - pub fn remove(&self, connection: &NetConnection) -> bool { - let node_id = *connection.node_id(); - let is_inbound = connection.is_inbound(); - let mut container = self.container.write(); - if let Entry::Occupied(entry) = container.connections.entry(node_id) { - if entry.get().is_inbound() != is_inbound { - return false; - } - - trace!(target: "secretstore_net", "{}: removing connection to {} at {}", - self.self_key_pair.public(), node_id, entry.get().node_address()); - entry.remove_entry(); - - true - } else { - false - } - } -} - -/// Listen incoming connections. -fn net_listen( - listen_address: &SocketAddr, - data: Arc, -) -> Result<(), Error> { - execute(&data.executor, net_listen_future(listen_address, data.clone())?); - Ok(()) -} - -/// Listen incoming connections future. -fn net_listen_future( - listen_address: &SocketAddr, - data: Arc, -) -> Result { - Ok(Box::new(TcpListener::bind(listen_address)? - .incoming() - .and_then(move |stream| { - net_accept_connection(data.clone(), stream); - Ok(()) - }) - .for_each(|_| Ok(())) - .then(|_| future::ok(())))) -} - -/// Accept incoming connection. -fn net_accept_connection( - data: Arc, - stream: TcpStream, -) { - execute(&data.executor, net_accept_connection_future(data.clone(), stream)); -} - -/// Accept incoming connection future. -fn net_accept_connection_future(data: Arc, stream: TcpStream) -> BoxedEmptyFuture { - Box::new(io_accept_connection(stream, data.self_key_pair.clone()) - .then(move |result| net_process_connection_result(data, None, result)) - .then(|_| future::ok(()))) -} - -/// Connect to remote node. -fn net_connect( - data: Arc, - remote: SocketAddr, -) { - execute(&data.executor, net_connect_future(data.clone(), remote)); -} - -/// Connect to remote node future. -fn net_connect_future( - data: Arc, - remote: SocketAddr, -) -> BoxedEmptyFuture { - let disconnected_nodes = data.container.disconnected_nodes(); - Box::new(io_connect(&remote, data.self_key_pair.clone(), disconnected_nodes) - .then(move |result| net_process_connection_result(data, Some(remote), result)) - .then(|_| future::ok(()))) -} - -/// Process network connection result. -fn net_process_connection_result( - data: Arc, - outbound_addr: Option, - result: Result>, TimeoutError>, -) -> IoFuture> { - match result { - Ok(DeadlineStatus::Meet(Ok(connection))) => { - let connection = Arc::new(NetConnection::new(data.executor.clone(), outbound_addr.is_none(), connection)); - if data.insert(connection.clone()) { - let maintain_action = data.trigger.lock().on_connection_established(connection.node_id()); - maintain_connection_trigger(data.clone(), maintain_action); - - return net_process_connection_messages(data, connection); - } - }, - Ok(DeadlineStatus::Meet(Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - }, - Ok(DeadlineStatus::Timeout) => { - warn!(target: "secretstore_net", "{}: timeout when establishing {} connection{}", - data.self_key_pair.public(), if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - }, - Err(err) => { - warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", - data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, - outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); - }, - } - - Box::new(future::ok(Ok(()))) -} - -/// Process connection messages. -fn net_process_connection_messages( - data: Arc, - connection: Arc, -) -> IoFuture> { - Box::new(connection - .read_message_future() - .then(move |result| - match result { - Ok((_, Ok(message))) => { - connection.set_last_message_time(Instant::now()); - data.message_processor.process_connection_message(connection.clone(), message); - // continue serving connection - let process_messages_future = net_process_connection_messages( - data.clone(), connection).then(|_| Ok(())); - execute(&data.executor, process_messages_future); - Box::new(future::ok(Ok(()))) - }, - Ok((_, Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", - data.self_key_pair.public(), err, connection.node_id()); - // continue serving connection - let process_messages_future = net_process_connection_messages( - data.clone(), connection).then(|_| Ok(())); - execute(&data.executor, process_messages_future); - Box::new(future::ok(Err(err))) - }, - Err(err) => { - let node_id = *connection.node_id(); - warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", - data.self_key_pair.public(), err, node_id); - // close connection - if data.remove(&*connection) { - let maintain_action = data.trigger.lock().on_connection_closed(&node_id); - maintain_connection_trigger(data, maintain_action); - } - Box::new(future::err(err)) - }, - } - )) -} - -/// Schedule connections. maintain. -fn net_schedule_maintain(data: Arc) { - let closure_data = data.clone(); - execute(&data.executor, Interval::new_interval(Duration::new(MAINTAIN_INTERVAL, 0)) - .and_then(move |_| Ok(net_maintain(closure_data.clone()))) - .for_each(|_| Ok(())) - .then(|_| future::ok(()))); -} - -/// Maintain network connections. -fn net_maintain(data: Arc) { - trace!(target: "secretstore_net", "{}: executing maintain procedures", data.self_key_pair.public()); - - update_nodes_set(data.clone()); - data.message_processor.maintain_sessions(); - net_keep_alive(data.clone()); - net_connect_disconnected(data); -} - -/// Send keep alive messages to remote nodes. -fn net_keep_alive(data: Arc) { - let now = Instant::now(); - let active_connections = data.active_connections(); - for connection in active_connections { - let last_message_diff = now - connection.last_message_time(); - if last_message_diff > KEEP_ALIVE_DISCONNECT_INTERVAL { - warn!(target: "secretstore_net", "{}: keep alive timeout for node {}", - data.self_key_pair.public(), connection.node_id()); - - let node_id = *connection.node_id(); - if data.remove(&*connection) { - let maintain_action = data.trigger.lock().on_connection_closed(&node_id); - maintain_connection_trigger(data.clone(), maintain_action); - } - data.message_processor.process_disconnect(&node_id); - } - else if last_message_diff > KEEP_ALIVE_SEND_INTERVAL { - connection.send_message(Message::Cluster(ClusterMessage::KeepAlive(message::KeepAlive {}))); - } - } -} - -/// Connect disconnected nodes. -fn net_connect_disconnected(data: Arc) { - let disconnected_nodes = data.disconnected_nodes(); - for (node_id, address) in disconnected_nodes { - if data.allow_connecting_to_higher_nodes || *data.self_key_pair.public() < node_id { - net_connect(data.clone(), address); - } - } -} - -/// Schedule future execution. -fn execute + Send + 'static>(executor: &Executor, f: F) { - if let Err(err) = future::Executor::execute(executor, Box::new(f)) { - error!("Secret store runtime unable to spawn task. Runtime is shutting down. ({:?})", err); - } -} - -/// Try to update active nodes set from connection trigger. -fn update_nodes_set(data: Arc) { - let maintain_action = data.trigger.lock().on_maintain(); - maintain_connection_trigger(data, maintain_action); -} - -/// Execute maintain procedures of connections trigger. -fn maintain_connection_trigger(data: Arc, maintain_action: Option) { - if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Session) { - let session_params = data.trigger.lock().maintain_session(); - if let Some(session_params) = session_params { - let session = data.message_processor.start_servers_set_change_session(session_params); - match session { - Ok(_) => trace!(target: "secretstore_net", "{}: started auto-migrate session", - data.self_key_pair.public()), - Err(err) => trace!(target: "secretstore_net", "{}: failed to start auto-migrate session with: {}", - data.self_key_pair.public(), err), - } - } - } - if maintain_action == Some(Maintain::SessionAndConnections) || maintain_action == Some(Maintain::Connections) { - let mut trigger = data.trigger.lock(); - let mut data = data.container.write(); - trigger.maintain_connections(&mut *data); - } -} - -/// Compose SocketAddr from configuration' address and port. -fn make_socket_address(address: &str, port: u16) -> Result { - let ip_address: IpAddr = address.parse().map_err(|_| Error::InvalidNodeAddress)?; - Ok(SocketAddr::new(ip_address, port)) -} diff --git a/secret_store/src/key_server_cluster/cluster_message_processor.rs b/secret_store/src/key_server_cluster/cluster_message_processor.rs deleted file mode 100644 index b06978f843..0000000000 --- a/secret_store/src/key_server_cluster/cluster_message_processor.rs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::sync::Arc; -use key_server_cluster::{Error, NodeId, NodeKeyPair}; -use key_server_cluster::cluster::{ServersSetChangeParams, new_servers_set_change_session}; -use key_server_cluster::cluster_sessions::{AdminSession}; -use key_server_cluster::cluster_connections::{ConnectionProvider, Connection}; -use key_server_cluster::cluster_sessions::{ClusterSession, ClusterSessions, ClusterSessionsContainer, - create_cluster_view}; -use key_server_cluster::cluster_sessions_creator::{ClusterSessionCreator, IntoSessionId}; -use key_server_cluster::message::{self, Message, ClusterMessage}; -use key_server_cluster::key_version_negotiation_session::{SessionImpl as KeyVersionNegotiationSession, - IsolatedSessionTransport as KeyVersionNegotiationSessionTransport, ContinueAction}; -use key_server_cluster::connection_trigger::ServersSetChangeSessionCreatorConnector; - -/// Something that is able to process signals/messages from other nodes. -pub trait MessageProcessor: Send + Sync { - /// Process disconnect from the remote node. - fn process_disconnect(&self, node: &NodeId); - /// Process single message from the connection. - fn process_connection_message(&self, connection: Arc, message: Message); - - /// Start servers set change session. This is typically used by ConnectionManager when - /// it detects that auto-migration session needs to be started. - fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error>; - /// Try to continue session after key version negotiation session is completed. - fn try_continue_session( - &self, - session: Option>> - ); - /// Maintain active sessions. Typically called by the ConnectionManager at some intervals. - /// Should cancel stalled sessions and send keep-alive messages for sessions that support it. - fn maintain_sessions(&self); -} - -/// Bridge between ConnectionManager and ClusterSessions. -pub struct SessionsMessageProcessor { - self_key_pair: Arc, - servers_set_change_creator_connector: Arc, - sessions: Arc, - connections: Arc, -} - -impl SessionsMessageProcessor { - /// Create new instance of SessionsMessageProcessor. - pub fn new( - self_key_pair: Arc, - servers_set_change_creator_connector: Arc, - sessions: Arc, - connections: Arc, - ) -> Self { - SessionsMessageProcessor { - self_key_pair, - servers_set_change_creator_connector, - sessions, - connections, - } - } - - /// Process single session message from connection. - fn process_message, D>( - &self, - sessions: &ClusterSessionsContainer, - connection: Arc, - mut message: Message, - ) -> Option> - where - Message: IntoSessionId - { - // get or create new session, if required - let mut sender = *connection.node_id(); - let session = self.prepare_session(sessions, &sender, &message); - // send error if session is not found, or failed to create - let session = match session { - Ok(session) => session, - Err(error) => { - // this is new session => it is not yet in container - warn!(target: "secretstore_net", - "{}: {} session read error '{}' when requested for session from node {}", - self.self_key_pair.public(), S::type_name(), error, sender); - if !message.is_error_message() { - let qed = "session_id only fails for cluster messages; - only session messages are passed to process_message; - qed"; - let session_id = message.into_session_id().expect(qed); - let session_nonce = message.session_nonce().expect(qed); - - connection.send_message(SC::make_error_message(session_id, session_nonce, error)); - } - return None; - }, - }; - - let session_id = session.id(); - let mut is_queued_message = false; - loop { - let message_result = session.on_message(&sender, &message); - match message_result { - Ok(_) => { - // if session is completed => stop - if session.is_finished() { - info!(target: "secretstore_net", - "{}: {} session completed", self.self_key_pair.public(), S::type_name()); - sessions.remove(&session_id); - return Some(session); - } - - // try to dequeue message - match sessions.dequeue_message(&session_id) { - Some((msg_sender, msg)) => { - is_queued_message = true; - sender = msg_sender; - message = msg; - }, - None => return Some(session), - } - }, - Err(Error::TooEarlyForRequest) => { - sessions.enqueue_message(&session_id, sender, message, is_queued_message); - return Some(session); - }, - Err(err) => { - warn!( - target: "secretstore_net", - "{}: {} session error '{}' when processing message {} from node {}", - self.self_key_pair.public(), - S::type_name(), - err, - message, - sender); - session.on_session_error(self.self_key_pair.public(), err); - sessions.remove(&session_id); - return Some(session); - }, - } - } - } - - /// Get or insert new session. - fn prepare_session, D>( - &self, - sessions: &ClusterSessionsContainer, - sender: &NodeId, - message: &Message - ) -> Result, Error> - where - Message: IntoSessionId - { - fn requires_all_connections(message: &Message) -> bool { - match *message { - Message::Generation(_) => true, - Message::ShareAdd(_) => true, - Message::ServersSetChange(_) => true, - _ => false, - } - } - - // get or create new session, if required - let session_id = message.into_session_id() - .expect("into_session_id fails for cluster messages only; - only session messages are passed to prepare_session; - qed"); - let is_initialization_message = message.is_initialization_message(); - let is_delegation_message = message.is_delegation_message(); - match is_initialization_message || is_delegation_message { - false => sessions.get(&session_id, true).ok_or(Error::NoActiveSessionWithId), - true => { - let creation_data = SC::creation_data_from_message(&message)?; - let master = if is_initialization_message { - *sender - } else { - *self.self_key_pair.public() - }; - let cluster = create_cluster_view( - self.self_key_pair.clone(), - self.connections.clone(), - requires_all_connections(&message))?; - - let nonce = Some(message.session_nonce().ok_or(Error::InvalidMessage)?); - let exclusive = message.is_exclusive_session_message(); - sessions.insert(cluster, master, session_id, nonce, exclusive, creation_data) - }, - } - } - - /// Process single cluster message from the connection. - fn process_cluster_message(&self, connection: Arc, message: ClusterMessage) { - match message { - ClusterMessage::KeepAlive(_) => { - let msg = Message::Cluster(ClusterMessage::KeepAliveResponse(message::KeepAliveResponse { - session_id: None, - })); - connection.send_message(msg) - }, - ClusterMessage::KeepAliveResponse(msg) => if let Some(session_id) = msg.session_id { - self.sessions.on_session_keep_alive(connection.node_id(), session_id.into()); - }, - _ => warn!(target: "secretstore_net", "{}: received unexpected message {} from node {} at {}", - self.self_key_pair.public(), message, connection.node_id(), connection.node_address()), - } - } -} - -impl MessageProcessor for SessionsMessageProcessor { - fn process_disconnect(&self, node: &NodeId) { - self.sessions.on_connection_timeout(node); - } - - fn process_connection_message(&self, connection: Arc, message: Message) { - trace!(target: "secretstore_net", "{}: received message {} from {}", - self.self_key_pair.public(), message, connection.node_id()); - - // error is ignored as we only process errors on session level - match message { - Message::Generation(message) => self - .process_message(&self.sessions.generation_sessions, connection, Message::Generation(message)) - .map(|_| ()).unwrap_or_default(), - Message::Encryption(message) => self - .process_message(&self.sessions.encryption_sessions, connection, Message::Encryption(message)) - .map(|_| ()).unwrap_or_default(), - Message::Decryption(message) => self - .process_message(&self.sessions.decryption_sessions, connection, Message::Decryption(message)) - .map(|_| ()).unwrap_or_default(), - Message::SchnorrSigning(message) => self - .process_message(&self.sessions.schnorr_signing_sessions, connection, Message::SchnorrSigning(message)) - .map(|_| ()).unwrap_or_default(), - Message::EcdsaSigning(message) => self - .process_message(&self.sessions.ecdsa_signing_sessions, connection, Message::EcdsaSigning(message)) - .map(|_| ()).unwrap_or_default(), - Message::ServersSetChange(message) => { - let message = Message::ServersSetChange(message); - let is_initialization_message = message.is_initialization_message(); - let session = self.process_message(&self.sessions.admin_sessions, connection, message); - if is_initialization_message { - if let Some(session) = session { - self.servers_set_change_creator_connector - .set_key_servers_set_change_session(session.clone()); - } - } - }, - Message::KeyVersionNegotiation(message) => { - let session = self.process_message( - &self.sessions.negotiation_sessions, connection, Message::KeyVersionNegotiation(message)); - self.try_continue_session(session); - }, - Message::ShareAdd(message) => self.process_message( - &self.sessions.admin_sessions, connection, Message::ShareAdd(message)) - .map(|_| ()).unwrap_or_default(), - Message::Cluster(message) => self.process_cluster_message(connection, message), - } - } - - fn try_continue_session( - &self, - session: Option>> - ) { - if let Some(session) = session { - let meta = session.meta(); - let is_master_node = meta.self_node_id == meta.master_node_id; - if is_master_node && session.is_finished() { - self.sessions.negotiation_sessions.remove(&session.id()); - match session.wait() { - Ok(Some((version, master))) => match session.take_continue_action() { - Some(ContinueAction::Decrypt( - session, origin, is_shadow_decryption, is_broadcast_decryption - )) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize( - origin, version, is_shadow_decryption, is_broadcast_decryption) - } else { - session.delegate( - master, origin, version, is_shadow_decryption, is_broadcast_decryption) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.decryption_sessions.remove(&session.id()); - } - }, - Some(ContinueAction::SchnorrSign(session, message_hash)) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.schnorr_signing_sessions.remove(&session.id()); - } - }, - Some(ContinueAction::EcdsaSign(session, message_hash)) => { - let initialization_error = if self.self_key_pair.public() == &master { - session.initialize(version, message_hash) - } else { - session.delegate(master, version, message_hash) - }; - - if let Err(error) = initialization_error { - session.on_session_error(&meta.self_node_id, error); - self.sessions.ecdsa_signing_sessions.remove(&session.id()); - } - }, - None => (), - }, - Ok(None) => unreachable!("is_master_node; session is finished; - negotiation version always finished with result on master; - qed"), - Err(error) => match session.take_continue_action() { - Some(ContinueAction::Decrypt(session, _, _, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.decryption_sessions.remove(&session.id()); - }, - Some(ContinueAction::SchnorrSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.schnorr_signing_sessions.remove(&session.id()); - }, - Some(ContinueAction::EcdsaSign(session, _)) => { - session.on_session_error(&meta.self_node_id, error); - self.sessions.ecdsa_signing_sessions.remove(&session.id()); - }, - None => (), - }, - } - } - } - } - - fn maintain_sessions(&self) { - self.sessions.stop_stalled_sessions(); - self.sessions.sessions_keep_alive(); - } - - fn start_servers_set_change_session(&self, params: ServersSetChangeParams) -> Result, Error> { - new_servers_set_change_session( - self.self_key_pair.clone(), - &*self.sessions, - self.connections.clone(), - self.servers_set_change_creator_connector.clone(), - params, - ) - } -} diff --git a/util/registrar/Cargo.toml b/util/registrar/Cargo.toml deleted file mode 100644 index 6f526af28c..0000000000 --- a/util/registrar/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -description = "Registar for Parity" -name = "registrar" -version = "0.0.1" -license = "GPL-3.0" -authors = ["Parity Technologies "] - -[dependencies] -futures = "0.1" -ethabi = "6.0" -ethabi-derive = "6.0" -ethabi-contract = "6.0" -keccak-hash = "0.1" diff --git a/util/registrar/res/registrar.json b/util/registrar/res/registrar.json deleted file mode 100644 index 38edcc7877..0000000000 --- a/util/registrar/res/registrar.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - {"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"set","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"}, - {"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"type":"function"}, - {"constant":false,"inputs":[],"name":"drain","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"type":"function"}, - {"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"type":"function"}, - {"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"type":"function"}, - {"constant":true,"inputs":[{"name":"","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"type":"function"}, - {"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"key","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"} -] diff --git a/util/registrar/src/lib.rs b/util/registrar/src/lib.rs deleted file mode 100644 index 79b70d3c9f..0000000000 --- a/util/registrar/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -extern crate ethabi; -extern crate futures; -extern crate keccak_hash; - -#[macro_use] -extern crate ethabi_derive; -#[macro_use] -extern crate ethabi_contract; - -mod registrar; -pub use registrar::{Asynchronous, Registrar, RegistrarClient, Synchronous}; diff --git a/util/registrar/src/registrar.rs b/util/registrar/src/registrar.rs deleted file mode 100644 index 418cb00809..0000000000 --- a/util/registrar/src/registrar.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethabi::{Address, Bytes}; -use futures::{future, Future, IntoFuture}; -use keccak_hash::keccak; -use std::sync::Arc; - -use_contract!(registrar, "res/registrar.json"); - -// Maps a domain name to an Ethereum address -const DNS_A_RECORD: &'static str = "A"; - -pub type Asynchronous = Box + Send>; -pub type Synchronous = Result; - -/// Registrar is dedicated interface to access the registrar contract -/// which in turn generates an address when a client requests one -pub struct Registrar { - client: Arc>, -} - -impl Registrar { - /// Registrar constructor - pub fn new(client: Arc>) -> Self { - Self { client: client } - } - - /// Generate an address for the given key - pub fn get_address<'a>( - &self, - key: &'a str, - ) -> Box + Send> { - // Address of the registrar itself - let registrar_address = match self.client.registrar_address() { - Ok(a) => a, - Err(e) => return Box::new(future::err(e)), - }; - - let hashed_key: [u8; 32] = keccak(key).into(); - let id = registrar::functions::get_address::encode_input(hashed_key, DNS_A_RECORD); - - let future = self - .client - .call_contract(registrar_address, id) - .and_then(move |address| { - registrar::functions::get_address::decode_output(&address) - .map_err(|e| e.to_string()) - }); - - Box::new(future) - } -} - -/// Registrar contract interface -/// Should execute transaction using current blockchain state. -pub trait RegistrarClient: Send + Sync { - /// Specifies synchronous or asynchronous communication - type Call: IntoFuture; - - /// Get registrar address - fn registrar_address(&self) -> Result; - /// Call Contract - fn call_contract(&self, address: Address, data: Bytes) -> Self::Call; -} From d3ba83405cdfa4b43110ed441ec1f49ca657300a Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Wed, 13 Jan 2021 17:06:55 +0000 Subject: [PATCH 042/107] fmt --- crates/ethcore/src/ethereum/mod.rs | 59 +++++++++++++++++++------ crates/ethcore/src/json_tests/runner.rs | 4 +- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/crates/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs index 70ce87455b..9c7c254355 100644 --- a/crates/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -76,7 +76,10 @@ pub fn new_volta<'a, T: Into>>(params: T) -> Spec { /// Create a new EWC mainnet chain spec. pub fn new_ewc<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/chainspec/ewc.json")) + load( + params.into(), + include_bytes!("../../res/chainspec/ewc.json"), + ) } /// Create a new Musicoin mainnet chain spec. @@ -99,7 +102,10 @@ pub fn new_ellaism<'a, T: Into>>(params: T) -> Spec { /// Create a new MIX mainnet chain spec. pub fn new_mix<'a, T: Into>>(params: T) -> Spec { - load(params.into(), include_bytes!("../../res/chainspec/mix.json")) + load( + params.into(), + include_bytes!("../../res/chainspec/mix.json"), + ) } /// Create a new Callisto chain spec @@ -183,12 +189,18 @@ pub fn new_homestead_test() -> Spec { /// Create a new Foundation Homestead-EIP150-era chain spec as though it never changed from Homestead/Frontier. pub fn new_eip150_test() -> Spec { - load(None, include_bytes!("../../res/chainspec/test/eip150_test.json")) + load( + None, + include_bytes!("../../res/chainspec/test/eip150_test.json"), + ) } /// Create a new Foundation Homestead-EIP161-era chain spec as though it never changed from Homestead/Frontier. pub fn new_eip161_test() -> Spec { - load(None, include_bytes!("../../res/chainspec/test/eip161_test.json")) + load( + None, + include_bytes!("../../res/chainspec/test/eip161_test.json"), + ) } /// Create a new Foundation Frontier/Homestead/DAO chain spec with transition points at #5 and #8. @@ -249,29 +261,42 @@ pub fn new_byzantium_to_constantinoplefixat5_test() -> Spec { /// Create a new Foundation Berlin era spec. pub fn new_berlin_test() -> Spec { - load(None, include_bytes!("../../res/chainspec/test/berlin_test.json")) + load( + None, + include_bytes!("../../res/chainspec/test/berlin_test.json"), + ) } /// Create a new YOLO spec pub fn new_yolo3_test() -> Spec { - load(None, include_bytes!("../../res/chainspec/test/yolo3_test.json")) + load( + None, + include_bytes!("../../res/chainspec/test/yolo3_test.json"), + ) } /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { - load(None, include_bytes!("../../res/chainspec/test/mcip3_test.json")) + load( + None, + include_bytes!("../../res/chainspec/test/mcip3_test.json"), + ) } // For tests /// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead. pub fn new_frontier_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/frontier_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/frontier_test.json" + )) } /// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. pub fn new_homestead_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/homestead_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/homestead_test.json" + )) } /// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier. @@ -281,7 +306,9 @@ pub fn new_eip210_test_machine() -> EthereumMachine { /// Create a new Foundation Byzantium era spec. pub fn new_byzantium_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/byzantium_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/byzantium_test.json" + )) } /// Create a new Foundation Constantinople era spec. @@ -293,12 +320,16 @@ pub fn new_constantinople_test_machine() -> EthereumMachine { /// Create a new Foundation St. Peter's (Contantinople Fix) era spec. pub fn new_constantinople_fix_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/st_peters_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/st_peters_test.json" + )) } /// Create a new Foundation Istanbul era spec. pub fn new_istanbul_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/istanbul_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/istanbul_test.json" + )) } /// Create a new Musicoin-MCIP3-era spec. @@ -308,7 +339,9 @@ pub fn new_mcip3_test_machine() -> EthereumMachine { /// Create new Kovan spec with wasm activated at certain block pub fn new_kovan_wasm_test_machine() -> EthereumMachine { - load_machine(include_bytes!("../../res/chainspec/test/kovan_wasm_test.json")) + load_machine(include_bytes!( + "../../res/chainspec/test/kovan_wasm_test.json" + )) } #[cfg(test)] diff --git a/crates/ethcore/src/json_tests/runner.rs b/crates/ethcore/src/json_tests/runner.rs index 2b8fa1f82f..1309175e32 100644 --- a/crates/ethcore/src/json_tests/runner.rs +++ b/crates/ethcore/src/json_tests/runner.rs @@ -232,8 +232,8 @@ impl TestRunner { #[test] fn ethereum_json_tests() { - let content = std::fs::read("res/json_tests.json") - .expect("cannot open ethereum tests spec file"); + let content = + std::fs::read("res/json_tests.json").expect("cannot open ethereum tests spec file"); let runner = TestRunner::load(content.as_slice()).expect("cannot load ethereum tests spec file"); println!("----------------------------------------------------"); From 814526a248ed947099f1b5741df1bacc70e8704b Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Wed, 13 Jan 2021 17:32:48 +0000 Subject: [PATCH 043/107] Fix CI --- .github/workflows/check.yml | 2 +- scripts/actions/validate-chainspecs.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 06d660c1eb..b8b1de4dd9 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -30,7 +30,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose + args: --locked --manifest-path crates/runtime/io/Cargo.toml --no-default-features --verbose - name: Run cargo check 3/3 uses: actions-rs/cargo@v1 with: diff --git a/scripts/actions/validate-chainspecs.sh b/scripts/actions/validate-chainspecs.sh index b5501b450e..de61ed2448 100755 --- a/scripts/actions/validate-chainspecs.sh +++ b/scripts/actions/validate-chainspecs.sh @@ -8,13 +8,14 @@ ERR=0 echo "________Validate chainspecs________" time cargo build --release -p chainspec --verbose --color=always -for spec in ethcore/res/*.json; do +for spec in crates/ethcore/res/chainspec/*.json; do if ! ./target/release/chainspec "$spec"; then ERR=1; fi done -for spec in ethcore/res/ethereum/*.json; do +for spec in crates/ethcore/res/chainspec/test/*.json; do if ! ./target/release/chainspec "$spec"; then ERR=1; fi done + #show sccache statistics #sccache --stop-server exit $ERR From eb876cb2d790185d19be22b963be5932ee0e4235 Mon Sep 17 00:00:00 2001 From: Adria Massanet Date: Thu, 14 Jan 2021 09:20:54 +0000 Subject: [PATCH 044/107] CI fix --- .github/workflows/check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index b8b1de4dd9..7c9b9c6e04 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -35,7 +35,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose + args: --locked --manifest-path crates/runtime/io/Cargo.toml --features "mio" --verbose - name: Run cargo check evmbin uses: actions-rs/cargo@v1 with: From ea25ffd79d953aea10b7f3ed0d7684dca9383bdb Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 17 Jan 2021 23:15:33 +0100 Subject: [PATCH 045/107] Added additional Sg-1,Ca-2,Ca-3 OE bootnodes (#222) --- crates/ethcore/res/chainspec/foundation.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/ethcore/res/chainspec/foundation.json b/crates/ethcore/res/chainspec/foundation.json index 663b703f3e..5af92bec2e 100644 --- a/crates/ethcore/res/chainspec/foundation.json +++ b/crates/ethcore/res/chainspec/foundation.json @@ -198,7 +198,10 @@ "enode://68f46370191198b71a1595dd453c489bbfe28036a9951fc0397fabd1b77462930b3c5a5359b20e99677855939be47b39fc8edcf1e9ff2522a922b86d233bf2df@144.217.153.76:30303", "enode://ffed6382e05ee42854d862f08e4e39b8452c50a5a5d399072c40f9a0b2d4ad34b0eb5312455ad8bcf0dcb4ce969dc89a9a9fd00183eaf8abf46bbcc59dc6e9d5@51.195.3.238:30303", "enode://b47b197244c054d385f25d7740b33cc7e2a74d6f715befad2b789fd3e3594bb1c8dd2ca2faf1a3bf6b4c9ec03e53b52301f722a2316b78976be03ccbe703c581@54.37.94.238:30303", - "enode://5f7d0794c464b2fcd514d41e16e4b535a98ac792a71ca9667c7cef35595dc34c9a1b793c0622554cf87f34006942abb526af7d2e37d715ac32ed02170556cce2@51.161.101.207:30303" + "enode://5f7d0794c464b2fcd514d41e16e4b535a98ac792a71ca9667c7cef35595dc34c9a1b793c0622554cf87f34006942abb526af7d2e37d715ac32ed02170556cce2@51.161.101.207:30303", + "enode://8e78d404250e33c0199d6e53696cabe14ea2b57d534f60be4c6bb4550d006a358806dd10e2994bc11287194cea904c6cb37eda47aa84e2367149f0c65b037288@51.79.213.98:30303", + "enode://cb886f1d2f0d9d686822fbdeba52f87d7b36b9982dda0f320496afe1d1fd4954bd5ee3f0066319dd6ea65c42b69168398ce79efcb984b64ab7242c97d152eb71@51.222.117.211:30303", + "enode://4a403f33a3fa6ae0cd790a91cf967db3e23e6d298158a7e30017c9c665b70e451e2188d7182fce743bfa64f91e04c5791c245cbf4d3b159931cf2cf0bb9b5ec5@51.161.101.207:30303" ], "accounts": { "0x0000000000000000000000000000000000000001": { From 1d07c4c06beef05d288a87e93947a59028141480 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 14 Jan 2021 15:55:52 +0100 Subject: [PATCH 046/107] fix Supplied instant is later than self --- bin/oe/informant.rs | 9 ++++++++- crates/ethcore/service/src/service.rs | 2 +- crates/ethcore/src/engines/authority_round/mod.rs | 2 +- crates/ethcore/src/snapshot/service.rs | 2 +- crates/net/network-devp2p/src/service.rs | 2 +- crates/runtime/io/src/lib.rs | 11 +++++++---- crates/runtime/io/src/service_mio.rs | 8 +++++--- crates/runtime/io/src/worker.rs | 4 ++-- 8 files changed, 26 insertions(+), 14 deletions(-) diff --git a/bin/oe/informant.rs b/bin/oe/informant.rs index a4b27a59f0..45d8eb3541 100644 --- a/bin/oe/informant.rs +++ b/bin/oe/informant.rs @@ -224,7 +224,14 @@ impl Informant { pub fn tick(&self) { let now = Instant::now(); - let elapsed = now.duration_since(*self.last_tick.read()); + let elapsed; + { + let last_tick = self.last_tick.read(); + if now < *last_tick + Duration::from_millis(1500) { + return; + } + elapsed = now - *last_tick; + } let (client_report, full_report) = { let last_report = self.last_report.lock(); diff --git a/crates/ethcore/service/src/service.rs b/crates/ethcore/service/src/service.rs index acfeefd3ad..9969be0efc 100644 --- a/crates/ethcore/service/src/service.rs +++ b/crates/ethcore/service/src/service.rs @@ -56,7 +56,7 @@ impl ClientService { _ipc_path: &Path, miner: Arc, ) -> Result { - let io_service = IoService::::start()?; + let io_service = IoService::::start("Client")?; info!( "Configured for {} using {} engine", diff --git a/crates/ethcore/src/engines/authority_round/mod.rs b/crates/ethcore/src/engines/authority_round/mod.rs index dc232c2f9d..19974d1a66 100644 --- a/crates/ethcore/src/engines/authority_round/mod.rs +++ b/crates/ethcore/src/engines/authority_round/mod.rs @@ -764,7 +764,7 @@ impl AuthorityRound { .start_step .unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))); let engine = Arc::new(AuthorityRound { - transition_service: IoService::<()>::start()?, + transition_service: IoService::<()>::start("AuRa")?, step: Arc::new(PermissionedStep { inner: Step { inner: AtomicUsize::new(initial_step as usize), diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index 09b254bbb3..9b94f1543c 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -1001,7 +1001,7 @@ mod tests { fn sends_async_messages() { let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()]; let client = generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices); - let service = IoService::::start().unwrap(); + let service = IoService::::start("Test").unwrap(); let spec = Spec::new_test(); let tempdir = TempDir::new("").unwrap(); diff --git a/crates/net/network-devp2p/src/service.rs b/crates/net/network-devp2p/src/service.rs index 14fd44bee0..7d28e7fc02 100644 --- a/crates/net/network-devp2p/src/service.rs +++ b/crates/net/network-devp2p/src/service.rs @@ -60,7 +60,7 @@ impl NetworkService { let host_handler = Arc::new(HostHandler { public_url: RwLock::new(None), }); - let io_service = IoService::::start()?; + let io_service = IoService::::start("devp2p")?; Ok(NetworkService { io_service, diff --git a/crates/runtime/io/src/lib.rs b/crates/runtime/io/src/lib.rs index 1142bb7f17..369b3b164f 100644 --- a/crates/runtime/io/src/lib.rs +++ b/crates/runtime/io/src/lib.rs @@ -46,7 +46,7 @@ //! } //! //! fn main () { -//! let mut service = IoService::::start().expect("Error creating network service"); +//! let mut service = IoService::::start("name").expect("Error creating network service"); //! service.register_handler(Arc::new(MyHandler)).unwrap(); //! //! // Wait for quit condition @@ -239,7 +239,8 @@ mod tests { let handler = Arc::new(MyHandler(atomic::AtomicBool::new(false))); - let service = IoService::::start().expect("Error creating network service"); + let service = + IoService::::start("Test").expect("Error creating network service"); service.register_handler(handler.clone()).unwrap(); service.send_message(MyMessage { data: 5 }).unwrap(); @@ -271,7 +272,8 @@ mod tests { let handler = Arc::new(MyHandler(atomic::AtomicBool::new(false))); - let service = IoService::::start().expect("Error creating network service"); + let service = + IoService::::start("Test").expect("Error creating network service"); service.register_handler(handler.clone()).unwrap(); thread::sleep(Duration::from_secs(2)); @@ -300,7 +302,8 @@ mod tests { let handler = Arc::new(MyHandler(atomic::AtomicUsize::new(0))); - let service = IoService::::start().expect("Error creating network service"); + let service = + IoService::::start("Test").expect("Error creating network service"); service.register_handler(handler.clone()).unwrap(); thread::sleep(Duration::from_secs(2)); diff --git a/crates/runtime/io/src/service_mio.rs b/crates/runtime/io/src/service_mio.rs index af383c7e9c..41cd7b19eb 100644 --- a/crates/runtime/io/src/service_mio.rs +++ b/crates/runtime/io/src/service_mio.rs @@ -210,6 +210,7 @@ where { /// Creates a new instance and registers it with the event loop. pub fn start( + symbolic_name: &str, event_loop: &mut EventLoop>, handlers: Arc>>>>, ) -> Result<(), IoError> { @@ -220,7 +221,7 @@ where let workers = (0..num_workers) .map(|i| { Worker::new( - i, + &format!("{}{}", symbolic_name, i), stealer.clone(), IoChannel::new(event_loop.channel(), Arc::downgrade(&handlers)), work_ready.clone(), @@ -534,7 +535,7 @@ where Message: Send + Sync + 'static, { /// Starts IO event loop - pub fn start() -> Result, IoError> { + pub fn start(symbolic_name: &'static str) -> Result, IoError> { let mut config = EventLoopBuilder::new(); config.messages_per_tick(1024); let mut event_loop = config.build().expect("Error creating event loop"); @@ -542,7 +543,8 @@ where let handlers = Arc::new(RwLock::new(Slab::with_capacity(MAX_HANDLERS))); let h = handlers.clone(); let thread = thread::spawn(move || { - IoManager::::start(&mut event_loop, h).expect("Error starting IO service"); + IoManager::::start(symbolic_name, &mut event_loop, h) + .expect("Error starting IO service"); }); Ok(IoService { thread: Some(thread), diff --git a/crates/runtime/io/src/worker.rs b/crates/runtime/io/src/worker.rs index 373c4b8362..a3b4b77213 100644 --- a/crates/runtime/io/src/worker.rs +++ b/crates/runtime/io/src/worker.rs @@ -59,7 +59,7 @@ pub struct Worker { impl Worker { /// Creates a new worker instance. pub fn new( - index: usize, + name: &str, stealer: deque::Stealer>, channel: IoChannel, wait: Arc, @@ -78,7 +78,7 @@ impl Worker { worker.thread = Some( thread::Builder::new() .stack_size(STACK_SIZE) - .name(format!("IO Worker #{}", index)) + .name(format!("Worker {}", name)) .spawn(move || { LOCAL_STACK_SIZE.with(|val| val.set(STACK_SIZE)); let ini = (stealer, channel.clone(), wait, wait_mutex.clone(), deleting); From a55799d52366574e6e62da71f26cfd0585ba487a Mon Sep 17 00:00:00 2001 From: Denis Granha Date: Tue, 19 Jan 2021 10:59:40 +0100 Subject: [PATCH 047/107] Set alpine version to 3.12.3 Alpine version is changed in order to prevent Cmake errors. Reference: https://gitlab.alpinelinux.org/alpine/aports/-/issues/12321. Intends to solve https://github.com/openethereum/openethereum/issues/230 --- scripts/docker/alpine/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker/alpine/Dockerfile b/scripts/docker/alpine/Dockerfile index 800a092caf..516b30370b 100644 --- a/scripts/docker/alpine/Dockerfile +++ b/scripts/docker/alpine/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:edge AS builder +FROM alpine:3.12.3 AS builder # show backtraces ENV RUST_BACKTRACE 1 @@ -18,7 +18,7 @@ COPY . /openethereum RUN cargo build --release --features final --target x86_64-alpine-linux-musl --verbose RUN strip target/x86_64-alpine-linux-musl/release/openethereum -FROM alpine:edge +FROM alpine:3.12.3 # show backtraces ENV RUST_BACKTRACE 1 From f3bdc0da3cf4ef70a90e973c24adf55fcab358bb Mon Sep 17 00:00:00 2001 From: draganrakita Date: Mon, 18 Jan 2021 21:43:03 +0100 Subject: [PATCH 048/107] Bump to 3.1.1 --- CHANGELOG.md | 80 ++++++++++++++++++++++------------ Cargo.lock | 4 +- Cargo.toml | 2 +- crates/util/version/Cargo.toml | 2 +- 4 files changed, 55 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fdf1b30ae..08cabf8ed4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,34 +1,56 @@ -## OpenEthereum v3.1RC1 +## OpenEthereum v3.1.1 -OpenEthereum 3.1rc1 is a candidate release based on v2.5.13 which is the last stable version known of the client that does not include any of the issues introduced in v2.7. -It removes non core features like Ethereum Classic, Private Transactions, Light Client, Updater, IPFS and Swarm support, currently deprecated flags such as expanse, kotti, mordor testnets. +Bug fixes: +* Ancient target set. InvalidStateRoot bug (#69) (#149) +* Update linked-hash-map to 0.5.3 + +Enhancements: +* Added additional Sg-1,Ca-2,Ca-3 OE bootnodes +* Add --ws-max-paxload (#155) +* Add flag to disable storage output in openethereum-evm tool #97 (#115) +* ethstore - remove unnecessary dir & tiny-keccak dependencies from the lib (#107) +* Sync block verification (#74) +* Add `wasmDisableTransition` spec option (#60) +* EIP2929 with journaling + Yolov3 (#79) +* EIP2565 impl (#82) +* TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135) + +DevOps: +* Add custom windows runner (#162) +* Remove sscache (#138) +* Fix deprecated set-env declaration (#106) + + +## OpenEthereum v3.1.0 + +OpenEthereum 3.1.0 is a release based on v2.5.13 which is the last stable version known of the client that does not include any of the issues introduced in v2.7. It removes non core features like Ethereum Classic, Private Transactions, Light Client, Updater, IPFS and Swarm support, currently deprecated flags such as expanse, kotti, mordor testnets. Database migration utility currently in beta: https://github.com/openethereum/3.1-db-upgrade-tool -The full list of included changes from v2.5.13 to v3.1: - -- Remove classic, kotti, mordor, expanse (#52) -- Added bad block header hash for ropsten (#49) -- Remove accounts bloom (#33) -- Bump jsonrpc-- to v15 -- Implement eth/64, remove eth/62 (#46) -- No snapshotting by default (#11814) -- Update Ellaism chainspec -- Prometheus, heavy memory calls removed (#27) -- Update ethereum/tests -- Implement JSON test suite (#11801) -- Fix issues during block sync (#11265) -- Fix race same block (#11400) -- EIP-2537: Precompile for BLS12-381 curve operations (#11707) -- Remove private transactions -- Remove GetNodeData -- Remove IPFS integration (#11532) -- Remove updater -- Remove light client -- Remove C and Java bindings (#11346) -- Remove whisper (#10855) -- EIP-2315: Simple Subroutines for the EVM (#11629) -- Remove deprecated flags (removal of --geth flag) -- Remove support for hardware wallets (#10678) -- Update bootnodes +The full list of included changes from v2.5.13 to v3.1.0: +* Use ubuntu-16.04 for glibc compatibility (#11888) (#73) +* Remove classic, kotti, mordor, expanse (#52) +* Added bad block header hash for ropsten (#49) +* Remove accounts bloom (#33) +* Bump jsonrpc-- to v15 +* Implement eth/64, remove eth/62 (#46) +* No snapshotting by default (#11814) +* Update Ellaism chainspec +* Prometheus, heavy memory calls removed (#27) +* Update ethereum/tests +* Implement JSON test suite (#11801) +* Fix issues during block sync (#11265) +* Fix race same block (#11400) +* EIP-2537: Precompile for BLS12-381 curve operations (#11707) +* Remove private transactions +* Remove GetNodeData +* Remove IPFS integration (#11532) +* Remove updater +* Remove light client +* Remove C and Java bindings (#11346) +* Remove whisper (#10855) +* EIP-2315: Simple Subroutines for the EVM (#11629) +* Remove deprecated flags (removal of --geth flag) +* Remove support for hardware wallets (#10678) +* Update bootnodes diff --git a/Cargo.lock b/Cargo.lock index 01f122fe1f..56afaddccc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2824,7 +2824,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openethereum" -version = "3.1.0-rc1" +version = "3.1.1" dependencies = [ "ansi_term 0.10.2", "atty", @@ -3187,7 +3187,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "3.1.0-rc1" +version = "3.1.1" dependencies = [ "parity-bytes", "rlp 0.3.0", diff --git a/Cargo.toml b/Cargo.toml index aed85d0390..a9106e73e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "OpenEthereum" name = "openethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "3.1.0-rc1" +version = "3.1.1" license = "GPL-3.0" authors = [ "OpenEthereum developers", diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index ab1099eb90..8e67657f9e 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "parity-version" # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) -version = "3.1.0-rc1" +version = "3.1.1" authors = ["Parity Technologies "] build = "build.rs" From 59d891edf4a0ee823f5d7c261f17710094fcbe0e Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 21 Jan 2021 17:23:15 +0100 Subject: [PATCH 049/107] Snapshot manifest block added to prometheus (#232) Co-authored-by: adria0.eth <5526331+adria0@users.noreply.github.com> --- crates/ethcore/src/snapshot/service.rs | 7 +++++++ crates/ethcore/src/snapshot/traits.rs | 3 +++ crates/ethcore/sync/src/api.rs | 11 +++++++++++ crates/ethcore/sync/src/tests/snapshot.rs | 6 ++++++ crates/rpc/src/v1/tests/helpers/snapshot_service.rs | 3 +++ 5 files changed, 30 insertions(+) diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index 9b94f1543c..b94d36199f 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -853,6 +853,13 @@ impl SnapshotService for Service { self.reader.read().as_ref().map(|r| r.manifest().clone()) } + fn manifest_block(&self) -> Option<(u64, H256)> { + self.reader.read().as_ref().map(|reader| { + let manifest = reader.manifest(); + (manifest.block_number, manifest.block_hash) + }) + } + fn supported_versions(&self) -> Option<(u64, u64)> { self.engine .snapshot_components() diff --git a/crates/ethcore/src/snapshot/traits.rs b/crates/ethcore/src/snapshot/traits.rs index 6b17d2f03c..e0d5560227 100644 --- a/crates/ethcore/src/snapshot/traits.rs +++ b/crates/ethcore/src/snapshot/traits.rs @@ -26,6 +26,9 @@ pub trait SnapshotService: Sync + Send { /// Query the most recent manifest data. fn manifest(&self) -> Option; + /// Query the most recent snapshoted block number and hash. + fn manifest_block(&self) -> Option<(u64, H256)>; + /// Get the supported range of snapshot version numbers. /// `None` indicates warp sync isn't supported by the consensus engine. fn supported_versions(&self) -> Option<(u64, u64)>; diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index 5cea92488b..aa82fe7765 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -406,6 +406,11 @@ impl PrometheusMetrics for EthSync { let restoration = self.eth_handler.snapshot_service.restoration_status(); let creation = self.eth_handler.snapshot_service.creation_status(); + let (manifest_block_num, _) = self + .eth_handler + .snapshot_service + .manifest_block() + .unwrap_or((0, H256::zero())); prometheus_gauge( r, @@ -427,6 +432,12 @@ impl PrometheusMetrics for EthSync { 0 }, ); + prometheus_gauge( + r, + "snapshot_manifest_block", + "First block number of the present snapshot", + manifest_block_num as i64, + ); } } diff --git a/crates/ethcore/sync/src/tests/snapshot.rs b/crates/ethcore/sync/src/tests/snapshot.rs index 03ae2873ee..89f635b5f6 100644 --- a/crates/ethcore/sync/src/tests/snapshot.rs +++ b/crates/ethcore/sync/src/tests/snapshot.rs @@ -89,6 +89,12 @@ impl SnapshotService for TestSnapshotService { self.manifest.as_ref().cloned() } + fn manifest_block(&self) -> Option<(u64, H256)> { + self.manifest + .as_ref() + .map(|manifest| (manifest.block_number, manifest.block_hash)) + } + fn supported_versions(&self) -> Option<(u64, u64)> { Some((1, 2)) } diff --git a/crates/rpc/src/v1/tests/helpers/snapshot_service.rs b/crates/rpc/src/v1/tests/helpers/snapshot_service.rs index cbc4d79d89..cc2bbbcb81 100644 --- a/crates/rpc/src/v1/tests/helpers/snapshot_service.rs +++ b/crates/rpc/src/v1/tests/helpers/snapshot_service.rs @@ -44,6 +44,9 @@ impl SnapshotService for TestSnapshotService { fn manifest(&self) -> Option { None } + fn manifest_block(&self) -> Option<(u64, H256)> { + None + } fn supported_versions(&self) -> Option<(u64, u64)> { None } From 52d966ccaa5ae5b438b425ef1c25d3b1f446fd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <4142+huitseeker@users.noreply.github.com> Date: Thu, 21 Jan 2021 12:27:35 -0500 Subject: [PATCH 050/107] Cleans up a number of Option / Result patterns and warts (#226) --- bin/oe/configuration.rs | 6 +-- bin/oe/helpers.rs | 21 ++++----- bin/oe/logger/src/lib.rs | 9 ++-- crates/accounts/ethkey/src/random.rs | 5 +-- crates/accounts/ethstore/src/json/crypto.rs | 10 +---- crates/accounts/ethstore/src/json/key_file.rs | 15 ++----- crates/concensus/ethash/src/compute.rs | 2 +- crates/ethcore/src/client/client.rs | 44 +++++++------------ .../engines/validator_set/safe_contract.rs | 7 ++- crates/ethcore/src/executive.rs | 20 ++------- crates/ethcore/src/state/account.rs | 20 ++++----- crates/ethcore/src/state/mod.rs | 5 +-- crates/ethcore/sync/src/api.rs | 21 ++++----- crates/net/network-devp2p/src/node_table.rs | 5 +-- crates/rpc/src/v1/impls/eth.rs | 20 ++++----- crates/rpc/src/v1/impls/parity_set.rs | 7 ++- 16 files changed, 76 insertions(+), 141 deletions(-) diff --git a/bin/oe/configuration.rs b/bin/oe/configuration.rs index 5982594e53..fe7a71917c 100644 --- a/bin/oe/configuration.rs +++ b/bin/oe/configuration.rs @@ -518,10 +518,8 @@ impl Configuration { } fn ip_filter(&self) -> Result { - match IpFilter::parse(self.args.arg_allow_ips.as_str()) { - Ok(allow_ip) => Ok(allow_ip), - Err(_) => Err("Invalid IP filter value".to_owned()), - } + IpFilter::parse(self.args.arg_allow_ips.as_str()) + .map_err(|_| "Invalid IP filter value".to_owned()) } fn min_peers(&self) -> u32 { diff --git a/bin/oe/helpers.rs b/bin/oe/helpers.rs index 76d28defd3..01f8310736 100644 --- a/bin/oe/helpers.rs +++ b/bin/oe/helpers.rs @@ -105,10 +105,10 @@ pub fn to_block_id(s: &str) -> Result { pub fn to_u256(s: &str) -> Result { if let Ok(decimal) = U256::from_dec_str(s) { Ok(decimal) - } else if let Ok(hex) = clean_0x(s).parse() { - Ok(hex) } else { - Err(format!("Invalid numeric value: {}", s)) + clean_0x(s) + .parse() + .map_err(|_| format!("Invalid numeric value: {}", s)) } } @@ -171,15 +171,12 @@ pub fn to_price(s: &str) -> Result { } pub fn join_set(set: Option<&HashSet>) -> Option { - match set { - Some(s) => Some( - s.iter() - .map(|s| s.as_str()) - .collect::>() - .join(","), - ), - None => None, - } + set.map(|s| { + s.iter() + .map(|s| s.as_str()) + .collect::>() + .join(",") + }) } /// Flush output buffer. diff --git a/bin/oe/logger/src/lib.rs b/bin/oe/logger/src/lib.rs index 44412a05a5..11465225a4 100644 --- a/bin/oe/logger/src/lib.rs +++ b/bin/oe/logger/src/lib.rs @@ -157,10 +157,11 @@ pub fn setup_log(config: &Config) -> Result, String> { Ok(logs) }) // couldn't create new logger - try to fall back on previous logger. - .or_else(|err| match ROTATING_LOGGER.lock().upgrade() { - Some(l) => Ok(l), - // no previous logger. fatal. - None => Err(format!("{:?}", err)), + .or_else(|err| { + ROTATING_LOGGER + .lock() + .upgrade() + .ok_or_else(|| format!("{:?}", err)) }) } diff --git a/crates/accounts/ethkey/src/random.rs b/crates/accounts/ethkey/src/random.rs index 6bf833d276..3efc4df97e 100644 --- a/crates/accounts/ethkey/src/random.rs +++ b/crates/accounts/ethkey/src/random.rs @@ -25,10 +25,7 @@ impl Generator for Random { fn generate(&mut self) -> Result { let mut rng = OsRng::new()?; - match rng.generate() { - Ok(pair) => Ok(pair), - Err(void) => match void {}, // LLVM unreachable - } + rng.generate().or_else(|void| match void {}) } } diff --git a/crates/accounts/ethstore/src/json/crypto.rs b/crates/accounts/ethstore/src/json/crypto.rs index 2afe5bbd15..74d17daa5b 100644 --- a/crates/accounts/ethstore/src/json/crypto.rs +++ b/crates/accounts/ethstore/src/json/crypto.rs @@ -159,10 +159,7 @@ impl<'a> Visitor<'a> for CryptoVisitor { (Some(_), None) => return Err(V::Error::missing_field("cipherparams")), }; - let ciphertext = match ciphertext { - Some(ciphertext) => ciphertext, - None => return Err(V::Error::missing_field("ciphertext")), - }; + let ciphertext = ciphertext.ok_or_else(|| V::Error::missing_field("ciphertext"))?; let kdf = match (kdf, kdfparams) { (Some(KdfSer::Pbkdf2), Some(KdfSerParams::Pbkdf2(params))) => Kdf::Pbkdf2(params), @@ -172,10 +169,7 @@ impl<'a> Visitor<'a> for CryptoVisitor { (Some(_), None) => return Err(V::Error::missing_field("kdfparams")), }; - let mac = match mac { - Some(mac) => mac, - None => return Err(V::Error::missing_field("mac")), - }; + let mac = mac.ok_or_else(|| V::Error::missing_field("mac"))?; let result = Crypto { cipher: cipher, diff --git a/crates/accounts/ethstore/src/json/key_file.rs b/crates/accounts/ethstore/src/json/key_file.rs index 480493a9cd..9c2aec51e0 100644 --- a/crates/accounts/ethstore/src/json/key_file.rs +++ b/crates/accounts/ethstore/src/json/key_file.rs @@ -169,20 +169,11 @@ impl<'a> Visitor<'a> for KeyFileVisitor { } } - let id = match id { - Some(id) => id, - None => return Err(V::Error::missing_field("id")), - }; + let id = id.ok_or_else(|| V::Error::missing_field("id"))?; - let version = match version { - Some(version) => version, - None => return Err(V::Error::missing_field("version")), - }; + let version = version.ok_or_else(|| V::Error::missing_field("version"))?; - let crypto = match crypto { - Some(crypto) => crypto, - None => return Err(V::Error::missing_field("crypto")), - }; + let crypto = crypto.ok_or_else(|| V::Error::missing_field("crypto"))?; let result = KeyFile { id: id, diff --git a/crates/concensus/ethash/src/compute.rs b/crates/concensus/ethash/src/compute.rs index c378c754f7..648b157b1d 100644 --- a/crates/concensus/ethash/src/compute.rs +++ b/crates/concensus/ethash/src/compute.rs @@ -198,7 +198,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) struct MixBuf { half_mix: Node, compress_bytes: [u8; MIX_WORDS], - }; + } if full_size % MIX_WORDS != 0 { panic!("Unaligned full size"); diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index c5e8dd7a86..80531f7211 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -1240,10 +1240,7 @@ impl Client { return Some(state); } - let block_number = match self.block_number(id) { - Some(num) => num, - None => return None, - }; + let block_number = self.block_number(id)?; self.block_header(id).and_then(|header| { let db = self.state_db.read().boxed_clone(); @@ -1370,15 +1367,12 @@ impl Client { None => best_block_number.saturating_sub(history), }; - match self.block_hash(BlockId::Number(start_num)) { - Some(h) => h, - None => return Err(snapshot::Error::InvalidStartingBlock(at).into()), - } + self.block_hash(BlockId::Number(start_num)) + .ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))? } - _ => match self.block_hash(at) { - Some(hash) => hash, - None => return Err(snapshot::Error::InvalidStartingBlock(at).into()), - }, + _ => self + .block_hash(at) + .ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))?, }; let processing_threads = self.config.snapshot.processing_threads; @@ -2407,18 +2401,13 @@ impl BlockChainClient for Client { .collect::>() } else { // Otherwise, we use a slower version that finds a link between from_block and to_block. - let from_hash = match Self::block_hash(&chain, filter.from_block) { - Some(val) => val, - None => return Err(filter.from_block.clone()), - }; - let from_number = match chain.block_number(&from_hash) { - Some(val) => val, - None => return Err(BlockId::Hash(from_hash)), - }; - let to_hash = match Self::block_hash(&chain, filter.to_block) { - Some(val) => val, - None => return Err(filter.to_block.clone()), - }; + let from_hash = Self::block_hash(&chain, filter.from_block) + .ok_or_else(|| filter.from_block.clone())?; + let from_number = chain + .block_number(&from_hash) + .ok_or_else(|| BlockId::Hash(from_hash))?; + let to_hash = + Self::block_hash(&chain, filter.to_block).ok_or_else(|| filter.to_block.clone())?; let blooms = filter.bloom_possibilities(); let bloom_match = |header: &encoded::Header| { @@ -2432,10 +2421,9 @@ impl BlockChainClient for Client { let mut current_hash = to_hash; loop { - let header = match chain.block_header_data(¤t_hash) { - Some(val) => val, - None => return Err(BlockId::Hash(current_hash)), - }; + let header = chain + .block_header_data(¤t_hash) + .ok_or_else(|| BlockId::Hash(current_hash))?; if bloom_match(&header) { blocks.push(current_hash); } diff --git a/crates/ethcore/src/engines/validator_set/safe_contract.rs b/crates/ethcore/src/engines/validator_set/safe_contract.rs index 39256c360e..6e36015aa8 100644 --- a/crates/ethcore/src/engines/validator_set/safe_contract.rs +++ b/crates/ethcore/src/engines/validator_set/safe_contract.rs @@ -292,10 +292,9 @@ impl ValidatorSafeContract { }); // only last log is taken into account - match decoded_events.next() { - None => None, - Some(matched_event) => Some(SimpleList::new(matched_event.new_set)), - } + decoded_events + .next() + .map(|matched_event| SimpleList::new(matched_event.new_set)) } } diff --git a/crates/ethcore/src/executive.rs b/crates/ethcore/src/executive.rs index dddc53ec70..485bb4275e 100644 --- a/crates/ethcore/src/executive.rs +++ b/crates/ethcore/src/executive.rs @@ -623,10 +623,7 @@ impl<'a> CallCreateExecutive<'a> { tracer, vm_tracer, ); - match exec.exec(&mut ext) { - Ok(val) => Ok(val.finalize(ext)), - Err(err) => Err(err), - } + exec.exec(&mut ext).map(|val| val.finalize(ext)) }; let res = match out { @@ -694,10 +691,7 @@ impl<'a> CallCreateExecutive<'a> { tracer, vm_tracer, ); - match exec.exec(&mut ext) { - Ok(val) => Ok(val.finalize(ext)), - Err(err) => Err(err), - } + exec.exec(&mut ext).map(|val| val.finalize(ext)) }; let res = match out { @@ -763,10 +757,7 @@ impl<'a> CallCreateExecutive<'a> { tracer, vm_tracer, ); - match exec.exec(&mut ext) { - Ok(val) => Ok(val.finalize(ext)), - Err(err) => Err(err), - } + exec.exec(&mut ext).map(|val| val.finalize(ext)) }; let res = match out { @@ -840,10 +831,7 @@ impl<'a> CallCreateExecutive<'a> { tracer, vm_tracer, ); - match exec.exec(&mut ext) { - Ok(val) => Ok(val.finalize(ext)), - Err(err) => Err(err), - } + exec.exec(&mut ext).map(|val| val.finalize(ext)) }; let res = match out { diff --git a/crates/ethcore/src/state/account.rs b/crates/ethcore/src/state/account.rs index b6504c1765..799fc24d6e 100644 --- a/crates/ethcore/src/state/account.rs +++ b/crates/ethcore/src/state/account.rs @@ -298,13 +298,10 @@ impl Account { /// Get cached original storage value after last state commitment. Returns `None` if the key is not in the cache. pub fn cached_original_storage_at(&self, key: &H256) -> Option { match &self.original_storage_cache { - Some((_, ref original_storage_cache)) => { - if let Some(value) = original_storage_cache.borrow_mut().get_mut(key) { - Some(value.clone()) - } else { - None - } - } + Some((_, ref original_storage_cache)) => original_storage_cache + .borrow_mut() + .get_mut(key) + .map(|value| value.clone()), None => self.cached_moved_original_storage_at(key), } } @@ -317,11 +314,10 @@ impl Account { return Some(H256::new()); } - if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) { - Some(value.clone()) - } else { - None - } + self.storage_cache + .borrow_mut() + .get_mut(key) + .map(|value| value.clone()) } /// return the balance associated with this account. diff --git a/crates/ethcore/src/state/mod.rs b/crates/ethcore/src/state/mod.rs index 5759f5f4fd..f15e2b77d0 100644 --- a/crates/ethcore/src/state/mod.rs +++ b/crates/ethcore/src/state/mod.rs @@ -246,10 +246,7 @@ pub fn prove_transaction_virtual + Send + Syn factories, ); - let mut state = match res { - Ok(state) => state, - Err(_) => return None, - }; + let mut state = res.ok()?; let options = TransactOptions::with_no_tracing() .dont_check_nonce() diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index aa82fe7765..a512d7a838 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -294,10 +294,7 @@ impl SyncProvider for EthSync { .into_iter() .zip(peer_info) .filter_map(|(peer_id, peer_info)| { - let session_info = match ctx.session_info(peer_id) { - None => return None, - Some(info) => info, - }; + let session_info = ctx.session_info(peer_id)?; Some(PeerInfo { id: session_info.id.map(|id| format!("{:x}", id)), @@ -746,14 +743,14 @@ impl NetworkConfiguration { Ok(BasicNetworkConfiguration { config_path: self.config_path, net_config_path: self.net_config_path, - listen_address: match self.listen_address { - None => None, - Some(addr) => Some(SocketAddr::from_str(&addr)?), - }, - public_address: match self.public_address { - None => None, - Some(addr) => Some(SocketAddr::from_str(&addr)?), - }, + listen_address: self + .listen_address + .map(|addr| SocketAddr::from_str(&addr)) + .transpose()?, + public_address: self + .public_address + .map(|addr| SocketAddr::from_str(&addr)) + .transpose()?, udp_port: self.udp_port, nat_enabled: self.nat_enabled, discovery_enabled: self.discovery_enabled, diff --git a/crates/net/network-devp2p/src/node_table.rs b/crates/net/network-devp2p/src/node_table.rs index 65e9463752..03232e2ff8 100644 --- a/crates/net/network-devp2p/src/node_table.rs +++ b/crates/net/network-devp2p/src/node_table.rs @@ -503,10 +503,7 @@ impl Drop for NodeTable { /// Check if node url is valid pub fn validate_node_url(url: &str) -> Option { - match Node::from_str(url) { - Ok(_) => None, - Err(e) => Some(e), - } + Node::from_str(url).err() } mod json { diff --git a/crates/rpc/src/v1/impls/eth.rs b/crates/rpc/src/v1/impls/eth.rs index 928990d4ee..aa6529380f 100644 --- a/crates/rpc/src/v1/impls/eth.rs +++ b/crates/rpc/src/v1/impls/eth.rs @@ -683,10 +683,10 @@ where let num = num.unwrap_or_default(); try_bf!(check_known(&*self.client, num.clone())); - let res = match self.client.balance(&address, self.get_state(num)) { - Some(balance) => Ok(balance), - None => Err(errors::state_pruned()), - }; + let res = self + .client + .balance(&address, self.get_state(num)) + .ok_or_else(|| errors::state_pruned()); Box::new(future::done(res)) } @@ -779,17 +779,13 @@ where self.client.nonce(&address, BlockId::Latest) }); - match nonce { - Some(nonce) => Ok(nonce), - None => Err(errors::database("latest nonce missing")), - } + nonce.ok_or_else(|| errors::database("latest nonce missing")) } number => { try_bf!(check_known(&*self.client, number.clone())); - match self.client.nonce(&address, block_number_to_id(number)) { - Some(nonce) => Ok(nonce), - None => Err(errors::state_pruned()), - } + self.client + .nonce(&address, block_number_to_id(number)) + .ok_or_else(|| errors::state_pruned()) } }; diff --git a/crates/rpc/src/v1/impls/parity_set.rs b/crates/rpc/src/v1/impls/parity_set.rs index aad0fbf8c6..21489d0349 100644 --- a/crates/rpc/src/v1/impls/parity_set.rs +++ b/crates/rpc/src/v1/impls/parity_set.rs @@ -110,10 +110,9 @@ where F: Fetch + 'static, { fn set_min_gas_price(&self, gas_price: U256) -> Result { - match self.miner.set_minimal_gas_price(gas_price) { - Ok(success) => Ok(success), - Err(e) => Err(errors::unsupported(e, None)), - } + self.miner + .set_minimal_gas_price(gas_price) + .map_err(|e| errors::unsupported(e, None)) } fn set_transactions_limit(&self, _limit: usize) -> Result { From cfc6439f2e21b60f1a890265b7fc8781862eaa3c Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 28 Jan 2021 17:23:01 +0100 Subject: [PATCH 051/107] Local EIP2930 and EN/DE block tests (#237) --- .../res/chainspec/test/eip2930_test.json | 69 + crates/ethcore/res/json_tests.json | 27 +- .../local_tests/block_en_de/acl_block_0.json | 42 + .../local_tests/block_en_de/acl_block_1.json | 65 + .../local_tests/block_en_de/acl_block_2.json | 102 + .../local_tests/block_en_de/acl_block_3.json | 153 + .../local_tests/block_en_de/acl_block_4.json | 218 ++ .../local_tests/block_en_de/acl_block_5.json | 297 ++ .../local_tests/block_en_de/acl_block_6.json | 390 ++ .../local_tests/block_en_de/acl_block_7.json | 497 +++ .../local_tests/block_en_de/acl_block_8.json | 619 ++++ .../local_tests/block_en_de/acl_block_9.json | 754 ++++ .../res/local_tests/block_en_de/simple.json | 38 + .../res/local_tests/chain/eip2930.json | 3149 +++++++++++++++++ crates/ethcore/src/client/evm_test_client.rs | 3 +- crates/ethcore/src/ethereum/mod.rs | 8 + crates/ethcore/src/json_tests/chain.rs | 2 +- crates/ethcore/src/json_tests/local.rs | 202 ++ crates/ethcore/src/json_tests/mod.rs | 1 + crates/ethcore/src/json_tests/runner.rs | 20 +- .../types/src/transaction/transaction.rs | 7 + .../types/src/transaction/transaction_id.rs | 12 +- crates/ethjson/src/blockchain/block.rs | 8 +- crates/ethjson/src/blockchain/transaction.rs | 29 +- crates/ethjson/src/bytes.rs | 2 +- crates/ethjson/src/lib.rs | 1 + crates/ethjson/src/local_tests/mod.rs | 26 + crates/ethjson/src/spec/spec.rs | 1 + crates/ethjson/src/test/mod.rs | 11 + 29 files changed, 6724 insertions(+), 29 deletions(-) create mode 100644 crates/ethcore/res/chainspec/test/eip2930_test.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_0.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_1.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_2.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_3.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_4.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_5.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_6.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_7.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_8.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/acl_block_9.json create mode 100644 crates/ethcore/res/local_tests/block_en_de/simple.json create mode 100644 crates/ethcore/res/local_tests/chain/eip2930.json create mode 100644 crates/ethcore/src/json_tests/local.rs create mode 100644 crates/ethjson/src/local_tests/mod.rs diff --git a/crates/ethcore/res/chainspec/test/eip2930_test.json b/crates/ethcore/res/chainspec/test/eip2930_test.json new file mode 100644 index 0000000000..764d255df1 --- /dev/null +++ b/crates/ethcore/res/chainspec/test/eip2930_test.json @@ -0,0 +1,69 @@ +{ + "name": "YoloEIP2930", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x1BC16D674EC80000", + "homesteadTransition": "0x0", + "eip100bTransition": "0x0", + "difficultyBombDelays": { + "0": 5000000 + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x0", + "eip1344Transition": "0x0", + "eip1706Transition": "0x0", + "eip1884Transition": "0x0", + "eip2028Transition": "0x0", + "eip2315Transition": "0x0", + "eip2929Transition": "0x0", + "eip2930Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000539", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x47e7c4" + }, + "accounts": { + "000000000000000000000000000000000000aaaa": { + "balance": "0", + "code": "0x5854505854503231" + }, + "71562b71999873db5b286df957af199ec94617f7": { + "balance": "0x3b9aca00" + } + } +} diff --git a/crates/ethcore/res/json_tests.json b/crates/ethcore/res/json_tests.json index 7fa2059846..a795bd0c08 100644 --- a/crates/ethcore/res/json_tests.json +++ b/crates/ethcore/res/json_tests.json @@ -1,24 +1,32 @@ { + "local": [ + { + "path": "res/local_tests/block_en_de", + "test_type": "block_en_de" + } + ], "chain": [ + { + "path": "res/local_tests/chain", + "skip": [] + }, { "path": "res/json_tests/BlockchainTests", - "skip" : [] + "skip": [] }, { "path": "res/json_tests/LegacyTests/Constantinople/BlockchainTests", - "skip" : [] + "skip": [] } ], "state": [ { "path": "res/json_tests/GeneralStateTests", - "skip" : [] - + "skip": [] }, { "path": "res/json_tests/LegacyTests/Constantinople/GeneralStateTests", - "skip" : [] - + "skip": [] } ], "difficulty": [ @@ -42,10 +50,7 @@ ], "trie": [ { - "path": [ - "res/json_tests/TrieTests/trietest.json", - "res/json_tests/TrieTests/trieanyorder.json" - ], + "path": ["res/json_tests/TrieTests/trietest.json", "res/json_tests/TrieTests/trieanyorder.json"], "triespec": "Generic" }, { @@ -57,4 +62,4 @@ "triespec": "Secure" } ] -} \ No newline at end of file +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_0.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_0.json new file mode 100644 index 0000000000..c7edcb0314 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_0.json @@ -0,0 +1,42 @@ +{ + "acl_block_0": { + "rlp": "f90263f901f5a0151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23faa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79a0e8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4a07f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48262740a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f868f866800a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a0e7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194bea04d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bfc0", + "header": { + "parentHash": "0x151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23fa", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79", + "transactionsTrie": "0xe8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4", + "receiptTrie": "0x7f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2a", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x1", + "gasLimit": "0x47e7c4", + "gasUsed": "0x6274", + "timestamp": "0xa", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x9aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68" + }, + "transactions": [ + { + "type": "0x0", + "chainId": null, + "nonce": "0x0", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec88", + "r": "0xe7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194be", + "s": "0x4d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bf", + "hash": "0x7e122173adcc02b9a3c94da426f65c7d46e724e8e3fdb16be73d5e0405e280b6" + } + ], + "uncles": null, + "receipts": null + } +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_1.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_1.json new file mode 100644 index 0000000000..318df8f47b --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_1.json @@ -0,0 +1,65 @@ +{ + "acl_block_1": { + "rlp": "f9032df901f5a09aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0fb70f6c0512e7979903607bba8a4f1b18c2dd1060a8eff1b777a2182d05af524a0dfcad019a36acdf0f3fac6b3db02bf1d70012a0bd3eadabea87b856be9a6f1cca0a7a57ba954834e69b55d9115305f14f7faff9beb83443f7bb5526585848c6aefb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000028347e7c482dd201480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90131b8c701f8c486796f6c6f7632010a8301e24194000000000000000000000000000000000000aaaa8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000001a0a9efa6b5fd3c2f210c4ec7232058d8dd30c93a456b4f6074429fb09bbd73eb4fa070632eff8bf0933381917c9161a98494e34fc7b836ee150445cae9ab151d267bf866020a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a055a39da3ce02c75e976ad84f608771080811a5ef322c6b6536c362f716c60985a018ab5df4198436eacd0e991f59bdeb8da9a75c678067db6b1a4d07881555c7a8c0", + "header": { + "parentHash": "0x9aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xfb70f6c0512e7979903607bba8a4f1b18c2dd1060a8eff1b777a2182d05af524", + "transactionsTrie": "0xdfcad019a36acdf0f3fac6b3db02bf1d70012a0bd3eadabea87b856be9a6f1cc", + "receiptTrie": "0xa7a57ba954834e69b55d9115305f14f7faff9beb83443f7bb5526585848c6aef", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x2", + "gasLimit": "0x47e7c4", + "gasUsed": "0xdd20", + "timestamp": "0x14", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xe1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748c" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + [ + "0x0000000000000000000000000000000000000000", + [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + ] + ], + "v": "0x1", + "r": "0xa9efa6b5fd3c2f210c4ec7232058d8dd30c93a456b4f6074429fb09bbd73eb4f", + "s": "0x70632eff8bf0933381917c9161a98494e34fc7b836ee150445cae9ab151d267b", + "hash": "0x1916413ac8d1d5ee4eda786e5fe29509a109910f800894e0e18eb84abb7564cb" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x2", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec88", + "r": "0x55a39da3ce02c75e976ad84f608771080811a5ef322c6b6536c362f716c60985", + "s": "0x18ab5df4198436eacd0e991f59bdeb8da9a75c678067db6b1a4d07881555c7a8", + "hash": "0x54c6cfb51cbbe2c562e17a0d6ee1324f1b50013a9b9d47589cedcf0ec4ac342a" + } + ], + "uncles": null, + "receipts": null + } +} \ No newline at end of file diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_2.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_2.json new file mode 100644 index 0000000000..901fbad846 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_2.json @@ -0,0 +1,102 @@ +{ + "acl_block_2": { + "rlp": "f904b1f901f6a0e1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a025e5b4b7668760c0aa01d44c061d77e24b53f6d247d3e1d85a91e23646c1d679a0be53a36dd90786b4cd30fb0f3677ad3ce5f804a5615872a7b0512b6be82639a2a076946d9f034a6657c6832a6ad4df3ef0ddf3fa9f3f8be98ea64880fb23bd23e3b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000038347e7c48301883c1e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f902b4b9012301f9011f86796f6c6f7632030a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a0635c44b8110989ef84c77de11a377f19cbd84660559ed76b37ba0f7fdee1fb40a012e1576d168301614720c68f1a9e9d5ed20e23622dab6c3587b11177155d59f4b9012301f9011f86796f6c6f7632040a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a00380e446bf3992ee1df44b8177a11e948dc52cc3faa8eae059a52b7183126c0fa05206f0f35648d3b8f23092d4d7bdccb926967d840a269cf65b706a8a359b9029f866050a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0ea5de382dbf422aa1bd156547a2bc3a9357d745a68cdc9203b14812307068567a0388f7425b873ae204d43d91f4997ca41d2af6759be49538b174a06f67d5741b5c0", + "header": { + "parentHash": "0xe1807e7366284bc72d34c8f02318f81c6598454dbff4c6cdd71e872cd8d5748c", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x25e5b4b7668760c0aa01d44c061d77e24b53f6d247d3e1d85a91e23646c1d679", + "transactionsTrie": "0xbe53a36dd90786b4cd30fb0f3677ad3ce5f804a5615872a7b0512b6be82639a2", + "receiptTrie": "0x76946d9f034a6657c6832a6ad4df3ef0ddf3fa9f3f8be98ea64880fb23bd23e3", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x3", + "gasLimit": "0x47e7c4", + "gasUsed": "0x1883c", + "timestamp": "0x1e", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x1615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785ce" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x3", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x635c44b8110989ef84c77de11a377f19cbd84660559ed76b37ba0f7fdee1fb40", + "s": "0x12e1576d168301614720c68f1a9e9d5ed20e23622dab6c3587b11177155d59f4", + "hash": "0x54471f503901f2c2fe392e43df0377a11f9a1cd9cde0ec5c68c89eac1723e02a" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x4", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x380e446bf3992ee1df44b8177a11e948dc52cc3faa8eae059a52b7183126c0f", + "s": "0x5206f0f35648d3b8f23092d4d7bdccb926967d840a269cf65b706a8a359b9029", + "hash": "0xe3a1354e84d22ebbca0c55751937b075083f0f0e3a47c65fc7249d86f872f268" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x5", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0xea5de382dbf422aa1bd156547a2bc3a9357d745a68cdc9203b14812307068567", + "s": "0x388f7425b873ae204d43d91f4997ca41d2af6759be49538b174a06f67d5741b5", + "hash": "0x44b1e9999ac02a3b0daf1391be16bb00a262079706418697094bab5f37b522d7" + } + ], + "uncles": null, + "receipts": null + } +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_3.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_3.json new file mode 100644 index 0000000000..060c209d0b --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_3.json @@ -0,0 +1,153 @@ +{ + "acl_block_3": { + "rlp": "f906ebf901f6a01615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0e2c895d53740e942c84623e1612189e72eea9e767b150cc0d8802b490f2574b2a060b6fa13cd50ea3732f59eb726368639dea2006ab4b67dc5730ea27b0cd75732a058ac726e0fc55cd550539c38baf3f6023615e2657ceedccc21ce7edd6516bc31b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000048347e7c4830263c82880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f904eeb9017f01f9017b86796f6c6f7632060a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0587b3fd59a84469be7c918ae73047141027d27c47cc63f3cf13c6161bf92efaaa0453d3cd2dffd1f048a58fb1046917327f5e95cc8aedc47f82d41bffebfe31bbdb9017f01f9017b86796f6c6f7632070a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000080a0b1944f4797bf4da4d041a66be9c41c317b40d158894103ccd50de5e4ca174b4aa079d6834c013b40d0039ca6755cecc72938461e5b8cd8d3619ddcdfb15c15b866b9017f01f9017b86796f6c6f7632080a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0793cd38309611e0117269275243fc3761fe233dc371918e450b547c70132c033a07276d4b20788938ca0ff7e4e921aec7739103dc73d3b953f47947ef194720757f866090a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a0a6528544064aef10d166e16d3968ae83aa29161beb57f2756dfd1151682adbe7a0507fe2d475ffab209e718345a3ad9fb20fee6e15a8c4980df3ed8ff0a714367ac0", + "header": { + "parentHash": "0x1615129d2aa7b437cd40e3aa1a5794af9e40b07b9b017014e4123cefeef785ce", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xe2c895d53740e942c84623e1612189e72eea9e767b150cc0d8802b490f2574b2", + "transactionsTrie": "0x60b6fa13cd50ea3732f59eb726368639dea2006ab4b67dc5730ea27b0cd75732", + "receiptTrie": "0x58ac726e0fc55cd550539c38baf3f6023615e2657ceedccc21ce7edd6516bc31", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x4", + "gasLimit": "0x47e7c4", + "gasUsed": "0x263c8", + "timestamp": "0x28", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xc6340ac0a1b76cae78479a4bc6211031550719fa9b58ae42d773dce7ff7409ce" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x6", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x587b3fd59a84469be7c918ae73047141027d27c47cc63f3cf13c6161bf92efaa", + "s": "0x453d3cd2dffd1f048a58fb1046917327f5e95cc8aedc47f82d41bffebfe31bbd", + "hash": "0xbc9b06b5d31e6e257a3c25048e935ba433c68fdd5fa5d0ddd726d5ab7356aafd" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x7", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xb1944f4797bf4da4d041a66be9c41c317b40d158894103ccd50de5e4ca174b4a", + "s": "0x79d6834c013b40d0039ca6755cecc72938461e5b8cd8d3619ddcdfb15c15b866", + "hash": "0x474ec2766068f9e9d0548aca3769ca406fdde21ba87c254d9230c18be35fe99a" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x8", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x793cd38309611e0117269275243fc3761fe233dc371918e450b547c70132c033", + "s": "0x7276d4b20788938ca0ff7e4e921aec7739103dc73d3b953f47947ef194720757", + "hash": "0xe46963eb63cd75a120990ca597532020bc2dcefc4588025c0d50901681a7aae9" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x9", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec88", + "r": "0xa6528544064aef10d166e16d3968ae83aa29161beb57f2756dfd1151682adbe7", + "s": "0x507fe2d475ffab209e718345a3ad9fb20fee6e15a8c4980df3ed8ff0a714367a", + "hash": "0x61fc16fea6b57d81f269e733cdd15d994bbc10dc6e9b0acbedbe32e6fe70a06c" + } + ], + "uncles": null, + "receipts": null + } +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_4.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_4.json new file mode 100644 index 0000000000..bcbbb7eaaf --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_4.json @@ -0,0 +1,218 @@ +{ + "acl_block_4": { + "rlp": "f909d9f901f6a0c6340ac0a1b76cae78479a4bc6211031550719fa9b58ae42d773dce7ff7409cea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a08bea5accbb5e586ad84279f37b06ccd9cec79f9547e1c34545a361b61117ca66a05266aab4415ef7659530a0baa876d3ab26aff199f13b97084aed767412cf0f88a08899161ab693e740c3ee7323e114f575342c83f25fd7bda246bc1e5722e0b98cb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000058347e7c483036fc43280a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f907dcb901da01f901d686796f6c6f76320a0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a07e073e922b0f9195abdd479c2b988c00d3565063baaecbb5bc03d45ec611cbaca07e2d47eb81702ceefbf765d6283586b09c2e9fe2b02ffeea13c72efdd5425aa7b901da01f901d686796f6c6f76320b0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a0ad1eb53988eba191181ab17026bc73bfa5744c7feb385ff50c1d135262b4b550a06e0fde038fe6bb5e6a03724e5ed67b76bac528425fa6a31364f498d418c96343b901da01f901d686796f6c6f76320c0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a0b819a58c2bd8516b9afbb2410e16de4e4243e8c67ac6901211a931f2f39ff2e2a0053e42e62d88ef4174f01eebe5f3177f4eae4ab0bceaa44f638550678068518eb901da01f901d686796f6c6f76320d0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a0dcb383f7cbd502d0d61c5daa2894011476c260daf07f150b52bd8e753929d458a049c149cca5a3e7ee659a1c3205980215d0148369309b8678ea88056f9c4e69a9f8660e0a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0f8305a294ad8c2928246ff9dc008296bec497d70653962a0e17da9cea8618034a05a6ae3809c6fad8ad302100d58d4e08eef51e25634ceb55eee5a07a837e75e03c0", + "header": { + "parentHash": "0xc6340ac0a1b76cae78479a4bc6211031550719fa9b58ae42d773dce7ff7409ce", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x8bea5accbb5e586ad84279f37b06ccd9cec79f9547e1c34545a361b61117ca66", + "transactionsTrie": "0x5266aab4415ef7659530a0baa876d3ab26aff199f13b97084aed767412cf0f88", + "receiptTrie": "0x8899161ab693e740c3ee7323e114f575342c83f25fd7bda246bc1e5722e0b98c", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x5", + "gasLimit": "0x47e7c4", + "gasUsed": "0x36fc4", + "timestamp": "0x32", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x43335db66263d3d83223a37683ddd526ee3b81bdcd3ec1a477894b7659e31df5" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0xa", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x7e073e922b0f9195abdd479c2b988c00d3565063baaecbb5bc03d45ec611cbac", + "s": "0x7e2d47eb81702ceefbf765d6283586b09c2e9fe2b02ffeea13c72efdd5425aa7", + "hash": "0x0f4f39a875669b88862f40083726c9c38bb2bd12b787dc59f3840f9a2aa9dad1" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0xb", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xad1eb53988eba191181ab17026bc73bfa5744c7feb385ff50c1d135262b4b550", + "s": "0x6e0fde038fe6bb5e6a03724e5ed67b76bac528425fa6a31364f498d418c96343", + "hash": "0x19f8ea997fa31ab0379efc68fd9b09283dbdd0ed46141f21b4f692c4adb31f1e" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0xc", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xb819a58c2bd8516b9afbb2410e16de4e4243e8c67ac6901211a931f2f39ff2e2", + "s": "0x53e42e62d88ef4174f01eebe5f3177f4eae4ab0bceaa44f638550678068518e", + "hash": "0xee900bcfba7a74d9e45568af7f8db691c39a357f5088b64bbf4c18bd1e4241bb" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0xd", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xdcb383f7cbd502d0d61c5daa2894011476c260daf07f150b52bd8e753929d458", + "s": "0x49c149cca5a3e7ee659a1c3205980215d0148369309b8678ea88056f9c4e69a9", + "hash": "0xa74fcf06517f9561b55d31ce00afbaa4f53772291af96521872640e38da51525" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0xe", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0xf8305a294ad8c2928246ff9dc008296bec497d70653962a0e17da9cea8618034", + "s": "0x5a6ae3809c6fad8ad302100d58d4e08eef51e25634ceb55eee5a07a837e75e03", + "hash": "0x96739f62b1e4583c97fc3ce618f4490fcb8667186826b99ee18ca3d4e3252136" + } + ], + "uncles": null, + "receipts": null + } +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_5.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_5.json new file mode 100644 index 0000000000..e317adea32 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_5.json @@ -0,0 +1,297 @@ +{ + "acl_block_5": { + "rlp": "f90d7df901f6a043335db66263d3d83223a37683ddd526ee3b81bdcd3ec1a477894b7659e31df5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a03445ee9a221c8bd9c3a797ef91fe8aa41239a6404a649f289fefd7965d5f6b3da0fa6a9116e469a63a136448d15dd4415bb6c42cd6824a7453788bcf86639b3343a069895a3818b4067d65cbb9b94c3e9caade084f303e10aadcbd4ed2337d6f7e37b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000068347e7c48304ac303c80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90b80b9023501f9023186796f6c6f76320f0a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a0f84927e5d33e51a97efeeae35148a17aebee690b543f863d55aa0b98cf62803aa01f44785c907379109661088df919b456a0cbcf0d72900237faedc3b2746556c3b9023501f9023186796f6c6f7632100a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a08e2a80d3a51965fd3bf3375329d98bae924f21b84ab1948f822e238a688270d7a051fc270b2b6bebb3a718e06f7a1772029042ce938ec741a9623f5283e84b8442b9023501f9023186796f6c6f7632110a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a05541f7da809ec62ec9643748b6d8a64411388f6c1999c8f6a067fae224b7497ca04ce552578d1619c80b14e6f95f472bb7e242b3fdcac449415a58150473feecefb9023501f9023186796f6c6f7632120a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a01f872d6fb4eb7398254fe7811cf405fcbc11b83ea61f50c26feec13c62527ad0a026acd00dbbd0eef10a7c213e616df22f3a9fd1d61d31ed0abb257e0efc8abf06b9023501f9023186796f6c6f7632130a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a03fb9c1360e7a1a9cf45efed449c609b585df3b2ecfa5eb67eecba63c55699f11a072ef40cefb4fbfe2f54df284741effb28c2cf25128e3aec5003d9809c2e82d01f866140a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0a68b33f12348a1053208c0783d7504f90a58da7f9ca2ead1275526cce7d700bda019c01948a0479c1a3774a203686acc9727830503fab6fdeed06b69e60b93755fc0", + "header": { + "parentHash": "0x43335db66263d3d83223a37683ddd526ee3b81bdcd3ec1a477894b7659e31df5", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x3445ee9a221c8bd9c3a797ef91fe8aa41239a6404a649f289fefd7965d5f6b3d", + "transactionsTrie": "0xfa6a9116e469a63a136448d15dd4415bb6c42cd6824a7453788bcf86639b3343", + "receiptTrie": "0x69895a3818b4067d65cbb9b94c3e9caade084f303e10aadcbd4ed2337d6f7e37", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x6", + "gasLimit": "0x47e7c4", + "gasUsed": "0x4ac30", + "timestamp": "0x3c", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x00acaefd90b8d42561f10a6e20a23b94f045aa26d7134fabfbc34e5ff1c4e6d5" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0xf", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xf84927e5d33e51a97efeeae35148a17aebee690b543f863d55aa0b98cf62803a", + "s": "0x1f44785c907379109661088df919b456a0cbcf0d72900237faedc3b2746556c3", + "hash": "0xc0ec239a159d9e67d986161ce20d8852e7c70c4e57c27c5fe28ae8fab1038a23" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x10", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x8e2a80d3a51965fd3bf3375329d98bae924f21b84ab1948f822e238a688270d7", + "s": "0x51fc270b2b6bebb3a718e06f7a1772029042ce938ec741a9623f5283e84b8442", + "hash": "0xd4b78fd3de465b52bfbce75278243c0c211d7ff466eda2e4d2c8c4939616c34b" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x11", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x5541f7da809ec62ec9643748b6d8a64411388f6c1999c8f6a067fae224b7497c", + "s": "0x4ce552578d1619c80b14e6f95f472bb7e242b3fdcac449415a58150473feecef", + "hash": "0xbbf1c7cb4e14723a928ca4bc73890ee9449203cd71d987075cb468212e4cf213" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x12", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x1f872d6fb4eb7398254fe7811cf405fcbc11b83ea61f50c26feec13c62527ad0", + "s": "0x26acd00dbbd0eef10a7c213e616df22f3a9fd1d61d31ed0abb257e0efc8abf06", + "hash": "0xb50bdbaa03ec0bddb84f4d9076385d53e4382cb5045dc1f172dce5f60064313c" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x13", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x3fb9c1360e7a1a9cf45efed449c609b585df3b2ecfa5eb67eecba63c55699f11", + "s": "0x72ef40cefb4fbfe2f54df284741effb28c2cf25128e3aec5003d9809c2e82d01", + "hash": "0x8f6cbdeadca58cca5c2d42b7f39d1806db196a4932785eea9c67d644664abb7c" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x14", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0xa68b33f12348a1053208c0783d7504f90a58da7f9ca2ead1275526cce7d700bd", + "s": "0x19c01948a0479c1a3774a203686acc9727830503fab6fdeed06b69e60b93755f", + "hash": "0x75376d730e7b5186a1e3e4e32c022308a2d66391f99dff2d59cf39e038b885c7" + } + ], + "uncles": null, + "receipts": null + } +} diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_6.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_6.json new file mode 100644 index 0000000000..afab478abe --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_6.json @@ -0,0 +1,390 @@ +{ + "acl_block_6": { + "rlp": "f911d6f901f6a000acaefd90b8d42561f10a6e20a23b94f045aa26d7134fabfbc34e5ff1c4e6d5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0acb9bda9ea5166689f2f8f67f60f64318ee0c7aed856eea3bb4249c5f2ad5a58a08af39529cb5c3295713bfac629dc4cc1bde29a12516e83a7cb8b202dea6f9cfca015eecb22e64ad01d793e4d4ff4ddd217d68f454307f933772da76f4ac75b667fb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000078347e7c48306190c4680a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90fd9b9029001f9028c86796f6c6f7632150a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000001a08a7ce0cf467cf9d04698c542fc7b7ef55651236b567a1dfed8dfc20f008f95d9a02ed15779e036579cd66a997a5ccb9626063fabe129d1a0f84d1addb8f3e30fbcb9028f01f9028b86796f6c6f7632160a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000809f051a77732323ba3f1e6442bff54782d2b80c30be64e1f74fec63eb74e3dadca05ee7edef5e1314dc96391cc67961785d37c597fb428a2498bd242c3dcd52a8f3b9029001f9028c86796f6c6f7632170a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000001a03ad054d140cb8053f42ac9df18fabb57a781a3132cee7d3bc98fcc380e6a1cc6a069c8972ded2412fb79a9dcb676daf6804aa5c7ebd3ff1aedd2a8481731506341b9029001f9028c86796f6c6f7632180a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a073ead15ab6ed0d83080db28bf82b89a80e7ecd74880f9a73fe0b8804882b2606a063458665267cffbe0ecfb343aad3559166c4e4c3c1e14eead7f3457fb3ea75eab9029001f9028c86796f6c6f7632190a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a04ac58f1d695790cc5156fcebfcf0cf8da35849c91fcc2cd05407055a675419aea05ebaa55e4a32ac00aefc8ca57cc0e36c3b1b4743f5b7274e49a11d6b9cc3047cb9029001f9028c86796f6c6f76321a0a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a0e38d4c971e4723dcac613f59975c5ea9b1200bc2b1569b820ddb6766eec521dea07a8f1d82a92f9937039cfe305a13ca54a8e6f22da2839430cfaeba4af65c2427f8661b0a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a075f7b1ed94b4206c1c8aa19422b4e8e9aaff7ad643a41364072880112e0785b4a0185475d900d76df4bf16a218f10ba336b7041134c90da33a0a16c6406564ba46c0", + "header": { + "parentHash": "0x00acaefd90b8d42561f10a6e20a23b94f045aa26d7134fabfbc34e5ff1c4e6d5", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xacb9bda9ea5166689f2f8f67f60f64318ee0c7aed856eea3bb4249c5f2ad5a58", + "transactionsTrie": "0x8af39529cb5c3295713bfac629dc4cc1bde29a12516e83a7cb8b202dea6f9cfc", + "receiptTrie": "0x15eecb22e64ad01d793e4d4ff4ddd217d68f454307f933772da76f4ac75b667f", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x7", + "gasLimit": "0x47e7c4", + "gasUsed": "0x6190c", + "timestamp": "0x46", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x2bb50258633ccfdf3f5b07258e3c9866ed9f878a7582230569d4ffc45952a66c" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x15", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x8a7ce0cf467cf9d04698c542fc7b7ef55651236b567a1dfed8dfc20f008f95d9", + "s": "0x2ed15779e036579cd66a997a5ccb9626063fabe129d1a0f84d1addb8f3e30fbc", + "hash": "0xef6960cc8cbb52be918b8e91c3574e8f07c714d2baf7320ffe2c71e20cd39103" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x16", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x51a77732323ba3f1e6442bff54782d2b80c30be64e1f74fec63eb74e3dadc", + "s": "0x5ee7edef5e1314dc96391cc67961785d37c597fb428a2498bd242c3dcd52a8f3", + "hash": "0x910bc3ffde097228c2d20d787bd90b9e277f987ea6972ff659503f8a074b78ff" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x17", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x3ad054d140cb8053f42ac9df18fabb57a781a3132cee7d3bc98fcc380e6a1cc6", + "s": "0x69c8972ded2412fb79a9dcb676daf6804aa5c7ebd3ff1aedd2a8481731506341", + "hash": "0x66dd5793d6ecbd978c41a5d15556f1a16a03fd15149809badab65f8f0b6809c7" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x18", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x73ead15ab6ed0d83080db28bf82b89a80e7ecd74880f9a73fe0b8804882b2606", + "s": "0x63458665267cffbe0ecfb343aad3559166c4e4c3c1e14eead7f3457fb3ea75ea", + "hash": "0xeba7afbdf52f13058232961a6d35b76a2901c32622da72daf20bee4362a457a0" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x19", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x4ac58f1d695790cc5156fcebfcf0cf8da35849c91fcc2cd05407055a675419ae", + "s": "0x5ebaa55e4a32ac00aefc8ca57cc0e36c3b1b4743f5b7274e49a11d6b9cc3047c", + "hash": "0xce8deb76b2475215931a1b5afd4deca2ba9f706bee21ca1e68671ed90177f785" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1a", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xe38d4c971e4723dcac613f59975c5ea9b1200bc2b1569b820ddb6766eec521de", + "s": "0x7a8f1d82a92f9937039cfe305a13ca54a8e6f22da2839430cfaeba4af65c2427", + "hash": "0x6de8e432fa9a3d8320397c7bece78828a47311a2a055a98e855aa4868bd8e351" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x1b", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0x75f7b1ed94b4206c1c8aa19422b4e8e9aaff7ad643a41364072880112e0785b4", + "s": "0x185475d900d76df4bf16a218f10ba336b7041134c90da33a0a16c6406564ba46", + "hash": "0x0dc4c78b1636726787970269ff17c855444e1d27eee8c0fd516e51176f574f71" + } + ], + "uncles": null, + "receipts": null + } +} \ No newline at end of file diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_7.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_7.json new file mode 100644 index 0000000000..0937f13d73 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_7.json @@ -0,0 +1,497 @@ +{ + "acl_block_7": { + "rlp": "f916e7f901f6a02bb50258633ccfdf3f5b07258e3c9866ed9f878a7582230569d4ffc45952a66ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0a55899fdbfa99a7feaabb51608ce4b0c2912596f2229ffeacb2ef05fb55b71b7a0e28fe6b703978af3d2eda206f6f959e2d833afaf418028a9503271f4f20a40d9a03f8954dac53eb0caa13809bae6c1bbfb729aa10778ac528e62113114b758e633b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000088347e7c48307b6585080a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f914eab902eb01f902e786796f6c6f76321c0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0643459a4e9aba8d232302442f95e7f6d89b06f273443a8710f9bb55496df1994a06e3f8765c4f399486454c64cf54b1396df2812c7d5fdcadb47a66f83ec553cd5b902eb01f902e786796f6c6f76321d0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a09862a3737fe1d45c7b256ff22a50d567b88c04212b39396ab41a1e9c62d4f44ea04c797c4b78681cc16aea9a18e59923264c744c17d9861560693473f927c28f54b902eb01f902e786796f6c6f76321e0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a08e24d4c713f644e38223cd600c56c65fd64d74fa3c1659ebf2ef719284c74802a00412a2733ba0c5fa7da40dc6b199351f0c04ed4c455607546d25d6efbc3e9a12b902eb01f902e786796f6c6f76321f0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0fc7721a6ca78e74eaadbbbbbfd6fa990fd9993a29a6d552f5c12d7256feebaa5a0166a3b40a0e0d86b95dac8a83dd1f0eb61f107bcb6f670cc114c3dd67f193d01b902eb01f902e786796f6c6f7632200a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0d1dac5d229b36766e7cc6a3d87596c6b72c1b579cccdc62a5b4438a04a46d3fea0053a8afe9e411247a65370e1d4e83cdcec9dc41a0b595999f3e41b07be014d10b902eb01f902e786796f6c6f7632210a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0251ab5147fb99b3c222fc99157ef6a6603659c2465bb9bb2662679fce6c12077a03c4ed0c45754fc479583126bf2d88c0bf323310f2f946f3bbeee44e73bf744c0b902eb01f902e786796f6c6f7632220a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0664de330a9c9b3e4041e347332a30d0f88358063de52c6cefcc5a8ce397f96f3a013ea85012f7a62739610e48ea51e170275c56f0f8d1896520f1ef84d4f3e389ef866230a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0a3bdc8174d2fbe9c404ff490e77555039f1c37bddbe60d8e60c1228f9964f02da015572f4a595159746f9f11554059312ccdbc05e6bf8831469338bb78dcb43b5ac0", + "header": { + "parentHash": "0x2bb50258633ccfdf3f5b07258e3c9866ed9f878a7582230569d4ffc45952a66c", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xa55899fdbfa99a7feaabb51608ce4b0c2912596f2229ffeacb2ef05fb55b71b7", + "transactionsTrie": "0xe28fe6b703978af3d2eda206f6f959e2d833afaf418028a9503271f4f20a40d9", + "receiptTrie": "0x3f8954dac53eb0caa13809bae6c1bbfb729aa10778ac528e62113114b758e633", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x8", + "gasLimit": "0x47e7c4", + "gasUsed": "0x7b658", + "timestamp": "0x50", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xfa221b6492050cfc24b906b20ce208b3dc4ba841e564395f2900c4a175158a1e" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1c", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x643459a4e9aba8d232302442f95e7f6d89b06f273443a8710f9bb55496df1994", + "s": "0x6e3f8765c4f399486454c64cf54b1396df2812c7d5fdcadb47a66f83ec553cd5", + "hash": "0x21840bf8b516a15569f253f9b7900d052f86f9173b02a240ccbddbc38f912498" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1d", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x9862a3737fe1d45c7b256ff22a50d567b88c04212b39396ab41a1e9c62d4f44e", + "s": "0x4c797c4b78681cc16aea9a18e59923264c744c17d9861560693473f927c28f54", + "hash": "0x5ed7369fea0e90818ced675a993efa699628286583417244fb136a4f73a2e90f" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1e", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x8e24d4c713f644e38223cd600c56c65fd64d74fa3c1659ebf2ef719284c74802", + "s": "0x412a2733ba0c5fa7da40dc6b199351f0c04ed4c455607546d25d6efbc3e9a12", + "hash": "0x24c0cd928e6bce21401dce170c98a80acd33ef4c6c6be3d0ea58127c0a049185" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x1f", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xfc7721a6ca78e74eaadbbbbbfd6fa990fd9993a29a6d552f5c12d7256feebaa5", + "s": "0x166a3b40a0e0d86b95dac8a83dd1f0eb61f107bcb6f670cc114c3dd67f193d01", + "hash": "0x755cc55d927e952bff7e51f70471c7a8b53cbbb76e855d0fe6148afc099967f8" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x20", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xd1dac5d229b36766e7cc6a3d87596c6b72c1b579cccdc62a5b4438a04a46d3fe", + "s": "0x53a8afe9e411247a65370e1d4e83cdcec9dc41a0b595999f3e41b07be014d10", + "hash": "0xabd736140ee8fe129b0db888c7808298e015be3f52cf530bfb064828b9801806" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x21", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x251ab5147fb99b3c222fc99157ef6a6603659c2465bb9bb2662679fce6c12077", + "s": "0x3c4ed0c45754fc479583126bf2d88c0bf323310f2f946f3bbeee44e73bf744c0", + "hash": "0x1c71ff8b515e449b4597ba4e08f4bd1558716e5253e9fb62c117a01f0c859124" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x22", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x664de330a9c9b3e4041e347332a30d0f88358063de52c6cefcc5a8ce397f96f3", + "s": "0x13ea85012f7a62739610e48ea51e170275c56f0f8d1896520f1ef84d4f3e389e", + "hash": "0x698566ee27aac8dda0c7bfd0b3e5b9c122a9ac81053dce700b3ef9fa156b35f7" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x23", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0xa3bdc8174d2fbe9c404ff490e77555039f1c37bddbe60d8e60c1228f9964f02d", + "s": "0x15572f4a595159746f9f11554059312ccdbc05e6bf8831469338bb78dcb43b5a", + "hash": "0x95aa3328bed08bb31056e79cdb10c890d3c645493c928e4546a2d65b821380ca" + } + ], + "uncles": null, + "receipts": null + } +} \ No newline at end of file diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_8.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_8.json new file mode 100644 index 0000000000..faf1292d28 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_8.json @@ -0,0 +1,619 @@ +{ + + "acl_block_8": { + "rlp": "f91cadf901f6a0fa221b6492050cfc24b906b20ce208b3dc4ba841e564395f2900c4a175158a1ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0b38b2ff96bb62a36840bd31e6b02a1ded156d8f571b35eef02d08f311fe03f65a08876562acbd95cb180c7599816bd6c954f8feadf02891b7c41b6369fb31c2e1ea0b78dc917392b3a6757a3545c29f0300f401c1d07303215ad0d4023a170a1c99fb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000098347e7c4830984145a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f91ab0b9034601f9034286796f6c6f7632240a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0d9c848f01ea535491946502971d8abd4640243394078a51efa4577c690910027a046c1247d86cb8b09209974eb3e667c82b81307c622124099c93a46811509dca6b9034601f9034286796f6c6f7632250a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a07595a92f015a9aeba3135f9fd3bcf743f058503f7e9dbc470d195d35bcb4eaa3a050cf2c39959208961f5bf9b890ec98473c631ba668b41455ed91c8711bc5c7b2b9034601f9034286796f6c6f7632260a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0949a0a2f11aa9958d32c9e4d734497ed74dd851d57b28981f606e5be517a2f56a05493ccac5f48b724388a824ee3df6c0c54922faea0ed911cd6e7993d72e105b0b9034601f9034286796f6c6f7632270a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a03eae4a21a7648d2b33940a601a37bc24eb1f0472611a3321867edf423970db98a02a87c17c6c8116a0df110e51da727d953569e5f48f61d80f6e7aa67ee88491d0b9034601f9034286796f6c6f7632280a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a07fcccf7db8f6f715b4467798328ecd812de95a9e00b16064108f220c131b1feba00b32d45c342f74907d7999a4bfc13b2bc0f6dee4336fdfb4847e182f80204785b9034601f9034286796f6c6f7632290a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0b25c865ca6bd22c9dc046adc53d7419d9696a13f16baf97593672f2033c200c1a061b26c60cfa8af36154a4555c20501c30af193104a779ac20266e8a09da30b6bb9034601f9034286796f6c6f76322a0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0f97719ddd5d72d9269b5fe95b7646cc2719d67824a7784bea322afdcd79ce119a022e4250977257258c863fcb766b88494b884750fa6023db8410fac8a0a100eadb9034601f9034286796f6c6f76322b0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a073c0c49e7f0c7c4343c80d726733c06810b8efeee8907f2fc65519258a93fa67a0140d4d304c84d40e85e98eb5f073698f9f0d44f9051c25e98aa3da1f975cb771f8662c0a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a04a8911c73aa392f7472d0f3b8de07c06df21cec19b50eb5b913f2b4d4e9b3d6aa00a9d8d20c17644f8db37b6a2f00dc330a8c3c09f5fc5aa065f2410e3a3340a9dc0", + "header": { + "parentHash": "0xfa221b6492050cfc24b906b20ce208b3dc4ba841e564395f2900c4a175158a1e", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xb38b2ff96bb62a36840bd31e6b02a1ded156d8f571b35eef02d08f311fe03f65", + "transactionsTrie": "0x8876562acbd95cb180c7599816bd6c954f8feadf02891b7c41b6369fb31c2e1e", + "receiptTrie": "0xb78dc917392b3a6757a3545c29f0300f401c1d07303215ad0d4023a170a1c99f", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x9", + "gasLimit": "0x47e7c4", + "gasUsed": "0x98414", + "timestamp": "0x5a", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x84dda3788f42b7e41a084407d725a58c201ce7cfadd97e886cb976dda22c9921" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x24", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xd9c848f01ea535491946502971d8abd4640243394078a51efa4577c690910027", + "s": "0x46c1247d86cb8b09209974eb3e667c82b81307c622124099c93a46811509dca6", + "hash": "0xaf54d730700aef32f551db22595085bf45e85e605d75484e89a727527e96129b" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x25", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x7595a92f015a9aeba3135f9fd3bcf743f058503f7e9dbc470d195d35bcb4eaa3", + "s": "0x50cf2c39959208961f5bf9b890ec98473c631ba668b41455ed91c8711bc5c7b2", + "hash": "0xde28554defa0795db3c147bda91a23ffcb30b80cf26f28ab96d6ead60a69d2b9" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x26", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x949a0a2f11aa9958d32c9e4d734497ed74dd851d57b28981f606e5be517a2f56", + "s": "0x5493ccac5f48b724388a824ee3df6c0c54922faea0ed911cd6e7993d72e105b0", + "hash": "0x285d3401abaa281c502acc4bf59ec59a6c7bce62f9a46bfc6b3100b97152f528" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x27", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x3eae4a21a7648d2b33940a601a37bc24eb1f0472611a3321867edf423970db98", + "s": "0x2a87c17c6c8116a0df110e51da727d953569e5f48f61d80f6e7aa67ee88491d0", + "hash": "0x85c6d289b56245b7b6e4ccdd514e2b6792c9f3e956ea4968d69593a3030f4499" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x28", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x7fcccf7db8f6f715b4467798328ecd812de95a9e00b16064108f220c131b1feb", + "s": "0xb32d45c342f74907d7999a4bfc13b2bc0f6dee4336fdfb4847e182f80204785", + "hash": "0x846c5fce7829817683d7be03b6f08f39ef79dbeed0ec64e1901962f8d83ddedd" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x29", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xb25c865ca6bd22c9dc046adc53d7419d9696a13f16baf97593672f2033c200c1", + "s": "0x61b26c60cfa8af36154a4555c20501c30af193104a779ac20266e8a09da30b6b", + "hash": "0xeddbe8867f8555f92fdd42d03872467509551a645f7bd92a050fbabaf506865c" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x2a", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xf97719ddd5d72d9269b5fe95b7646cc2719d67824a7784bea322afdcd79ce119", + "s": "0x22e4250977257258c863fcb766b88494b884750fa6023db8410fac8a0a100ead", + "hash": "0x026824663c75c144366419e4448cb29453f70d891245e0264bf94c9478bc28ae" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x2b", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x73c0c49e7f0c7c4343c80d726733c06810b8efeee8907f2fc65519258a93fa67", + "s": "0x140d4d304c84d40e85e98eb5f073698f9f0d44f9051c25e98aa3da1f975cb771", + "hash": "0x877c3067e2ead44ec4be1d4dcda3571213325d93291f32c3f674cff01947cf0a" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x2c", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0x4a8911c73aa392f7472d0f3b8de07c06df21cec19b50eb5b913f2b4d4e9b3d6a", + "s": "0xa9d8d20c17644f8db37b6a2f00dc330a8c3c09f5fc5aa065f2410e3a3340a9d", + "hash": "0xca741c6398b7e3bfdafc46c3c97ac22a8c1002744231e1702c0bbc2245d2ba34" + } + ], + "uncles": null, + "receipts": null + } +} \ No newline at end of file diff --git a/crates/ethcore/res/local_tests/block_en_de/acl_block_9.json b/crates/ethcore/res/local_tests/block_en_de/acl_block_9.json new file mode 100644 index 0000000000..99884804fa --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/acl_block_9.json @@ -0,0 +1,754 @@ +{ + + "acl_block_9": { + "rlp": "f92329f901f6a084dda3788f42b7e41a084407d725a58c201ce7cfadd97e886cb976dda22c9921a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a091503e4466860227794cecc7e441abc9bad4ef57114c08af408cb6bf58980235a0de7408c49f9332211cbf0ea0d6d6697ee9ebef4b9cb53869168834956153d45ca0c18851ede636a1298652a8dd6bffb065e7c198417660bf20f97731be93d46cefb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000a8347e7c4830b82406480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f9212cb903a101f9039d86796f6c6f76322d0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a0cc5c7d6d2250816d5cebafe393914fd6ff39702ef9647d907c196c4240858446a068082151d6d9fbe47e3fed849328dce66ab6b0976a106d0a5423b18b0be201e2b903a101f9039d86796f6c6f76322e0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a005620469222dcdb8378eecec565b89c69d653397b14160ff49052ac67699150ea06f343d9c86ee05ff23f562d5b21f763a34ecf00cda60b267f9dc124661dd69c7b903a101f9039d86796f6c6f76322f0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a072b8ee28e31595dc01388151d9a293a832dfca58c22d48d8c24681e5e52b95f0a0156cd769bbcafaca1ce2691542aafc05ec3156dee26988d780e2915f67415437b903a101f9039d86796f6c6f7632300a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a022ffc9f0594be343e16e448e15aa2298f097c88c8e951020e9055f70537e6cbba022d8161cd97590d9fdfe61bc0ce34face1a221f6d9a50c96ffc185c7b6eb1a33b903a101f9039d86796f6c6f7632310a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0e9834fd907d82587ac1c3d1f4998fbe914142834ec86e34293e11d22279eb6f4a0594a4a7b79798e466e41125fcfa9c08e548a4f6bba7bab3a17769d6cd15d4926b903a101f9039d86796f6c6f7632320a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a0cad758b73761dc79fbe62ea6ecae306c2f8a9a614bddd2ee379f9924ecf26d9ba006d5955b0769de282012278bf43d83bbee144dc61893d2d0f1daad9463af9677b903a101f9039d86796f6c6f7632330a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a01bd327017a42d3bdce1b192716c730eda6b990d9f12ee14286872daa5a36ecf8a0407ec3dd532be0377aa774e6352fa12e15f1ce8e09a39a520449b2a6bbf2d0aab903a101f9039d86796f6c6f7632340a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a001a2f42cdd339b157cd736cade0641489bf345f6bc0a657075d329797a9ef331a0696ca3e566854a52d4b6514fcfddf796dfa18762ce350d86d14612b0e177ccc2b903a101f9039d86796f6c6f7632350a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a02f63a43500e78623d38149a0bd2a331c616202312aff7d4047ee080c02139e7aa021d1a2144e9fea759d3e650a91f576b9a502c4a84cab745f8c9b8e15618c33cdf866360a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec87a0ed4c15a3ff67c17eef207d8e7beef31af80a63ab8e03738c10f1483f7e8f6203a0495d2bea850f073e20c79fbef96ccab6ca3367059e3fa4704f8f22f48dc318cac0", + "header": { + "parentHash": "0x84dda3788f42b7e41a084407d725a58c201ce7cfadd97e886cb976dda22c9921", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x91503e4466860227794cecc7e441abc9bad4ef57114c08af408cb6bf58980235", + "transactionsTrie": "0xde7408c49f9332211cbf0ea0d6d6697ee9ebef4b9cb53869168834956153d45c", + "receiptTrie": "0xc18851ede636a1298652a8dd6bffb065e7c198417660bf20f97731be93d46cef", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0xa", + "gasLimit": "0x47e7c4", + "gasUsed": "0xb8240", + "timestamp": "0x64", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xd8e7665bdcb0b053e18bc9dc565765b3c93aaf3938d03a6b24df816dbc44f5df" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x2d", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xcc5c7d6d2250816d5cebafe393914fd6ff39702ef9647d907c196c4240858446", + "s": "0x68082151d6d9fbe47e3fed849328dce66ab6b0976a106d0a5423b18b0be201e2", + "hash": "0xf59de76965a4c6ab43ba656320bcc151c1c5b2dd3e9c61077bfada88c60f9d91" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x2e", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x5620469222dcdb8378eecec565b89c69d653397b14160ff49052ac67699150e", + "s": "0x6f343d9c86ee05ff23f562d5b21f763a34ecf00cda60b267f9dc124661dd69c7", + "hash": "0xf9800f0463832ba38394196d74415d925b0fe48a6accc44fce76294cef1c6542" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x2f", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x72b8ee28e31595dc01388151d9a293a832dfca58c22d48d8c24681e5e52b95f0", + "s": "0x156cd769bbcafaca1ce2691542aafc05ec3156dee26988d780e2915f67415437", + "hash": "0x8d7f71e167aed00e7f98a3d6efef0455a915affcff0b6d96ac26e65bb65a6ce9" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x30", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x22ffc9f0594be343e16e448e15aa2298f097c88c8e951020e9055f70537e6cbb", + "s": "0x22d8161cd97590d9fdfe61bc0ce34face1a221f6d9a50c96ffc185c7b6eb1a33", + "hash": "0x478e063e01971fa8990da37b2709d4b7f53c3724df94d9bdf685cc1c3eafb459" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x31", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xe9834fd907d82587ac1c3d1f4998fbe914142834ec86e34293e11d22279eb6f4", + "s": "0x594a4a7b79798e466e41125fcfa9c08e548a4f6bba7bab3a17769d6cd15d4926", + "hash": "0x6e6eb6cfc365c3ee3e4b575d92844c7742505b62aa3d5765a41bcf7f61d787b1" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x32", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xcad758b73761dc79fbe62ea6ecae306c2f8a9a614bddd2ee379f9924ecf26d9b", + "s": "0x6d5955b0769de282012278bf43d83bbee144dc61893d2d0f1daad9463af9677", + "hash": "0x79de88fa2ac7f1ef13e596f9c4732fd06eaa968b5afd9fd6efa9564ddedd04e4" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x33", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x1bd327017a42d3bdce1b192716c730eda6b990d9f12ee14286872daa5a36ecf8", + "s": "0x407ec3dd532be0377aa774e6352fa12e15f1ce8e09a39a520449b2a6bbf2d0aa", + "hash": "0x849ad53627a411a79641b82d23f40f76544ef7cc185518560810c02cd163dddf" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x34", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x1a2f42cdd339b157cd736cade0641489bf345f6bc0a657075d329797a9ef331", + "s": "0x696ca3e566854a52d4b6514fcfddf796dfa18762ce350d86d14612b0e177ccc2", + "hash": "0xbae361665e925aa04f59f41a7f23bac56bd69ca40262cb55afc6a9446aa12f77" + }, + { + "type": "0x1", + "chainId": "0x796f6c6f7632", + "nonce": "0x35", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x2f63a43500e78623d38149a0bd2a331c616202312aff7d4047ee080c02139e7a", + "s": "0x21d1a2144e9fea759d3e650a91f576b9a502c4a84cab745f8c9b8e15618c33cd", + "hash": "0x8d7a600d5de038029800c6d10b5dbd5ace67324fd75dfe3e31f5b48ce6a19b9c" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x36", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0xf2ded8deec87", + "r": "0xed4c15a3ff67c17eef207d8e7beef31af80a63ab8e03738c10f1483f7e8f6203", + "s": "0x495d2bea850f073e20c79fbef96ccab6ca3367059e3fa4704f8f22f48dc318ca", + "hash": "0xefe1036e9043183eb61a8042ca97c8260da7eb2ef1d6969d9404e1e6ec48f490" + } + ], + "uncles": null, + "receipts": null + } +} \ No newline at end of file diff --git a/crates/ethcore/res/local_tests/block_en_de/simple.json b/crates/ethcore/res/local_tests/block_en_de/simple.json new file mode 100644 index 0000000000..bdb7b1f1a5 --- /dev/null +++ b/crates/ethcore/res/local_tests/block_en_de/simple.json @@ -0,0 +1,38 @@ +{ + "legacy_block": { + "rlp": "f90263f901f5a0151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23faa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79a0e8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4a07f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48262740a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f868f866800a8301e24194000000000000000000000000000000000000aaaa808086f2ded8deec88a0e7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194bea04d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bfc0", + "header": { + "parentHash": "0x151b04645af991f513d5e11f8ed62e12b73f080af9c7a6a3d98fd6b1503f23fa", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x968408b8a2f170bc78230cc2fac3881120a93f7392cf26b609566d8648abfd79", + "transactionsTrie": "0xe8137f2b67ac4680d8103f8b1cd7c05c49f56e4df464b0a79253679f38df9ab4", + "receiptTrie": "0x7f53535270d749f41b9d783aa1abcfceb73cc2a16ecde789cd3bc97a42fbda2a", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x1", + "gasLimit": "0x47e7c4", + "gasUsed": "0x6274", + "timestamp": "0xa", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x9aa9cdb2afc4ebf893c32b67dedf1dea4291673bf4e80d3227a4e7f8d0feaf68" + }, + "transactions": [ + { + "nonce": "0x0", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "v": "0xf2ded8deec88", + "r": "0xe7545c5664e63873d7aeb4bb5f92152c3366a9095c9140e5f8453af0998194be", + "s": "0x4d24143ac9bc97c0aa07a7074c12ab60484d83d3b447b1e5e6ba5cbf421675bf", + "hash": "0x7e122173adcc02b9a3c94da426f65c7d46e724e8e3fdb16be73d5e0405e280b6" + } + ], + "uncleHeaders": null + } +} diff --git a/crates/ethcore/res/local_tests/chain/eip2930.json b/crates/ethcore/res/local_tests/chain/eip2930.json new file mode 100644 index 0000000000..241030b1b4 --- /dev/null +++ b/crates/ethcore/res/local_tests/chain/eip2930.json @@ -0,0 +1,3149 @@ +{ + "testEIP2930_transactions": { + "_info": { + "comment": "Local test for EIP-2930" + }, + "genesisBlockHeader": { + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x020000", + "extraData": "0x", + "gasLimit": "0x47e7c4", + "gasUsed": "0x00", + "hash": "0xf0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000539", + "number": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot": "0xf24461ff2b080dba58ee5fa4b546efbadb7b74b33b8ce3ac5b8bf84b5cad5d27", + "timestamp": "0x00", + "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre": { + "000000000000000000000000000000000000aaaa": { + "balance": "0x0", + "code": "0x5854505854503231" + }, + "71562b71999873db5b286df957af199ec94617f7": { + "balance": "0x3b9aca00" + } + }, + "network": "EIP2930", + "sealEngine": "NoProof", + "lastblockhash": "0x105d8befc05cb9c21add67408bcc7512de148cd9a7cc8932efa294e2672aba55", + "blocks": [ + { + "rlp": "f9025df901f5a0f0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0007b54c20187b01cb2caad4dd377234b591ffc3502590d7b05ef2949785542b2a0076eed3b92e039d9b8e35b21d5603350177b75c35c8ee13654f582f21a92dd69a0ea2fe1d08440864d23add61591d18dd8900e010ceca13b5ae797c699a44b5684b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48262de0a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a8301e24194000000000000000000000000000000000000aaaa808025a04a8784ece5812005fadff24bee6b002f3b736196c97fa73e31a015d89731a9dba07fb3784b5bbd59d2a00acdc86cb84f8b279f5f80b4af9d0e944f06ba5388c811c0", + "header": { + "parentHash": "0xf0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x007b54c20187b01cb2caad4dd377234b591ffc3502590d7b05ef2949785542b2", + "transactionsTrie": "0x076eed3b92e039d9b8e35b21d5603350177b75c35c8ee13654f582f21a92dd69", + "receiptTrie": "0xea2fe1d08440864d23add61591d18dd8900e010ceca13b5ae797c699a44b5684", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x1", + "gasLimit": "0x47e7c4", + "gasUsed": "0x62de", + "timestamp": "0xa", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xb44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7" + }, + "transactions": [ + { + "nonce": "0x0", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "v": "0x25", + "r": "0x4a8784ece5812005fadff24bee6b002f3b736196c97fa73e31a015d89731a9db", + "s": "0x7fb3784b5bbd59d2a00acdc86cb84f8b279f5f80b4af9d0e944f06ba5388c811", + "hash": "0x8dea84417453c9cc0dbbcdf9224fc37cbe93b6e8a9ffdb8e7eb3ddeedd43c375" + } + ], + "uncleHeaders": null + }, + { + "rlp": "f90321f901f5a0b44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0ed1f713ffe43640afc36f435f181056c1a960b2ddcd6714dbef775ade09aa2c9a0ea2164b24b79d9708108afa05a267ddbf42971d34a215dd6158fb48776932c0ea0543bb9ba3c84c66db2c71d2cc38a17d6e708597dd397b0e8946e36a9eca94f1eb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000028347e7c482ddf41480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90125b8c101f8be01010a8301e24194000000000000000000000000000000000000aaaa8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000080a082dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234dba072228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0f860020a8301e24194000000000000000000000000000000000000aaaa808026a09756172d336ab702075c6dbaaa979455c385aa03039d601205350680c4eff09ca03000821620e1771ca10b4b3639bb8932e2cb1f91f90714cf0cc4d6b418f944f1c0", + "header": { + "parentHash": "0xb44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xed1f713ffe43640afc36f435f181056c1a960b2ddcd6714dbef775ade09aa2c9", + "transactionsTrie": "0xea2164b24b79d9708108afa05a267ddbf42971d34a215dd6158fb48776932c0e", + "receiptsTrie": "0x543bb9ba3c84c66db2c71d2cc38a17d6e708597dd397b0e8946e36a9eca94f1e", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x2", + "gasLimit": "0x47e7c4", + "gasUsed": "0xddf4", + "timestamp": "0x14", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x45ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26d" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x82dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234db", + "s": "0x72228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0", + "hash": "0x41760e65a1d237e001cfe56427ebb03f0c377f6fa17ae19ec00d40a363ae16be" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x2", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0x9756172d336ab702075c6dbaaa979455c385aa03039d601205350680c4eff09c", + "s": "0x3000821620e1771ca10b4b3639bb8932e2cb1f91f90714cf0cc4d6b418f944f1", + "hash": "0x7c331109477a2ebca4778b7818a367e5b7bda7e056bbcf64837cd0c62e008431" + } + ], + "uncles": null + }, + { + "rlp": "f9049ff901f6a045ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a009b41b08cacf63fd56a588d65befca63f4799dd457ccfcffc1b7ff8b7c899026a0a7c68fc60a677940cb5c3e2ecbeff781ba95eb2dc5edbe041d1a569fa98b9070a03a26b9965725737c7bdaa1de02677d782a1148027aa3a5bbf29658d16013cb4cb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000038347e7c48301897a1e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f902a2b9011d01f9011901030a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a0748de538b4a9502e4bf7d7c29ee80dcd342e802518257260c318877c1306e455a043faaa4d106d49940a193f6016c10159a9013074951ff718404b1f717d274887b9011d01f9011901040a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000080a0a831c9d4a1e27dbc92a5558cdc3006a42d5cd38c6e18052ab280674e7e6d1009a04c09b35aba855dd92c2e67411f2345374ab54c110cc9f248dea3777310a11a35f860050a8301e24194000000000000000000000000000000000000aaaa808026a0f3d58c384589aa560311587a19a39acfbed506b50b6332455f8a01b7a4a0b208a0710821dcc271fbf3bf0cd2ed45ebf7d212095b2d7b743c6ddc5f0bd220c692b4c0", + + "header": { + "parentHash": "0x45ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26d", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x09b41b08cacf63fd56a588d65befca63f4799dd457ccfcffc1b7ff8b7c899026", + "transactionsTrie": "0xa7c68fc60a677940cb5c3e2ecbeff781ba95eb2dc5edbe041d1a569fa98b9070", + "receiptsTrie": "0x3a26b9965725737c7bdaa1de02677d782a1148027aa3a5bbf29658d16013cb4c", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x3", + "gasLimit": "0x47e7c4", + "gasUsed": "0x1897a", + "timestamp": "0x1e", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x6e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290fa" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x3", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x748de538b4a9502e4bf7d7c29ee80dcd342e802518257260c318877c1306e455", + "s": "0x43faaa4d106d49940a193f6016c10159a9013074951ff718404b1f717d274887", + "hash": "0x418a0f670998b3e1ca5250843306910bb7546acb1c04f491350a8033d912bdaf" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x4", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xa831c9d4a1e27dbc92a5558cdc3006a42d5cd38c6e18052ab280674e7e6d1009", + "s": "0x4c09b35aba855dd92c2e67411f2345374ab54c110cc9f248dea3777310a11a35", + "hash": "0x016263d1b70105fb24bba2ff1bae4ec620d7481318e6d0974aa96fb202724c53" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x5", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0xf3d58c384589aa560311587a19a39acfbed506b50b6332455f8a01b7a4a0b208", + "s": "0x710821dcc271fbf3bf0cd2ed45ebf7d212095b2d7b743c6ddc5f0bd220c692b4", + "hash": "0x703e00e61cd19d8dbbd58a15f885fe3d82954a6c7f1854e64df9d8c9a839d2dd" + } + ], + "uncles": null + }, + { + "rlp": "f906d3f901f6a06e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290faa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0e80199c64d2bee27c7a1be67fe8b01020a9231e172da0d6fabca44d98864a5d4a08c70cadb678d31ea2a57b14ae2e7eaab22c7a816f5d3ee94091db45f1a4af49ea0aa5401f56c2e0708e601d13442bf1827d6554607ef573f08f8d2ebf51e948dd8b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000048347e7c4830265702880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f904d6b9017901f9017501060a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a07e3e6761f5735046aa7c8c495159186e0e017c7cad769757d3b993fcf84bb936a0503471fceed0db87a3c62f8686c09eab381354506c648ad2ea46d9076b87664eb9017901f9017501070a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a076012a1e4b16f5bc566caf00e901121c3b55bc26a225d772dad4858cd9aeadcca00ea768134e684c0561b0b22e0c7db3246fafb82c56bc0e7d58aed1c7e67ef423b9017901f9017501080a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0d4a82519d087bbce6e55aaa4775ad916200ab69b47a472e28837956c24f40feea04cf399e1fb199615600b77c9601dcbc7bc41b25dc4351842a36aa69ce597ee9bf860090a8301e24194000000000000000000000000000000000000aaaa808025a0c1761a83dfd95d3c129280692c9fecb528a914d5c6441fe55eb942e58aa066b0a0605fc74c46a2a75de2e05c03d11518930b809c504833152116c8ccfb8685986ec0", + + "header": { + "parentHash": "0x6e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290fa", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xe80199c64d2bee27c7a1be67fe8b01020a9231e172da0d6fabca44d98864a5d4", + "transactionsTrie": "0x8c70cadb678d31ea2a57b14ae2e7eaab22c7a816f5d3ee94091db45f1a4af49e", + "receiptsTrie": "0xaa5401f56c2e0708e601d13442bf1827d6554607ef573f08f8d2ebf51e948dd8", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x4", + "gasLimit": "0x47e7c4", + "gasUsed": "0x26570", + "timestamp": "0x28", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x6", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x7e3e6761f5735046aa7c8c495159186e0e017c7cad769757d3b993fcf84bb936", + "s": "0x503471fceed0db87a3c62f8686c09eab381354506c648ad2ea46d9076b87664e", + "hash": "0x4f66c5df18e409248018353adfe21033c44badfe7083a6980f574aff886dae3e" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x7", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x76012a1e4b16f5bc566caf00e901121c3b55bc26a225d772dad4858cd9aeadcc", + "s": "0xea768134e684c0561b0b22e0c7db3246fafb82c56bc0e7d58aed1c7e67ef423", + "hash": "0xf90baa5007a69f5469b887e2d2a7f817bb274ce841ec5afc5f45f8c7bc6be0b5" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x8", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xd4a82519d087bbce6e55aaa4775ad916200ab69b47a472e28837956c24f40fee", + "s": "0x4cf399e1fb199615600b77c9601dcbc7bc41b25dc4351842a36aa69ce597ee9b", + "hash": "0x251d97291fa072eff47197043843376c29efc4fcd6b23d78867d6225e6ccdcaa" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x9", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x25", + "r": "0xc1761a83dfd95d3c129280692c9fecb528a914d5c6441fe55eb942e58aa066b0", + "s": "0x605fc74c46a2a75de2e05c03d11518930b809c504833152116c8ccfb8685986e", + "hash": "0xdd8271981828697d28de1c2d1148458a30c5e86464484f1695ff21e56d83bc91" + } + ], + "uncles": null + }, + { + "rlp": "f909bbf901f6a0160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a02dd6f4e5613640e8ae817f50e3538926b946632953b2ef14f47e21ab2a1f0bcaa0d663e9fec41620bc34664fd2ab65046c6d5de9306d2d710425d01ddd7c767683a09dec9f28e6d236deda6a9d0aeff7271bef8649c01f14232a2a8b59293a4864acb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000058347e7c4830371d63280a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f907beb901d401f901d0010a0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a0f345e830d6eb32d68ff5e9c2bf35308b891a5901c28bb1c04f6b04313d691cf4a0373dfbd0ffa2339e007dfc5f1a1c4fd3aa73efb9419ebb7e53db6bc84c976240b901d401f901d0010b0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a060f333f746a7b18a39d3a0401eaa346cfc424fcb054cffa349f99130597b6f4aa02ca60577b215332a1c248e85b9b93664054af3701f0a6f5c553e180e7dcdb4e8b901d401f901d0010c0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a0479dfabb47ad82e5e5c1b0629fc87b715e3a0ba698c6bee3ff9bd29ef84a1e93a0381d0c2994e6e97f646ca1864ec1f66ae0c47a8fcfdef882041e6db8d413d1d0b901d401f901d0010d0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a08d36697d1b52d80b56113e088245173946fde2e72c29ffa2d0289b39dc9100e5a05758c471f9ca7c197e7e7f9b29cb134dc8f4e67aec83c8a52e05b8831a577e85f8600e0a8301e24194000000000000000000000000000000000000aaaa808026a0db585ae1362cccecf8c2cf6953207d4cfe0eb30aaddf750aa55a0b8a459ab22aa053aac6352d9a6b9599dfa512b2a01a1cf3498428cf96136fab5ec7c305acb462c0", + + "header": { + "parentHash": "0x160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x2dd6f4e5613640e8ae817f50e3538926b946632953b2ef14f47e21ab2a1f0bca", + "transactionsTrie": "0xd663e9fec41620bc34664fd2ab65046c6d5de9306d2d710425d01ddd7c767683", + "receiptsTrie": "0x9dec9f28e6d236deda6a9d0aeff7271bef8649c01f14232a2a8b59293a4864ac", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x5", + "gasLimit": "0x47e7c4", + "gasUsed": "0x371d6", + "timestamp": "0x32", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xe5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0xa", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xf345e830d6eb32d68ff5e9c2bf35308b891a5901c28bb1c04f6b04313d691cf4", + "s": "0x373dfbd0ffa2339e007dfc5f1a1c4fd3aa73efb9419ebb7e53db6bc84c976240", + "hash": "0xb7b9c42dcc90d9856bf566ef1744c98fa17393ca720420c4d1dda1098c2f537d" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0xb", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x60f333f746a7b18a39d3a0401eaa346cfc424fcb054cffa349f99130597b6f4a", + "s": "0x2ca60577b215332a1c248e85b9b93664054af3701f0a6f5c553e180e7dcdb4e8", + "hash": "0x1b57c427bb124ed65ab83db75ddb5af12aeaa66affd902b684b4bab6ebf31817" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0xc", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x479dfabb47ad82e5e5c1b0629fc87b715e3a0ba698c6bee3ff9bd29ef84a1e93", + "s": "0x381d0c2994e6e97f646ca1864ec1f66ae0c47a8fcfdef882041e6db8d413d1d0", + "hash": "0x6642d59ce47df5df3b0ff96829f56264171dbfca7bdbf8b3caaead85ab17ce9b" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0xd", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x8d36697d1b52d80b56113e088245173946fde2e72c29ffa2d0289b39dc9100e5", + "s": "0x5758c471f9ca7c197e7e7f9b29cb134dc8f4e67aec83c8a52e05b8831a577e85", + "hash": "0x7087dd064ddd164d8564913acde103d30d1e6ffd3c4b828242ab5662c5d27f98" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0xe", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0xdb585ae1362cccecf8c2cf6953207d4cfe0eb30aaddf750aa55a0b8a459ab22a", + "s": "0x53aac6352d9a6b9599dfa512b2a01a1cf3498428cf96136fab5ec7c305acb462", + "hash": "0xa6ded463647cde7d52f6889b7f3c0a142cf3d82b1d3cca606c72a08ee64129f1" + } + ], + "uncles": null + }, + { + "rlp": "f90d59f901f6a0e5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a07f2172fc6b1093884e559297c4161da6687ccf9405841d5e5cb79566e1698540a0f881eb8830d5ed90a6d1de5ef56dbd715bf679721aa70ccc2fde6050558fe065a03c399ef07b92c03dd962c9b51708ec00bfa279dad6afda270f332f79e3e60db4b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000068347e7c48304aeac3c80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90b5cb9022f01f9022b010f0a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a0cfbef0051e5b8a313532cc98410f5135948915a3d046ac28083d0d8f0fdfa660a05520ab4a5ce35c1d8c70cff148eefe0a2833ba0ed6f2781f839cc7edc8bf575eb9022f01f9022b01100a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a0d42a5ec165486f09e6d8faf3a93c87c4f0cc6b4d15ebbc2dedca7e4ef35a4555a00c129f489b2213092f5863b7a936ece05bdcb26a4513603c9f4b84ab0d9acd15b9022f01f9022b01110a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a0307eb02650c740c599c347d7dad1b390fa8dc24d216eb2ba769dc711aae32789a077af8cfb89aa87266d3b691ddb75be4221fb2b188e1c4470daaa707d44161200b9022f01f9022b01120a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a044ef64e26f79482731ceaef418439ebb497806df367f598ebf5d9981f5414a4da04b0d7d566fb8e7cba207385fdad173c9f961fe23fe3961e07c4a31df20c31a03b9022f01f9022b01130a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a078688c9ef5a7925528910547dc39f1b359a5e230f850310f599098c32876443ea06462d6bc2778d84c5af517d383483e0685b8fccbd424196951c1e509964a27e0f860140a8301e24194000000000000000000000000000000000000aaaa808025a0ec8f9c89aa1f4f795d8b45ff41c871721d994858a1374411c4878532001a4ba5a027f11a383c603c28321baad48830d6090c9b0164e2d26d632a73ecd809ae53c7c0", + + "header": { + "parentHash": "0xe5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x7f2172fc6b1093884e559297c4161da6687ccf9405841d5e5cb79566e1698540", + "transactionsTrie": "0xf881eb8830d5ed90a6d1de5ef56dbd715bf679721aa70ccc2fde6050558fe065", + "receiptsTrie": "0x3c399ef07b92c03dd962c9b51708ec00bfa279dad6afda270f332f79e3e60db4", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x6", + "gasLimit": "0x47e7c4", + "gasUsed": "0x4aeac", + "timestamp": "0x3c", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x5ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0xf", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xcfbef0051e5b8a313532cc98410f5135948915a3d046ac28083d0d8f0fdfa660", + "s": "0x5520ab4a5ce35c1d8c70cff148eefe0a2833ba0ed6f2781f839cc7edc8bf575e", + "hash": "0x8bc25d0f8a8a24ba715fdd3f29e7f7302befa1446b4736538d45e3862cf67631" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x10", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xd42a5ec165486f09e6d8faf3a93c87c4f0cc6b4d15ebbc2dedca7e4ef35a4555", + "s": "0xc129f489b2213092f5863b7a936ece05bdcb26a4513603c9f4b84ab0d9acd15", + "hash": "0x96132f15280252a7ca473a4a5f4c126f610d34f2007cda6b0007a003ef6fd6ec" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x11", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x307eb02650c740c599c347d7dad1b390fa8dc24d216eb2ba769dc711aae32789", + "s": "0x77af8cfb89aa87266d3b691ddb75be4221fb2b188e1c4470daaa707d44161200", + "hash": "0x377ead486a6468dcd837e8047543ceb4dfa65684f927eca80f40adf7144dcbba" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x12", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x44ef64e26f79482731ceaef418439ebb497806df367f598ebf5d9981f5414a4d", + "s": "0x4b0d7d566fb8e7cba207385fdad173c9f961fe23fe3961e07c4a31df20c31a03", + "hash": "0x3f92ce1202d56635eb6c088f1cd3a6604dae60f3100a68f330d1722c324f2ab4" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x13", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x78688c9ef5a7925528910547dc39f1b359a5e230f850310f599098c32876443e", + "s": "0x6462d6bc2778d84c5af517d383483e0685b8fccbd424196951c1e509964a27e0", + "hash": "0x029b987cd062bc3e738d944990266cffeaed74340531450373d34666ad4fabd6" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x14", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x25", + "r": "0xec8f9c89aa1f4f795d8b45ff41c871721d994858a1374411c4878532001a4ba5", + "s": "0x27f11a383c603c28321baad48830d6090c9b0164e2d26d632a73ecd809ae53c7", + "hash": "0xc79cc4aae86b02b8b9787867a98670cf6d022af0fee3c0a3abdbddf29f21f7df" + } + ], + "uncles": null + }, + { + "rlp": "f911adf901f6a05ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0dd07cac1fd50a2d47b3faf9514b2a3e385fcd6e3102760f6bea1f919515cacffa0637d26d4cecdd55c7927c6d203ce40b7d9faf363fff990c3fc5e502f5edc1eada0ed9cc53fd0eee79528719ca973156891c6be9ddfe7bb9a788d4a3bc1d261773bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000078347e7c483061bf24680a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90fb0b9028a01f9028601150a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a069e444997b9e7db9d3c351acb17da1666358ec8ce1fe34e6084f7347bfcfa83aa064e539a2efbab6c0ec01f1d6d38bf97218a3e42db66a84e35945f65afc4af52cb9028a01f9028601160a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a0a3290dc9c69c2ddd720698de596e2585102f14a5fafa3332abb0fe3e7857a58ba00ad0540e2e37a1fc9a0c03b3a69c420210f86331641c4ee8cf8005cd44db7b5eb9028a01f9028601170a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a0423621e9b3b5f003d15cea8eacd765dcbd7b9de4bff637ff57b3c3e184cac5dea0149abd25789e4ce0a24aa63f230e5afe934ab7d9096db737af7e2d5703914a70b9028a01f9028601180a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a03828c9ac89048c829d2636170dfae92e653be033c684f228fbf5a9bce141fcaaa00902674169c7dcb2eb4faec66d9ba35c31eb1316755cf19ac82d33358e63fca9b9028a01f9028601190a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000001a091d9a0233ab5773c83179adcae0f99f21985e280f44760cb99f91fda53dc1ee6a0592fde4635dffe070b989902dee4f7a14b2d43410ee4ac2f025d16bfeeccec24b9028a01f90286011a0a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a04c38274334089ba26be1ab238d9fe74e0e2e12d746f458fe5711f48f51842b6ba0222563aefd3f81edc662de7b039aa61b189404451201f3a28471f34dbfefac71f8601b0a8301e24194000000000000000000000000000000000000aaaa808026a072b8abde69e482a1cb7c88df29ef92502f35b070c0d19b2a1b646b1dbf0d898ca069f1474f53b876d271e3ec33cbaad5204b381e4ebc4ea1cd343ac6930d0ea2a7c0", + + "header": { + "parentHash": "0x5ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xdd07cac1fd50a2d47b3faf9514b2a3e385fcd6e3102760f6bea1f919515cacff", + "transactionsTrie": "0x637d26d4cecdd55c7927c6d203ce40b7d9faf363fff990c3fc5e502f5edc1ead", + "receiptsTrie": "0xed9cc53fd0eee79528719ca973156891c6be9ddfe7bb9a788d4a3bc1d261773b", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x7", + "gasLimit": "0x47e7c4", + "gasUsed": "0x61bf2", + "timestamp": "0x46", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x85a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x15", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x69e444997b9e7db9d3c351acb17da1666358ec8ce1fe34e6084f7347bfcfa83a", + "s": "0x64e539a2efbab6c0ec01f1d6d38bf97218a3e42db66a84e35945f65afc4af52c", + "hash": "0x479eba011395274523b321f282bdad6374850bc40749047a9278e122b38d4aaf" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x16", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xa3290dc9c69c2ddd720698de596e2585102f14a5fafa3332abb0fe3e7857a58b", + "s": "0xad0540e2e37a1fc9a0c03b3a69c420210f86331641c4ee8cf8005cd44db7b5e", + "hash": "0x84c8d5f6e8a706a936b12d149ef7228484cdb6cc7bdbef7a6bbc3092e3e0842c" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x17", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x423621e9b3b5f003d15cea8eacd765dcbd7b9de4bff637ff57b3c3e184cac5de", + "s": "0x149abd25789e4ce0a24aa63f230e5afe934ab7d9096db737af7e2d5703914a70", + "hash": "0x7da302eb420f10e9cf3c121db86496e259ae2b42dccda2de10fefce5d5aa139b" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x18", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x3828c9ac89048c829d2636170dfae92e653be033c684f228fbf5a9bce141fcaa", + "s": "0x902674169c7dcb2eb4faec66d9ba35c31eb1316755cf19ac82d33358e63fca9", + "hash": "0xbba5577e03b997efc268fe0912e19e0063750626ce6f9b166066e02e470ac086" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x19", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x91d9a0233ab5773c83179adcae0f99f21985e280f44760cb99f91fda53dc1ee6", + "s": "0x592fde4635dffe070b989902dee4f7a14b2d43410ee4ac2f025d16bfeeccec24", + "hash": "0x26c52e93b532bca09107f40f9ccf238466f51e15f5ecdc17f9a16eea62087cea" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1a", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x4c38274334089ba26be1ab238d9fe74e0e2e12d746f458fe5711f48f51842b6b", + "s": "0x222563aefd3f81edc662de7b039aa61b189404451201f3a28471f34dbfefac71", + "hash": "0x5ba61c8fabacaa0e87f207125bf3a25a784a6f429aa2ae1f76ffe95c9a34eb54" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x1b", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0x72b8abde69e482a1cb7c88df29ef92502f35b070c0d19b2a1b646b1dbf0d898c", + "s": "0x69f1474f53b876d271e3ec33cbaad5204b381e4ebc4ea1cd343ac6930d0ea2a7", + "hash": "0xfa60faf2f9a1f4cbf19ba6ba746e0c633ba5fe2957f08be0dbc2c883039029ba" + } + ], + "uncles": null + }, + { + "rlp": "f916b7f901f6a085a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a01e11ee12288a40ff864df1f6ad3300fc9371c1eb357053df51d5cab2f3e5ba89a0e63a171d8cdd66b30bc70906336d255376adeff892e5c18acfb514c3c5848c24a05f714113fe44466c533b2b5e101539de21cb8d1debeca1765154c2e69d035d21b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000088347e7c48307b9a85080a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f914bab902e501f902e1011c0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0a345838333ae268c00da46ed42deae5088daedff5386352968959edb1dcafc8ba011c4f1440e894902a1af266c8e03f04ca5956bfad430c365be9657611afc53f4b902e501f902e1011d0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0c3640d17818544e39d623aab79b0781c80cb3981929b24fcc562684b65eff002a04406cba22f6306b0afab3a1a7a2a6b414416a122f3d33023e91b71e5c227a780b902e501f902e1011e0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0542d0389eb1173f9f5224ae0af0aacbbb7c7949ddd13d7b9392e72cefbc090c1a0571c6726ba9a4c65c1c4194fc140497febf9be09accc161ed7f40773a6b4b4afb902e501f902e1011f0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a08e1a10e344a9e62d70d610a21980dd7d0e50df1308d993e74db1a49f65556c0aa052fbe60de2d4ca53e28a0092df33497116f4a5a7fbc40621b962e6ff7c5f725ab902e501f902e101200a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0eac4f60d9f9d85f2a5cc04603f78a3053d1846678090a934b36ffa415e2ed90ba0076694d37e45b009b59b70f60fe3a949d199cbe8602b4fc9921a6e18b9401e75b902e501f902e101210a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0d8abc8bbfeda7780f9f5e5c49511080672f1627bf44a6d20ce630bb9ba707c64a02c3083fa0cc4fc2a9df6ee0e7ce34b2070c892466d7ac06ef8afc097e7948ccfb902e501f902e101220a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0614a1003abc9483c9d19a9e4eb50f52b43f33ea1cd3e05a9d4222d175128dd9fa02cf9924ee66bea724611b185851cd20d6e832ddd8b32f7960e9a2c8436bac4f1f860230a8301e24194000000000000000000000000000000000000aaaa808025a0e0908d8cb32c6746e997b494f9e64980a05739781e91334305c73f9f29db4c39a05cc81dfae6a0b36f702d9ab38d5f5e4241ad8d9e5ce03dc139050a1a2271dc22c0", + + "header": { + "parentHash": "0x85a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x1e11ee12288a40ff864df1f6ad3300fc9371c1eb357053df51d5cab2f3e5ba89", + "transactionsTrie": "0xe63a171d8cdd66b30bc70906336d255376adeff892e5c18acfb514c3c5848c24", + "receiptsTrie": "0x5f714113fe44466c533b2b5e101539de21cb8d1debeca1765154c2e69d035d21", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x8", + "gasLimit": "0x47e7c4", + "gasUsed": "0x7b9a8", + "timestamp": "0x50", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0xc48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1c", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xa345838333ae268c00da46ed42deae5088daedff5386352968959edb1dcafc8b", + "s": "0x11c4f1440e894902a1af266c8e03f04ca5956bfad430c365be9657611afc53f4", + "hash": "0xa1456d53037869e0971392226802336d49c748bbac2334b87ff4df29b3096199" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1d", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xc3640d17818544e39d623aab79b0781c80cb3981929b24fcc562684b65eff002", + "s": "0x4406cba22f6306b0afab3a1a7a2a6b414416a122f3d33023e91b71e5c227a780", + "hash": "0x287d84df82c46eb31a591ccbee5bbc6f3707983a1d7aea8ac1ec22bf2d8e8922" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1e", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x542d0389eb1173f9f5224ae0af0aacbbb7c7949ddd13d7b9392e72cefbc090c1", + "s": "0x571c6726ba9a4c65c1c4194fc140497febf9be09accc161ed7f40773a6b4b4af", + "hash": "0x7cc4498d64074114b14b9bbc356b74662c0674c36bab54e5401530ab51f76d2d" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x1f", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x8e1a10e344a9e62d70d610a21980dd7d0e50df1308d993e74db1a49f65556c0a", + "s": "0x52fbe60de2d4ca53e28a0092df33497116f4a5a7fbc40621b962e6ff7c5f725a", + "hash": "0xa65617192b2b1308a0b1c53cbe81ce7f33ad1c1ff1f2cce522e29d740291cd86" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x20", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xeac4f60d9f9d85f2a5cc04603f78a3053d1846678090a934b36ffa415e2ed90b", + "s": "0x76694d37e45b009b59b70f60fe3a949d199cbe8602b4fc9921a6e18b9401e75", + "hash": "0xaff285b353ae7ef059f3357da968cb76b0eda97f094a9245e283d9e86538ec2a" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x21", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xd8abc8bbfeda7780f9f5e5c49511080672f1627bf44a6d20ce630bb9ba707c64", + "s": "0x2c3083fa0cc4fc2a9df6ee0e7ce34b2070c892466d7ac06ef8afc097e7948ccf", + "hash": "0x36c86aeb97a7a82df05f31708ad2acfa2e17fb8b8bea3e5c9809a3672504d124" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x22", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x614a1003abc9483c9d19a9e4eb50f52b43f33ea1cd3e05a9d4222d175128dd9f", + "s": "0x2cf9924ee66bea724611b185851cd20d6e832ddd8b32f7960e9a2c8436bac4f1", + "hash": "0x089b7cca10e8b9b9442e62acbcd0d45d2aca3773d89956c80d42c27640b3cf61" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x23", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x25", + "r": "0xe0908d8cb32c6746e997b494f9e64980a05739781e91334305c73f9f29db4c39", + "s": "0x5cc81dfae6a0b36f702d9ab38d5f5e4241ad8d9e5ce03dc139050a1a2271dc22", + "hash": "0xe871bdeea9aa4506fe8b2439849892ba9f2d853277ec6f565be1d84be0ed13ef" + } + ], + "uncles": null + }, + { + "rlp": "f91c77f901f6a0c48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0a463cb31e670fe25b7b5dfbbc793dd928db33a8b845298467c48809be4e5a7f7a087c8e925a1221e6e3a1d4b605f87848777f5ba38168c2ccc5cf024762ead055ca0638157d19e0340249b3934837bf99770474d939b2ae93f2d1c7f5db19d6d041db901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000098347e7c4830987ce5a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f91a7ab9034001f9033c01240a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0170a46887a741e98bb82c99fc68d86e32447508bb3558699294ff562fb6b9be2a003764ba59caab09b25f16eb1e0d6be0b071fd7aebefc88a7c056f4ebeaa8cb5bb9034001f9033c01250a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a007775a2a2180025ae4c2b63a20e586538fab33ff619ca6a937d6865360be8dcba061f490b7c60e665854bc5dc4b5f40bb2c31625788c10b98035c8f525adadee53b9034001f9033c01260a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a02b3b6c19247342eb2062761e24e1d753c032c3b4f4f146b091b2240877483e59a0235f14770796cb22d2cd2e41f63af49b10cf208000be2ba789bb120096b989b8b9034001f9033c01270a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a0805dca3053d94bad7b563b604a976388595eb8834eaf3ef7973de21bcc9ca97ca05c37e3a461283d51557dfb0f740065dcc4d0aef005829805a504643e5523b489b9034001f9033c01280a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a047522841a060cc664997d11fdec3e929a65a6ee124a47bc82dd873e79b80adbba06cae9c3319fbe8a1206db7ed2063288f707811fd06ba558da8e2187bdc41d375b9034001f9033c01290a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0a87b7830fe657f02a195aa1b2617501bcb52b95ebbd9479277f3dfa22de1b0e3a061d0c1acb8066f8dd3b3ef18f714cd0132247dab45c3481c2b7fc6cfb9708ef7b9034001f9033c012a0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a0b7fb8508b5e3993af55d04f6e58732037ac0dc5a1ac5538bf9dae95e52c1d005a00656240da661eea32298774cf810e858a6b8999ae5b9564e708a55e15ae4a051b9034001f9033c012b0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a016a3a0af3ff0279ea62d7554131ad7670ccb83850bd6d0bb66cbaa45c46e5c35a055a9915e20c483e9237f0bfef99455d43ac1f22a438a9485b6e1f3dbbab441abf8602c0a8301e24194000000000000000000000000000000000000aaaa808026a0cffdf83faecfc8fe7e2e83570f0bcd9ef0e4914fd645dc8399bbd5bc8d483762a067ab197437466269980d4b18a1ed11744d7dceeae934729b14094fe31f5875a5c0", + + "header": { + "parentHash": "0xc48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xa463cb31e670fe25b7b5dfbbc793dd928db33a8b845298467c48809be4e5a7f7", + "transactionsTrie": "0x87c8e925a1221e6e3a1d4b605f87848777f5ba38168c2ccc5cf024762ead055c", + "receiptsTrie": "0x638157d19e0340249b3934837bf99770474d939b2ae93f2d1c7f5db19d6d041d", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0x9", + "gasLimit": "0x47e7c4", + "gasUsed": "0x987ce", + "timestamp": "0x5a", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x35ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x24", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x170a46887a741e98bb82c99fc68d86e32447508bb3558699294ff562fb6b9be2", + "s": "0x3764ba59caab09b25f16eb1e0d6be0b071fd7aebefc88a7c056f4ebeaa8cb5b", + "hash": "0x6efd98eee12ad55ea61c467a685c5405d71a5d7eee0bf7446610a71bbb252978" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x25", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x7775a2a2180025ae4c2b63a20e586538fab33ff619ca6a937d6865360be8dcb", + "s": "0x61f490b7c60e665854bc5dc4b5f40bb2c31625788c10b98035c8f525adadee53", + "hash": "0xfc8f3b59421c55961e9148b55df36202cef47250717448b712ed8532a8dc3f8d" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x26", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x2b3b6c19247342eb2062761e24e1d753c032c3b4f4f146b091b2240877483e59", + "s": "0x235f14770796cb22d2cd2e41f63af49b10cf208000be2ba789bb120096b989b8", + "hash": "0x9998aabf75a918d993edb60f8f58c07280a8334e58a372b8c83ebaedcbe896ad" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x27", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x805dca3053d94bad7b563b604a976388595eb8834eaf3ef7973de21bcc9ca97c", + "s": "0x5c37e3a461283d51557dfb0f740065dcc4d0aef005829805a504643e5523b489", + "hash": "0x743c766ef64a159e1ff83fd958c7caeaa8c869ca370529ad5f807f14feeaad7b" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x28", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x47522841a060cc664997d11fdec3e929a65a6ee124a47bc82dd873e79b80adbb", + "s": "0x6cae9c3319fbe8a1206db7ed2063288f707811fd06ba558da8e2187bdc41d375", + "hash": "0xe6b1c6f51ac44f84d3e38ab6f238f313180a91c18079f44bb1af392b7b48c87a" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x29", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xa87b7830fe657f02a195aa1b2617501bcb52b95ebbd9479277f3dfa22de1b0e3", + "s": "0x61d0c1acb8066f8dd3b3ef18f714cd0132247dab45c3481c2b7fc6cfb9708ef7", + "hash": "0x4ce8251dac66134f50748d70e59acee7f3395f57c163ac321800337a0b11f1e7" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x2a", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0xb7fb8508b5e3993af55d04f6e58732037ac0dc5a1ac5538bf9dae95e52c1d005", + "s": "0x656240da661eea32298774cf810e858a6b8999ae5b9564e708a55e15ae4a051", + "hash": "0xb7dc9ae376bd9065b403bb143020f589b860dee65a5a9ebd7e0bd1abc9eae5fb" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x2b", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x16a3a0af3ff0279ea62d7554131ad7670ccb83850bd6d0bb66cbaa45c46e5c35", + "s": "0x55a9915e20c483e9237f0bfef99455d43ac1f22a438a9485b6e1f3dbbab441ab", + "hash": "0xcf7e327a838d9b07eabff38f6f7f39c7bcb36463e114f66934ea451abb9b87bf" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x2c", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0xcffdf83faecfc8fe7e2e83570f0bcd9ef0e4914fd645dc8399bbd5bc8d483762", + "s": "0x67ab197437466269980d4b18a1ed11744d7dceeae934729b14094fe31f5875a5", + "hash": "0xe6a49397da6f57aacebcf4024e6a07c4a724042db248cc668926ec2a2abc2394" + } + ], + "uncles": null + }, + { + "rlp": "f922edf901f6a035ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0ae01e8e74d19be46a3f2b56e79c331634e3032efce2ffed6ad37577f66039d91a088a579ae5732b49cd956fc12234d3a4f7c2ed60303cadea178f1be33c9f49f06a0971e38f6ae7b4aeef32a9c1b53b9e2e84eb491c73022449d16c95db564cccc5db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000a8347e7c4830b86646480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f920f0b9039b01f90397012d0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a03783f158de899ff6bce0d79e211d82575a1971fc971e56116868a0121848e57aa02ccf7dbac3b9aef50a9400d635636b7c15eca0d0f9b7ff25a0d09b56596f75aab9039b01f90397012e0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a03593ee4a77441877a447d120b2070f1c2324e9600fdbad39c31fe75a5c1ca42ba04ec37cdb3c934e95ea349b981de041ebb29036b7f4c5dadd0890967b05e5b945b9039b01f90397012f0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a048e3a7c884ea3e5672f6aa3b7f5dcd7e4fbf0be5998a4bbb9ee74c860607443aa0441fd36310421832f8a0025be07ce02d8833af7ecc179ec7b186d3f0278734c1b9039b01f9039701300a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0e7081190ea699d97f818678ef971a391812196e3ee94d04c4551e2dd0657db3aa02c3a9ba4de5beebd2c8a3a2eb1788534599af6b40e7f1b3b5c37071553214f9eb9039b01f9039701310a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a059e183f642034975125dd0bb9b36722412cffebf2af31025ad8800eaf6199f28a00a456535d0a974c936d49d7d69884995189407fbedf819878e8ed1894d1282aeb9039b01f9039701320a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a077032f089f9761459f4a0bd8a64465a50be1c84e1512fdfe5961ee3bb5d57553a00d0f8bdd0b070cdf1af711855847e11293e7a0424d471a0e28088de8238ce270b9039b01f9039701330a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0912278d20ab6b8033ca071a3757d6bf038f17e9634cac85c6684cd42672d88f6a00b0292c31a9f510d3a53653a1fbe0b76dc54f8a13a2a8b7aa3a877c91a24fb5fb9039b01f9039701340a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0960b49da258aa006edc7580bd5c91be701feabae628e0c47a95559fa5c6dc4a6a066654bf09aa64a93a95463c86588d45192589286855efe67f05a4ab6c8fa7553b9039b01f9039701350a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a0538f7a084177da0422c9e663b708dee81627264abf6152d7bfb6f1dc8a9a5b11a07baaa50e351a6d338ac5765d487a3a54bee29483516b9c64bed35cf6c5bc776ef860360a8301e24194000000000000000000000000000000000000aaaa808026a0822285a75be8c0cf90edf1031b03d949468c9c66bdb63897ae9fc96b167eaa3ba07478bac2f9fe6a63e632b0861b86add7c5a9e8b117e26788e00418d72eeba0d6c0", + + "header": { + "parentHash": "0x35ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201", + "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "coinbase": "0x0100000000000000000000000000000000000000", + "stateRoot": "0xae01e8e74d19be46a3f2b56e79c331634e3032efce2ffed6ad37577f66039d91", + "transactionsTrie": "0x88a579ae5732b49cd956fc12234d3a4f7c2ed60303cadea178f1be33c9f49f06", + "receiptsTrie": "0x971e38f6ae7b4aeef32a9c1b53b9e2e84eb491c73022449d16c95db564cccc5d", + "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0x20000", + "number": "0xa", + "gasLimit": "0x47e7c4", + "gasUsed": "0xb8664", + "timestamp": "0x64", + "extraData": "0x", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000", + "hash": "0x105d8befc05cb9c21add67408bcc7512de148cd9a7cc8932efa294e2672aba55" + }, + "transactions": [ + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x2d", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x3783f158de899ff6bce0d79e211d82575a1971fc971e56116868a0121848e57a", + "s": "0x2ccf7dbac3b9aef50a9400d635636b7c15eca0d0f9b7ff25a0d09b56596f75aa", + "hash": "0x16751472a59dc59d9454f22c089631bb065bbb92bdd389a15a71c63fb8fb2db2" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x2e", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x3593ee4a77441877a447d120b2070f1c2324e9600fdbad39c31fe75a5c1ca42b", + "s": "0x4ec37cdb3c934e95ea349b981de041ebb29036b7f4c5dadd0890967b05e5b945", + "hash": "0x60e0f978ce01c1221b1de4e27c4428d0cfa5592c5d0f36006a35337404c27a44" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x2f", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x48e3a7c884ea3e5672f6aa3b7f5dcd7e4fbf0be5998a4bbb9ee74c860607443a", + "s": "0x441fd36310421832f8a0025be07ce02d8833af7ecc179ec7b186d3f0278734c1", + "hash": "0x07c2da48c6082bac84bbfdec573e67d3e86df68b762e1f9ed7393653cae834d1" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x30", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0xe7081190ea699d97f818678ef971a391812196e3ee94d04c4551e2dd0657db3a", + "s": "0x2c3a9ba4de5beebd2c8a3a2eb1788534599af6b40e7f1b3b5c37071553214f9e", + "hash": "0x148e2d26da5a0e8b0932842a7a2c1fe964776a1be3978684af9528c6bef79918" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x31", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x59e183f642034975125dd0bb9b36722412cffebf2af31025ad8800eaf6199f28", + "s": "0xa456535d0a974c936d49d7d69884995189407fbedf819878e8ed1894d1282ae", + "hash": "0xa13299621bd0d81ad5c373fb7357f6abb528475d8d1b08bb8b2e4176f0e2e303" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x32", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x77032f089f9761459f4a0bd8a64465a50be1c84e1512fdfe5961ee3bb5d57553", + "s": "0xd0f8bdd0b070cdf1af711855847e11293e7a0424d471a0e28088de8238ce270", + "hash": "0xa956c3e12fa0fdfd93e2e9c14e6c63a63db49aabe9dbeceb4ee2cf71777f6c59" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x33", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x912278d20ab6b8033ca071a3757d6bf038f17e9634cac85c6684cd42672d88f6", + "s": "0xb0292c31a9f510d3a53653a1fbe0b76dc54f8a13a2a8b7aa3a877c91a24fb5f", + "hash": "0x54fab10dc75cfa4bae509e25830b8914d9b15a12a71c1f68b79904e2d3599e90" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x34", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x0", + "r": "0x960b49da258aa006edc7580bd5c91be701feabae628e0c47a95559fa5c6dc4a6", + "s": "0x66654bf09aa64a93a95463c86588d45192589286855efe67f05a4ab6c8fa7553", + "hash": "0x2fc87ef663f4a57b922fc51029045e03bac37ae0a8b126b1ba22e362a6b6635d" + }, + { + "type": "0x1", + "chainId": "0x1", + "nonce": "0x35", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": [ + { + "address": "0x0000000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0100000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0100000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0200000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0200000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0300000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0300000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0400000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0400000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0500000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0500000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0600000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0600000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0700000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0700000000000000000000000000000000000000000000000000000000000000" + ] + }, + { + "address": "0x0800000000000000000000000000000000000000", + "storageKeys": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0800000000000000000000000000000000000000000000000000000000000000" + ] + } + ], + "v": "0x1", + "r": "0x538f7a084177da0422c9e663b708dee81627264abf6152d7bfb6f1dc8a9a5b11", + "s": "0x7baaa50e351a6d338ac5765d487a3a54bee29483516b9c64bed35cf6c5bc776e", + "hash": "0xf522c9cb3ff8f935d2ec3ca405a7480a43d959a16e1a192e705a5613a0e3d3f5" + }, + { + "type": "0x0", + "chainId": null, + "nonce": "0x36", + "gasPrice": "0xa", + "gasLimit": "0x1e241", + "to": "0x000000000000000000000000000000000000aaaa", + "value": "0x0", + "data": "0x", + "accessList": null, + "v": "0x26", + "r": "0x822285a75be8c0cf90edf1031b03d949468c9c66bdb63897ae9fc96b167eaa3b", + "s": "0x7478bac2f9fe6a63e632b0861b86add7c5a9e8b117e26788e00418d72eeba0d6", + "hash": "0x52079ee865e89ec93150543232702a9b4a5660debb803017357b9039c38c2aab" + } + ], + "uncles": null + } + ] + } +} diff --git a/crates/ethcore/src/client/evm_test_client.rs b/crates/ethcore/src/client/evm_test_client.rs index d55e9faf45..7e088efa03 100644 --- a/crates/ethcore/src/client/evm_test_client.rs +++ b/crates/ethcore/src/client/evm_test_client.rs @@ -68,7 +68,7 @@ impl fmt::Display for EvmTestError { } } -use ethereum; +use ethereum::{self}; use ethjson::spec::ForkSpec; /// Simplified, single-block EVM test client. @@ -99,6 +99,7 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Homestead => Some(ethereum::new_homestead_test()), ForkSpec::EIP150 => Some(ethereum::new_eip150_test()), ForkSpec::EIP158 => Some(ethereum::new_eip161_test()), + ForkSpec::EIP2930 => Some(ethereum::new_eip2930_test()), ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()), diff --git a/crates/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs index 9c7c254355..91fb5062b6 100644 --- a/crates/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -267,6 +267,14 @@ pub fn new_berlin_test() -> Spec { ) } +/// Create a new Foundation Berlin era spec. +pub fn new_eip2930_test() -> Spec { + load( + None, + include_bytes!("../../res/chainspec/test/eip2930_test.json"), + ) +} + /// Create a new YOLO spec pub fn new_yolo3_test() -> Spec { load( diff --git a/crates/ethcore/src/json_tests/chain.rs b/crates/ethcore/src/json_tests/chain.rs index 0b489f90d3..f923fd2160 100644 --- a/crates/ethcore/src/json_tests/chain.rs +++ b/crates/ethcore/src/json_tests/chain.rs @@ -208,7 +208,7 @@ pub fn json_chain_test( match block { Ok(block) => { let num = block.header.number(); - trace!(target: "json-tests", "{} – Importing {} bytes. Block #{}", name, bytes_len, num); + debug!(target: "json-tests", "{} – Importing {} bytes. Block #{}", name, bytes_len, num); let res = client.import_block(block); if let Err(e) = res { warn!(target: "json-tests", "{} – Error importing block #{}: {:?}", name, num, e); diff --git a/crates/ethcore/src/json_tests/local.rs b/crates/ethcore/src/json_tests/local.rs new file mode 100644 index 0000000000..79c239dad5 --- /dev/null +++ b/crates/ethcore/src/json_tests/local.rs @@ -0,0 +1,202 @@ +use super::HookType; +use ethereum_types::U256; +use ethjson::{self, blockchain::Block}; +use log::warn; +use rlp::RlpStream; +use std::path::Path; +use types::transaction::{TypedTransaction, TypedTxId, UnverifiedTransaction}; +use verification::queue::kind::blocks::Unverified; + +pub fn json_local_block_en_de_test( + _test: ðjson::test::LocalTests, + path: &Path, + json_data: &[u8], + start_stop_hook: &mut H, +) -> Vec { + let tests = ethjson::local_tests::BlockEnDeTest::load(json_data).expect(&format!( + "Could not parse JSON chain test data from {}", + path.display() + )); + let mut failed = Vec::new(); + + for (name, ref_block) in tests.into_iter() { + start_stop_hook(&name, HookType::OnStart); + + let block = Unverified::from_rlp(ref_block.rlp()); + let block = match block { + Ok(block) => block, + Err(decoder_err) => { + warn!(target: "json-tests", "Error decoding test block: {:?}", decoder_err); + failed.push(name.clone()); + continue; + } + }; + if !is_same_block(&ref_block, &block) { + println!("block failed {:?}", block); + failed.push(name.clone()) + } + + start_stop_hook(&name, HookType::OnStop); + } + failed +} + +fn rlp_append_block(block: &Unverified) -> Vec { + let mut rlps = RlpStream::new(); + rlps.begin_list(3); + rlps.append(&block.header); + UnverifiedTransaction::rlp_append_list(&mut rlps, &block.transactions); + rlps.append_list(&block.uncles); + rlps.out() +} + +pub fn is_same_block(ref_block: &Block, block: &Unverified) -> bool { + let test_exp = |exp: bool, err: &str| -> bool { + if !exp { + println!("Test mismatch on:{}", err); + } + exp + }; + + let header_ok = if let Some(ref header) = ref_block.header { + test_exp(*block.header.gas_used() == header.gas_used.0, "Gas used") + && test_exp( + *block.header.uncles_hash() == header.uncles_hash.0, + "Uncles hash", + ) + && test_exp( + *block.header.transactions_root() == header.transactions_root.0, + "Transaction Root", + ) + && test_exp( + block.header.timestamp() == header.timestamp.0.as_u64(), + "Timestamp", + ) + && test_exp( + *block.header.state_root() == header.state_root.0, + "StateRoot", + ) + && test_exp( + *block.header.receipts_root() == header.receipts_root.0, + "ReceiptsRoot", + ) + && test_exp( + *block.header.parent_hash() == header.parent_hash.0, + "ParentHash", + ) + && test_exp( + block.header.number() == header.number.0.as_u64(), + "Blocn Number", + ) + && test_exp(block.header.hash() == header.hash.0, "Header hash") + && test_exp(*block.header.gas_limit() == header.gas_limit.0, "GasLimit") + && test_exp(*block.header.gas_used() == header.gas_used.0, "GasUsed") + && test_exp( + *block.header.extra_data() == header.extra_data.0, + "ExtraData", + ) + && test_exp( + *block.header.difficulty() == header.difficulty.0, + "Difficulty", + ) + && test_exp(*block.header.author() == header.author.0, "Author") + && test_exp(*block.header.log_bloom() == header.bloom.0, "Bloom") + } else { + true + }; + + // check transactions + let transaction_ok = if let Some(ref txs) = ref_block.transactions { + let mut is_all_ok = true; + for (ref_tx, tx) in txs.iter().zip(block.transactions.iter()) { + // check signatures + let mut is_ok = test_exp(U256::from(tx.signature().r()) == ref_tx.r.0, "Sig R") + && test_exp(U256::from(tx.signature().s()) == ref_tx.s.0, "Sig S"); + is_ok = is_ok + && if let Some(chain_id) = ref_tx.chain_id { + test_exp(tx.chain_id() == Some(chain_id.0.as_u64()), "Chain Id") + } else { + true + }; + // check type + let ttype = if let Some(ttype) = ref_tx.transaction_type { + let ttype = ttype.0.byte(0); + if let Some(id) = TypedTxId::from_u8_id(ttype) { + id + } else { + println!("Unknown transaction {}", ttype); + continue; + } + } else { + TypedTxId::Legacy + }; + is_ok = is_ok + && test_exp(tx.tx().nonce == ref_tx.nonce.0, "Tx nonce") + && test_exp(tx.tx().gas_price == ref_tx.gas_price.0, "Tx gas price") + && test_exp(tx.tx().gas == ref_tx.gas_limit.0, "Tx gas") + && test_exp(tx.tx().value == ref_tx.value.0, "Tx value") + && test_exp(tx.tx().data == ref_tx.data.0, "Tx data") + && test_exp(ref_tx.hash.is_some(), "tx hash is none"); + + if let Some(hash) = ref_tx.hash { + is_ok = is_ok && test_exp(tx.hash() == hash, "Hash mismatch"); + } + + // check specific tx data + is_ok = is_ok + && match ttype { + TypedTxId::Legacy => { + test_exp(tx.original_v() == ref_tx.v.0.as_u64(), "Original Sig V") + } + TypedTxId::AccessList => { + test_exp(tx.standard_v() as u64 == ref_tx.v.0.as_u64(), "Sig V"); + let al = match tx.as_unsigned() { + TypedTransaction::AccessList(tx) => &tx.access_list, + _ => { + println!("Wrong data in tx type"); + continue; + } + }; + if let Some(ref ref_al) = ref_tx.access_list { + if ref_al.len() != al.len() { + println!("Access list mismatch"); + continue; + } + let mut is_ok = true; + for (al, ref_al) in al.iter().zip(ref_al.iter()) { + is_ok = is_ok && test_exp(al.0 == ref_al.address, "AL address"); + if al.1.len() != ref_al.storage_keys.len() { + println!("Access list mismatch"); + continue; + } + for (key, ref_key) in al.1.iter().zip(ref_al.storage_keys.iter()) { + is_ok = is_ok && test_exp(key == ref_key, "Key mismatch"); + } + } + is_ok + } else { + false + } + } + }; + + if !is_ok { + println!( + "Transaction not valid got: {:?} \n expected:{:?}\n", + tx, ref_tx + ); + } + is_all_ok = is_ok && is_all_ok; + } + is_all_ok + } else { + true + }; + + let encript_ok = { + let rlp = rlp_append_block(&block); + rlp == ref_block.rlp() + }; + + header_ok && transaction_ok && encript_ok +} diff --git a/crates/ethcore/src/json_tests/mod.rs b/crates/ethcore/src/json_tests/mod.rs index 004d86d69b..5cda1f28e7 100644 --- a/crates/ethcore/src/json_tests/mod.rs +++ b/crates/ethcore/src/json_tests/mod.rs @@ -19,6 +19,7 @@ mod chain; mod difficulty; mod executive; +mod local; mod state; mod test_common; mod transaction; diff --git a/crates/ethcore/src/json_tests/runner.rs b/crates/ethcore/src/json_tests/runner.rs index 1309175e32..a82af46cc3 100644 --- a/crates/ethcore/src/json_tests/runner.rs +++ b/crates/ethcore/src/json_tests/runner.rs @@ -1,6 +1,6 @@ use ethjson::test::{ - ChainTests, DifficultyTests, EthereumTestSuite, ExecutiveTests, StateTests, TestChainSpec, - TestTrieSpec, TransactionTests, TrieTests, + ChainTests, DifficultyTests, EthereumTestSuite, ExecutiveTests, LocalTests, StateTests, + TestChainSpec, TestTrieSpec, TransactionTests, TrieTests, }; use globset::Glob; use log::info; @@ -83,6 +83,9 @@ impl TestRunner { /// Run the tests pub fn run(&self) -> TestResult { let mut res = TestResult::zero(); + for t in &self.0.local { + res += Self::run_local_tests(&t); + } for t in &self.0.chain { res += Self::run_chain_tests(&t); } @@ -141,6 +144,19 @@ impl TestRunner { false } + fn run_local_tests(test: &LocalTests) -> TestResult { + match test.test_type.as_str() { + "block_en_de" => Self::run1( + test, + &test.path, + |test: &LocalTests, path: &Path, json: &[u8]| { + super::local::json_local_block_en_de_test(test, &path, &json, &mut |_, _| {}) + }, + ), + _ => TestResult::zero(), + } + } + fn run_chain_tests(test: &ChainTests) -> TestResult { Self::run1( test, diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index ae8bf75b09..af225dcaca 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -707,6 +707,13 @@ impl UnverifiedTransaction { self.unsigned.rlp_append(s, self.chain_id, &self.signature); } + pub fn rlp_append_list(s: &mut RlpStream, tx_list: &[UnverifiedTransaction]) { + s.begin_list(tx_list.len()); + for tx in tx_list.iter() { + tx.unsigned.rlp_append(s, tx.chain_id, &tx.signature); + } + } + pub fn encode(&self) -> Vec { self.unsigned.encode(self.chain_id, &self.signature) } diff --git a/crates/ethcore/types/src/transaction/transaction_id.rs b/crates/ethcore/types/src/transaction/transaction_id.rs index 833a678cd0..2b5b5ae2b2 100644 --- a/crates/ethcore/types/src/transaction/transaction_id.rs +++ b/crates/ethcore/types/src/transaction/transaction_id.rs @@ -23,7 +23,17 @@ use std::convert::TryFrom; #[repr(u8)] pub enum TypedTxId { AccessList = 0x01, - Legacy = 0x80, // With 0x80 we are sure that all other types will not overlap + Legacy = 0x00, +} + +impl TypedTxId { + pub fn from_u8_id(n: u8) -> Option { + match n { + 0 => Some(Self::Legacy), + 1 => Some(Self::AccessList), + _ => None, + } + } } impl Default for TypedTxId { diff --git a/crates/ethjson/src/blockchain/block.rs b/crates/ethjson/src/blockchain/block.rs index 087c17fffb..045a42f335 100644 --- a/crates/ethjson/src/blockchain/block.rs +++ b/crates/ethjson/src/blockchain/block.rs @@ -23,11 +23,11 @@ use bytes::Bytes; #[derive(Debug, PartialEq, Deserialize)] pub struct Block { #[serde(rename = "blockHeader")] - header: Option
, - rlp: Bytes, - transactions: Option>, + pub header: Option
, + pub rlp: Bytes, + pub transactions: Option>, #[serde(rename = "uncleHeaders")] - uncles: Option>, + pub uncles: Option>, } impl Block { diff --git a/crates/ethjson/src/blockchain/transaction.rs b/crates/ethjson/src/blockchain/transaction.rs index 58fa270904..8f89de1b51 100644 --- a/crates/ethjson/src/blockchain/transaction.rs +++ b/crates/ethjson/src/blockchain/transaction.rs @@ -17,18 +17,31 @@ //! Blockchain test transaction deserialization. use bytes::Bytes; +use ethereum_types::{H160, H256}; use uint::Uint; /// Blockchain test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Transaction { - data: Bytes, - gas_limit: Uint, - gas_price: Uint, - nonce: Uint, - r: Uint, - s: Uint, - v: Uint, - value: Uint, + #[serde(rename = "type")] + pub transaction_type: Option, + pub data: Bytes, + pub gas_limit: Uint, + pub gas_price: Uint, + pub nonce: Uint, + pub r: Uint, + pub s: Uint, + pub v: Uint, + pub value: Uint, + pub chain_id: Option, + pub access_list: Option>, + pub hash: Option, +} + +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccessList { + pub address: H160, + pub storage_keys: Vec, } diff --git a/crates/ethjson/src/bytes.rs b/crates/ethjson/src/bytes.rs index 848a6359f8..bc9804f5d9 100644 --- a/crates/ethjson/src/bytes.rs +++ b/crates/ethjson/src/bytes.rs @@ -25,7 +25,7 @@ use std::{fmt, ops::Deref, str::FromStr}; /// Lenient bytes json deserialization for test json files. #[derive(Default, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] -pub struct Bytes(Vec); +pub struct Bytes(pub Vec); impl Bytes { /// Creates bytes struct. diff --git a/crates/ethjson/src/lib.rs b/crates/ethjson/src/lib.rs index c0641c4705..2f8b67d19c 100644 --- a/crates/ethjson/src/lib.rs +++ b/crates/ethjson/src/lib.rs @@ -31,6 +31,7 @@ extern crate maplit; pub mod blockchain; pub mod bytes; pub mod hash; +pub mod local_tests; pub mod maybe; pub mod spec; pub mod state; diff --git a/crates/ethjson/src/local_tests/mod.rs b/crates/ethjson/src/local_tests/mod.rs new file mode 100644 index 0000000000..f051528fb4 --- /dev/null +++ b/crates/ethjson/src/local_tests/mod.rs @@ -0,0 +1,26 @@ +use blockchain::block::Block; +use serde_json::{self, Error}; +use std::{collections::BTreeMap, io::Read}; + +/// Blockchain test deserializer. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockEnDeTest(BTreeMap); + +impl IntoIterator for BlockEnDeTest { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl BlockEnDeTest { + /// Loads test from json. + pub fn load(reader: R) -> Result + where + R: Read, + { + serde_json::from_reader(reader) + } +} diff --git a/crates/ethjson/src/spec/spec.rs b/crates/ethjson/src/spec/spec.rs index 250562d86d..df3a514869 100644 --- a/crates/ethjson/src/spec/spec.rs +++ b/crates/ethjson/src/spec/spec.rs @@ -25,6 +25,7 @@ use std::io::Read; pub enum ForkSpec { EIP150, EIP158, + EIP2930, Frontier, Homestead, Byzantium, diff --git a/crates/ethjson/src/test/mod.rs b/crates/ethjson/src/test/mod.rs index cf77f6a377..e4d69a27e2 100644 --- a/crates/ethjson/src/test/mod.rs +++ b/crates/ethjson/src/test/mod.rs @@ -123,6 +123,8 @@ impl SkipStates { /// Describes a github.com/ethereum/tests suite #[derive(Debug, PartialEq, Deserialize)] pub struct EthereumTestSuite { + /// local tests + pub local: Vec, /// Blockchain tests pub chain: Vec, /// State tests @@ -159,6 +161,15 @@ pub enum TestTrieSpec { Secure, } +/// A set of local tests +#[derive(Debug, PartialEq, Deserialize)] +pub struct LocalTests { + /// Path of the json tests + pub path: PathBuf, + /// Test type + pub test_type: String, +} + /// A set of blockchain tests #[derive(Debug, PartialEq, Deserialize)] pub struct ChainTests { From a831379ad86adc720e0f82c167cdc3680aba3612 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 1 Feb 2021 08:34:44 +0100 Subject: [PATCH 052/107] Yolo3 spec (#241) Update Yolo3 --- crates/ethcore/res/chainspec/goerli.json | 12 +- .../res/chainspec/test/yolo3_test.json | 879 ++++++++++++++++-- 2 files changed, 817 insertions(+), 74 deletions(-) diff --git a/crates/ethcore/res/chainspec/goerli.json b/crates/ethcore/res/chainspec/goerli.json index 4c00cc43ec..b3ab53730f 100644 --- a/crates/ethcore/res/chainspec/goerli.json +++ b/crates/ethcore/res/chainspec/goerli.json @@ -132,11 +132,11 @@ "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { "alt_bn128_const_operations": { "price": 500 } } }, "0x17d433": { "info": "EIP 1108 transition at block 1_561_651 (0x17d433)", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { "alt_bn128_const_operations": { "price": 150 } } } } } @@ -147,11 +147,11 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { "alt_bn128_const_operations": { "price": 40000 } } }, "0x17d433": { "info": "EIP 1108 transition at block 1_561_651 (0x17d433)", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { "alt_bn128_const_operations": { "price": 6000 } } } } } @@ -162,11 +162,11 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } }, "0x17d433": { "info": "EIP 1108 transition at block 1_561_651 (0x17d433)", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 } } } } } diff --git a/crates/ethcore/res/chainspec/test/yolo3_test.json b/crates/ethcore/res/chainspec/test/yolo3_test.json index bb04f77482..30c0b91eb7 100644 --- a/crates/ethcore/res/chainspec/test/yolo3_test.json +++ b/crates/ethcore/res/chainspec/test/yolo3_test.json @@ -1,69 +1,68 @@ { - "name": "Yolo (test)", + "name": "Yolo3", "engine": { - "Ethash": { + "clique": { "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x1BC16D674EC80000", - "homesteadTransition": "0x0", - "eip100bTransition": "0x0", - "difficultyBombDelays": { - "0": 5000000 - } + "epoch": 30000, + "period": 15 } } }, "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x1", - "maxCodeSize": 24576, - "maxCodeSizeTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", - "eip140Transition": "0x0", - "eip211Transition": "0x0", - "eip214Transition": "0x0", - "eip155Transition": "0x0", - "eip658Transition": "0x0", - "eip145Transition": "0x0", "eip1014Transition": "0x0", "eip1052Transition": "0x0", - "eip1283Transition": "0x0", "eip1283DisableTransition": "0x0", "eip1283ReenableTransition": "0x0", + "eip1283Transition": "0x0", "eip1344Transition": "0x0", + "eip140Transition": "0x0", + "eip145Transition": "0x0", + "eip150Transition": "0x0", + "eip155Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", "eip1706Transition": "0x0", "eip1884Transition": "0x0", "eip2028Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", "eip2315Transition": "0x0", "eip2929Transition": "0x0", - "eip2930Transition": "0x0" + "eip2930Transition": "0x0", + "eip658Transition": "0x0", + "gasLimitBoundDivisor": "0x0400", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "133519467574835", + "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" }, "genesis": { + "author": "0x0000000000000000000000000000000000000000", + "difficulty": "0x1", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000008a37866fd3627c9205a37c8685666f32ec07bb1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x47b760", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "seal": { "ethereum": { - "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0000000000000000" } }, - "difficulty": "0x400000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", - "gasLimit": "0x1388" + "timestamp": "0x60117f8b" }, + "nodes": [ + "enode://9e1096aa59862a6f164994cb5cb16f5124d6c992cdbf4535ff7dea43ea1512afe5448dca9df1b7ab0726129603f1a3336b631e4d7a1a44c94daddd03241587f9@3.9.20.133:30303" + ], "accounts": { + "0000000000000000000000000000000000000000": { + "balance": "0x1" + }, "0000000000000000000000000000000000000001": { - "balance": "1", + "balance": "0x1", "builtin": { "name": "ecrecover", "pricing": { @@ -75,7 +74,7 @@ } }, "0000000000000000000000000000000000000002": { - "balance": "1", + "balance": "0x1", "builtin": { "name": "sha256", "pricing": { @@ -87,7 +86,7 @@ } }, "0000000000000000000000000000000000000003": { - "balance": "1", + "balance": "0x1", "builtin": { "name": "ripemd160", "pricing": { @@ -99,7 +98,7 @@ } }, "0000000000000000000000000000000000000004": { - "balance": "1", + "balance": "0x1", "builtin": { "name": "identity", "pricing": { @@ -111,27 +110,24 @@ } }, "0000000000000000000000000000000000000005": { + "balance": "0x1", "builtin": { - "name": "modexp", "activate_at": "0x00", + "name": "modexp", "pricing": { "0": { - "price" : { "modexp2565": { } } + "price": { + "modexp2565": {} + } } } } }, "0000000000000000000000000000000000000006": { + "balance": "0x1", "builtin": { "name": "alt_bn128_add", "pricing": { - "0": { - "price": { - "alt_bn128_const_operations": { - "price": 500 - } - } - }, "0": { "info": "EIP 1108 transition", "price": { @@ -144,16 +140,10 @@ } }, "0000000000000000000000000000000000000007": { + "balance": "0x1", "builtin": { "name": "alt_bn128_mul", "pricing": { - "0": { - "price": { - "alt_bn128_const_operations": { - "price": 40000 - } - } - }, "0": { "info": "EIP 1108 transition", "price": { @@ -166,17 +156,10 @@ } }, "0000000000000000000000000000000000000008": { + "balance": "0x1", "builtin": { "name": "alt_bn128_pairing", "pricing": { - "0": { - "price": { - "alt_bn128_pairing": { - "base": 100000, - "pair": 80000 - } - } - }, "0": { "info": "EIP 1108 transition", "price": { @@ -190,15 +173,775 @@ } }, "0000000000000000000000000000000000000009": { + "balance": "0x1", "builtin": { - "name": "blake2_f", "activate_at": "0x00", + "name": "blake2_f", "pricing": { "blake2_f": { "gas_per_round": 1 } } } + }, + "0x000000000000000000000000000000000000000a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "0x1" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "0x1" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "0x1" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "0x1" + }, + "0e89e2aedb1cfcdb9424d41a1f218f4132738172": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "60adc0f89a41af237ce73554ede170d733ec14e0": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "799d329e5f583419167cd722962485926e338f4a": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "7cf5b79bfe291a67ab02b393e456ccc4c266f753": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "8a8eafb1cf62bfbeb1741769dae1a9dd47996192": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "8ba1f109551bd432803012645ac136ddd64dba72": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "b02a2eda1b317fbd16760128836b0ac59b560e9d": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" } } -} \ No newline at end of file +} From 2e23ca353fbe2102df16f823a4952fb96be70682 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Mon, 1 Feb 2021 16:40:00 +0100 Subject: [PATCH 053/107] Use berlin chainspec for unit test, yolo3 for testnet (#244) * Fix yolo+berlin specs * fix yolo3 maximumExtraDataSize * fmt --- bin/oe/cli/mod.rs | 2 +- bin/oe/params.rs | 4 ++++ .../{test/yolo3_test.json => yolo3.json} | 2 +- crates/ethcore/src/client/evm_test_client.rs | 1 - crates/ethcore/src/ethereum/mod.rs | 15 ++++++------ crates/ethjson/src/spec/spec.rs | 1 - crates/vm/evm/src/tests.rs | 24 +++++++++---------- crates/vm/vm/src/schedule.rs | 10 +------- crates/vm/vm/src/tests.rs | 9 +------ 9 files changed, 27 insertions(+), 41 deletions(-) rename crates/ethcore/res/chainspec/{test/yolo3_test.json => yolo3.json} (99%) diff --git a/bin/oe/cli/mod.rs b/bin/oe/cli/mod.rs index 871b4fc466..54e229957b 100644 --- a/bin/oe/cli/mod.rs +++ b/bin/oe/cli/mod.rs @@ -248,7 +248,7 @@ usage! { ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(), "--chain=[CHAIN]", - "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, morden, ropsten, kovan, rinkeby, goerli, poasokol, testnet, or dev.", + "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, morden, ropsten, kovan, rinkeby, goerli, poasokol, testnet, yolo3 or dev.", ARG arg_keys_path: (String) = "$BASE/keys", or |c: &Config| c.parity.as_ref()?.keys_path.clone(), "--keys-path=[PATH]", diff --git a/bin/oe/params.rs b/bin/oe/params.rs index 3d3163b19e..b1be1cafb3 100644 --- a/bin/oe/params.rs +++ b/bin/oe/params.rs @@ -51,6 +51,7 @@ pub enum SpecType { Rinkeby, Goerli, Sokol, + Yolo3, Dev, Custom(String), } @@ -81,6 +82,7 @@ impl str::FromStr for SpecType { "rinkeby" => SpecType::Rinkeby, "goerli" | "görli" | "testnet" => SpecType::Goerli, "sokol" | "poasokol" => SpecType::Sokol, + "yolo3" => SpecType::Yolo3, "dev" => SpecType::Dev, other => SpecType::Custom(other.into()), }; @@ -106,6 +108,7 @@ impl fmt::Display for SpecType { SpecType::Rinkeby => "rinkeby", SpecType::Goerli => "goerli", SpecType::Sokol => "sokol", + SpecType::Yolo3 => "yolo3", SpecType::Dev => "dev", SpecType::Custom(ref custom) => custom, }) @@ -131,6 +134,7 @@ impl SpecType { SpecType::Rinkeby => Ok(ethereum::new_rinkeby(params)), SpecType::Goerli => Ok(ethereum::new_goerli(params)), SpecType::Sokol => Ok(ethereum::new_sokol(params)), + SpecType::Yolo3 => Ok(ethereum::new_yolo3(params)), SpecType::Dev => Ok(Spec::new_instant()), SpecType::Custom(ref filename) => { let file = fs::File::open(filename).map_err(|e| { diff --git a/crates/ethcore/res/chainspec/test/yolo3_test.json b/crates/ethcore/res/chainspec/yolo3.json similarity index 99% rename from crates/ethcore/res/chainspec/test/yolo3_test.json rename to crates/ethcore/res/chainspec/yolo3.json index 30c0b91eb7..d15c0a9d31 100644 --- a/crates/ethcore/res/chainspec/test/yolo3_test.json +++ b/crates/ethcore/res/chainspec/yolo3.json @@ -35,7 +35,7 @@ "gasLimitBoundDivisor": "0x0400", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", - "maximumExtraDataSize": "0x20", + "maximumExtraDataSize": "0xffff", "minGasLimit": "0x1388", "networkID": "133519467574835", "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" diff --git a/crates/ethcore/src/client/evm_test_client.rs b/crates/ethcore/src/client/evm_test_client.rs index 7e088efa03..b8a39d4e6b 100644 --- a/crates/ethcore/src/client/evm_test_client.rs +++ b/crates/ethcore/src/client/evm_test_client.rs @@ -109,7 +109,6 @@ impl<'a> EvmTestClient<'a> { Some(ethereum::new_byzantium_to_constantinoplefixat5_test()) } ForkSpec::Berlin => Some(ethereum::new_berlin_test()), - ForkSpec::Yolo3 => Some(ethereum::new_yolo3_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 diff --git a/crates/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs index 91fb5062b6..3691c422c7 100644 --- a/crates/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -163,6 +163,13 @@ pub fn new_sokol<'a, T: Into>>(params: T) -> Spec { include_bytes!("../../res/chainspec/poasokol.json"), ) } +/// Create a new YOLO spec +pub fn new_yolo3<'a, T: Into>>(params: T) -> Spec { + load( + params.into(), + include_bytes!("../../res/chainspec/yolo3.json"), + ) +} // For tests @@ -275,14 +282,6 @@ pub fn new_eip2930_test() -> Spec { ) } -/// Create a new YOLO spec -pub fn new_yolo3_test() -> Spec { - load( - None, - include_bytes!("../../res/chainspec/test/yolo3_test.json"), - ) -} - /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { load( diff --git a/crates/ethjson/src/spec/spec.rs b/crates/ethjson/src/spec/spec.rs index df3a514869..39610023bf 100644 --- a/crates/ethjson/src/spec/spec.rs +++ b/crates/ethjson/src/spec/spec.rs @@ -39,7 +39,6 @@ pub enum ForkSpec { ByzantiumToConstantinopleAt5, ByzantiumToConstantinopleFixAt5, Berlin, - Yolo3, } /// Spec deserialization. diff --git a/crates/vm/evm/src/tests.rs b/crates/vm/evm/src/tests.rs index a6d359d5ad..14fa069411 100644 --- a/crates/vm/evm/src/tests.rs +++ b/crates/vm/evm/src/tests.rs @@ -1046,7 +1046,7 @@ fn test_subs_simple(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(18); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let gas_left = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1064,7 +1064,7 @@ fn test_subs_two_levels(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(36); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let gas_left = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1082,7 +1082,7 @@ fn test_subs_invalid_jump(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(24); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let current = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1101,7 +1101,7 @@ fn test_subs_shallow_return_stack(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(24); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let current = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1136,7 +1136,7 @@ fn test_subs_substack_limit(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(1_000_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let gas_left = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1154,7 +1154,7 @@ fn test_subs_substack_out(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(1_000_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let current = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1175,7 +1175,7 @@ fn test_subs_sub_at_end(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(30); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let gas_left = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1192,7 +1192,7 @@ fn test_subs_walk_into_subroutine(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(100); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_berlin(); + let mut ext = FakeExt::new_berlin(Address::zero(), Address::zero(), &[]); let current = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1578,7 +1578,7 @@ fn test_access_list_ext_at_precompiles(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(8653); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_yolo3( + let mut ext = FakeExt::new_berlin( Address::from("0x0000000000000000000000000000000000000000"), Address::from("0x000000000000000000000000636F6E7472616374"), &[ @@ -1602,7 +1602,7 @@ fn test_access_list_extcodecopy_twice(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(2835); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_yolo3( + let mut ext = FakeExt::new_berlin( Address::from("0x0000000000000000000000000000000000000000"), Address::from("0x000000000000000000000000636F6E7472616374"), &[], @@ -1628,7 +1628,7 @@ fn test_access_list_sload_sstore(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(44529); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_yolo3( + let mut ext = FakeExt::new_berlin( Address::from("0x0000000000000000000000000000000000000000"), Address::from("0x000000000000000000000000636F6E7472616374"), &[], @@ -1648,7 +1648,7 @@ fn test_access_list_cheap_expensive_cheap(factory: super::Factory) { let mut params = ActionParams::default(); params.gas = U256::from(2869); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new_yolo3( + let mut ext = FakeExt::new_berlin( Address::from("0x0000000000000000000000000000000000000000"), Address::from("0x000000000000000000000000636F6E7472616374"), &[Address::from("0x0000000000000000000000000000000000000004")], diff --git a/crates/vm/vm/src/schedule.rs b/crates/vm/vm/src/schedule.rs index cd258b69ce..80643acd28 100644 --- a/crates/vm/vm/src/schedule.rs +++ b/crates/vm/vm/src/schedule.rs @@ -335,16 +335,8 @@ impl Schedule { schedule } - /// Schedule for the Berlin fork of the Ethereum main net. - pub fn new_berlin() -> Schedule { - let mut schedule = Self::new_istanbul(); - schedule.have_subs = true; // EIP 2315 - - schedule - } - /// Schedule for the Yolov3 testnet of the Ethereum main net. - pub fn new_yolo3() -> Schedule { + pub fn new_berlin() -> Schedule { let mut schedule = Self::new_istanbul(); schedule.have_subs = true; // EIP 2315 diff --git a/crates/vm/vm/src/tests.rs b/crates/vm/vm/src/tests.rs index 17a3f09d7b..6bcb46fd25 100644 --- a/crates/vm/vm/src/tests.rs +++ b/crates/vm/vm/src/tests.rs @@ -118,16 +118,9 @@ impl FakeExt { } /// New fake externalities with Berlin schedule rules - pub fn new_berlin() -> Self { + pub fn new_berlin(from: Address, to: Address, builtins: &[Address]) -> Self { let mut ext = FakeExt::default(); ext.schedule = Schedule::new_berlin(); - ext - } - - /// New fake externalities with YoloV2 schedule rules - pub fn new_yolo3(from: Address, to: Address, builtins: &[Address]) -> Self { - let mut ext = FakeExt::default(); - ext.schedule = Schedule::new_yolo3(); ext.access_list.enable(); ext.access_list.insert_address(from); ext.access_list.insert_address(to); From 65c5e6dfd317d962507cf853e7aa28bda8f394d0 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 2 Feb 2021 16:26:55 +0100 Subject: [PATCH 054/107] EIP-2930 RPC and TypedTransactionView support (#245) * TypedTransactionView for EIP-2930 * Enable EIP-2930 in RPC calls * type field added to TypedTransactionView --- crates/ethcore/types/src/encoded.rs | 4 +- .../types/src/transaction/transaction.rs | 2 +- crates/ethcore/types/src/views/block.rs | 6 +- crates/ethcore/types/src/views/body.rs | 6 +- crates/ethcore/types/src/views/mod.rs | 4 +- crates/ethcore/types/src/views/transaction.rs | 131 --------- .../types/src/views/typed_transaction.rs | 252 ++++++++++++++++++ crates/rpc/src/v1/helpers/dispatch/full.rs | 2 +- crates/rpc/src/v1/helpers/dispatch/signing.rs | 2 +- .../helpers/external_signer/signing_queue.rs | 2 +- crates/rpc/src/v1/helpers/fake_sign.rs | 2 +- crates/rpc/src/v1/helpers/requests.rs | 8 +- crates/rpc/src/v1/tests/mocked/signer.rs | 18 +- crates/rpc/src/v1/types/call_request.rs | 11 +- crates/rpc/src/v1/types/confirmations.rs | 4 +- crates/rpc/src/v1/types/receipt.rs | 2 +- crates/rpc/src/v1/types/transaction.rs | 7 +- .../rpc/src/v1/types/transaction_request.rs | 19 +- 18 files changed, 301 insertions(+), 181 deletions(-) delete mode 100644 crates/ethcore/types/src/views/transaction.rs create mode 100644 crates/ethcore/types/src/views/typed_transaction.rs diff --git a/crates/ethcore/types/src/encoded.rs b/crates/ethcore/types/src/encoded.rs index 1a13e2668e..daf15eba0e 100644 --- a/crates/ethcore/types/src/encoded.rs +++ b/crates/ethcore/types/src/encoded.rs @@ -210,7 +210,7 @@ impl Body { } /// A view over each transaction in the block. - pub fn transaction_views(&self) -> Vec { + pub fn transaction_views(&self) -> Vec { self.view().transaction_views() } @@ -405,7 +405,7 @@ impl Block { } /// A view over each transaction in the block. - pub fn transaction_views(&self) -> Vec { + pub fn transaction_views(&self) -> Vec { self.view().transaction_views() } diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index af225dcaca..bf760eb77f 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -267,7 +267,7 @@ impl AccessListTx { &mut self.transaction } - // decode bytes by this payload spec: rlp([3, [chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]]) + // decode bytes by this payload spec: rlp([1, [chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS]]) pub fn decode(tx: &[u8]) -> Result { let tx_rlp = &Rlp::new(tx); diff --git a/crates/ethcore/types/src/views/block.rs b/crates/ethcore/types/src/views/block.rs index 237cf8694c..e540d0a380 100644 --- a/crates/ethcore/types/src/views/block.rs +++ b/crates/ethcore/types/src/views/block.rs @@ -22,7 +22,7 @@ use ethereum_types::H256; use hash::keccak; use header::Header; use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; -use views::{HeaderView, TransactionView}; +use views::{HeaderView, TypedTransactionView}; /// View onto block rlp. pub struct BlockView<'a> { @@ -114,10 +114,10 @@ impl<'a> BlockView<'a> { } /// Return List of transactions in given block. - pub fn transaction_views(&self) -> Vec> { + pub fn transaction_views(&self) -> Vec> { self.transactions_rlp() .iter() - .map(TransactionView::new) + .map(TypedTransactionView::new) .collect() } diff --git a/crates/ethcore/types/src/views/body.rs b/crates/ethcore/types/src/views/body.rs index 0fcc8eb38a..055a54f5ee 100644 --- a/crates/ethcore/types/src/views/body.rs +++ b/crates/ethcore/types/src/views/body.rs @@ -22,7 +22,7 @@ use ethereum_types::H256; use hash::keccak; use header::Header; use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; -use views::{HeaderView, TransactionView}; +use views::{HeaderView, TypedTransactionView}; use BlockNumber; /// View onto block rlp. @@ -95,10 +95,10 @@ impl<'a> BodyView<'a> { self.transactions_rlp().item_count() } /// Return List of transactions in given block. - pub fn transaction_views(&self) -> Vec> { + pub fn transaction_views(&self) -> Vec> { self.transactions_rlp() .iter() - .map(TransactionView::new) + .map(TypedTransactionView::new) .collect() } diff --git a/crates/ethcore/types/src/views/mod.rs b/crates/ethcore/types/src/views/mod.rs index 312e5ecc1f..bb0574c5a7 100644 --- a/crates/ethcore/types/src/views/mod.rs +++ b/crates/ethcore/types/src/views/mod.rs @@ -21,10 +21,10 @@ mod view_rlp; mod block; mod body; mod header; -mod transaction; +mod typed_transaction; pub use self::{ - block::BlockView, body::BodyView, header::HeaderView, transaction::TransactionView, + block::BlockView, body::BodyView, header::HeaderView, typed_transaction::TypedTransactionView, view_rlp::ViewRlp, }; diff --git a/crates/ethcore/types/src/views/transaction.rs b/crates/ethcore/types/src/views/transaction.rs deleted file mode 100644 index d20115cbb2..0000000000 --- a/crates/ethcore/types/src/views/transaction.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -//! View onto transaction rlp -use super::ViewRlp; -use bytes::Bytes; -use ethereum_types::{H256, U256}; -use hash::keccak; - -/// View onto transaction rlp. -pub struct TransactionView<'a> { - rlp: ViewRlp<'a>, -} - -impl<'a> TransactionView<'a> { - /// Creates new view onto valid transaction rlp. - /// Use the `view!` macro to create this view in order to capture debugging info. - /// - /// # Example - /// - /// ``` - /// #[macro_use] - /// extern crate common_types as types; - /// - /// use types::views::{TransactionView}; - /// - /// fn main() { - /// let bytes : &[u8] = &[]; - /// let tx_view = view!(TransactionView, bytes); - /// } - /// ``` - pub fn new(rlp: ViewRlp<'a>) -> TransactionView<'a> { - TransactionView { rlp: rlp } - } - - /// Return reference to underlaying rlp. - pub fn rlp(&self) -> &ViewRlp<'a> { - &self.rlp - } - - /// Returns transaction hash. - pub fn hash(&self) -> H256 { - keccak(self.rlp.as_raw()) - } - - /// Get the nonce field of the transaction. - pub fn nonce(&self) -> U256 { - self.rlp.val_at(0) - } - - /// Get the gas_price field of the transaction. - pub fn gas_price(&self) -> U256 { - self.rlp.val_at(1) - } - - /// Get the gas field of the transaction. - pub fn gas(&self) -> U256 { - self.rlp.val_at(2) - } - - /// Get the value field of the transaction. - pub fn value(&self) -> U256 { - self.rlp.val_at(4) - } - - /// Get the data field of the transaction. - pub fn data(&self) -> Bytes { - self.rlp.val_at(5) - } - - /// Get the v field of the transaction. - pub fn v(&self) -> u8 { - let r: u16 = self.rlp.val_at(6); - r as u8 - } - - /// Get the r field of the transaction. - pub fn r(&self) -> U256 { - self.rlp.val_at(7) - } - - /// Get the s field of the transaction. - pub fn s(&self) -> U256 { - self.rlp.val_at(8) - } -} - -#[cfg(test)] -mod tests { - use super::TransactionView; - use rustc_hex::FromHex; - - #[test] - fn test_transaction_view() { - let rlp = "f87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".from_hex().unwrap(); - - let view = view!(TransactionView, &rlp); - assert_eq!(view.nonce(), 0.into()); - assert_eq!(view.gas_price(), 1.into()); - assert_eq!(view.gas(), 0x61a8.into()); - assert_eq!(view.value(), 0xa.into()); - assert_eq!( - view.data(), - "0000000000000000000000000000000000000000000000000000000000" - .from_hex() - .unwrap() - ); - assert_eq!( - view.r(), - "48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353".into() - ); - assert_eq!( - view.s(), - "efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".into() - ); - assert_eq!(view.v(), 0x1b); - } -} diff --git a/crates/ethcore/types/src/views/typed_transaction.rs b/crates/ethcore/types/src/views/typed_transaction.rs new file mode 100644 index 0000000000..3a504c1178 --- /dev/null +++ b/crates/ethcore/types/src/views/typed_transaction.rs @@ -0,0 +1,252 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! View onto transaction rlp +use std::convert::TryInto; + +use crate::transaction::{signature, TypedTxId}; + +use super::ViewRlp; +use bytes::Bytes; +use ethereum_types::{H256, U256}; +use hash::keccak; +use rlp::Rlp; + +/// View onto transaction rlp. Assumption is this is part of block. +/// Typed Transaction View. It handles raw bytes to search for particular field. +/// Access tx: +/// 1 | [chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, senderV, senderR, senderS] +/// Legacy tx: +/// [nonce, gasPrice, gasLimit, to, value, data, senderV, senderR, senderS] +pub struct TypedTransactionView<'a> { + rlp: ViewRlp<'a>, + transaction_type: TypedTxId, +} +impl<'a> TypedTransactionView<'a> { + /// Creates new view onto valid transaction rlp. + /// Use the `view!` macro to create this view in order to capture debugging info. + /// + /// # Example + /// + /// ``` + /// #[macro_use] + /// extern crate common_types as types; + /// + /// use types::views::{TransactionView}; + /// + /// fn main() { + /// let bytes : &[u8] = &[]; + /// let tx_view = view!(TransactionView, bytes); + /// } + /// ``` + pub fn new(rlp: ViewRlp<'a>) -> TypedTransactionView<'a> { + let transaction_type = Self::extract_transaction_type(&rlp.rlp); + TypedTransactionView { + rlp: rlp, + transaction_type, + } + } + + /// Extract transaction type from rlp bytes. + fn extract_transaction_type(rlp: &Rlp) -> TypedTxId { + if rlp.is_list() { + return TypedTxId::Legacy; + } + let tx = rlp.data().expect("unable to decode tx rlp"); + let id = tx[0].try_into().expect("unable to decode tx type"); + if id == TypedTxId::Legacy { + panic!("Transaction RLP View should be valid. Legacy byte found"); + } + id + } + + /// Returns reference to transaction type. + pub fn transaction_type(&self) -> &TypedTxId { + &self.transaction_type + } + + /// Returns transaction hash. + pub fn hash(&self) -> H256 { + match self.transaction_type { + TypedTxId::Legacy => keccak(self.rlp.as_raw()), + _ => keccak(self.rlp.rlp.data().unwrap()), + } + } + + /// Get chain Id field of the transaction. + pub fn chain_id(&self) -> u64 { + match self.transaction_type { + TypedTxId::Legacy => { + signature::extract_chain_id_from_legacy_v(self.rlp.val_at(6)).unwrap_or(0) + } + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(1), + } + } + + /// Get the nonce field of the transaction. + pub fn nonce(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(0), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(1), + } + } + + /// Get the gas_price field of the transaction. + pub fn gas_price(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(1), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(2), + } + } + + /// Get the gas field of the transaction. + pub fn gas(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(2), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(3), + } + } + + /// Get the value field of the transaction. + pub fn value(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(4), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(5), + } + } + + /// Get the data field of the transaction. + pub fn data(&self) -> Bytes { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(5), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(6), + } + } + + /// Get the v field of the transaction. + pub fn legacy_v(&self) -> u8 { + let r = match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(6), + TypedTxId::AccessList => { + let chain_id = match self.chain_id() { + 0 => None, + n => Some(n), + }; + signature::add_chain_replay_protection( + view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(8), + chain_id, + ) + } + }; + r as u8 + } + + pub fn standard_v(&self) -> u8 { + match self.transaction_type { + TypedTxId::Legacy => signature::extract_standard_v(self.rlp.val_at(6)), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(8), + } + } + + /// Get the r field of the transaction. + pub fn r(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(7), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(9), + } + } + + /// Get the s field of the transaction. + pub fn s(&self) -> U256 { + match self.transaction_type { + TypedTxId::Legacy => self.rlp.val_at(8), + TypedTxId::AccessList => view!(Self, &self.rlp.rlp.data().unwrap()[1..]) + .rlp + .val_at(10), + } + } +} + +#[cfg(test)] +mod tests { + use super::TypedTransactionView; + use rustc_hex::FromHex; + + #[test] + fn test_transaction_view() { + let rlp = "f87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".from_hex().unwrap(); + + let view = view!(TypedTransactionView, &rlp); + assert_eq!(view.nonce(), 0.into()); + assert_eq!(view.gas_price(), 1.into()); + assert_eq!(view.gas(), 0x61a8.into()); + assert_eq!(view.value(), 0xa.into()); + assert_eq!( + view.data(), + "0000000000000000000000000000000000000000000000000000000000" + .from_hex() + .unwrap() + ); + assert_eq!( + view.r(), + "48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353".into() + ); + assert_eq!( + view.s(), + "efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".into() + ); + assert_eq!(view.legacy_v(), 0x1b); + } + + #[test] + fn test_access_list_transaction_view() { + let rlp = "b8c101f8be01010a8301e24194000000000000000000000000000000000000aaaa8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000080a082dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234dba072228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0".from_hex().unwrap(); + + let view = view!(TypedTransactionView, &rlp); + assert_eq!(view.nonce(), 0x1.into()); + assert_eq!(view.gas_price(), 0xa.into()); + assert_eq!(view.gas(), 0x1e241.into()); + assert_eq!(view.value(), 0x0.into()); + assert_eq!(view.data(), "".from_hex().unwrap()); + assert_eq!( + view.r(), + "82dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234db".into() + ); + assert_eq!( + view.s(), + "72228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0".into() + ); + assert_eq!(view.standard_v(), 0x0); + } +} diff --git a/crates/rpc/src/v1/helpers/dispatch/full.rs b/crates/rpc/src/v1/helpers/dispatch/full.rs index 36874e6d1c..87424755ef 100644 --- a/crates/rpc/src/v1/helpers/dispatch/full.rs +++ b/crates/rpc/src/v1/helpers/dispatch/full.rs @@ -120,7 +120,7 @@ impl Dispatcher }; Box::new(future::ok(FilledTransactionRequest { - tx_type: request.tx_type, + transaction_type: request.transaction_type, from, used_default_from: request.from.is_none(), to: request.to, diff --git a/crates/rpc/src/v1/helpers/dispatch/signing.rs b/crates/rpc/src/v1/helpers/dispatch/signing.rs index d07cb3eccd..5cc8f9357c 100644 --- a/crates/rpc/src/v1/helpers/dispatch/signing.rs +++ b/crates/rpc/src/v1/helpers/dispatch/signing.rs @@ -59,7 +59,7 @@ impl super::Accounts for Signer { value: filled.value, data: filled.data, }; - let t = match filled.tx_type { + let t = match filled.transaction_type { TypedTxId::Legacy => TypedTransaction::Legacy(legacy_tx), TypedTxId::AccessList => { if filled.access_list.is_none() { diff --git a/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs b/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs index deec5c3b4e..e7c0319382 100644 --- a/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs +++ b/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs @@ -256,7 +256,7 @@ mod test { fn request() -> ConfirmationPayload { ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from(2)), diff --git a/crates/rpc/src/v1/helpers/fake_sign.rs b/crates/rpc/src/v1/helpers/fake_sign.rs index b692f502f7..21cedad1e6 100644 --- a/crates/rpc/src/v1/helpers/fake_sign.rs +++ b/crates/rpc/src/v1/helpers/fake_sign.rs @@ -35,7 +35,7 @@ pub fn sign_call(request: CallRequest) -> Result { value: request.value.unwrap_or_default(), data: request.data.unwrap_or_default(), }; - let tx_typed = match request.tx_type { + let tx_typed = match request.transaction_type { TypedTxId::Legacy => TypedTransaction::Legacy(tx_legacy), TypedTxId::AccessList => TypedTransaction::AccessList(AccessListTx::new( tx_legacy, diff --git a/crates/rpc/src/v1/helpers/requests.rs b/crates/rpc/src/v1/helpers/requests.rs index 848a8d4156..cc17ac4cd8 100644 --- a/crates/rpc/src/v1/helpers/requests.rs +++ b/crates/rpc/src/v1/helpers/requests.rs @@ -24,7 +24,7 @@ use v1::types::{Origin, TransactionCondition}; #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct TransactionRequest { /// type of transaction. - pub tx_type: TypedTxId, + pub transaction_type: TypedTxId, /// Sender pub from: Option
, /// Recipient @@ -49,7 +49,7 @@ pub struct TransactionRequest { #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct FilledTransactionRequest { /// type of transaction. - pub tx_type: TypedTxId, + pub transaction_type: TypedTxId, /// Sender pub from: Address, /// Indicates if the sender was filled by default value. @@ -75,7 +75,7 @@ pub struct FilledTransactionRequest { impl From for TransactionRequest { fn from(r: FilledTransactionRequest) -> Self { TransactionRequest { - tx_type: r.tx_type, + transaction_type: r.transaction_type, from: Some(r.from), to: r.to, gas_price: Some(r.gas_price), @@ -93,7 +93,7 @@ impl From for TransactionRequest { #[derive(Debug, Default, PartialEq)] pub struct CallRequest { /// type of transaction. - pub tx_type: TypedTxId, + pub transaction_type: TypedTxId, /// From pub from: Option
, /// To diff --git a/crates/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs index 6ef3eb1e7a..6c0bcee84f 100644 --- a/crates/rpc/src/v1/tests/mocked/signer.rs +++ b/crates/rpc/src/v1/tests/mocked/signer.rs @@ -91,7 +91,7 @@ fn should_return_list_of_items_to_confirm() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -138,7 +138,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -176,7 +176,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Address::from(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), @@ -242,7 +242,7 @@ fn should_confirm_transaction_and_dispatch() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -307,7 +307,7 @@ fn should_alter_the_sender_and_nonce() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: 0.into(), used_default_from: false, to: Some(recipient), @@ -373,7 +373,7 @@ fn should_confirm_transaction_with_token() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -441,7 +441,7 @@ fn should_confirm_transaction_with_rlp() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), @@ -507,7 +507,7 @@ fn should_return_error_when_sender_does_not_match() { .signer .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Address::default(), used_default_from: false, to: Some(recipient), @@ -574,7 +574,7 @@ fn should_confirm_sign_transaction_with_rlp() { .signer .add_request( ConfirmationPayload::SignTransaction(FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: address, used_default_from: false, to: Some(recipient), diff --git a/crates/rpc/src/v1/types/call_request.rs b/crates/rpc/src/v1/types/call_request.rs index d27125eedc..0972dd6bdd 100644 --- a/crates/rpc/src/v1/types/call_request.rs +++ b/crates/rpc/src/v1/types/call_request.rs @@ -25,7 +25,8 @@ use v1::{helpers::CallRequest as Request, types::Bytes}; pub struct CallRequest { /// transaction type #[serde(default)] - pub tx_type: TypedTxId, + #[serde(rename = "type")] + pub transaction_type: TypedTxId, /// From pub from: Option, /// To @@ -47,7 +48,7 @@ pub struct CallRequest { impl Into for CallRequest { fn into(self) -> Request { Request { - tx_type: self.tx_type, + transaction_type: self.transaction_type, from: self.from.map(Into::into), to: self.to.map(Into::into), gas_price: self.gas_price.map(Into::into), @@ -84,7 +85,7 @@ mod tests { assert_eq!( deserialized, CallRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from(1)), to: Some(H160::from(2)), gas_price: Some(U256::from(1)), @@ -110,7 +111,7 @@ mod tests { let deserialized: CallRequest = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, CallRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap()), to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: Some(U256::from_str("9184e72a000").unwrap()), @@ -130,7 +131,7 @@ mod tests { assert_eq!( deserialized, CallRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from(1)), to: None, gas_price: None, diff --git a/crates/rpc/src/v1/types/confirmations.rs b/crates/rpc/src/v1/types/confirmations.rs index 200c0afcba..b489f354c4 100644 --- a/crates/rpc/src/v1/types/confirmations.rs +++ b/crates/rpc/src/v1/types/confirmations.rs @@ -331,7 +331,7 @@ mod tests { id: 15.into(), payload: helpers::ConfirmationPayload::SendTransaction( helpers::FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: 0.into(), used_default_from: false, to: None, @@ -362,7 +362,7 @@ mod tests { id: 15.into(), payload: helpers::ConfirmationPayload::SignTransaction( helpers::FilledTransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: 0.into(), used_default_from: false, to: None, diff --git a/crates/rpc/src/v1/types/receipt.rs b/crates/rpc/src/v1/types/receipt.rs index 9a978af499..37042ad1a1 100644 --- a/crates/rpc/src/v1/types/receipt.rs +++ b/crates/rpc/src/v1/types/receipt.rs @@ -26,7 +26,7 @@ use v1::types::Log; #[serde(rename_all = "camelCase")] pub struct Receipt { /// Transaction Type - #[serde(skip_serializing)] + #[serde(rename = "type")] pub transaction_type: TypedTxId, /// Transaction Hash pub transaction_hash: Option, diff --git a/crates/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs index 86bb7278c1..6d6bf419ca 100644 --- a/crates/rpc/src/v1/types/transaction.rs +++ b/crates/rpc/src/v1/types/transaction.rs @@ -30,6 +30,9 @@ use v1::types::{Bytes, TransactionCondition}; #[derive(Debug, Default, Clone, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct Transaction { + /// transaction type + #[serde(rename = "type")] + pub transaction_type: u8, /// Hash pub hash: H256, /// Nonce @@ -70,11 +73,7 @@ pub struct Transaction { pub s: U256, /// Transaction activates at specified block. pub condition: Option, - /// transaction type - #[serde(skip_serializing)] - pub transaction_type: u8, /// optional access list - #[serde(skip_serializing)] pub access_list: AccessList, } diff --git a/crates/rpc/src/v1/types/transaction_request.rs b/crates/rpc/src/v1/types/transaction_request.rs index 7995244086..bace3af04c 100644 --- a/crates/rpc/src/v1/types/transaction_request.rs +++ b/crates/rpc/src/v1/types/transaction_request.rs @@ -33,8 +33,8 @@ use std::fmt; pub struct TransactionRequest { /// type of transaction. If none we assume it is legacy #[serde(default)] - #[serde(skip_serializing)] - pub tx_type: TypedTxId, + #[serde(rename = "type")] + pub transaction_type: TypedTxId, /// Sender pub from: Option, /// Recipient @@ -52,7 +52,6 @@ pub struct TransactionRequest { /// Delay until this block condition. pub condition: Option, /// Access list - #[serde(skip_serializing)] pub access_list: Option, } @@ -105,7 +104,7 @@ impl fmt::Display for TransactionRequest { impl From for TransactionRequest { fn from(r: helpers::TransactionRequest) -> Self { TransactionRequest { - tx_type: r.tx_type, + transaction_type: r.transaction_type, from: r.from.map(Into::into), to: r.to.map(Into::into), gas_price: r.gas_price.map(Into::into), @@ -122,7 +121,7 @@ impl From for TransactionRequest { impl From for TransactionRequest { fn from(r: helpers::FilledTransactionRequest) -> Self { TransactionRequest { - tx_type: r.tx_type, + transaction_type: r.transaction_type, from: Some(r.from), to: r.to, gas_price: Some(r.gas_price), @@ -139,7 +138,7 @@ impl From for TransactionRequest { impl Into for TransactionRequest { fn into(self) -> helpers::TransactionRequest { helpers::TransactionRequest { - tx_type: self.tx_type, + transaction_type: self.transaction_type, from: self.from.map(Into::into), to: self.to.map(Into::into), gas_price: self.gas_price.map(Into::into), @@ -179,7 +178,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from(1)), to: Some(H160::from(2)), gas_price: Some(U256::from(1)), @@ -206,7 +205,7 @@ mod tests { let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); assert_eq!(deserialized, TransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from_str("b60e8dd61c5d32be8058bb8eb970870f07233155").unwrap()), to: Some(H160::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: Some(U256::from_str("9184e72a000").unwrap()), @@ -227,7 +226,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from(1).into()), to: None, gas_price: None, @@ -256,7 +255,7 @@ mod tests { assert_eq!( deserialized, TransactionRequest { - tx_type: Default::default(), + transaction_type: Default::default(), from: Some(H160::from_str("b5f7502a2807cb23615c7456055e1d65b2508625").unwrap()), to: Some(H160::from_str("895d32f2db7d01ebb50053f9e48aacf26584fe40").unwrap()), gas_price: Some(U256::from_str("0ba43b7400").unwrap()), From 6d81fce451ffeb4275f442cbab83e6f64d40904f Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 4 Feb 2021 11:39:10 +0100 Subject: [PATCH 055/107] Update EWF's chains with Istanbul transition block numbers (#11482) (#254) Co-authored-by: Artem Vorotnikov --- crates/ethcore/res/chainspec/ewc.json | 28 +++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/ethcore/res/chainspec/ewc.json b/crates/ethcore/res/chainspec/ewc.json index 632b577815..4a115c391e 100644 --- a/crates/ethcore/res/chainspec/ewc.json +++ b/crates/ethcore/res/chainspec/ewc.json @@ -27,6 +27,11 @@ "eip145Transition": "0x0", "eip1014Transition": "0x0", "eip1052Transition": "0x0", + "eip1283Transition": "0x4b1bb6", + "eip1344Transition": "0x4b1bb6", + "eip1706Transition": "0x4b1bb6", + "eip1884Transition": "0x4b1bb6", + "eip2028Transition": "0x4b1bb6", "registrar": "0x1204700000000000000000000000000000000006" }, "genesis": { @@ -112,8 +117,8 @@ "0": { "price": { "alt_bn128_const_operations": { "price": 500 }} }, - "0x7fffffffffffff": { - "info": "EIP 1108 transition", + "0x4b1bb6": { + "info": "EIP 1108 transition at block 4_922_294 (0x4b1bb6)", "price": { "alt_bn128_const_operations": { "price": 150 }} } } @@ -127,8 +132,8 @@ "0": { "price": { "alt_bn128_const_operations": { "price": 40000 }} }, - "0x7fffffffffffff": { - "info": "EIP 1108 transition", + "0x4b1bb6": { + "info": "EIP 1108 transition at block 4_922_294 (0x4b1bb6)", "price": { "alt_bn128_const_operations": { "price": 6000 }} } } @@ -142,13 +147,24 @@ "0": { "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} }, - "0x7fffffffffffff": { - "info": "EIP 1108 transition", + "0x4b1bb6": { + "info": "EIP 1108 transition at block 4_922_294 (0x4b1bb6)", "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} } } } }, + "0x0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0x4b1bb6", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + }, "0x1204700000000000000000000000000000000005": { "constructor": "0x60806040523480156200001157600080fd5b50604051620024c8380380620024c883398101806040528101908080518201929190602001805190602001909291905050506000825182603282111580156200005a5750818111155b801562000068575060008114155b801562000076575060008214155b15156200008257600080fd5b600092505b8451831015620001bd57600260008685815181101515620000a457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16158015620001335750600085848151811015156200011057fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614155b15156200013f57600080fd5b60016002600087868151811015156200015457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550828060010193505062000087565b8460039080519060200190620001d5929190620001e8565b50836004819055505050505050620002bd565b82805482825590600052602060002090810192821562000264579160200282015b82811115620002635782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019062000209565b5b50905062000273919062000277565b5090565b620002ba91905b80821115620002b657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016200027e565b5090565b90565b6121fb80620002cd6000396000f30060806040526004361061011d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063025e7c2714610177578063173825d9146101e457806320ea8d86146102275780632f54bf6e146102545780633411c81c146102af57806354741525146103145780637065cb4814610363578063784547a7146103a65780638b51d13f146103eb5780639ace38c21461042c578063a0e67e2b14610517578063a8abe69a14610583578063b5dc40c314610627578063b77bf600146106a9578063ba51a6df146106d4578063c01a8c8414610701578063c64274741461072e578063d74f8edd146107d5578063dc8452cd14610800578063e20056e61461082b578063ee22610b1461088e575b6000341115610175573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b34801561018357600080fd5b506101a2600480360381019080803590602001909291905050506108bb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f057600080fd5b50610225600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506108f9565b005b34801561023357600080fd5b5061025260048036038101908080359060200190929190505050610b92565b005b34801561026057600080fd5b50610295600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d3a565b604051808215151515815260200191505060405180910390f35b3480156102bb57600080fd5b506102fa60048036038101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d5a565b604051808215151515815260200191505060405180910390f35b34801561032057600080fd5b5061034d600480360381019080803515159060200190929190803515159060200190929190505050610d89565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b506103a4600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e1b565b005b3480156103b257600080fd5b506103d160048036038101908080359060200190929190505050611020565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b5061041660048036038101908080359060200190929190505050611105565b6040518082815260200191505060405180910390f35b34801561043857600080fd5b50610457600480360381019080803590602001909291905050506111d0565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156104d95780820151818401526020810190506104be565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b34801561052357600080fd5b5061052c6112c5565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561056f578082015181840152602081019050610554565b505050509050019250505060405180910390f35b34801561058f57600080fd5b506105d06004803603810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611353565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156106135780820151818401526020810190506105f8565b505050509050019250505060405180910390f35b34801561063357600080fd5b50610652600480360381019080803590602001909291905050506114c4565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561069557808201518184015260208101905061067a565b505050509050019250505060405180910390f35b3480156106b557600080fd5b506106be611701565b6040518082815260200191505060405180910390f35b3480156106e057600080fd5b506106ff60048036038101908080359060200190929190505050611707565b005b34801561070d57600080fd5b5061072c600480360381019080803590602001909291905050506117c1565b005b34801561073a57600080fd5b506107bf600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929050505061199e565b6040518082815260200191505060405180910390f35b3480156107e157600080fd5b506107ea6119bd565b6040518082815260200191505060405180910390f35b34801561080c57600080fd5b506108156119c2565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b5061088c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119c8565b005b34801561089a57600080fd5b506108b960048036038101908080359060200190929190505050611cdd565b005b6003818154811015156108ca57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561093557600080fd5b81600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561098e57600080fd5b6000600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600091505b600160038054905003821015610b13578273ffffffffffffffffffffffffffffffffffffffff16600383815481101515610a2157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610b06576003600160038054905003815481101515610a7f57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600383815481101515610ab957fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610b13565b81806001019250506109eb565b6001600381818054905003915081610b2b91906120fe565b506003805490506004541115610b4a57610b49600380549050611707565b5b8273ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a2505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610beb57600080fd5b81336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515610c5657600080fd5b8360008082815260200190815260200160002060030160009054906101000a900460ff16151515610c8657600080fd5b60006001600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b60026020528060005260406000206000915054906101000a900460ff1681565b60016020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600554811015610e1457838015610dc8575060008082815260200190815260200160002060030160009054906101000a900460ff16155b80610dfb5750828015610dfa575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b15610e07576001820191505b8080600101915050610d91565b5092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610e5557600080fd5b80600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515610eaf57600080fd5b8160008173ffffffffffffffffffffffffffffffffffffffff1614151515610ed657600080fd5b60016003805490500160045460328211158015610ef35750818111155b8015610f00575060008114155b8015610f0d575060008214155b1515610f1857600080fd5b6001600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060038590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000809150600090505b6003805490508110156110fd5760016000858152602001908152602001600020600060038381548110151561105e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156110dd576001820191505b6004548214156110f057600192506110fe565b808060010191505061102d565b5b5050919050565b600080600090505b6003805490508110156111ca5760016000848152602001908152602001600020600060038381548110151561113e57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156111bd576001820191505b808060010191505061110d565b50919050565b60006020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156112a85780601f1061127d576101008083540402835291602001916112a8565b820191906000526020600020905b81548152906001019060200180831161128b57829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b6060600380548060200260200160405190810160405280929190818152602001828054801561134957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116112ff575b5050505050905090565b60608060008060055460405190808252806020026020018201604052801561138a5781602001602082028038833980820191505090505b50925060009150600090505b600554811015611436578580156113cd575060008082815260200190815260200160002060030160009054906101000a900460ff16155b8061140057508480156113ff575060008082815260200190815260200160002060030160009054906101000a900460ff165b5b156114295780838381518110151561141457fe5b90602001906020020181815250506001820191505b8080600101915050611396565b8787036040519080825280602002602001820160405280156114675781602001602082028038833980820191505090505b5093508790505b868110156114b957828181518110151561148457fe5b906020019060200201518489830381518110151561149e57fe5b9060200190602002018181525050808060010191505061146e565b505050949350505050565b6060806000806003805490506040519080825280602002602001820160405280156114fe5781602001602082028038833980820191505090505b50925060009150600090505b60038054905081101561164b5760016000868152602001908152602001600020600060038381548110151561153b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561163e576003818154811015156115c257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683838151811015156115fb57fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506001820191505b808060010191505061150a565b8160405190808252806020026020018201604052801561167a5781602001602082028038833980820191505090505b509350600090505b818110156116f957828181518110151561169857fe5b9060200190602002015184828151811015156116b057fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611682565b505050919050565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561174157600080fd5b60038054905081603282111580156117595750818111155b8015611766575060008114155b8015611773575060008214155b151561177e57600080fd5b826004819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561181a57600080fd5b81600080600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415151561187657600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515156118e257600080fd5b600180600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361199785611cdd565b5050505050565b60006119ab848484611f85565b90506119b6816117c1565b9392505050565b603281565b60045481565b60003073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0457600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611a5d57600080fd5b82600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151515611ab757600080fd5b600092505b600380549050831015611ba0578473ffffffffffffffffffffffffffffffffffffffff16600384815481101515611aef57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b935783600384815481101515611b4657fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611ba0565b8280600101935050611abc565b6000600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b600033600260008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611d3857600080fd5b82336001600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515611da357600080fd5b8460008082815260200190815260200160002060030160009054906101000a900460ff16151515611dd357600080fd5b611ddc86611020565b15611f7d57600080878152602001908152602001600020945060018560030160006101000a81548160ff021916908315150217905550611efa8560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201805460018160011615610100020316600290049050886002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611ef05780601f10611ec557610100808354040283529160200191611ef0565b820191906000526020600020905b815481529060010190602001808311611ed357829003601f168201915b50505050506120d7565b15611f3157857f33e13ecb54c3076d8e8bb8c2881800a4d972b792045ffae98fdf46df365fed7560405160405180910390a2611f7c565b857f526441bb6c1aba3c9a4a6ca1d6545da9c2333c8c48343ef398eb858d72b7923660405160405180910390a260008560030160006101000a81548160ff0219169083151502179055505b5b505050505050565b60008360008173ffffffffffffffffffffffffffffffffffffffff1614151515611fae57600080fd5b60055491506080604051908101604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018481526020016000151581525060008084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061206d92919061212a565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506001600560008282540192505081905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000806040516020840160008287838a8c6187965a03f19250505080915050949350505050565b8154818355818111156121255781836000526020600020918201910161212491906121aa565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061216b57805160ff1916838001178555612199565b82800160010185558215612199579182015b8281111561219857825182559160200191906001019061217d565b5b5090506121a691906121aa565b5090565b6121cc91905b808211156121c85760008160009055506001016121b0565b5090565b905600a165627a7a72305820b0d992f257e70d565448b927a3ae764342039a864112d5d5bb1ac1bd52e4104e00290000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000060000000000000000000000000cb1437200aea736788f1fc56f327c0456c3598d00000000000000000000000074dd76e24b2cfb43c1b1a4498295d553d0843746000000000000000000000000eeb4ceee443f9e0d17bdbd6daa241681ee5e51c2000000000000000000000000a005caea55375ae20e3aaef746113535503abc1900000000000000000000000090ae948bb410838bff9d024ed849df6a7267dacf000000000000000000000000740a5c5742833bed72489fe6bf7efc9b79428989" }, From bbecb0415ef1ffe5d1c15d9a0fd19de859f0eb1a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 4 Feb 2021 14:10:48 +0100 Subject: [PATCH 056/107] Remove eth/63 protocol version (#252) * Remove eth/63 protocol --- crates/ethcore/sync/src/api.rs | 5 ++--- crates/ethcore/sync/src/chain/handler.rs | 26 +++++++++--------------- crates/ethcore/sync/src/chain/mod.rs | 7 ++----- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index a512d7a838..18d662597e 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -31,8 +31,7 @@ use std::{ use chain::{ fork_filter::ForkFilterApi, ChainSyncApi, SyncState, SyncStatus as EthSyncStatus, - ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64, PAR_PROTOCOL_VERSION_1, - PAR_PROTOCOL_VERSION_2, + ETH_PROTOCOL_VERSION_64, PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, }; use ethcore::{ client::{BlockChainClient, ChainMessageType, ChainNotify, NewBlocks}, @@ -576,7 +575,7 @@ impl ChainNotify for EthSync { .register_protocol( self.eth_handler.clone(), self.subprotocol_name, - &[ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64], + &[ETH_PROTOCOL_VERSION_64], ) .unwrap_or_else(|e| warn!("Error registering ethereum protocol: {:?}", e)); // register the warp sync subprotocol diff --git a/crates/ethcore/sync/src/chain/handler.rs b/crates/ethcore/sync/src/chain/handler.rs index 2aa9c5c6e9..029c6659d2 100644 --- a/crates/ethcore/sync/src/chain/handler.rs +++ b/crates/ethcore/sync/src/chain/handler.rs @@ -42,8 +42,8 @@ use super::sync_packet::{ use super::{ BlockSet, ChainSync, ForkConfirmation, PacketProcessError, PeerAsking, PeerInfo, SyncRequester, - SyncState, ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64, MAX_NEW_BLOCK_AGE, MAX_NEW_HASHES, - PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, + SyncState, ETH_PROTOCOL_VERSION_64, MAX_NEW_BLOCK_AGE, MAX_NEW_HASHES, PAR_PROTOCOL_VERSION_1, + PAR_PROTOCOL_VERSION_2, }; /// The Chain Sync Handler: handles responses from peers @@ -669,7 +669,7 @@ impl SyncHandler { .next() .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; - let eth_protocol_version = io.protocol_version(Ð_PROTOCOL, peer_id); + let _eth_protocol_version = io.protocol_version(Ð_PROTOCOL, peer_id); let warp_protocol_version = io.protocol_version(&PAR_PROTOCOL, peer_id); let warp_protocol = warp_protocol_version != 0; @@ -692,16 +692,12 @@ impl SyncHandler { .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; let forkid_validation_error = { - if eth_protocol_version >= ETH_PROTOCOL_VERSION_64.0 { - let fork_id = rlp04::Rlp::new(r.as_raw()).val_at(5)?; - r_iter.next().ok_or(rlp::DecoderError::RlpIsTooShort)?; - sync.fork_filter - .is_compatible(io.chain(), fork_id) - .err() - .map(|e| (fork_id, e)) - } else { - None - } + let fork_id = rlp04::Rlp::new(r.as_raw()).val_at(5)?; + r_iter.next().ok_or(rlp::DecoderError::RlpIsTooShort)?; + sync.fork_filter + .is_compatible(io.chain(), fork_id) + .err() + .map(|e| (fork_id, e)) }; let snapshot_hash = if warp_protocol { Some( @@ -790,9 +786,7 @@ impl SyncHandler { || (warp_protocol && (peer.protocol_version < PAR_PROTOCOL_VERSION_1.0 || peer.protocol_version > PAR_PROTOCOL_VERSION_2.0)) - || (!warp_protocol - && (peer.protocol_version < ETH_PROTOCOL_VERSION_63.0 - || peer.protocol_version > ETH_PROTOCOL_VERSION_64.0)) + || (!warp_protocol && peer.protocol_version != ETH_PROTOCOL_VERSION_64.0) { trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, peer.protocol_version); return Err(DownloaderImportError::Invalid); diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index e6a869d719..4536ad2fea 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -155,8 +155,6 @@ impl From for PacketProcessError { /// 64 version of Ethereum protocol. pub const ETH_PROTOCOL_VERSION_64: (u8, u8) = (64, 0x11); -/// 63 version of Ethereum protocol. -pub const ETH_PROTOCOL_VERSION_63: (u8, u8) = (63, 0x11); /// 1 version of OpenEthereum protocol and the packet count. pub const PAR_PROTOCOL_VERSION_1: (u8, u8) = (1, 0x15); /// 2 version of OpenEthereum protocol (consensus messages added). @@ -1292,9 +1290,8 @@ impl ChainSync { packet.append(&primitive_types07::U256(chain.total_difficulty.0)); packet.append(&primitive_types07::H256(chain.best_block_hash.0)); packet.append(&primitive_types07::H256(chain.genesis_hash.0)); - if eth_protocol_version >= ETH_PROTOCOL_VERSION_64.0 { - packet.append(&self.fork_filter.current(io.chain())); - } + packet.append(&self.fork_filter.current(io.chain())); + if warp_protocol { let manifest = io.snapshot_service().manifest(); let block_number = manifest.as_ref().map_or(0, |m| m.block_number); From f40e198eb767e342120cedb9bda87c11c348d99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20M=C3=BCller?= Date: Fri, 5 Feb 2021 13:33:39 +0100 Subject: [PATCH 057/107] Give IoService a consistent interface (#257) The start() method had two different signatures depending on configuration. Since ethcore is built with either config depending on the build target, this resulted in compiler errors for either evmbin or oe. --- crates/runtime/io/src/service_non_mio.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/runtime/io/src/service_non_mio.rs b/crates/runtime/io/src/service_non_mio.rs index 96148a01e3..376abb9d96 100644 --- a/crates/runtime/io/src/service_non_mio.rs +++ b/crates/runtime/io/src/service_non_mio.rs @@ -267,7 +267,9 @@ where Message: Send + Sync + 'static, { /// Starts IO event loop - pub fn start() -> Result, IoError> { + pub fn start(_symbolic_name: &'static str) -> Result, IoError> { + // This minimal implementation of IoService does have named Workers + // like the mio-dependent one does, so _symbolic_name is ignored. let (tx, rx) = deque::fifo(); let shared = Arc::new(Shared { From 6b4e56b214ed5468cf1ba4fcd84dfbf54bba4412 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 8 Feb 2021 14:55:03 +0100 Subject: [PATCH 058/107] AccessList in JSONRPC. And enabling github action tests (#255) * Enabling github action tests * Fix failing tests * AccessList to Option in json * failing rust example removed * AccessList for jsonrpc * Tx type as sequence, AccessList as type --- .github/workflows/build-test.yml | 5 +++ .../types/src/transaction/transaction.rs | 3 +- .../types/src/transaction/transaction_id.rs | 10 ++++++ .../types/src/views/typed_transaction.rs | 14 -------- crates/ethjson/src/blockchain/transaction.rs | 6 ++-- crates/rpc/src/v1/helpers/dispatch/signing.rs | 14 +++++--- crates/rpc/src/v1/helpers/fake_sign.rs | 25 +++++++++---- crates/rpc/src/v1/helpers/requests.rs | 13 ++++--- crates/rpc/src/v1/tests/mocked/eth.rs | 6 ++-- crates/rpc/src/v1/tests/mocked/parity.rs | 2 +- crates/rpc/src/v1/tests/mocked/parity_set.rs | 2 +- crates/rpc/src/v1/tests/mocked/signer.rs | 4 +-- crates/rpc/src/v1/tests/mocked/signing.rs | 4 +-- .../rpc/src/v1/tests/mocked/signing_unsafe.rs | 2 +- crates/rpc/src/v1/types/block.rs | 2 +- crates/rpc/src/v1/types/call_request.rs | 13 ++++--- crates/rpc/src/v1/types/confirmations.rs | 4 +-- crates/rpc/src/v1/types/mod.rs | 2 ++ crates/rpc/src/v1/types/receipt.rs | 15 ++++---- crates/rpc/src/v1/types/transaction.rs | 31 +++++++++------- .../src/v1/types/transaction_access_list.rs | 36 +++++++++++++++++++ .../rpc/src/v1/types/transaction_request.rs | 12 +++---- 22 files changed, 144 insertions(+), 81 deletions(-) create mode 100644 crates/rpc/src/v1/types/transaction_access_list.rs diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 6410be554c..344591c0a0 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -33,3 +33,8 @@ jobs: with: command: test args: --locked --all --release --features "json-tests" --verbose --no-run + - name: Run tests for ${{ matrix.platform }} + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked --all --release --features "json-tests" --verbose diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index bf760eb77f..230d469f2c 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -24,7 +24,8 @@ use heapsize::HeapSizeOf; use rlp::{self, DecoderError, Rlp, RlpStream}; use std::{convert::TryInto, ops::Deref}; -pub type AccessList = Vec<(H160, Vec)>; +pub type AccessListItem = (H160, Vec); +pub type AccessList = Vec; use super::TypedTxId; diff --git a/crates/ethcore/types/src/transaction/transaction_id.rs b/crates/ethcore/types/src/transaction/transaction_id.rs index 2b5b5ae2b2..cb31d1937c 100644 --- a/crates/ethcore/types/src/transaction/transaction_id.rs +++ b/crates/ethcore/types/src/transaction/transaction_id.rs @@ -16,6 +16,7 @@ //! Transaction Id. +use ethereum_types::U64; use serde_repr::*; use std::convert::TryFrom; @@ -34,6 +35,15 @@ impl TypedTxId { _ => None, } } + + #[allow(non_snake_case)] + pub fn from_U64_id(n: &U64) -> Option { + match n.0[0] { + 0x0 => Some(Self::Legacy), + 0x1 => Some(Self::AccessList), + _ => None, + } + } } impl Default for TypedTxId { diff --git a/crates/ethcore/types/src/views/typed_transaction.rs b/crates/ethcore/types/src/views/typed_transaction.rs index 3a504c1178..c74d91bc0c 100644 --- a/crates/ethcore/types/src/views/typed_transaction.rs +++ b/crates/ethcore/types/src/views/typed_transaction.rs @@ -38,20 +38,6 @@ pub struct TypedTransactionView<'a> { impl<'a> TypedTransactionView<'a> { /// Creates new view onto valid transaction rlp. /// Use the `view!` macro to create this view in order to capture debugging info. - /// - /// # Example - /// - /// ``` - /// #[macro_use] - /// extern crate common_types as types; - /// - /// use types::views::{TransactionView}; - /// - /// fn main() { - /// let bytes : &[u8] = &[]; - /// let tx_view = view!(TransactionView, bytes); - /// } - /// ``` pub fn new(rlp: ViewRlp<'a>) -> TypedTransactionView<'a> { let transaction_type = Self::extract_transaction_type(&rlp.rlp); TypedTransactionView { diff --git a/crates/ethjson/src/blockchain/transaction.rs b/crates/ethjson/src/blockchain/transaction.rs index 8f89de1b51..003beb306f 100644 --- a/crates/ethjson/src/blockchain/transaction.rs +++ b/crates/ethjson/src/blockchain/transaction.rs @@ -35,13 +35,15 @@ pub struct Transaction { pub v: Uint, pub value: Uint, pub chain_id: Option, - pub access_list: Option>, + pub access_list: Option, pub hash: Option, } +pub type AccessList = Vec; + #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct AccessList { +pub struct AccessListItem { pub address: H160, pub storage_keys: Vec, } diff --git a/crates/rpc/src/v1/helpers/dispatch/signing.rs b/crates/rpc/src/v1/helpers/dispatch/signing.rs index 5cc8f9357c..0514d85abb 100644 --- a/crates/rpc/src/v1/helpers/dispatch/signing.rs +++ b/crates/rpc/src/v1/helpers/dispatch/signing.rs @@ -59,17 +59,23 @@ impl super::Accounts for Signer { value: filled.value, data: filled.data, }; - let t = match filled.transaction_type { - TypedTxId::Legacy => TypedTransaction::Legacy(legacy_tx), - TypedTxId::AccessList => { + let t = match TypedTxId::from_U64_id(&filled.transaction_type) { + Some(TypedTxId::Legacy) => TypedTransaction::Legacy(legacy_tx), + Some(TypedTxId::AccessList) => { if filled.access_list.is_none() { return Err(Error::new(ErrorCode::InvalidParams)); } TypedTransaction::AccessList(AccessListTx::new( legacy_tx, - filled.access_list.unwrap(), + filled + .access_list + .unwrap_or_default() + .into_iter() + .map(Into::into) + .collect(), )) } + None => return Err(Error::new(ErrorCode::InvalidParams)), }; let hash = t.signature_hash(chain_id); diff --git a/crates/rpc/src/v1/helpers/fake_sign.rs b/crates/rpc/src/v1/helpers/fake_sign.rs index 21cedad1e6..1948752d4c 100644 --- a/crates/rpc/src/v1/helpers/fake_sign.rs +++ b/crates/rpc/src/v1/helpers/fake_sign.rs @@ -20,7 +20,7 @@ use types::transaction::{ }; use ethereum_types::U256; -use jsonrpc_core::Error; +use jsonrpc_core::{Error, ErrorCode}; use v1::helpers::CallRequest; pub fn sign_call(request: CallRequest) -> Result { @@ -35,12 +35,23 @@ pub fn sign_call(request: CallRequest) -> Result { value: request.value.unwrap_or_default(), data: request.data.unwrap_or_default(), }; - let tx_typed = match request.transaction_type { - TypedTxId::Legacy => TypedTransaction::Legacy(tx_legacy), - TypedTxId::AccessList => TypedTransaction::AccessList(AccessListTx::new( - tx_legacy, - request.access_list.unwrap_or_default(), - )), + let tx_typed = match TypedTxId::from_U64_id(&request.transaction_type) { + Some(TypedTxId::Legacy) => TypedTransaction::Legacy(tx_legacy), + Some(TypedTxId::AccessList) => { + if request.access_list.is_none() { + return Err(Error::new(ErrorCode::InvalidParams)); + } + TypedTransaction::AccessList(AccessListTx::new( + tx_legacy, + request + .access_list + .unwrap_or_default() + .into_iter() + .map(Into::into) + .collect(), + )) + } + _ => return Err(Error::new(ErrorCode::InvalidParams)), }; Ok(tx_typed.fake_sign(from)) } diff --git a/crates/rpc/src/v1/helpers/requests.rs b/crates/rpc/src/v1/helpers/requests.rs index cc17ac4cd8..24d0d78265 100644 --- a/crates/rpc/src/v1/helpers/requests.rs +++ b/crates/rpc/src/v1/helpers/requests.rs @@ -15,16 +15,15 @@ // along with OpenEthereum. If not, see . use bytes::Bytes; -use ethereum_types::{Address, H256, U256}; -use types::transaction::{AccessList, TypedTxId}; +use ethereum_types::{Address, H256, U256, U64}; -use v1::types::{Origin, TransactionCondition}; +use v1::types::{AccessList, Origin, TransactionCondition}; /// Transaction request coming from RPC #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct TransactionRequest { /// type of transaction. - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// Sender pub from: Option
, /// Recipient @@ -49,7 +48,7 @@ pub struct TransactionRequest { #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct FilledTransactionRequest { /// type of transaction. - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// Sender pub from: Address, /// Indicates if the sender was filled by default value. @@ -84,7 +83,7 @@ impl From for TransactionRequest { data: Some(r.data), nonce: r.nonce, condition: r.condition, - access_list: r.access_list, + access_list: r.access_list.map(Into::into), } } } @@ -93,7 +92,7 @@ impl From for TransactionRequest { #[derive(Debug, Default, PartialEq)] pub struct CallRequest { /// type of transaction. - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// From pub from: Option
, /// To diff --git a/crates/rpc/src/v1/tests/mocked/eth.rs b/crates/rpc/src/v1/tests/mocked/eth.rs index 00ea5c6c2d..abc19975d4 100644 --- a/crates/rpc/src/v1/tests/mocked/eth.rs +++ b/crates/rpc/src/v1/tests/mocked/eth.rs @@ -707,7 +707,7 @@ fn rpc_eth_pending_transaction_by_hash() { .insert(H256::zero(), tx); } - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"type":"0x0","v":"0x1b","value":"0xa"},"id":1}"#; let request = r#"{ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", @@ -1184,7 +1184,7 @@ fn rpc_eth_transaction_receipt() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"0x0"},"id":1}"#; assert_eq!( tester.io.handle_request_sync(request), @@ -1238,7 +1238,7 @@ fn rpc_eth_pending_receipt() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0","type":"0x0"},"id":1}"#; assert_eq!( tester.io.handle_request_sync(request), Some(response.to_owned()) diff --git a/crates/rpc/src/v1/tests/mocked/parity.rs b/crates/rpc/src/v1/tests/mocked/parity.rs index ea1b7c31a5..608a44fabe 100644 --- a/crates/rpc/src/v1/tests/mocked/parity.rs +++ b/crates/rpc/src/v1/tests/mocked/parity.rs @@ -492,7 +492,7 @@ fn rpc_parity_block_receipts() { "params": [], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0"}],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0","type":"0x0"}],"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/crates/rpc/src/v1/tests/mocked/parity_set.rs b/crates/rpc/src/v1/tests/mocked/parity_set.rs index bea2000a3a..011c29be03 100644 --- a/crates/rpc/src/v1/tests/mocked/parity_set.rs +++ b/crates/rpc/src/v1/tests/mocked/parity_set.rs @@ -202,7 +202,7 @@ fn rpc_parity_remove_transaction() { .to_owned() + &format!("0x{:x}", hash) + r#""], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x1f","value":"0x9184e72a"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"type":"0x0","v":"0x1f","value":"0x9184e72a"},"id":1}"#; miner.pending_transactions.lock().insert(hash, signed); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); diff --git a/crates/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs index 6c0bcee84f..917ad9ae12 100644 --- a/crates/rpc/src/v1/tests/mocked/signer.rs +++ b/crates/rpc/src/v1/tests/mocked/signer.rs @@ -118,7 +118,7 @@ fn should_return_list_of_items_to_confirm() { let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let response = concat!( r#"{"jsonrpc":"2.0","result":["#, - r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, + r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","type":"0x0","value":"0x1"}}},"#, r#"{"id":"0x2","origin":"unknown","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","data":"0x05"}}}"#, r#"],"id":1}"# ); @@ -637,7 +637,7 @@ fn should_confirm_sign_transaction_with_rlp() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x1""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/tests/mocked/signing.rs b/crates/rpc/src/v1/tests/mocked/signing.rs index fdeb9b4963..f2b809b2fa 100644 --- a/crates/rpc/src/v1/tests/mocked/signing.rs +++ b/crates/rpc/src/v1/tests/mocked/signing.rs @@ -418,7 +418,7 @@ fn should_add_sign_transaction_to_the_queue() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; @@ -610,7 +610,7 @@ fn should_compose_transaction() { let response = r#"{"jsonrpc":"2.0","result":{"condition":null,"data":"0x","from":"0x"# .to_owned() + &from - + r#"","gas":"0x5208","gasPrice":"0x4a817c800","nonce":"0x0","to":null,"value":"0x5"},"id":1}"#; + + r#"","gas":"0x5208","gasPrice":"0x4a817c800","nonce":"0x0","to":null,"type":"0x0","value":"0x5"},"id":1}"#; // then let res = tester.io.handle_request(&request).wait().unwrap(); diff --git a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs index c52127736f..fde44ed933 100644 --- a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs +++ b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -226,7 +226,7 @@ fn rpc_eth_sign_transaction() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/types/block.rs b/crates/rpc/src/v1/types/block.rs index 49c603fdeb..5951e1a829 100644 --- a/crates/rpc/src/v1/types/block.rs +++ b/crates/rpc/src/v1/types/block.rs @@ -221,7 +221,7 @@ mod tests { let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( serialized, - r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}]"# + r#"[{"type":"0x0","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}]"# ); let t = BlockTransactions::Hashes(vec![H256::default().into()]); diff --git a/crates/rpc/src/v1/types/call_request.rs b/crates/rpc/src/v1/types/call_request.rs index 0972dd6bdd..dd7a637457 100644 --- a/crates/rpc/src/v1/types/call_request.rs +++ b/crates/rpc/src/v1/types/call_request.rs @@ -14,19 +14,21 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use ethereum_types::{H160, U256}; -use types::transaction::{AccessList, TypedTxId}; -use v1::{helpers::CallRequest as Request, types::Bytes}; +use ethereum_types::{H160, U256, U64}; +use v1::{ + helpers::CallRequest as Request, + types::{AccessList, Bytes}, +}; /// Call request #[derive(Debug, Default, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct CallRequest { - /// transaction type + /// transaction type. Defaults to legacy type. #[serde(default)] #[serde(rename = "type")] - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// From pub from: Option, /// To @@ -42,6 +44,7 @@ pub struct CallRequest { /// Nonce pub nonce: Option, /// Access list + #[serde(skip_serializing_if = "Option::is_none")] pub access_list: Option, } diff --git a/crates/rpc/src/v1/types/confirmations.rs b/crates/rpc/src/v1/types/confirmations.rs index b489f354c4..1dfbe78347 100644 --- a/crates/rpc/src/v1/types/confirmations.rs +++ b/crates/rpc/src/v1/types/confirmations.rs @@ -349,7 +349,7 @@ mod tests { // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#; + let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"type":"0x0","from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); @@ -380,7 +380,7 @@ mod tests { // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#; + let expected = r#"{"id":"0xf","payload":{"signTransaction":{"type":"0x0","from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); diff --git a/crates/rpc/src/v1/types/mod.rs b/crates/rpc/src/v1/types/mod.rs index 2da3457d6e..ce07f538a3 100644 --- a/crates/rpc/src/v1/types/mod.rs +++ b/crates/rpc/src/v1/types/mod.rs @@ -40,6 +40,7 @@ mod sync; mod trace; mod trace_filter; mod transaction; +mod transaction_access_list; mod transaction_condition; mod transaction_request; mod work; @@ -75,6 +76,7 @@ pub use self::{ trace::{LocalizedTrace, TraceResults, TraceResultsWithTransactionHash}, trace_filter::TraceFilter, transaction::{LocalTransactionStatus, RichRawTransaction, Transaction}, + transaction_access_list::{AccessList, AccessListItem}, transaction_condition::TransactionCondition, transaction_request::TransactionRequest, work::Work, diff --git a/crates/rpc/src/v1/types/receipt.rs b/crates/rpc/src/v1/types/receipt.rs index 37042ad1a1..64b6c696da 100644 --- a/crates/rpc/src/v1/types/receipt.rs +++ b/crates/rpc/src/v1/types/receipt.rs @@ -15,10 +15,7 @@ // along with OpenEthereum. If not, see . use ethereum_types::{Bloom as H2048, H160, H256, U256, U64}; -use types::{ - receipt::{LocalizedReceipt, RichReceipt, TransactionOutcome, TypedReceipt}, - transaction::TypedTxId, -}; +use types::receipt::{LocalizedReceipt, RichReceipt, TransactionOutcome, TypedReceipt}; use v1::types::Log; /// Receipt @@ -27,7 +24,7 @@ use v1::types::Log; pub struct Receipt { /// Transaction Type #[serde(rename = "type")] - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// Transaction Hash pub transaction_hash: Option, /// Transaction index @@ -81,7 +78,7 @@ impl From for Receipt { Receipt { to: r.to.map(Into::into), from: Some(r.from), - transaction_type: r.transaction_type, + transaction_type: U64::from(r.transaction_type as u8), transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: Some(r.block_hash), @@ -102,7 +99,7 @@ impl From for Receipt { Receipt { from: Some(r.from), to: r.to.map(Into::into), - transaction_type: r.transaction_type, + transaction_type: U64::from(r.transaction_type as u8), transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: None, @@ -120,7 +117,7 @@ impl From for Receipt { impl From for Receipt { fn from(r: TypedReceipt) -> Self { - let transaction_type = r.tx_type(); + let transaction_type = U64::from(r.tx_type() as u8); let r = r.receipt().clone(); Receipt { from: None, @@ -148,7 +145,7 @@ mod tests { #[test] fn receipt_serialization() { - let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","from":null,"to":null,"blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined","removed":false}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":"0x1"}"#; + let s = r#"{"type":"0x0","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","from":null,"to":null,"blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined","removed":false}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":"0x1"}"#; let receipt = Receipt { from: None, diff --git a/crates/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs index 6d6bf419ca..42060097a4 100644 --- a/crates/rpc/src/v1/types/transaction.rs +++ b/crates/rpc/src/v1/types/transaction.rs @@ -21,10 +21,9 @@ use ethereum_types::{H160, H256, H512, U256, U64}; use miner; use serde::{ser::SerializeStruct, Serialize, Serializer}; use types::transaction::{ - AccessList, Action, LocalizedTransaction, PendingTransaction, SignedTransaction, - TypedTransaction, + Action, LocalizedTransaction, PendingTransaction, SignedTransaction, TypedTransaction, }; -use v1::types::{Bytes, TransactionCondition}; +use v1::types::{AccessList, Bytes, TransactionCondition}; /// Transaction #[derive(Debug, Default, Clone, PartialEq, Serialize)] @@ -32,7 +31,7 @@ use v1::types::{Bytes, TransactionCondition}; pub struct Transaction { /// transaction type #[serde(rename = "type")] - pub transaction_type: u8, + pub transaction_type: U64, /// Hash pub hash: H256, /// Nonce @@ -74,7 +73,8 @@ pub struct Transaction { /// Transaction activates at specified block. pub condition: Option, /// optional access list - pub access_list: AccessList, + #[serde(skip_serializing_if = "Option::is_none")] + pub access_list: Option, } /// Local Transaction Status @@ -186,9 +186,9 @@ impl Transaction { let scheme = CreateContractAddress::FromSenderAndNonce; let access_list = if let TypedTransaction::AccessList(al) = t.as_unsigned() { - al.access_list.clone() + Some(al.access_list.clone().into_iter().map(Into::into).collect()) } else { - Vec::new() + None }; Transaction { @@ -220,7 +220,7 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, - transaction_type: t.signed.tx_type() as u8, + transaction_type: U64::from(t.signed.tx_type() as u8), access_list, } } @@ -230,9 +230,9 @@ impl Transaction { let signature = t.signature(); let scheme = CreateContractAddress::FromSenderAndNonce; let access_list = if let TypedTransaction::AccessList(al) = t.as_unsigned() { - al.access_list.clone() + Some(al.access_list.clone().into_iter().map(Into::into).collect()) } else { - Vec::new() + None }; Transaction { hash: t.hash(), @@ -263,7 +263,7 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, - transaction_type: t.tx_type() as u8, + transaction_type: U64::from(t.tx_type() as u8), access_list, } } @@ -303,15 +303,20 @@ impl LocalTransactionStatus { #[cfg(test)] mod tests { use super::{LocalTransactionStatus, Transaction}; + use ethereum_types::U64; use serde_json; + use types::transaction::TypedTxId; + use v1::types::AccessListItem; #[test] fn test_transaction_serialize() { - let t = Transaction::default(); + let mut t = Transaction::default(); + t.transaction_type = U64::from(TypedTxId::AccessList as u8); + t.access_list = Some(vec![AccessListItem::default()]); let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( serialized, - r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}"# + r#"{"type":"0x1","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null,"accessList":[{"address":"0x0000000000000000000000000000000000000000","storageKeys":[]}]}"# ); } diff --git a/crates/rpc/src/v1/types/transaction_access_list.rs b/crates/rpc/src/v1/types/transaction_access_list.rs new file mode 100644 index 0000000000..810537e694 --- /dev/null +++ b/crates/rpc/src/v1/types/transaction_access_list.rs @@ -0,0 +1,36 @@ +use ethereum_types::{H160, H256}; +use serde::Serialize; +use std::vec::Vec; +use types::transaction::AccessListItem as InnerAccessListItem; + +pub type AccessList = Vec; +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AccessListItem { + address: H160, + storage_keys: Vec, +} + +impl AccessListItem { + pub fn new(address: H160, storage_keys: Vec) -> Self { + Self { + address, + storage_keys, + } + } +} + +impl From for AccessListItem { + fn from(item: InnerAccessListItem) -> Self { + AccessListItem { + address: item.0, + storage_keys: item.1, + } + } +} + +impl From for InnerAccessListItem { + fn from(item: AccessListItem) -> Self { + (item.address, item.storage_keys) + } +} diff --git a/crates/rpc/src/v1/types/transaction_request.rs b/crates/rpc/src/v1/types/transaction_request.rs index bace3af04c..9f5756f7b6 100644 --- a/crates/rpc/src/v1/types/transaction_request.rs +++ b/crates/rpc/src/v1/types/transaction_request.rs @@ -17,11 +17,10 @@ //! `TransactionRequest` type use ansi_term::Colour; -use ethereum_types::{H160, U256}; -use types::transaction::{AccessList, TypedTxId}; +use ethereum_types::{H160, U256, U64}; use v1::{ helpers, - types::{Bytes, TransactionCondition}, + types::{AccessList, Bytes, TransactionCondition}, }; use std::fmt; @@ -31,10 +30,10 @@ use std::fmt; #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct TransactionRequest { - /// type of transaction. If none we assume it is legacy + /// type of transaction. Defaults to legacy type. #[serde(default)] #[serde(rename = "type")] - pub transaction_type: TypedTxId, + pub transaction_type: U64, /// Sender pub from: Option, /// Recipient @@ -52,6 +51,7 @@ pub struct TransactionRequest { /// Delay until this block condition. pub condition: Option, /// Access list + #[serde(skip_serializing_if = "Option::is_none")] pub access_list: Option, } @@ -130,7 +130,7 @@ impl From for TransactionRequest { data: Some(r.data.into()), nonce: r.nonce, condition: r.condition, - access_list: r.access_list, + access_list: r.access_list.map(Into::into), } } } From dbf9a1cd9850f6501ac226eb52ddea7ec6987e27 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Feb 2021 15:58:35 +0100 Subject: [PATCH 059/107] EIP-2930 spec change for signature hash (#261) * EIP-2930 spec change for signature hash * Removing eip2930 test blocks --- .../res/chainspec/test/eip2930_test.json | 69 - crates/ethcore/res/json_tests.json | 4 - .../res/local_tests/chain/eip2930.json | 3149 ----------------- crates/ethcore/src/client/evm_test_client.rs | 1 - crates/ethcore/src/ethereum/mod.rs | 8 - .../types/src/transaction/transaction.rs | 34 +- crates/ethjson/src/spec/spec.rs | 1 - 7 files changed, 7 insertions(+), 3259 deletions(-) delete mode 100644 crates/ethcore/res/chainspec/test/eip2930_test.json delete mode 100644 crates/ethcore/res/local_tests/chain/eip2930.json diff --git a/crates/ethcore/res/chainspec/test/eip2930_test.json b/crates/ethcore/res/chainspec/test/eip2930_test.json deleted file mode 100644 index 764d255df1..0000000000 --- a/crates/ethcore/res/chainspec/test/eip2930_test.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "YoloEIP2930", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x1BC16D674EC80000", - "homesteadTransition": "0x0", - "eip100bTransition": "0x0", - "difficultyBombDelays": { - "0": 5000000 - } - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x1", - "maxCodeSize": 24576, - "maxCodeSizeTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", - "eip140Transition": "0x0", - "eip211Transition": "0x0", - "eip214Transition": "0x0", - "eip155Transition": "0x0", - "eip658Transition": "0x0", - "eip145Transition": "0x0", - "eip1014Transition": "0x0", - "eip1052Transition": "0x0", - "eip1283Transition": "0x0", - "eip1283DisableTransition": "0x0", - "eip1283ReenableTransition": "0x0", - "eip1344Transition": "0x0", - "eip1706Transition": "0x0", - "eip1884Transition": "0x0", - "eip2028Transition": "0x0", - "eip2315Transition": "0x0", - "eip2929Transition": "0x0", - "eip2930Transition": "0x0" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000539", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x20000", - "gasLimit": "0x47e7c4" - }, - "accounts": { - "000000000000000000000000000000000000aaaa": { - "balance": "0", - "code": "0x5854505854503231" - }, - "71562b71999873db5b286df957af199ec94617f7": { - "balance": "0x3b9aca00" - } - } -} diff --git a/crates/ethcore/res/json_tests.json b/crates/ethcore/res/json_tests.json index a795bd0c08..1b7943930a 100644 --- a/crates/ethcore/res/json_tests.json +++ b/crates/ethcore/res/json_tests.json @@ -6,10 +6,6 @@ } ], "chain": [ - { - "path": "res/local_tests/chain", - "skip": [] - }, { "path": "res/json_tests/BlockchainTests", "skip": [] diff --git a/crates/ethcore/res/local_tests/chain/eip2930.json b/crates/ethcore/res/local_tests/chain/eip2930.json deleted file mode 100644 index 241030b1b4..0000000000 --- a/crates/ethcore/res/local_tests/chain/eip2930.json +++ /dev/null @@ -1,3149 +0,0 @@ -{ - "testEIP2930_transactions": { - "_info": { - "comment": "Local test for EIP-2930" - }, - "genesisBlockHeader": { - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "difficulty": "0x020000", - "extraData": "0x", - "gasLimit": "0x47e7c4", - "gasUsed": "0x00", - "hash": "0xf0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000539", - "number": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "stateRoot": "0xf24461ff2b080dba58ee5fa4b546efbadb7b74b33b8ce3ac5b8bf84b5cad5d27", - "timestamp": "0x00", - "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" - }, - "pre": { - "000000000000000000000000000000000000aaaa": { - "balance": "0x0", - "code": "0x5854505854503231" - }, - "71562b71999873db5b286df957af199ec94617f7": { - "balance": "0x3b9aca00" - } - }, - "network": "EIP2930", - "sealEngine": "NoProof", - "lastblockhash": "0x105d8befc05cb9c21add67408bcc7512de148cd9a7cc8932efa294e2672aba55", - "blocks": [ - { - "rlp": "f9025df901f5a0f0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0007b54c20187b01cb2caad4dd377234b591ffc3502590d7b05ef2949785542b2a0076eed3b92e039d9b8e35b21d5603350177b75c35c8ee13654f582f21a92dd69a0ea2fe1d08440864d23add61591d18dd8900e010ceca13b5ae797c699a44b5684b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48262de0a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a8301e24194000000000000000000000000000000000000aaaa808025a04a8784ece5812005fadff24bee6b002f3b736196c97fa73e31a015d89731a9dba07fb3784b5bbd59d2a00acdc86cb84f8b279f5f80b4af9d0e944f06ba5388c811c0", - "header": { - "parentHash": "0xf0962fddf00ed1647996646504666df666ecc558eb8a5bcd65af206a64e79a93", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0x007b54c20187b01cb2caad4dd377234b591ffc3502590d7b05ef2949785542b2", - "transactionsTrie": "0x076eed3b92e039d9b8e35b21d5603350177b75c35c8ee13654f582f21a92dd69", - "receiptTrie": "0xea2fe1d08440864d23add61591d18dd8900e010ceca13b5ae797c699a44b5684", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x1", - "gasLimit": "0x47e7c4", - "gasUsed": "0x62de", - "timestamp": "0xa", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0xb44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7" - }, - "transactions": [ - { - "nonce": "0x0", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "v": "0x25", - "r": "0x4a8784ece5812005fadff24bee6b002f3b736196c97fa73e31a015d89731a9db", - "s": "0x7fb3784b5bbd59d2a00acdc86cb84f8b279f5f80b4af9d0e944f06ba5388c811", - "hash": "0x8dea84417453c9cc0dbbcdf9224fc37cbe93b6e8a9ffdb8e7eb3ddeedd43c375" - } - ], - "uncleHeaders": null - }, - { - "rlp": "f90321f901f5a0b44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0ed1f713ffe43640afc36f435f181056c1a960b2ddcd6714dbef775ade09aa2c9a0ea2164b24b79d9708108afa05a267ddbf42971d34a215dd6158fb48776932c0ea0543bb9ba3c84c66db2c71d2cc38a17d6e708597dd397b0e8946e36a9eca94f1eb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000028347e7c482ddf41480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90125b8c101f8be01010a8301e24194000000000000000000000000000000000000aaaa8080f85bf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000080a082dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234dba072228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0f860020a8301e24194000000000000000000000000000000000000aaaa808026a09756172d336ab702075c6dbaaa979455c385aa03039d601205350680c4eff09ca03000821620e1771ca10b4b3639bb8932e2cb1f91f90714cf0cc4d6b418f944f1c0", - "header": { - "parentHash": "0xb44579073851e99fe60940bf6217a6eae1908918eb89c2ad8ba7cdd31104aef7", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0xed1f713ffe43640afc36f435f181056c1a960b2ddcd6714dbef775ade09aa2c9", - "transactionsTrie": "0xea2164b24b79d9708108afa05a267ddbf42971d34a215dd6158fb48776932c0e", - "receiptsTrie": "0x543bb9ba3c84c66db2c71d2cc38a17d6e708597dd397b0e8946e36a9eca94f1e", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x2", - "gasLimit": "0x47e7c4", - "gasUsed": "0xddf4", - "timestamp": "0x14", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x45ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26d" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x82dc119130f280bd72e3fd4e10220e35b767031b84b8dd1f64085e0158f234db", - "s": "0x72228551e678a8a6c6e9bae0ae786b8839c7fda0a994caddd23910f45f385cc0", - "hash": "0x41760e65a1d237e001cfe56427ebb03f0c377f6fa17ae19ec00d40a363ae16be" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x2", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0x9756172d336ab702075c6dbaaa979455c385aa03039d601205350680c4eff09c", - "s": "0x3000821620e1771ca10b4b3639bb8932e2cb1f91f90714cf0cc4d6b418f944f1", - "hash": "0x7c331109477a2ebca4778b7818a367e5b7bda7e056bbcf64837cd0c62e008431" - } - ], - "uncles": null - }, - { - "rlp": "f9049ff901f6a045ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a009b41b08cacf63fd56a588d65befca63f4799dd457ccfcffc1b7ff8b7c899026a0a7c68fc60a677940cb5c3e2ecbeff781ba95eb2dc5edbe041d1a569fa98b9070a03a26b9965725737c7bdaa1de02677d782a1148027aa3a5bbf29658d16013cb4cb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000038347e7c48301897a1e80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f902a2b9011d01f9011901030a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000001a0748de538b4a9502e4bf7d7c29ee80dcd342e802518257260c318877c1306e455a043faaa4d106d49940a193f6016c10159a9013074951ff718404b1f717d274887b9011d01f9011901040a8301e24194000000000000000000000000000000000000aaaa8080f8b6f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0010000000000000000000000000000000000000000000000000000000000000080a0a831c9d4a1e27dbc92a5558cdc3006a42d5cd38c6e18052ab280674e7e6d1009a04c09b35aba855dd92c2e67411f2345374ab54c110cc9f248dea3777310a11a35f860050a8301e24194000000000000000000000000000000000000aaaa808026a0f3d58c384589aa560311587a19a39acfbed506b50b6332455f8a01b7a4a0b208a0710821dcc271fbf3bf0cd2ed45ebf7d212095b2d7b743c6ddc5f0bd220c692b4c0", - - "header": { - "parentHash": "0x45ce9fae124eb06c68394ffb53edd1c0e46cf957185b18a3c43821266b71f26d", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0x09b41b08cacf63fd56a588d65befca63f4799dd457ccfcffc1b7ff8b7c899026", - "transactionsTrie": "0xa7c68fc60a677940cb5c3e2ecbeff781ba95eb2dc5edbe041d1a569fa98b9070", - "receiptsTrie": "0x3a26b9965725737c7bdaa1de02677d782a1148027aa3a5bbf29658d16013cb4c", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x3", - "gasLimit": "0x47e7c4", - "gasUsed": "0x1897a", - "timestamp": "0x1e", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x6e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290fa" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x3", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x748de538b4a9502e4bf7d7c29ee80dcd342e802518257260c318877c1306e455", - "s": "0x43faaa4d106d49940a193f6016c10159a9013074951ff718404b1f717d274887", - "hash": "0x418a0f670998b3e1ca5250843306910bb7546acb1c04f491350a8033d912bdaf" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x4", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xa831c9d4a1e27dbc92a5558cdc3006a42d5cd38c6e18052ab280674e7e6d1009", - "s": "0x4c09b35aba855dd92c2e67411f2345374ab54c110cc9f248dea3777310a11a35", - "hash": "0x016263d1b70105fb24bba2ff1bae4ec620d7481318e6d0974aa96fb202724c53" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x5", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0xf3d58c384589aa560311587a19a39acfbed506b50b6332455f8a01b7a4a0b208", - "s": "0x710821dcc271fbf3bf0cd2ed45ebf7d212095b2d7b743c6ddc5f0bd220c692b4", - "hash": "0x703e00e61cd19d8dbbd58a15f885fe3d82954a6c7f1854e64df9d8c9a839d2dd" - } - ], - "uncles": null - }, - { - "rlp": "f906d3f901f6a06e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290faa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0e80199c64d2bee27c7a1be67fe8b01020a9231e172da0d6fabca44d98864a5d4a08c70cadb678d31ea2a57b14ae2e7eaab22c7a816f5d3ee94091db45f1a4af49ea0aa5401f56c2e0708e601d13442bf1827d6554607ef573f08f8d2ebf51e948dd8b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000048347e7c4830265702880a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f904d6b9017901f9017501060a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a07e3e6761f5735046aa7c8c495159186e0e017c7cad769757d3b993fcf84bb936a0503471fceed0db87a3c62f8686c09eab381354506c648ad2ea46d9076b87664eb9017901f9017501070a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a076012a1e4b16f5bc566caf00e901121c3b55bc26a225d772dad4858cd9aeadcca00ea768134e684c0561b0b22e0c7db3246fafb82c56bc0e7d58aed1c7e67ef423b9017901f9017501080a8301e24194000000000000000000000000000000000000aaaa8080f90111f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0020000000000000000000000000000000000000000000000000000000000000001a0d4a82519d087bbce6e55aaa4775ad916200ab69b47a472e28837956c24f40feea04cf399e1fb199615600b77c9601dcbc7bc41b25dc4351842a36aa69ce597ee9bf860090a8301e24194000000000000000000000000000000000000aaaa808025a0c1761a83dfd95d3c129280692c9fecb528a914d5c6441fe55eb942e58aa066b0a0605fc74c46a2a75de2e05c03d11518930b809c504833152116c8ccfb8685986ec0", - - "header": { - "parentHash": "0x6e9b1043fdb0e72356fbfe34d83f96d8850f573d806e860ab2beade9666290fa", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0xe80199c64d2bee27c7a1be67fe8b01020a9231e172da0d6fabca44d98864a5d4", - "transactionsTrie": "0x8c70cadb678d31ea2a57b14ae2e7eaab22c7a816f5d3ee94091db45f1a4af49e", - "receiptsTrie": "0xaa5401f56c2e0708e601d13442bf1827d6554607ef573f08f8d2ebf51e948dd8", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x4", - "gasLimit": "0x47e7c4", - "gasUsed": "0x26570", - "timestamp": "0x28", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x6", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x7e3e6761f5735046aa7c8c495159186e0e017c7cad769757d3b993fcf84bb936", - "s": "0x503471fceed0db87a3c62f8686c09eab381354506c648ad2ea46d9076b87664e", - "hash": "0x4f66c5df18e409248018353adfe21033c44badfe7083a6980f574aff886dae3e" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x7", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x76012a1e4b16f5bc566caf00e901121c3b55bc26a225d772dad4858cd9aeadcc", - "s": "0xea768134e684c0561b0b22e0c7db3246fafb82c56bc0e7d58aed1c7e67ef423", - "hash": "0xf90baa5007a69f5469b887e2d2a7f817bb274ce841ec5afc5f45f8c7bc6be0b5" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x8", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xd4a82519d087bbce6e55aaa4775ad916200ab69b47a472e28837956c24f40fee", - "s": "0x4cf399e1fb199615600b77c9601dcbc7bc41b25dc4351842a36aa69ce597ee9b", - "hash": "0x251d97291fa072eff47197043843376c29efc4fcd6b23d78867d6225e6ccdcaa" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x9", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x25", - "r": "0xc1761a83dfd95d3c129280692c9fecb528a914d5c6441fe55eb942e58aa066b0", - "s": "0x605fc74c46a2a75de2e05c03d11518930b809c504833152116c8ccfb8685986e", - "hash": "0xdd8271981828697d28de1c2d1148458a30c5e86464484f1695ff21e56d83bc91" - } - ], - "uncles": null - }, - { - "rlp": "f909bbf901f6a0160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a02dd6f4e5613640e8ae817f50e3538926b946632953b2ef14f47e21ab2a1f0bcaa0d663e9fec41620bc34664fd2ab65046c6d5de9306d2d710425d01ddd7c767683a09dec9f28e6d236deda6a9d0aeff7271bef8649c01f14232a2a8b59293a4864acb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000058347e7c4830371d63280a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f907beb901d401f901d0010a0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a0f345e830d6eb32d68ff5e9c2bf35308b891a5901c28bb1c04f6b04313d691cf4a0373dfbd0ffa2339e007dfc5f1a1c4fd3aa73efb9419ebb7e53db6bc84c976240b901d401f901d0010b0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a060f333f746a7b18a39d3a0401eaa346cfc424fcb054cffa349f99130597b6f4aa02ca60577b215332a1c248e85b9b93664054af3701f0a6f5c553e180e7dcdb4e8b901d401f901d0010c0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000001a0479dfabb47ad82e5e5c1b0629fc87b715e3a0ba698c6bee3ff9bd29ef84a1e93a0381d0c2994e6e97f646ca1864ec1f66ae0c47a8fcfdef882041e6db8d413d1d0b901d401f901d0010d0a8301e24194000000000000000000000000000000000000aaaa8080f9016cf859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0030000000000000000000000000000000000000000000000000000000000000080a08d36697d1b52d80b56113e088245173946fde2e72c29ffa2d0289b39dc9100e5a05758c471f9ca7c197e7e7f9b29cb134dc8f4e67aec83c8a52e05b8831a577e85f8600e0a8301e24194000000000000000000000000000000000000aaaa808026a0db585ae1362cccecf8c2cf6953207d4cfe0eb30aaddf750aa55a0b8a459ab22aa053aac6352d9a6b9599dfa512b2a01a1cf3498428cf96136fab5ec7c305acb462c0", - - "header": { - "parentHash": "0x160a6eff205005f7e0dc27006b58e64e37b88592077debbc30b44589dbb95a95", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0x2dd6f4e5613640e8ae817f50e3538926b946632953b2ef14f47e21ab2a1f0bca", - "transactionsTrie": "0xd663e9fec41620bc34664fd2ab65046c6d5de9306d2d710425d01ddd7c767683", - "receiptsTrie": "0x9dec9f28e6d236deda6a9d0aeff7271bef8649c01f14232a2a8b59293a4864ac", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x5", - "gasLimit": "0x47e7c4", - "gasUsed": "0x371d6", - "timestamp": "0x32", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0xe5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0xa", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xf345e830d6eb32d68ff5e9c2bf35308b891a5901c28bb1c04f6b04313d691cf4", - "s": "0x373dfbd0ffa2339e007dfc5f1a1c4fd3aa73efb9419ebb7e53db6bc84c976240", - "hash": "0xb7b9c42dcc90d9856bf566ef1744c98fa17393ca720420c4d1dda1098c2f537d" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0xb", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x60f333f746a7b18a39d3a0401eaa346cfc424fcb054cffa349f99130597b6f4a", - "s": "0x2ca60577b215332a1c248e85b9b93664054af3701f0a6f5c553e180e7dcdb4e8", - "hash": "0x1b57c427bb124ed65ab83db75ddb5af12aeaa66affd902b684b4bab6ebf31817" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0xc", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x479dfabb47ad82e5e5c1b0629fc87b715e3a0ba698c6bee3ff9bd29ef84a1e93", - "s": "0x381d0c2994e6e97f646ca1864ec1f66ae0c47a8fcfdef882041e6db8d413d1d0", - "hash": "0x6642d59ce47df5df3b0ff96829f56264171dbfca7bdbf8b3caaead85ab17ce9b" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0xd", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x8d36697d1b52d80b56113e088245173946fde2e72c29ffa2d0289b39dc9100e5", - "s": "0x5758c471f9ca7c197e7e7f9b29cb134dc8f4e67aec83c8a52e05b8831a577e85", - "hash": "0x7087dd064ddd164d8564913acde103d30d1e6ffd3c4b828242ab5662c5d27f98" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0xe", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0xdb585ae1362cccecf8c2cf6953207d4cfe0eb30aaddf750aa55a0b8a459ab22a", - "s": "0x53aac6352d9a6b9599dfa512b2a01a1cf3498428cf96136fab5ec7c305acb462", - "hash": "0xa6ded463647cde7d52f6889b7f3c0a142cf3d82b1d3cca606c72a08ee64129f1" - } - ], - "uncles": null - }, - { - "rlp": "f90d59f901f6a0e5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a07f2172fc6b1093884e559297c4161da6687ccf9405841d5e5cb79566e1698540a0f881eb8830d5ed90a6d1de5ef56dbd715bf679721aa70ccc2fde6050558fe065a03c399ef07b92c03dd962c9b51708ec00bfa279dad6afda270f332f79e3e60db4b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000068347e7c48304aeac3c80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90b5cb9022f01f9022b010f0a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a0cfbef0051e5b8a313532cc98410f5135948915a3d046ac28083d0d8f0fdfa660a05520ab4a5ce35c1d8c70cff148eefe0a2833ba0ed6f2781f839cc7edc8bf575eb9022f01f9022b01100a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a0d42a5ec165486f09e6d8faf3a93c87c4f0cc6b4d15ebbc2dedca7e4ef35a4555a00c129f489b2213092f5863b7a936ece05bdcb26a4513603c9f4b84ab0d9acd15b9022f01f9022b01110a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a0307eb02650c740c599c347d7dad1b390fa8dc24d216eb2ba769dc711aae32789a077af8cfb89aa87266d3b691ddb75be4221fb2b188e1c4470daaa707d44161200b9022f01f9022b01120a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000080a044ef64e26f79482731ceaef418439ebb497806df367f598ebf5d9981f5414a4da04b0d7d566fb8e7cba207385fdad173c9f961fe23fe3961e07c4a31df20c31a03b9022f01f9022b01130a8301e24194000000000000000000000000000000000000aaaa8080f901c7f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0040000000000000000000000000000000000000000000000000000000000000001a078688c9ef5a7925528910547dc39f1b359a5e230f850310f599098c32876443ea06462d6bc2778d84c5af517d383483e0685b8fccbd424196951c1e509964a27e0f860140a8301e24194000000000000000000000000000000000000aaaa808025a0ec8f9c89aa1f4f795d8b45ff41c871721d994858a1374411c4878532001a4ba5a027f11a383c603c28321baad48830d6090c9b0164e2d26d632a73ecd809ae53c7c0", - - "header": { - "parentHash": "0xe5c7fd187ef4075bb9a3bd160b0e568be53ea693b284d20936277c249797f881", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0x7f2172fc6b1093884e559297c4161da6687ccf9405841d5e5cb79566e1698540", - "transactionsTrie": "0xf881eb8830d5ed90a6d1de5ef56dbd715bf679721aa70ccc2fde6050558fe065", - "receiptsTrie": "0x3c399ef07b92c03dd962c9b51708ec00bfa279dad6afda270f332f79e3e60db4", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x6", - "gasLimit": "0x47e7c4", - "gasUsed": "0x4aeac", - "timestamp": "0x3c", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x5ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0xf", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xcfbef0051e5b8a313532cc98410f5135948915a3d046ac28083d0d8f0fdfa660", - "s": "0x5520ab4a5ce35c1d8c70cff148eefe0a2833ba0ed6f2781f839cc7edc8bf575e", - "hash": "0x8bc25d0f8a8a24ba715fdd3f29e7f7302befa1446b4736538d45e3862cf67631" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x10", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xd42a5ec165486f09e6d8faf3a93c87c4f0cc6b4d15ebbc2dedca7e4ef35a4555", - "s": "0xc129f489b2213092f5863b7a936ece05bdcb26a4513603c9f4b84ab0d9acd15", - "hash": "0x96132f15280252a7ca473a4a5f4c126f610d34f2007cda6b0007a003ef6fd6ec" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x11", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x307eb02650c740c599c347d7dad1b390fa8dc24d216eb2ba769dc711aae32789", - "s": "0x77af8cfb89aa87266d3b691ddb75be4221fb2b188e1c4470daaa707d44161200", - "hash": "0x377ead486a6468dcd837e8047543ceb4dfa65684f927eca80f40adf7144dcbba" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x12", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x44ef64e26f79482731ceaef418439ebb497806df367f598ebf5d9981f5414a4d", - "s": "0x4b0d7d566fb8e7cba207385fdad173c9f961fe23fe3961e07c4a31df20c31a03", - "hash": "0x3f92ce1202d56635eb6c088f1cd3a6604dae60f3100a68f330d1722c324f2ab4" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x13", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x78688c9ef5a7925528910547dc39f1b359a5e230f850310f599098c32876443e", - "s": "0x6462d6bc2778d84c5af517d383483e0685b8fccbd424196951c1e509964a27e0", - "hash": "0x029b987cd062bc3e738d944990266cffeaed74340531450373d34666ad4fabd6" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x14", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x25", - "r": "0xec8f9c89aa1f4f795d8b45ff41c871721d994858a1374411c4878532001a4ba5", - "s": "0x27f11a383c603c28321baad48830d6090c9b0164e2d26d632a73ecd809ae53c7", - "hash": "0xc79cc4aae86b02b8b9787867a98670cf6d022af0fee3c0a3abdbddf29f21f7df" - } - ], - "uncles": null - }, - { - "rlp": "f911adf901f6a05ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0dd07cac1fd50a2d47b3faf9514b2a3e385fcd6e3102760f6bea1f919515cacffa0637d26d4cecdd55c7927c6d203ce40b7d9faf363fff990c3fc5e502f5edc1eada0ed9cc53fd0eee79528719ca973156891c6be9ddfe7bb9a788d4a3bc1d261773bb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000078347e7c483061bf24680a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f90fb0b9028a01f9028601150a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a069e444997b9e7db9d3c351acb17da1666358ec8ce1fe34e6084f7347bfcfa83aa064e539a2efbab6c0ec01f1d6d38bf97218a3e42db66a84e35945f65afc4af52cb9028a01f9028601160a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a0a3290dc9c69c2ddd720698de596e2585102f14a5fafa3332abb0fe3e7857a58ba00ad0540e2e37a1fc9a0c03b3a69c420210f86331641c4ee8cf8005cd44db7b5eb9028a01f9028601170a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a0423621e9b3b5f003d15cea8eacd765dcbd7b9de4bff637ff57b3c3e184cac5dea0149abd25789e4ce0a24aa63f230e5afe934ab7d9096db737af7e2d5703914a70b9028a01f9028601180a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a03828c9ac89048c829d2636170dfae92e653be033c684f228fbf5a9bce141fcaaa00902674169c7dcb2eb4faec66d9ba35c31eb1316755cf19ac82d33358e63fca9b9028a01f9028601190a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000001a091d9a0233ab5773c83179adcae0f99f21985e280f44760cb99f91fda53dc1ee6a0592fde4635dffe070b989902dee4f7a14b2d43410ee4ac2f025d16bfeeccec24b9028a01f90286011a0a8301e24194000000000000000000000000000000000000aaaa8080f90222f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0050000000000000000000000000000000000000000000000000000000000000080a04c38274334089ba26be1ab238d9fe74e0e2e12d746f458fe5711f48f51842b6ba0222563aefd3f81edc662de7b039aa61b189404451201f3a28471f34dbfefac71f8601b0a8301e24194000000000000000000000000000000000000aaaa808026a072b8abde69e482a1cb7c88df29ef92502f35b070c0d19b2a1b646b1dbf0d898ca069f1474f53b876d271e3ec33cbaad5204b381e4ebc4ea1cd343ac6930d0ea2a7c0", - - "header": { - "parentHash": "0x5ddaed99af17f5dce831bdb5f07a90ddf2cf530951e33da434a35985aa42c6c3", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0xdd07cac1fd50a2d47b3faf9514b2a3e385fcd6e3102760f6bea1f919515cacff", - "transactionsTrie": "0x637d26d4cecdd55c7927c6d203ce40b7d9faf363fff990c3fc5e502f5edc1ead", - "receiptsTrie": "0xed9cc53fd0eee79528719ca973156891c6be9ddfe7bb9a788d4a3bc1d261773b", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x7", - "gasLimit": "0x47e7c4", - "gasUsed": "0x61bf2", - "timestamp": "0x46", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x85a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x15", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x69e444997b9e7db9d3c351acb17da1666358ec8ce1fe34e6084f7347bfcfa83a", - "s": "0x64e539a2efbab6c0ec01f1d6d38bf97218a3e42db66a84e35945f65afc4af52c", - "hash": "0x479eba011395274523b321f282bdad6374850bc40749047a9278e122b38d4aaf" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x16", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xa3290dc9c69c2ddd720698de596e2585102f14a5fafa3332abb0fe3e7857a58b", - "s": "0xad0540e2e37a1fc9a0c03b3a69c420210f86331641c4ee8cf8005cd44db7b5e", - "hash": "0x84c8d5f6e8a706a936b12d149ef7228484cdb6cc7bdbef7a6bbc3092e3e0842c" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x17", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x423621e9b3b5f003d15cea8eacd765dcbd7b9de4bff637ff57b3c3e184cac5de", - "s": "0x149abd25789e4ce0a24aa63f230e5afe934ab7d9096db737af7e2d5703914a70", - "hash": "0x7da302eb420f10e9cf3c121db86496e259ae2b42dccda2de10fefce5d5aa139b" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x18", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x3828c9ac89048c829d2636170dfae92e653be033c684f228fbf5a9bce141fcaa", - "s": "0x902674169c7dcb2eb4faec66d9ba35c31eb1316755cf19ac82d33358e63fca9", - "hash": "0xbba5577e03b997efc268fe0912e19e0063750626ce6f9b166066e02e470ac086" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x19", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x91d9a0233ab5773c83179adcae0f99f21985e280f44760cb99f91fda53dc1ee6", - "s": "0x592fde4635dffe070b989902dee4f7a14b2d43410ee4ac2f025d16bfeeccec24", - "hash": "0x26c52e93b532bca09107f40f9ccf238466f51e15f5ecdc17f9a16eea62087cea" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1a", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x4c38274334089ba26be1ab238d9fe74e0e2e12d746f458fe5711f48f51842b6b", - "s": "0x222563aefd3f81edc662de7b039aa61b189404451201f3a28471f34dbfefac71", - "hash": "0x5ba61c8fabacaa0e87f207125bf3a25a784a6f429aa2ae1f76ffe95c9a34eb54" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x1b", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0x72b8abde69e482a1cb7c88df29ef92502f35b070c0d19b2a1b646b1dbf0d898c", - "s": "0x69f1474f53b876d271e3ec33cbaad5204b381e4ebc4ea1cd343ac6930d0ea2a7", - "hash": "0xfa60faf2f9a1f4cbf19ba6ba746e0c633ba5fe2957f08be0dbc2c883039029ba" - } - ], - "uncles": null - }, - { - "rlp": "f916b7f901f6a085a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a01e11ee12288a40ff864df1f6ad3300fc9371c1eb357053df51d5cab2f3e5ba89a0e63a171d8cdd66b30bc70906336d255376adeff892e5c18acfb514c3c5848c24a05f714113fe44466c533b2b5e101539de21cb8d1debeca1765154c2e69d035d21b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000088347e7c48307b9a85080a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f914bab902e501f902e1011c0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0a345838333ae268c00da46ed42deae5088daedff5386352968959edb1dcafc8ba011c4f1440e894902a1af266c8e03f04ca5956bfad430c365be9657611afc53f4b902e501f902e1011d0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0c3640d17818544e39d623aab79b0781c80cb3981929b24fcc562684b65eff002a04406cba22f6306b0afab3a1a7a2a6b414416a122f3d33023e91b71e5c227a780b902e501f902e1011e0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0542d0389eb1173f9f5224ae0af0aacbbb7c7949ddd13d7b9392e72cefbc090c1a0571c6726ba9a4c65c1c4194fc140497febf9be09accc161ed7f40773a6b4b4afb902e501f902e1011f0a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a08e1a10e344a9e62d70d610a21980dd7d0e50df1308d993e74db1a49f65556c0aa052fbe60de2d4ca53e28a0092df33497116f4a5a7fbc40621b962e6ff7c5f725ab902e501f902e101200a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000080a0eac4f60d9f9d85f2a5cc04603f78a3053d1846678090a934b36ffa415e2ed90ba0076694d37e45b009b59b70f60fe3a949d199cbe8602b4fc9921a6e18b9401e75b902e501f902e101210a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0d8abc8bbfeda7780f9f5e5c49511080672f1627bf44a6d20ce630bb9ba707c64a02c3083fa0cc4fc2a9df6ee0e7ce34b2070c892466d7ac06ef8afc097e7948ccfb902e501f902e101220a8301e24194000000000000000000000000000000000000aaaa8080f9027df859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0060000000000000000000000000000000000000000000000000000000000000001a0614a1003abc9483c9d19a9e4eb50f52b43f33ea1cd3e05a9d4222d175128dd9fa02cf9924ee66bea724611b185851cd20d6e832ddd8b32f7960e9a2c8436bac4f1f860230a8301e24194000000000000000000000000000000000000aaaa808025a0e0908d8cb32c6746e997b494f9e64980a05739781e91334305c73f9f29db4c39a05cc81dfae6a0b36f702d9ab38d5f5e4241ad8d9e5ce03dc139050a1a2271dc22c0", - - "header": { - "parentHash": "0x85a3ba47b898ffb9f4d3a286c438fdbae8f948acca51b69ba86e21e9b852c4a2", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0x1e11ee12288a40ff864df1f6ad3300fc9371c1eb357053df51d5cab2f3e5ba89", - "transactionsTrie": "0xe63a171d8cdd66b30bc70906336d255376adeff892e5c18acfb514c3c5848c24", - "receiptsTrie": "0x5f714113fe44466c533b2b5e101539de21cb8d1debeca1765154c2e69d035d21", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x8", - "gasLimit": "0x47e7c4", - "gasUsed": "0x7b9a8", - "timestamp": "0x50", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0xc48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1c", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xa345838333ae268c00da46ed42deae5088daedff5386352968959edb1dcafc8b", - "s": "0x11c4f1440e894902a1af266c8e03f04ca5956bfad430c365be9657611afc53f4", - "hash": "0xa1456d53037869e0971392226802336d49c748bbac2334b87ff4df29b3096199" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1d", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xc3640d17818544e39d623aab79b0781c80cb3981929b24fcc562684b65eff002", - "s": "0x4406cba22f6306b0afab3a1a7a2a6b414416a122f3d33023e91b71e5c227a780", - "hash": "0x287d84df82c46eb31a591ccbee5bbc6f3707983a1d7aea8ac1ec22bf2d8e8922" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1e", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x542d0389eb1173f9f5224ae0af0aacbbb7c7949ddd13d7b9392e72cefbc090c1", - "s": "0x571c6726ba9a4c65c1c4194fc140497febf9be09accc161ed7f40773a6b4b4af", - "hash": "0x7cc4498d64074114b14b9bbc356b74662c0674c36bab54e5401530ab51f76d2d" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x1f", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x8e1a10e344a9e62d70d610a21980dd7d0e50df1308d993e74db1a49f65556c0a", - "s": "0x52fbe60de2d4ca53e28a0092df33497116f4a5a7fbc40621b962e6ff7c5f725a", - "hash": "0xa65617192b2b1308a0b1c53cbe81ce7f33ad1c1ff1f2cce522e29d740291cd86" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x20", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xeac4f60d9f9d85f2a5cc04603f78a3053d1846678090a934b36ffa415e2ed90b", - "s": "0x76694d37e45b009b59b70f60fe3a949d199cbe8602b4fc9921a6e18b9401e75", - "hash": "0xaff285b353ae7ef059f3357da968cb76b0eda97f094a9245e283d9e86538ec2a" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x21", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xd8abc8bbfeda7780f9f5e5c49511080672f1627bf44a6d20ce630bb9ba707c64", - "s": "0x2c3083fa0cc4fc2a9df6ee0e7ce34b2070c892466d7ac06ef8afc097e7948ccf", - "hash": "0x36c86aeb97a7a82df05f31708ad2acfa2e17fb8b8bea3e5c9809a3672504d124" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x22", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x614a1003abc9483c9d19a9e4eb50f52b43f33ea1cd3e05a9d4222d175128dd9f", - "s": "0x2cf9924ee66bea724611b185851cd20d6e832ddd8b32f7960e9a2c8436bac4f1", - "hash": "0x089b7cca10e8b9b9442e62acbcd0d45d2aca3773d89956c80d42c27640b3cf61" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x23", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x25", - "r": "0xe0908d8cb32c6746e997b494f9e64980a05739781e91334305c73f9f29db4c39", - "s": "0x5cc81dfae6a0b36f702d9ab38d5f5e4241ad8d9e5ce03dc139050a1a2271dc22", - "hash": "0xe871bdeea9aa4506fe8b2439849892ba9f2d853277ec6f565be1d84be0ed13ef" - } - ], - "uncles": null - }, - { - "rlp": "f91c77f901f6a0c48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0a463cb31e670fe25b7b5dfbbc793dd928db33a8b845298467c48809be4e5a7f7a087c8e925a1221e6e3a1d4b605f87848777f5ba38168c2ccc5cf024762ead055ca0638157d19e0340249b3934837bf99770474d939b2ae93f2d1c7f5db19d6d041db901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000098347e7c4830987ce5a80a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f91a7ab9034001f9033c01240a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0170a46887a741e98bb82c99fc68d86e32447508bb3558699294ff562fb6b9be2a003764ba59caab09b25f16eb1e0d6be0b071fd7aebefc88a7c056f4ebeaa8cb5bb9034001f9033c01250a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a007775a2a2180025ae4c2b63a20e586538fab33ff619ca6a937d6865360be8dcba061f490b7c60e665854bc5dc4b5f40bb2c31625788c10b98035c8f525adadee53b9034001f9033c01260a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a02b3b6c19247342eb2062761e24e1d753c032c3b4f4f146b091b2240877483e59a0235f14770796cb22d2cd2e41f63af49b10cf208000be2ba789bb120096b989b8b9034001f9033c01270a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a0805dca3053d94bad7b563b604a976388595eb8834eaf3ef7973de21bcc9ca97ca05c37e3a461283d51557dfb0f740065dcc4d0aef005829805a504643e5523b489b9034001f9033c01280a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a047522841a060cc664997d11fdec3e929a65a6ee124a47bc82dd873e79b80adbba06cae9c3319fbe8a1206db7ed2063288f707811fd06ba558da8e2187bdc41d375b9034001f9033c01290a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a0a87b7830fe657f02a195aa1b2617501bcb52b95ebbd9479277f3dfa22de1b0e3a061d0c1acb8066f8dd3b3ef18f714cd0132247dab45c3481c2b7fc6cfb9708ef7b9034001f9033c012a0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000001a0b7fb8508b5e3993af55d04f6e58732037ac0dc5a1ac5538bf9dae95e52c1d005a00656240da661eea32298774cf810e858a6b8999ae5b9564e708a55e15ae4a051b9034001f9033c012b0a8301e24194000000000000000000000000000000000000aaaa8080f902d8f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0070000000000000000000000000000000000000000000000000000000000000080a016a3a0af3ff0279ea62d7554131ad7670ccb83850bd6d0bb66cbaa45c46e5c35a055a9915e20c483e9237f0bfef99455d43ac1f22a438a9485b6e1f3dbbab441abf8602c0a8301e24194000000000000000000000000000000000000aaaa808026a0cffdf83faecfc8fe7e2e83570f0bcd9ef0e4914fd645dc8399bbd5bc8d483762a067ab197437466269980d4b18a1ed11744d7dceeae934729b14094fe31f5875a5c0", - - "header": { - "parentHash": "0xc48af3c63e80dcf56fcc7c830c7ec5cd782896ad71193ad20beb3b29e73e11a9", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0xa463cb31e670fe25b7b5dfbbc793dd928db33a8b845298467c48809be4e5a7f7", - "transactionsTrie": "0x87c8e925a1221e6e3a1d4b605f87848777f5ba38168c2ccc5cf024762ead055c", - "receiptsTrie": "0x638157d19e0340249b3934837bf99770474d939b2ae93f2d1c7f5db19d6d041d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0x9", - "gasLimit": "0x47e7c4", - "gasUsed": "0x987ce", - "timestamp": "0x5a", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x35ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x24", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x170a46887a741e98bb82c99fc68d86e32447508bb3558699294ff562fb6b9be2", - "s": "0x3764ba59caab09b25f16eb1e0d6be0b071fd7aebefc88a7c056f4ebeaa8cb5b", - "hash": "0x6efd98eee12ad55ea61c467a685c5405d71a5d7eee0bf7446610a71bbb252978" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x25", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x7775a2a2180025ae4c2b63a20e586538fab33ff619ca6a937d6865360be8dcb", - "s": "0x61f490b7c60e665854bc5dc4b5f40bb2c31625788c10b98035c8f525adadee53", - "hash": "0xfc8f3b59421c55961e9148b55df36202cef47250717448b712ed8532a8dc3f8d" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x26", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x2b3b6c19247342eb2062761e24e1d753c032c3b4f4f146b091b2240877483e59", - "s": "0x235f14770796cb22d2cd2e41f63af49b10cf208000be2ba789bb120096b989b8", - "hash": "0x9998aabf75a918d993edb60f8f58c07280a8334e58a372b8c83ebaedcbe896ad" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x27", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x805dca3053d94bad7b563b604a976388595eb8834eaf3ef7973de21bcc9ca97c", - "s": "0x5c37e3a461283d51557dfb0f740065dcc4d0aef005829805a504643e5523b489", - "hash": "0x743c766ef64a159e1ff83fd958c7caeaa8c869ca370529ad5f807f14feeaad7b" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x28", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x47522841a060cc664997d11fdec3e929a65a6ee124a47bc82dd873e79b80adbb", - "s": "0x6cae9c3319fbe8a1206db7ed2063288f707811fd06ba558da8e2187bdc41d375", - "hash": "0xe6b1c6f51ac44f84d3e38ab6f238f313180a91c18079f44bb1af392b7b48c87a" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x29", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xa87b7830fe657f02a195aa1b2617501bcb52b95ebbd9479277f3dfa22de1b0e3", - "s": "0x61d0c1acb8066f8dd3b3ef18f714cd0132247dab45c3481c2b7fc6cfb9708ef7", - "hash": "0x4ce8251dac66134f50748d70e59acee7f3395f57c163ac321800337a0b11f1e7" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x2a", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0xb7fb8508b5e3993af55d04f6e58732037ac0dc5a1ac5538bf9dae95e52c1d005", - "s": "0x656240da661eea32298774cf810e858a6b8999ae5b9564e708a55e15ae4a051", - "hash": "0xb7dc9ae376bd9065b403bb143020f589b860dee65a5a9ebd7e0bd1abc9eae5fb" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x2b", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x16a3a0af3ff0279ea62d7554131ad7670ccb83850bd6d0bb66cbaa45c46e5c35", - "s": "0x55a9915e20c483e9237f0bfef99455d43ac1f22a438a9485b6e1f3dbbab441ab", - "hash": "0xcf7e327a838d9b07eabff38f6f7f39c7bcb36463e114f66934ea451abb9b87bf" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x2c", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0xcffdf83faecfc8fe7e2e83570f0bcd9ef0e4914fd645dc8399bbd5bc8d483762", - "s": "0x67ab197437466269980d4b18a1ed11744d7dceeae934729b14094fe31f5875a5", - "hash": "0xe6a49397da6f57aacebcf4024e6a07c4a724042db248cc668926ec2a2abc2394" - } - ], - "uncles": null - }, - { - "rlp": "f922edf901f6a035ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0ae01e8e74d19be46a3f2b56e79c331634e3032efce2ffed6ad37577f66039d91a088a579ae5732b49cd956fc12234d3a4f7c2ed60303cadea178f1be33c9f49f06a0971e38f6ae7b4aeef32a9c1b53b9e2e84eb491c73022449d16c95db564cccc5db9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000a8347e7c4830b86646480a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f920f0b9039b01f90397012d0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a03783f158de899ff6bce0d79e211d82575a1971fc971e56116868a0121848e57aa02ccf7dbac3b9aef50a9400d635636b7c15eca0d0f9b7ff25a0d09b56596f75aab9039b01f90397012e0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a03593ee4a77441877a447d120b2070f1c2324e9600fdbad39c31fe75a5c1ca42ba04ec37cdb3c934e95ea349b981de041ebb29036b7f4c5dadd0890967b05e5b945b9039b01f90397012f0a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a048e3a7c884ea3e5672f6aa3b7f5dcd7e4fbf0be5998a4bbb9ee74c860607443aa0441fd36310421832f8a0025be07ce02d8833af7ecc179ec7b186d3f0278734c1b9039b01f9039701300a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0e7081190ea699d97f818678ef971a391812196e3ee94d04c4551e2dd0657db3aa02c3a9ba4de5beebd2c8a3a2eb1788534599af6b40e7f1b3b5c37071553214f9eb9039b01f9039701310a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a059e183f642034975125dd0bb9b36722412cffebf2af31025ad8800eaf6199f28a00a456535d0a974c936d49d7d69884995189407fbedf819878e8ed1894d1282aeb9039b01f9039701320a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a077032f089f9761459f4a0bd8a64465a50be1c84e1512fdfe5961ee3bb5d57553a00d0f8bdd0b070cdf1af711855847e11293e7a0424d471a0e28088de8238ce270b9039b01f9039701330a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0912278d20ab6b8033ca071a3757d6bf038f17e9634cac85c6684cd42672d88f6a00b0292c31a9f510d3a53653a1fbe0b76dc54f8a13a2a8b7aa3a877c91a24fb5fb9039b01f9039701340a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000080a0960b49da258aa006edc7580bd5c91be701feabae628e0c47a95559fa5c6dc4a6a066654bf09aa64a93a95463c86588d45192589286855efe67f05a4ab6c8fa7553b9039b01f9039701350a8301e24194000000000000000000000000000000000000aaaa8080f90333f859940000000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000f859940100000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00100000000000000000000000000000000000000000000000000000000000000f859940200000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00200000000000000000000000000000000000000000000000000000000000000f859940300000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00300000000000000000000000000000000000000000000000000000000000000f859940400000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00400000000000000000000000000000000000000000000000000000000000000f859940500000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00500000000000000000000000000000000000000000000000000000000000000f859940600000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00600000000000000000000000000000000000000000000000000000000000000f859940700000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a00700000000000000000000000000000000000000000000000000000000000000f859940800000000000000000000000000000000000000f842a00000000000000000000000000000000000000000000000000000000000000000a0080000000000000000000000000000000000000000000000000000000000000001a0538f7a084177da0422c9e663b708dee81627264abf6152d7bfb6f1dc8a9a5b11a07baaa50e351a6d338ac5765d487a3a54bee29483516b9c64bed35cf6c5bc776ef860360a8301e24194000000000000000000000000000000000000aaaa808026a0822285a75be8c0cf90edf1031b03d949468c9c66bdb63897ae9fc96b167eaa3ba07478bac2f9fe6a63e632b0861b86add7c5a9e8b117e26788e00418d72eeba0d6c0", - - "header": { - "parentHash": "0x35ad84ebaa22053e24ac21d946c71e49e3cea2a3f2c0f373505bf2ee250f1201", - "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "coinbase": "0x0100000000000000000000000000000000000000", - "stateRoot": "0xae01e8e74d19be46a3f2b56e79c331634e3032efce2ffed6ad37577f66039d91", - "transactionsTrie": "0x88a579ae5732b49cd956fc12234d3a4f7c2ed60303cadea178f1be33c9f49f06", - "receiptsTrie": "0x971e38f6ae7b4aeef32a9c1b53b9e2e84eb491c73022449d16c95db564cccc5d", - "bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "difficulty": "0x20000", - "number": "0xa", - "gasLimit": "0x47e7c4", - "gasUsed": "0xb8664", - "timestamp": "0x64", - "extraData": "0x", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x0000000000000000", - "hash": "0x105d8befc05cb9c21add67408bcc7512de148cd9a7cc8932efa294e2672aba55" - }, - "transactions": [ - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x2d", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x3783f158de899ff6bce0d79e211d82575a1971fc971e56116868a0121848e57a", - "s": "0x2ccf7dbac3b9aef50a9400d635636b7c15eca0d0f9b7ff25a0d09b56596f75aa", - "hash": "0x16751472a59dc59d9454f22c089631bb065bbb92bdd389a15a71c63fb8fb2db2" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x2e", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x3593ee4a77441877a447d120b2070f1c2324e9600fdbad39c31fe75a5c1ca42b", - "s": "0x4ec37cdb3c934e95ea349b981de041ebb29036b7f4c5dadd0890967b05e5b945", - "hash": "0x60e0f978ce01c1221b1de4e27c4428d0cfa5592c5d0f36006a35337404c27a44" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x2f", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x48e3a7c884ea3e5672f6aa3b7f5dcd7e4fbf0be5998a4bbb9ee74c860607443a", - "s": "0x441fd36310421832f8a0025be07ce02d8833af7ecc179ec7b186d3f0278734c1", - "hash": "0x07c2da48c6082bac84bbfdec573e67d3e86df68b762e1f9ed7393653cae834d1" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x30", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0xe7081190ea699d97f818678ef971a391812196e3ee94d04c4551e2dd0657db3a", - "s": "0x2c3a9ba4de5beebd2c8a3a2eb1788534599af6b40e7f1b3b5c37071553214f9e", - "hash": "0x148e2d26da5a0e8b0932842a7a2c1fe964776a1be3978684af9528c6bef79918" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x31", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x59e183f642034975125dd0bb9b36722412cffebf2af31025ad8800eaf6199f28", - "s": "0xa456535d0a974c936d49d7d69884995189407fbedf819878e8ed1894d1282ae", - "hash": "0xa13299621bd0d81ad5c373fb7357f6abb528475d8d1b08bb8b2e4176f0e2e303" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x32", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x77032f089f9761459f4a0bd8a64465a50be1c84e1512fdfe5961ee3bb5d57553", - "s": "0xd0f8bdd0b070cdf1af711855847e11293e7a0424d471a0e28088de8238ce270", - "hash": "0xa956c3e12fa0fdfd93e2e9c14e6c63a63db49aabe9dbeceb4ee2cf71777f6c59" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x33", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x912278d20ab6b8033ca071a3757d6bf038f17e9634cac85c6684cd42672d88f6", - "s": "0xb0292c31a9f510d3a53653a1fbe0b76dc54f8a13a2a8b7aa3a877c91a24fb5f", - "hash": "0x54fab10dc75cfa4bae509e25830b8914d9b15a12a71c1f68b79904e2d3599e90" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x34", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x0", - "r": "0x960b49da258aa006edc7580bd5c91be701feabae628e0c47a95559fa5c6dc4a6", - "s": "0x66654bf09aa64a93a95463c86588d45192589286855efe67f05a4ab6c8fa7553", - "hash": "0x2fc87ef663f4a57b922fc51029045e03bac37ae0a8b126b1ba22e362a6b6635d" - }, - { - "type": "0x1", - "chainId": "0x1", - "nonce": "0x35", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": [ - { - "address": "0x0000000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0100000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0100000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0200000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0200000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0300000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0300000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0400000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0400000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0500000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0500000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0600000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0600000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0700000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0700000000000000000000000000000000000000000000000000000000000000" - ] - }, - { - "address": "0x0800000000000000000000000000000000000000", - "storageKeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0800000000000000000000000000000000000000000000000000000000000000" - ] - } - ], - "v": "0x1", - "r": "0x538f7a084177da0422c9e663b708dee81627264abf6152d7bfb6f1dc8a9a5b11", - "s": "0x7baaa50e351a6d338ac5765d487a3a54bee29483516b9c64bed35cf6c5bc776e", - "hash": "0xf522c9cb3ff8f935d2ec3ca405a7480a43d959a16e1a192e705a5613a0e3d3f5" - }, - { - "type": "0x0", - "chainId": null, - "nonce": "0x36", - "gasPrice": "0xa", - "gasLimit": "0x1e241", - "to": "0x000000000000000000000000000000000000aaaa", - "value": "0x0", - "data": "0x", - "accessList": null, - "v": "0x26", - "r": "0x822285a75be8c0cf90edf1031b03d949468c9c66bdb63897ae9fc96b167eaa3b", - "s": "0x7478bac2f9fe6a63e632b0861b86add7c5a9e8b117e26788e00418d72eeba0d6", - "hash": "0x52079ee865e89ec93150543232702a9b4a5660debb803017357b9039c38c2aab" - } - ], - "uncles": null - } - ] - } -} diff --git a/crates/ethcore/src/client/evm_test_client.rs b/crates/ethcore/src/client/evm_test_client.rs index b8a39d4e6b..a80a7c04a1 100644 --- a/crates/ethcore/src/client/evm_test_client.rs +++ b/crates/ethcore/src/client/evm_test_client.rs @@ -99,7 +99,6 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Homestead => Some(ethereum::new_homestead_test()), ForkSpec::EIP150 => Some(ethereum::new_eip150_test()), ForkSpec::EIP158 => Some(ethereum::new_eip161_test()), - ForkSpec::EIP2930 => Some(ethereum::new_eip2930_test()), ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()), diff --git a/crates/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs index 3691c422c7..b527ff9c91 100644 --- a/crates/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -274,14 +274,6 @@ pub fn new_berlin_test() -> Spec { ) } -/// Create a new Foundation Berlin era spec. -pub fn new_eip2930_test() -> Spec { - load( - None, - include_bytes!("../../res/chainspec/test/eip2930_test.json"), - ) -} - /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { load( diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 230d469f2c..28fdf8040f 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -142,11 +142,6 @@ pub struct Transaction { } impl Transaction { - /// The message hash of the transaction. This hash is used for signing transaction - pub fn signature_hash(&self, chain_id: Option) -> H256 { - keccak(self.encode(chain_id, None)) - } - /// encode raw transaction fn encode(&self, chain_id: Option, signature: Option<&SignatureComponents>) -> Vec { let mut stream = RlpStream::new(); @@ -321,21 +316,14 @@ impl AccessListTx { fn encode_payload( &self, - tx_type: Option, //used only for signature hashing for EIP-2930 chain_id: Option, signature: Option<&SignatureComponents>, ) -> RlpStream { let mut stream = RlpStream::new(); - let mut list_size = if signature.is_some() { 11 } else { 8 }; - list_size += if tx_type.is_some() { 1 } else { 0 }; + let list_size = if signature.is_some() { 11 } else { 8 }; stream.begin_list(list_size); - // append tx_type at beggining of list, this is used only for data hash for signature. - if let Some(tx_type) = tx_type { - stream.append(&tx_type); - } - // append chain_id. from EIP-2930: chainId is defined to be an integer of arbitrary size. stream.append(&(if let Some(n) = chain_id { n } else { 0 })); @@ -353,7 +341,7 @@ impl AccessListTx { } } - // append signature + // append signature if any if let Some(signature) = signature { signature.rlp_append(&mut stream); } @@ -366,7 +354,7 @@ impl AccessListTx { chain_id: Option, signature: Option<&SignatureComponents>, ) -> Vec { - let stream = self.encode_payload(None, chain_id, signature); + let stream = self.encode_payload(chain_id, signature); // make as vector of bytes [&[TypedTxId::AccessList as u8], stream.as_raw()].concat() } @@ -379,14 +367,6 @@ impl AccessListTx { ) { rlp.append(&self.encode(chain_id, Some(signature))); } - - pub fn signature_hash(&self, chain_id: Option) -> H256 { - keccak( - &self - .encode_payload(Some(TypedTxId::AccessList as u8), chain_id, None) - .as_raw(), - ) - } } #[derive(Debug, Clone, Eq, PartialEq)] @@ -406,10 +386,10 @@ impl TypedTransaction { /// The message hash of the transaction. pub fn signature_hash(&self, chain_id: Option) -> H256 { - match self { - Self::Legacy(tx) => tx.signature_hash(chain_id), - Self::AccessList(tx) => tx.signature_hash(chain_id), - } + keccak(match self { + Self::Legacy(tx) => tx.encode(chain_id, None), + Self::AccessList(tx) => tx.encode(chain_id, None), + }) } /// Signs the transaction as coming from `sender`. diff --git a/crates/ethjson/src/spec/spec.rs b/crates/ethjson/src/spec/spec.rs index 39610023bf..e5e23be778 100644 --- a/crates/ethjson/src/spec/spec.rs +++ b/crates/ethjson/src/spec/spec.rs @@ -25,7 +25,6 @@ use std::io::Read; pub enum ForkSpec { EIP150, EIP158, - EIP2930, Frontier, Homestead, Byzantium, From fb9699d8e187aa8ef76f6556b31099ff337771a8 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 17 Feb 2021 16:52:51 +0100 Subject: [PATCH 060/107] EIP-2930 remove type from legacy JSONRPC (#265) * EIP-2930 remove type from legacy JSONRPC * fmt --- crates/ethcore/types/src/receipt.rs | 7 +- .../types/src/transaction/transaction.rs | 4 +- .../types/src/transaction/transaction_id.rs | 74 +++++++++++++++---- .../types/src/views/typed_transaction.rs | 3 +- crates/rpc/src/v1/helpers/dispatch/signing.rs | 2 +- crates/rpc/src/v1/helpers/fake_sign.rs | 2 +- crates/rpc/src/v1/helpers/requests.rs | 6 +- crates/rpc/src/v1/tests/mocked/eth.rs | 6 +- crates/rpc/src/v1/tests/mocked/parity.rs | 2 +- crates/rpc/src/v1/tests/mocked/parity_set.rs | 2 +- crates/rpc/src/v1/tests/mocked/signer.rs | 4 +- crates/rpc/src/v1/tests/mocked/signing.rs | 4 +- .../rpc/src/v1/tests/mocked/signing_unsafe.rs | 2 +- crates/rpc/src/v1/types/block.rs | 2 +- crates/rpc/src/v1/types/call_request.rs | 5 +- crates/rpc/src/v1/types/confirmations.rs | 4 +- crates/rpc/src/v1/types/receipt.rs | 15 ++-- crates/rpc/src/v1/types/transaction.rs | 11 ++- .../rpc/src/v1/types/transaction_request.rs | 5 +- 19 files changed, 100 insertions(+), 60 deletions(-) diff --git a/crates/ethcore/types/src/receipt.rs b/crates/ethcore/types/src/receipt.rs index 6e361e4ac2..787c8f25f5 100644 --- a/crates/ethcore/types/src/receipt.rs +++ b/crates/ethcore/types/src/receipt.rs @@ -20,10 +20,7 @@ use super::transaction::TypedTxId; use ethereum_types::{Address, Bloom, H160, H256, U256}; use heapsize::HeapSizeOf; use rlp::{DecoderError, Rlp, RlpStream}; -use std::{ - convert::TryInto, - ops::{Deref, DerefMut}, -}; +use std::ops::{Deref, DerefMut}; use log_entry::{LocalizedLogEntry, LogEntry}; use BlockNumber; @@ -151,7 +148,7 @@ impl TypedReceipt { // at least one byte needs to be present return Err(DecoderError::RlpIncorrectListLen); } - let id = tx[0].try_into(); + let id = TypedTxId::try_from_wire_byte(tx[0]); if id.is_err() { return Err(DecoderError::Custom("Unknown transaction")); } diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 28fdf8040f..6a8b0b94da 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -22,7 +22,7 @@ use ethkey::{self, public_to_address, recover, Public, Secret, Signature}; use hash::keccak; use heapsize::HeapSizeOf; use rlp::{self, DecoderError, Rlp, RlpStream}; -use std::{convert::TryInto, ops::Deref}; +use std::ops::Deref; pub type AccessListItem = (H160, Vec); pub type AccessList = Vec; @@ -493,7 +493,7 @@ impl TypedTransaction { // at least one byte needs to be present return Err(DecoderError::RlpIncorrectListLen); } - let id = tx[0].try_into(); + let id = TypedTxId::try_from_wire_byte(tx[0]); if id.is_err() { return Err(DecoderError::Custom("Unknown transaction")); } diff --git a/crates/ethcore/types/src/transaction/transaction_id.rs b/crates/ethcore/types/src/transaction/transaction_id.rs index cb31d1937c..458029ac87 100644 --- a/crates/ethcore/types/src/transaction/transaction_id.rs +++ b/crates/ethcore/types/src/transaction/transaction_id.rs @@ -18,9 +18,8 @@ use ethereum_types::U64; use serde_repr::*; -use std::convert::TryFrom; -#[derive(Serialize_repr, Eq, Hash, Deserialize_repr, Debug, Clone, PartialEq)] +#[derive(Serialize_repr, Eq, Hash, Deserialize_repr, Debug, Copy, Clone, PartialEq)] #[repr(u8)] pub enum TypedTxId { AccessList = 0x01, @@ -28,6 +27,7 @@ pub enum TypedTxId { } impl TypedTxId { + // used in json tets pub fn from_u8_id(n: u8) -> Option { match n { 0 => Some(Self::Legacy), @@ -36,14 +36,30 @@ impl TypedTxId { } } + pub fn try_from_wire_byte(n: u8) -> Result { + match n { + x if x == TypedTxId::AccessList as u8 => Ok(TypedTxId::AccessList), + x if (x & 0x80) != 0x00 => Ok(TypedTxId::Legacy), + _ => Err(()), + } + } + #[allow(non_snake_case)] - pub fn from_U64_id(n: &U64) -> Option { - match n.0[0] { - 0x0 => Some(Self::Legacy), - 0x1 => Some(Self::AccessList), + pub fn from_U64_option_id(n: Option) -> Option { + match n.map(|t| t.as_u64()) { + None => Some(Self::Legacy), + Some(0x01) => Some(Self::AccessList), _ => None, } } + + #[allow(non_snake_case)] + pub fn to_U64_option_id(self) -> Option { + match self { + Self::Legacy => None, + _ => Some(U64::from(self as u8)), + } + } } impl Default for TypedTxId { @@ -52,14 +68,44 @@ impl Default for TypedTxId { } } -impl TryFrom for TypedTxId { - type Error = (); +#[cfg(test)] +mod tests { + use super::*; - fn try_from(v: u8) -> Result { - match v { - x if x == TypedTxId::AccessList as u8 => Ok(TypedTxId::AccessList), - x if (x & 0x80) != 0x00 => Ok(TypedTxId::Legacy), - _ => Err(()), - } + #[test] + fn typed_tx_id_try_from_wire() { + assert_eq!( + Ok(TypedTxId::AccessList), + TypedTxId::try_from_wire_byte(0x01) + ); + assert_eq!(Ok(TypedTxId::Legacy), TypedTxId::try_from_wire_byte(0x81)); + assert_eq!(Err(()), TypedTxId::try_from_wire_byte(0x00)); + assert_eq!(Err(()), TypedTxId::try_from_wire_byte(0x02)); + } + + #[test] + fn typed_tx_id_to_u64_option_id() { + assert_eq!(None, TypedTxId::Legacy.to_U64_option_id()); + assert_eq!( + Some(U64::from(0x01)), + TypedTxId::AccessList.to_U64_option_id() + ); + } + + #[test] + fn typed_tx_id_from_u64_option_id() { + assert_eq!(Some(TypedTxId::Legacy), TypedTxId::from_U64_option_id(None)); + assert_eq!( + Some(TypedTxId::AccessList), + TypedTxId::from_U64_option_id(Some(U64::from(0x01))) + ); + assert_eq!(None, TypedTxId::from_U64_option_id(Some(U64::from(0x02)))); + } + + #[test] + fn typed_tx_id_from_u8_id() { + assert_eq!(Some(TypedTxId::Legacy), TypedTxId::from_u8_id(0)); + assert_eq!(Some(TypedTxId::AccessList), TypedTxId::from_u8_id(1)); + assert_eq!(None, TypedTxId::from_u8_id(3)); } } diff --git a/crates/ethcore/types/src/views/typed_transaction.rs b/crates/ethcore/types/src/views/typed_transaction.rs index c74d91bc0c..e9a9da1152 100644 --- a/crates/ethcore/types/src/views/typed_transaction.rs +++ b/crates/ethcore/types/src/views/typed_transaction.rs @@ -15,7 +15,6 @@ // along with OpenEthereum. If not, see . //! View onto transaction rlp -use std::convert::TryInto; use crate::transaction::{signature, TypedTxId}; @@ -52,7 +51,7 @@ impl<'a> TypedTransactionView<'a> { return TypedTxId::Legacy; } let tx = rlp.data().expect("unable to decode tx rlp"); - let id = tx[0].try_into().expect("unable to decode tx type"); + let id = TypedTxId::try_from_wire_byte(tx[0]).expect("unable to decode tx type"); if id == TypedTxId::Legacy { panic!("Transaction RLP View should be valid. Legacy byte found"); } diff --git a/crates/rpc/src/v1/helpers/dispatch/signing.rs b/crates/rpc/src/v1/helpers/dispatch/signing.rs index 0514d85abb..3ff004d34b 100644 --- a/crates/rpc/src/v1/helpers/dispatch/signing.rs +++ b/crates/rpc/src/v1/helpers/dispatch/signing.rs @@ -59,7 +59,7 @@ impl super::Accounts for Signer { value: filled.value, data: filled.data, }; - let t = match TypedTxId::from_U64_id(&filled.transaction_type) { + let t = match TypedTxId::from_U64_option_id(filled.transaction_type) { Some(TypedTxId::Legacy) => TypedTransaction::Legacy(legacy_tx), Some(TypedTxId::AccessList) => { if filled.access_list.is_none() { diff --git a/crates/rpc/src/v1/helpers/fake_sign.rs b/crates/rpc/src/v1/helpers/fake_sign.rs index 1948752d4c..5d3318146e 100644 --- a/crates/rpc/src/v1/helpers/fake_sign.rs +++ b/crates/rpc/src/v1/helpers/fake_sign.rs @@ -35,7 +35,7 @@ pub fn sign_call(request: CallRequest) -> Result { value: request.value.unwrap_or_default(), data: request.data.unwrap_or_default(), }; - let tx_typed = match TypedTxId::from_U64_id(&request.transaction_type) { + let tx_typed = match TypedTxId::from_U64_option_id(request.transaction_type) { Some(TypedTxId::Legacy) => TypedTransaction::Legacy(tx_legacy), Some(TypedTxId::AccessList) => { if request.access_list.is_none() { diff --git a/crates/rpc/src/v1/helpers/requests.rs b/crates/rpc/src/v1/helpers/requests.rs index 24d0d78265..b8b32e5064 100644 --- a/crates/rpc/src/v1/helpers/requests.rs +++ b/crates/rpc/src/v1/helpers/requests.rs @@ -23,7 +23,7 @@ use v1::types::{AccessList, Origin, TransactionCondition}; #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct TransactionRequest { /// type of transaction. - pub transaction_type: U64, + pub transaction_type: Option, /// Sender pub from: Option
, /// Recipient @@ -48,7 +48,7 @@ pub struct TransactionRequest { #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] pub struct FilledTransactionRequest { /// type of transaction. - pub transaction_type: U64, + pub transaction_type: Option, /// Sender pub from: Address, /// Indicates if the sender was filled by default value. @@ -92,7 +92,7 @@ impl From for TransactionRequest { #[derive(Debug, Default, PartialEq)] pub struct CallRequest { /// type of transaction. - pub transaction_type: U64, + pub transaction_type: Option, /// From pub from: Option
, /// To diff --git a/crates/rpc/src/v1/tests/mocked/eth.rs b/crates/rpc/src/v1/tests/mocked/eth.rs index abc19975d4..00ea5c6c2d 100644 --- a/crates/rpc/src/v1/tests/mocked/eth.rs +++ b/crates/rpc/src/v1/tests/mocked/eth.rs @@ -707,7 +707,7 @@ fn rpc_eth_pending_transaction_by_hash() { .insert(H256::zero(), tx); } - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"type":"0x0","v":"0x1b","value":"0xa"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; let request = r#"{ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", @@ -1184,7 +1184,7 @@ fn rpc_eth_transaction_receipt() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"0x0"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","removed":false,"topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#; assert_eq!( tester.io.handle_request_sync(request), @@ -1238,7 +1238,7 @@ fn rpc_eth_pending_receipt() { "params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0","type":"0x0"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"contractAddress":null,"cumulativeGasUsed":"0x20","from":"0xb60e8dd61c5d32be8058bb8eb970870f07233155","gasUsed":"0x10","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionHash":"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238","transactionIndex":"0x0"},"id":1}"#; assert_eq!( tester.io.handle_request_sync(request), Some(response.to_owned()) diff --git a/crates/rpc/src/v1/tests/mocked/parity.rs b/crates/rpc/src/v1/tests/mocked/parity.rs index 608a44fabe..ea1b7c31a5 100644 --- a/crates/rpc/src/v1/tests/mocked/parity.rs +++ b/crates/rpc/src/v1/tests/mocked/parity.rs @@ -492,7 +492,7 @@ fn rpc_parity_block_receipts() { "params": [], "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0","type":"0x0"}],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000003","blockNumber":"0x0","contractAddress":null,"cumulativeGasUsed":"0x5208","from":"0x0000000000000000000000000000000000000009","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001","to":null,"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000001","transactionIndex":"0x0"}],"id":1}"#; assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } diff --git a/crates/rpc/src/v1/tests/mocked/parity_set.rs b/crates/rpc/src/v1/tests/mocked/parity_set.rs index 011c29be03..bea2000a3a 100644 --- a/crates/rpc/src/v1/tests/mocked/parity_set.rs +++ b/crates/rpc/src/v1/tests/mocked/parity_set.rs @@ -202,7 +202,7 @@ fn rpc_parity_remove_transaction() { .to_owned() + &format!("0x{:x}", hash) + r#""], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"type":"0x0","v":"0x1f","value":"0x9184e72a"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"chainId":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x49569012bc8523519642c337fded3f20ba987beab31e14c67223b3d31359956f","input":"0x","nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a801f0101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x1f","value":"0x9184e72a"},"id":1}"#; miner.pending_transactions.lock().insert(hash, signed); assert_eq!(io.handle_request_sync(&request), Some(response.to_owned())); diff --git a/crates/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs index 917ad9ae12..6c0bcee84f 100644 --- a/crates/rpc/src/v1/tests/mocked/signer.rs +++ b/crates/rpc/src/v1/tests/mocked/signer.rs @@ -118,7 +118,7 @@ fn should_return_list_of_items_to_confirm() { let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let response = concat!( r#"{"jsonrpc":"2.0","result":["#, - r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","type":"0x0","value":"0x1"}}},"#, + r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x2","origin":"unknown","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","data":"0x05"}}}"#, r#"],"id":1}"# ); @@ -637,7 +637,7 @@ fn should_confirm_sign_transaction_with_rlp() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x1""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/tests/mocked/signing.rs b/crates/rpc/src/v1/tests/mocked/signing.rs index f2b809b2fa..fdeb9b4963 100644 --- a/crates/rpc/src/v1/tests/mocked/signing.rs +++ b/crates/rpc/src/v1/tests/mocked/signing.rs @@ -418,7 +418,7 @@ fn should_add_sign_transaction_to_the_queue() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; @@ -610,7 +610,7 @@ fn should_compose_transaction() { let response = r#"{"jsonrpc":"2.0","result":{"condition":null,"data":"0x","from":"0x"# .to_owned() + &from - + r#"","gas":"0x5208","gasPrice":"0x4a817c800","nonce":"0x0","to":null,"type":"0x0","value":"0x5"},"id":1}"#; + + r#"","gas":"0x5208","gasPrice":"0x4a817c800","nonce":"0x0","to":null,"value":"0x5"},"id":1}"#; // then let res = tester.io.handle_request(&request).wait().unwrap(); diff --git a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs index fde44ed933..c52127736f 100644 --- a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs +++ b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -226,7 +226,7 @@ fn rpc_eth_sign_transaction() { + &format!("\"raw\":\"0x{}\",", rlp.to_hex()) + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) - + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"type":"0x0","# + + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/types/block.rs b/crates/rpc/src/v1/types/block.rs index 5951e1a829..49c603fdeb 100644 --- a/crates/rpc/src/v1/types/block.rs +++ b/crates/rpc/src/v1/types/block.rs @@ -221,7 +221,7 @@ mod tests { let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( serialized, - r#"[{"type":"0x0","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}]"# + r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}]"# ); let t = BlockTransactions::Hashes(vec![H256::default().into()]); diff --git a/crates/rpc/src/v1/types/call_request.rs b/crates/rpc/src/v1/types/call_request.rs index dd7a637457..609686040d 100644 --- a/crates/rpc/src/v1/types/call_request.rs +++ b/crates/rpc/src/v1/types/call_request.rs @@ -26,9 +26,8 @@ use v1::{ #[serde(rename_all = "camelCase")] pub struct CallRequest { /// transaction type. Defaults to legacy type. - #[serde(default)] - #[serde(rename = "type")] - pub transaction_type: U64, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, /// From pub from: Option, /// To diff --git a/crates/rpc/src/v1/types/confirmations.rs b/crates/rpc/src/v1/types/confirmations.rs index 1dfbe78347..b489f354c4 100644 --- a/crates/rpc/src/v1/types/confirmations.rs +++ b/crates/rpc/src/v1/types/confirmations.rs @@ -349,7 +349,7 @@ mod tests { // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"type":"0x0","from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#; + let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); @@ -380,7 +380,7 @@ mod tests { // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"signTransaction":{"type":"0x0","from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#; + let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); diff --git a/crates/rpc/src/v1/types/receipt.rs b/crates/rpc/src/v1/types/receipt.rs index 64b6c696da..dd083aabeb 100644 --- a/crates/rpc/src/v1/types/receipt.rs +++ b/crates/rpc/src/v1/types/receipt.rs @@ -23,8 +23,8 @@ use v1::types::Log; #[serde(rename_all = "camelCase")] pub struct Receipt { /// Transaction Type - #[serde(rename = "type")] - pub transaction_type: U64, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, /// Transaction Hash pub transaction_hash: Option, /// Transaction index @@ -78,7 +78,7 @@ impl From for Receipt { Receipt { to: r.to.map(Into::into), from: Some(r.from), - transaction_type: U64::from(r.transaction_type as u8), + transaction_type: r.transaction_type.to_U64_option_id(), transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: Some(r.block_hash), @@ -99,7 +99,7 @@ impl From for Receipt { Receipt { from: Some(r.from), to: r.to.map(Into::into), - transaction_type: U64::from(r.transaction_type as u8), + transaction_type: r.transaction_type.to_U64_option_id(), transaction_hash: Some(r.transaction_hash), transaction_index: Some(r.transaction_index.into()), block_hash: None, @@ -117,7 +117,7 @@ impl From for Receipt { impl From for Receipt { fn from(r: TypedReceipt) -> Self { - let transaction_type = U64::from(r.tx_type() as u8); + let transaction_type = r.tx_type().to_U64_option_id(); let r = r.receipt().clone(); Receipt { from: None, @@ -141,16 +141,17 @@ impl From for Receipt { #[cfg(test)] mod tests { use serde_json; + use types::transaction::TypedTxId; use v1::types::{Log, Receipt}; #[test] fn receipt_serialization() { - let s = r#"{"type":"0x0","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","from":null,"to":null,"blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined","removed":false}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":"0x1"}"#; + let s = r#"{"type":"0x1","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","from":null,"to":null,"blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined","removed":false}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f","status":"0x1"}"#; let receipt = Receipt { from: None, to: None, - transaction_type: Default::default(), + transaction_type: TypedTxId::AccessList.to_U64_option_id(), transaction_hash: Some(0.into()), transaction_index: Some(0.into()), block_hash: Some( diff --git a/crates/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs index 42060097a4..954425723a 100644 --- a/crates/rpc/src/v1/types/transaction.rs +++ b/crates/rpc/src/v1/types/transaction.rs @@ -30,8 +30,8 @@ use v1::types::{AccessList, Bytes, TransactionCondition}; #[serde(rename_all = "camelCase")] pub struct Transaction { /// transaction type - #[serde(rename = "type")] - pub transaction_type: U64, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, /// Hash pub hash: H256, /// Nonce @@ -220,7 +220,7 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, - transaction_type: U64::from(t.signed.tx_type() as u8), + transaction_type: t.signed.tx_type().to_U64_option_id(), access_list, } } @@ -263,7 +263,7 @@ impl Transaction { r: signature.r().into(), s: signature.s().into(), condition: None, - transaction_type: U64::from(t.tx_type() as u8), + transaction_type: t.tx_type().to_U64_option_id(), access_list, } } @@ -303,7 +303,6 @@ impl LocalTransactionStatus { #[cfg(test)] mod tests { use super::{LocalTransactionStatus, Transaction}; - use ethereum_types::U64; use serde_json; use types::transaction::TypedTxId; use v1::types::AccessListItem; @@ -311,7 +310,7 @@ mod tests { #[test] fn test_transaction_serialize() { let mut t = Transaction::default(); - t.transaction_type = U64::from(TypedTxId::AccessList as u8); + t.transaction_type = TypedTxId::AccessList.to_U64_option_id(); t.access_list = Some(vec![AccessListItem::default()]); let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( diff --git a/crates/rpc/src/v1/types/transaction_request.rs b/crates/rpc/src/v1/types/transaction_request.rs index 9f5756f7b6..8aab53876c 100644 --- a/crates/rpc/src/v1/types/transaction_request.rs +++ b/crates/rpc/src/v1/types/transaction_request.rs @@ -31,9 +31,8 @@ use std::fmt; #[serde(rename_all = "camelCase")] pub struct TransactionRequest { /// type of transaction. Defaults to legacy type. - #[serde(default)] - #[serde(rename = "type")] - pub transaction_type: U64, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub transaction_type: Option, /// Sender pub from: Option, /// Recipient From d8ce175846e4a608f02a2e064f46b7b721719fc0 Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Wed, 17 Feb 2021 19:43:09 +0100 Subject: [PATCH 061/107] Fix modexp, update tests, update berlin chainspec (#267) --- .../res/chainspec/test/berlin_test.json | 106 +----------------- crates/ethcore/res/json_tests | 2 +- crates/vm/builtin/src/lib.rs | 28 +++-- 3 files changed, 21 insertions(+), 115 deletions(-) diff --git a/crates/ethcore/res/chainspec/test/berlin_test.json b/crates/ethcore/res/chainspec/test/berlin_test.json index 610684a3e9..1cc68c7b76 100644 --- a/crates/ethcore/res/chainspec/test/berlin_test.json +++ b/crates/ethcore/res/chainspec/test/berlin_test.json @@ -115,8 +115,10 @@ "name": "modexp", "activate_at": "0x00", "pricing": { - "modexp": { - "divisor": 20 + "0": { + "price": { + "modexp2565": {} + } } } } @@ -199,106 +201,6 @@ } } } - }, - "000000000000000000000000000000000000000a": { - "builtin": { - "name": "bls12_381_g1_add", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 600 - } - } - } - }, - "000000000000000000000000000000000000000b": { - "builtin": { - "name": "bls12_381_g1_mul", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 12000 - } - } - } - }, - "000000000000000000000000000000000000000c": { - "builtin": { - "name": "bls12_381_g1_multiexp", - "activate_at": "0", - "pricing": { - "bls12_g1_multiexp": { - "base": 12000 - } - } - } - }, - "000000000000000000000000000000000000000d": { - "builtin": { - "name": "bls12_381_g2_add", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 4500 - } - } - } - }, - "000000000000000000000000000000000000000e": { - "builtin": { - "name": "bls12_381_g2_mul", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 55000 - } - } - } - }, - "000000000000000000000000000000000000000f": { - "builtin": { - "name": "bls12_381_g2_multiexp", - "activate_at": "0", - "pricing": { - "bls12_g2_multiexp": { - "base": 55000 - } - } - } - }, - "0000000000000000000000000000000000000010": { - "builtin": { - "name": "bls12_381_pairing", - "activate_at": "0", - "pricing": { - "bls12_pairing": { - "base": 115000, - "pair": 23000 - } - } - } - }, - "0000000000000000000000000000000000000011": { - "builtin": { - "name": "bls12_381_fp_to_g1", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 5500 - } - } - } - }, - "0000000000000000000000000000000000000012": { - "builtin": { - "name": "bls12_381_fp2_to_g2", - "activate_at": "0", - "pricing": { - "bls12_const_operations": { - "price": 110000 - } - } - } } } } \ No newline at end of file diff --git a/crates/ethcore/res/json_tests b/crates/ethcore/res/json_tests index f55f344ad2..1508126ea0 160000 --- a/crates/ethcore/res/json_tests +++ b/crates/ethcore/res/json_tests @@ -1 +1 @@ -Subproject commit f55f344ad25cb97ebf4f3d72eca7a263aabde818 +Subproject commit 1508126ea04cd61495b60db2f036ac823de274b1 diff --git a/crates/vm/builtin/src/lib.rs b/crates/vm/builtin/src/lib.rs index 62caf5e381..5ba9247724 100644 --- a/crates/vm/builtin/src/lib.rs +++ b/crates/vm/builtin/src/lib.rs @@ -260,7 +260,7 @@ impl Pricer for Modexp2565Pricer { } bit_no -= 1; } - 0 + 1 } fn calculate_multiplication_complexity(base_len: u64, modulus_len: u64) -> f64 { @@ -283,17 +283,21 @@ impl Pricer for Modexp2565Pricer { let (base_len, exp_len, exp_low, mod_len) = ModexpPricer::parse_input(input); - if let Some(cost) = ModexpPricer::check_input_boundaries(&base_len, &exp_len, &mod_len) { - return cost; - } - - let (base_len, exp_len, mod_len) = - (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); - - let multiplication_complexity = calculate_multiplication_complexity(base_len, mod_len); - let iteration_count = calculate_iteration_count(exp_len, &exp_low); - let computed = (multiplication_complexity * iteration_count as f64 / 3f64).floor() as u64; - U256::from(std::cmp::max(200, computed)) + let cost = if let Some(cost) = + ModexpPricer::check_input_boundaries(&base_len, &exp_len, &mod_len) + { + cost + } else { + let (base_len, exp_len, mod_len) = + (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); + + let multiplication_complexity = calculate_multiplication_complexity(base_len, mod_len); + let iteration_count = calculate_iteration_count(exp_len, &exp_low); + let computed = + (multiplication_complexity * iteration_count as f64 / 3f64).floor() as u64; + U256::from(computed) + }; + std::cmp::max(U256::from(200), cost) } } From 98563b0a451aade6048a2ed940103cee107e4a9a Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 19 Feb 2021 12:52:24 +0100 Subject: [PATCH 062/107] Change ProtocolId to U64. yolo3x spec (#271) * Change ProtocolId to U64 and make it support variable subprotocol names* * Add yolo3x testnet --- bin/oe/run.rs | 10 ++++------ crates/ethcore/res/chainspec/yolo3.json | 13 ++++++++++--- crates/ethcore/sync/Cargo.toml | 1 - crates/ethcore/sync/src/api.rs | 10 +++++----- crates/ethcore/sync/src/chain/handler.rs | 4 ++-- crates/ethcore/sync/src/chain/mod.rs | 4 ++-- crates/ethcore/sync/src/sync_io.rs | 6 +++--- crates/ethcore/sync/src/tests/helpers.rs | 4 ++-- crates/net/network-devp2p/src/host.rs | 2 +- crates/net/network-devp2p/src/lib.rs | 12 +++++++----- crates/net/network-devp2p/src/session.rs | 10 +++++----- crates/net/network-devp2p/tests/tests.rs | 14 ++++++++++++-- crates/net/network/src/lib.rs | 19 ++++++------------- 13 files changed, 59 insertions(+), 50 deletions(-) diff --git a/bin/oe/run.rs b/bin/oe/run.rs index 59548bf700..e4eae651f7 100644 --- a/bin/oe/run.rs +++ b/bin/oe/run.rs @@ -34,7 +34,7 @@ use ethcore::{ }; use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore_service::ClientService; -use ethereum_types::H256; +use ethereum_types::{H256, U64}; use helpers::{execute_upgrades, passwords_from_files, to_client_config}; use informant::{FullNodeInformantData, Informant}; use journaldb::Algorithm; @@ -227,12 +227,10 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result id, None => spec.network_id(), }; - if spec.subprotocol_name().len() != 3 { - warn!("Your chain specification's subprotocol length is not 3. Ignoring."); + if spec.subprotocol_name().len() > 8 { + warn!("Your chain specification's subprotocol length is more then 8. Ignoring."); } else { - sync_config - .subprotocol_name - .clone_from_slice(spec.subprotocol_name().as_bytes()); + sync_config.subprotocol_name = U64::from(spec.subprotocol_name().as_bytes()) } sync_config.fork_block = spec.fork_block(); diff --git a/crates/ethcore/res/chainspec/yolo3.json b/crates/ethcore/res/chainspec/yolo3.json index d15c0a9d31..114de8c113 100644 --- a/crates/ethcore/res/chainspec/yolo3.json +++ b/crates/ethcore/res/chainspec/yolo3.json @@ -37,13 +37,14 @@ "maxCodeSizeTransition": "0x0", "maximumExtraDataSize": "0xffff", "minGasLimit": "0x1388", - "networkID": "133519467574835", + "networkID": "34180983699157880", + "chainID": "34180983699157880", "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" }, "genesis": { "author": "0x0000000000000000000000000000000000000000", "difficulty": "0x1", - "extraData": "0x00000000000000000000000000000000000000000000000000000000000000008a37866fd3627c9205a37c8685666f32ec07bb1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x00000000000000000000000000000000000000000000000000000000000000001041afbcb359d5a8dc58c15b2ff51354ff8a217d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gasLimit": "0x47b760", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "seal": { @@ -52,7 +53,7 @@ "nonce": "0x0000000000000000" } }, - "timestamp": "0x60117f8b" + "timestamp": "0x6027dd2e" }, "nodes": [ "enode://9e1096aa59862a6f164994cb5cb16f5124d6c992cdbf4535ff7dea43ea1512afe5448dca9df1b7ab0726129603f1a3336b631e4d7a1a44c94daddd03241587f9@3.9.20.133:30303" @@ -925,6 +926,9 @@ "0e89e2aedb1cfcdb9424d41a1f218f4132738172": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, + "1041afbcb359d5a8dc58c15b2ff51354ff8a217d": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, "60adc0f89a41af237ce73554ede170d733ec14e0": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" }, @@ -942,6 +946,9 @@ }, "b02a2eda1b317fbd16760128836b0ac59b560e9d": { "balance": "0x200000000000000000000000000000000000000000000000000000000000000" + }, + "df0a88b2b68c673713a8ec826003676f272e3573": { + "balance": "0x200000000000000000000000000000000000000000000000000000000000000" } } } diff --git a/crates/ethcore/sync/Cargo.toml b/crates/ethcore/sync/Cargo.toml index 590eab7826..5295370654 100644 --- a/crates/ethcore/sync/Cargo.toml +++ b/crates/ethcore/sync/Cargo.toml @@ -37,7 +37,6 @@ trace-time = "0.1" triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" } stats = { path = "../../util/stats" } - [dev-dependencies] env_logger = "0.5" ethcore = { path = "..", features = ["test-helpers"] } diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index 18d662597e..e5576aaebb 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -37,7 +37,7 @@ use ethcore::{ client::{BlockChainClient, ChainMessageType, ChainNotify, NewBlocks}, snapshot::SnapshotService, }; -use ethereum_types::{H256, H512, U256}; +use ethereum_types::{H256, H512, U256, U64}; use ethkey::Secret; use io::TimerToken; use network::IpFilter; @@ -55,9 +55,9 @@ use types::{ }; /// OpenEthereum sync protocol -pub const PAR_PROTOCOL: ProtocolId = *b"par"; +pub const PAR_PROTOCOL: ProtocolId = U64([0x706172]); // hexadecimal number of "par"; /// Ethereum sync protocol -pub const ETH_PROTOCOL: ProtocolId = *b"eth"; +pub const ETH_PROTOCOL: ProtocolId = U64([0x657468]); // hexadecimal number of "eth"; /// Determine warp sync status. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -104,7 +104,7 @@ pub struct SyncConfig { /// Network ID pub network_id: u64, /// Main "eth" subprotocol name. - pub subprotocol_name: [u8; 3], + pub subprotocol_name: ProtocolId, /// Fork block to check pub fork_block: Option<(BlockNumber, H256)>, /// Enable snapshot sync @@ -230,7 +230,7 @@ pub struct EthSync { /// Main (eth/par) protocol handler eth_handler: Arc, /// The main subprotocol name - subprotocol_name: [u8; 3], + subprotocol_name: ProtocolId, /// Priority tasks notification channel priority_tasks: Mutex>, } diff --git a/crates/ethcore/sync/src/chain/handler.rs b/crates/ethcore/sync/src/chain/handler.rs index 029c6659d2..a37eb862bf 100644 --- a/crates/ethcore/sync/src/chain/handler.rs +++ b/crates/ethcore/sync/src/chain/handler.rs @@ -669,8 +669,8 @@ impl SyncHandler { .next() .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; - let _eth_protocol_version = io.protocol_version(Ð_PROTOCOL, peer_id); - let warp_protocol_version = io.protocol_version(&PAR_PROTOCOL, peer_id); + let _eth_protocol_version = io.protocol_version(ETH_PROTOCOL, peer_id); + let warp_protocol_version = io.protocol_version(PAR_PROTOCOL, peer_id); let warp_protocol = warp_protocol_version != 0; let network_id = r_iter diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index 4536ad2fea..60596233ee 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -1272,8 +1272,8 @@ impl ChainSync { /// Send Status message fn send_status(&mut self, io: &mut dyn SyncIo, peer: PeerId) -> Result<(), network::Error> { - let eth_protocol_version = io.protocol_version(Ð_PROTOCOL, peer); - let warp_protocol_version = io.protocol_version(&PAR_PROTOCOL, peer); + let eth_protocol_version = io.protocol_version(ETH_PROTOCOL, peer); + let warp_protocol_version = io.protocol_version(PAR_PROTOCOL, peer); let warp_protocol = warp_protocol_version != 0; let protocol = if warp_protocol { warp_protocol_version diff --git a/crates/ethcore/sync/src/sync_io.rs b/crates/ethcore/sync/src/sync_io.rs index 92c47a635b..fd811e469e 100644 --- a/crates/ethcore/sync/src/sync_io.rs +++ b/crates/ethcore/sync/src/sync_io.rs @@ -47,7 +47,7 @@ pub trait SyncIo { /// Returns information on p2p session fn peer_session_info(&self, peer_id: PeerId) -> Option; /// Maximum mutually supported version of a gien protocol. - fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8; + fn protocol_version(&self, protocol: ProtocolId, peer_id: PeerId) -> u8; /// Returns if the chain block queue empty fn is_chain_queue_empty(&self) -> bool { self.chain().is_queue_empty() @@ -121,9 +121,9 @@ impl<'s> SyncIo for NetSyncIo<'s> { self.network.is_expired() } - fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8 { + fn protocol_version(&self, protocol: ProtocolId, peer_id: PeerId) -> u8 { self.network - .protocol_version(*protocol, peer_id) + .protocol_version(protocol, peer_id) .unwrap_or(0) } diff --git a/crates/ethcore/sync/src/tests/helpers.rs b/crates/ethcore/sync/src/tests/helpers.rs index 105e4760d8..4beb7d1f1d 100644 --- a/crates/ethcore/sync/src/tests/helpers.rs +++ b/crates/ethcore/sync/src/tests/helpers.rs @@ -168,8 +168,8 @@ where None } - fn protocol_version(&self, protocol: &ProtocolId, _peer_id: PeerId) -> u8 { - if protocol == &PAR_PROTOCOL { + fn protocol_version(&self, protocol: ProtocolId, _peer_id: PeerId) -> u8 { + if protocol == PAR_PROTOCOL { PAR_PROTOCOL_VERSION_2.0 } else { ETH_PROTOCOL_VERSION_64.0 diff --git a/crates/net/network-devp2p/src/host.rs b/crates/net/network-devp2p/src/host.rs index e82aa4ceef..cb36da9a90 100644 --- a/crates/net/network-devp2p/src/host.rs +++ b/crates/net/network-devp2p/src/host.rs @@ -95,7 +95,7 @@ pub struct CapabilityInfo { impl Encodable for CapabilityInfo { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(2); - s.append(&&self.protocol[..]); + s.append(&self.protocol.as_u64()); s.append(&self.version); } } diff --git a/crates/net/network-devp2p/src/lib.rs b/crates/net/network-devp2p/src/lib.rs index 47d9018a50..5b955ea45f 100644 --- a/crates/net/network-devp2p/src/lib.rs +++ b/crates/net/network-devp2p/src/lib.rs @@ -21,27 +21,29 @@ //! ```rust //! extern crate ethcore_network as net; //! extern crate ethcore_network_devp2p as devp2p; +//! extern crate ethereum_types as types; //! use net::*; //! use devp2p::NetworkService; //! use std::sync::Arc; //! use std::time::Duration; +//! use types::U64; //! //! struct MyHandler; //! //! impl NetworkProtocolHandler for MyHandler { -//! fn initialize(&self, io: &NetworkContext) { +//! fn initialize(&self, io: &dyn NetworkContext) { //! io.register_timer(0, Duration::from_secs(1)); //! } //! -//! fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { +//! fn read(&self, io: &dyn NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { //! println!("Received {} ({} bytes) from {}", packet_id, data.len(), peer); //! } //! -//! fn connected(&self, io: &NetworkContext, peer: &PeerId) { +//! fn connected(&self, io: &dyn NetworkContext, peer: &PeerId) { //! println!("Connected {}", peer); //! } //! -//! fn disconnected(&self, io: &NetworkContext, peer: &PeerId) { +//! fn disconnected(&self, io: &dyn NetworkContext, peer: &PeerId) { //! println!("Disconnected {}", peer); //! } //! } @@ -49,7 +51,7 @@ //! fn main () { //! let mut service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service"); //! service.start().expect("Error starting service"); -//! service.register_protocol(Arc::new(MyHandler), *b"myp", &[(1u8, 1u8)]); +//! service.register_protocol(Arc::new(MyHandler), U64::from(0x000aaa00), &[(1u8, 1u8)]); //! //! // Wait for quit condition //! // ... diff --git a/crates/net/network-devp2p/src/session.rs b/crates/net/network-devp2p/src/session.rs index e6e0188960..80539be3d2 100644 --- a/crates/net/network-devp2p/src/session.rs +++ b/crates/net/network-devp2p/src/session.rs @@ -87,7 +87,7 @@ pub enum SessionData { /// Packet data data: Vec, /// Packet protocol ID - protocol: [u8; 3], + protocol: ProtocolId, /// Zero based packet ID packet_id: u8, }, @@ -255,7 +255,7 @@ impl Session { } /// Checks if peer supports given capability - pub fn have_capability(&self, protocol: [u8; 3]) -> bool { + pub fn have_capability(&self, protocol: ProtocolId) -> bool { self.info .capabilities .iter() @@ -263,7 +263,7 @@ impl Session { } /// Checks if peer supports given capability - pub fn capability_version(&self, protocol: [u8; 3]) -> Option { + pub fn capability_version(&self, protocol: ProtocolId) -> Option { self.info .capabilities .iter() @@ -313,7 +313,7 @@ impl Session { pub fn send_packet( &mut self, io: &IoContext, - protocol: Option<[u8; 3]>, + protocol: Option, packet_id: u8, data: &[u8], ) -> Result<(), Error> @@ -321,7 +321,7 @@ impl Session { Message: Send + Sync + Clone, { if protocol.is_some() && (self.info.capabilities.is_empty() || !self.had_hello) { - debug!(target: "network", "Sending to unconfirmed session {}, protocol: {:?}, packet: {}", self.token(), protocol.as_ref().map(|p| str::from_utf8(&p[..]).unwrap_or("??")), packet_id); + debug!(target: "network", "Sending to unconfirmed session {}, protocol: {:?}, packet: {}", self.token(), protocol.map(|p| str::from_utf8(&p.as_u64().to_ne_bytes()).unwrap_or("??").to_string()), packet_id); bail!(ErrorKind::BadProtocol); } if self.expired() { diff --git a/crates/net/network-devp2p/tests/tests.rs b/crates/net/network-devp2p/tests/tests.rs index 426d0d9404..ab97c2c157 100644 --- a/crates/net/network-devp2p/tests/tests.rs +++ b/crates/net/network-devp2p/tests/tests.rs @@ -18,12 +18,14 @@ extern crate env_logger; extern crate ethcore_io as io; extern crate ethcore_network; extern crate ethcore_network_devp2p; +extern crate ethereum_types; extern crate ethkey; extern crate parity_bytes; extern crate parking_lot; use ethcore_network::*; use ethcore_network_devp2p::NetworkService; +use ethereum_types::U64; use ethkey::{Generator, Random}; use io::TimerToken; use parity_bytes::Bytes; @@ -57,7 +59,11 @@ impl TestProtocol { pub fn register(service: &mut NetworkService, drop_session: bool) -> Arc { let handler = Arc::new(TestProtocol::new(drop_session)); service - .register_protocol(handler.clone(), *b"tst", &[(42u8, 1u8), (43u8, 1u8)]) + .register_protocol( + handler.clone(), + U64::from(0x000aaa00), + &[(42u8, 1u8), (43u8, 1u8)], + ) .expect("Error registering test protocol handler"); handler } @@ -111,7 +117,11 @@ fn net_service() { .expect("Error creating network service"); service.start().unwrap(); service - .register_protocol(Arc::new(TestProtocol::new(false)), *b"myp", &[(1u8, 1u8)]) + .register_protocol( + Arc::new(TestProtocol::new(false)), + U64::from(0x000aff00), + &[(1u8, 1u8)], + ) .unwrap(); } diff --git a/crates/net/network/src/lib.rs b/crates/net/network/src/lib.rs index ecf30b86d8..5c0f40a6a6 100644 --- a/crates/net/network/src/lib.rs +++ b/crates/net/network/src/lib.rs @@ -50,7 +50,7 @@ pub use error::{DisconnectReason, Error, ErrorKind}; pub use io::TimerToken; use client_version::ClientVersion; -use ethereum_types::H512; +use ethereum_types::{H512, U64}; use ethkey::Secret; use ipnetwork::{IpNetwork, IpNetworkError}; use rlp::{Decodable, DecoderError, Rlp}; @@ -66,7 +66,7 @@ use std::{ /// Protocol handler level packet id pub type PacketId = u8; /// Protocol / handler id -pub type ProtocolId = [u8; 3]; +pub type ProtocolId = U64; /// Node public key pub type NodeId = H512; @@ -136,16 +136,9 @@ pub struct PeerCapabilityInfo { impl Decodable for PeerCapabilityInfo { fn decode(rlp: &Rlp) -> Result { - let p: Vec = rlp.val_at(0)?; - if p.len() != 3 { - return Err(DecoderError::Custom( - "Invalid subprotocol string length. Should be 3", - )); - } - let mut p2: ProtocolId = [0u8; 3]; - p2.clone_from_slice(&p); + let p: u64 = rlp.val_at(0)?; Ok(PeerCapabilityInfo { - protocol: p2, + protocol: U64::from(p), version: rlp.val_at(1)?, }) } @@ -155,7 +148,7 @@ impl ToString for PeerCapabilityInfo { fn to_string(&self) -> String { format!( "{}/{}", - str::from_utf8(&self.protocol[..]).unwrap_or("???"), + str::from_utf8(&self.protocol.as_u64().to_ne_bytes()).unwrap_or("???"), self.version ) } @@ -163,7 +156,7 @@ impl ToString for PeerCapabilityInfo { #[derive(Debug, Clone, PartialEq, Eq)] pub struct SessionCapabilityInfo { - pub protocol: [u8; 3], + pub protocol: ProtocolId, pub version: u8, pub packet_count: u8, pub id_offset: u8, From d5c2a0fbe2204f88da808085190c173d2f43a96a Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 23 Feb 2021 13:46:08 +0100 Subject: [PATCH 063/107] Fix for TypedTx enabling and hash generation. Tweak sig V in RPC. (#272) * Fix for TypedTx hash generation from RlpView * Tweaks on sig V field in RPC * Fix for eip2930 incomming tx --- crates/ethcore/src/json_tests/local.rs | 2 +- crates/ethcore/src/machine/impls.rs | 2 +- .../types/src/transaction/transaction.rs | 12 ++++++-- crates/ethcore/types/src/views/block.rs | 3 +- crates/ethcore/types/src/views/body.rs | 3 +- crates/rpc/src/v1/tests/mocked/signer.rs | 2 +- crates/rpc/src/v1/tests/mocked/signing.rs | 2 +- .../rpc/src/v1/tests/mocked/signing_unsafe.rs | 2 +- crates/rpc/src/v1/types/block.rs | 2 +- crates/rpc/src/v1/types/transaction.rs | 28 ++++++++++++++----- 10 files changed, 41 insertions(+), 17 deletions(-) diff --git a/crates/ethcore/src/json_tests/local.rs b/crates/ethcore/src/json_tests/local.rs index 79c239dad5..ebbf252530 100644 --- a/crates/ethcore/src/json_tests/local.rs +++ b/crates/ethcore/src/json_tests/local.rs @@ -146,7 +146,7 @@ pub fn is_same_block(ref_block: &Block, block: &Unverified) -> bool { is_ok = is_ok && match ttype { TypedTxId::Legacy => { - test_exp(tx.original_v() == ref_tx.v.0.as_u64(), "Original Sig V") + test_exp(tx.legacy_v() == ref_tx.v.0.as_u64(), "Original Sig V") } TypedTxId::AccessList => { test_exp(tx.standard_v() as u64 == ref_tx.v.0.as_u64(), "Sig V"); diff --git a/crates/ethcore/src/machine/impls.rs b/crates/ethcore/src/machine/impls.rs index 5bfaba1d33..b11a463b22 100644 --- a/crates/ethcore/src/machine/impls.rs +++ b/crates/ethcore/src/machine/impls.rs @@ -469,7 +469,7 @@ impl EthereumMachine { .map_err(|e| transaction::Error::InvalidRlp(e.to_string()))?; match tx.tx_type() { - transaction::TypedTxId::AccessList if schedule.eip2930 => { + transaction::TypedTxId::AccessList if !schedule.eip2930 => { return Err(transaction::Error::TransactionTypeNotEnabled) } _ => (), diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 6a8b0b94da..66f477fd90 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -735,11 +735,19 @@ impl UnverifiedTransaction { self.signature.standard_v } - /// The `v` value that appears in the RLP. - pub fn original_v(&self) -> u64 { + /// The legacy `v` value that contains signatures v and chain_id for replay protection. + pub fn legacy_v(&self) -> u64 { signature::add_chain_replay_protection(self.signature.standard_v, self.chain_id) } + /// The `v` value that appears in the RLP. + pub fn v(&self) -> u64 { + match self.unsigned { + TypedTransaction::Legacy(_) => self.legacy_v(), + _ => self.signature.standard_v as u64, + } + } + /// The chain ID, or `None` if this is a global transaction. pub fn chain_id(&self) -> Option { self.chain_id diff --git a/crates/ethcore/types/src/views/block.rs b/crates/ethcore/types/src/views/block.rs index e540d0a380..7b3b3e44d6 100644 --- a/crates/ethcore/types/src/views/block.rs +++ b/crates/ethcore/types/src/views/block.rs @@ -125,7 +125,8 @@ impl<'a> BlockView<'a> { pub fn transaction_hashes(&self) -> Vec { self.transactions_rlp() .iter() - .map(|rlp| keccak(rlp.as_raw())) + .map(TypedTransactionView::new) + .map(|t| t.hash()) .collect() } diff --git a/crates/ethcore/types/src/views/body.rs b/crates/ethcore/types/src/views/body.rs index 055a54f5ee..3bdf7f2743 100644 --- a/crates/ethcore/types/src/views/body.rs +++ b/crates/ethcore/types/src/views/body.rs @@ -106,7 +106,8 @@ impl<'a> BodyView<'a> { pub fn transaction_hashes(&self) -> Vec { self.transactions_rlp() .iter() - .map(|rlp| keccak(rlp.as_raw())) + .map(TypedTransactionView::new) + .map(|t| t.hash()) .collect() } diff --git a/crates/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs index 6c0bcee84f..58dc1232f4 100644 --- a/crates/rpc/src/v1/tests/mocked/signer.rs +++ b/crates/rpc/src/v1/tests/mocked/signer.rs @@ -638,7 +638,7 @@ fn should_confirm_sign_transaction_with_rlp() { + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# - + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + + &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + r#""value":"0x1""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/tests/mocked/signing.rs b/crates/rpc/src/v1/tests/mocked/signing.rs index fdeb9b4963..dd7ae5a9b2 100644 --- a/crates/rpc/src/v1/tests/mocked/signing.rs +++ b/crates/rpc/src/v1/tests/mocked/signing.rs @@ -419,7 +419,7 @@ fn should_add_sign_transaction_to_the_queue() { + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# - + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + + &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs index c52127736f..088c95b83f 100644 --- a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs +++ b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -227,7 +227,7 @@ fn rpc_eth_sign_transaction() { + &format!("\"s\":\"0x{:x}\",", U256::from(signature.s())) + &format!("\"standardV\":\"0x{:x}\",", U256::from(t.standard_v())) + r#""to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","transactionIndex":null,"# - + &format!("\"v\":\"0x{:x}\",", U256::from(t.original_v())) + + &format!("\"v\":\"0x{:x}\",", U256::from(t.v())) + r#""value":"0x9184e72a""# + r#"}},"id":1}"#; diff --git a/crates/rpc/src/v1/types/block.rs b/crates/rpc/src/v1/types/block.rs index 49c603fdeb..0a620dc25c 100644 --- a/crates/rpc/src/v1/types/block.rs +++ b/crates/rpc/src/v1/types/block.rs @@ -221,7 +221,7 @@ mod tests { let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( serialized, - r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}]"# + r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"v":"0x0","r":"0x0","s":"0x0","condition":null}]"# ); let t = BlockTransactions::Hashes(vec![H256::default().into()]); diff --git a/crates/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs index 954425723a..14f7608e7a 100644 --- a/crates/rpc/src/v1/types/transaction.rs +++ b/crates/rpc/src/v1/types/transaction.rs @@ -22,6 +22,7 @@ use miner; use serde::{ser::SerializeStruct, Serialize, Serializer}; use types::transaction::{ Action, LocalizedTransaction, PendingTransaction, SignedTransaction, TypedTransaction, + TypedTxId, }; use v1::types::{AccessList, Bytes, TransactionCondition}; @@ -62,8 +63,9 @@ pub struct Transaction { pub public_key: Option, /// The network id of the transaction, if any. pub chain_id: Option, - /// The standardised V field of the signature (0 or 1). - pub standard_v: U256, + /// The standardised V field of the signature (0 or 1). Used by legacy transaction + #[serde(skip_serializing_if = "Option::is_none")] + pub standard_v: Option, /// The standardised V field of the signature. pub v: U256, /// The R field of the signature. @@ -191,6 +193,12 @@ impl Transaction { None }; + let standard_v = if t.tx_type() == TypedTxId::Legacy { + Some(t.standard_v()) + } else { + None + }; + Transaction { hash: t.hash(), nonce: t.tx().nonce, @@ -215,8 +223,8 @@ impl Transaction { raw: Bytes::new(t.signed.encode()), public_key: t.recover_public().ok().map(Into::into), chain_id: t.chain_id().map(U64::from), - standard_v: t.standard_v().into(), - v: t.original_v().into(), + standard_v: standard_v.map(Into::into), + v: t.v().into(), r: signature.r().into(), s: signature.s().into(), condition: None, @@ -234,6 +242,12 @@ impl Transaction { } else { None }; + let standard_v = if t.tx_type() == TypedTxId::Legacy { + Some(t.standard_v()) + } else { + None + }; + Transaction { hash: t.hash(), nonce: t.tx().nonce, @@ -258,8 +272,8 @@ impl Transaction { raw: t.encode().into(), public_key: t.public_key().map(Into::into), chain_id: t.chain_id().map(U64::from), - standard_v: t.standard_v().into(), - v: t.original_v().into(), + standard_v: standard_v.map(Into::into), + v: t.v().into(), r: signature.r().into(), s: signature.s().into(), condition: None, @@ -315,7 +329,7 @@ mod tests { let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( serialized, - r#"{"type":"0x1","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null,"accessList":[{"address":"0x0000000000000000000000000000000000000000","storageKeys":[]}]}"# + r#"{"type":"0x1","hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"v":"0x0","r":"0x0","s":"0x0","condition":null,"accessList":[{"address":"0x0000000000000000000000000000000000000000","storageKeys":[]}]}"# ); } From 0bb2f8f6b816a5d22f11e016354fde1d6dd4fe90 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Tue, 23 Feb 2021 13:44:09 +0100 Subject: [PATCH 064/107] Berlin hardfork blocks --- crates/ethcore/res/chainspec/foundation.json | 21 +++++++++++++++---- crates/ethcore/res/chainspec/goerli.json | 19 ++++++++++++++--- crates/ethcore/res/chainspec/rinkeby.json | 19 ++++++++++++++--- crates/ethcore/res/chainspec/ropsten.json | 22 ++++++++++++++++---- crates/ethcore/sync/src/chain/fork_filter.rs | 15 +++++++++---- 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/crates/ethcore/res/chainspec/foundation.json b/crates/ethcore/res/chainspec/foundation.json index 5af92bec2e..991fe18f57 100644 --- a/crates/ethcore/res/chainspec/foundation.json +++ b/crates/ethcore/res/chainspec/foundation.json @@ -166,10 +166,13 @@ "eip1014Transition": "0x6f1580", "eip1052Transition": "0x6f1580", "eip1283Transition": "0x8a61c8", + "eip1344Transition": "0x8a61c8", "eip1706Transition": "0x8a61c8", "eip1884Transition": "0x8a61c8", "eip2028Transition": "0x8a61c8", - "eip1344Transition": "0x8a61c8" + "eip2315Transition": "0xbad420", + "eip2929Transition": "0xbad420", + "eip2930Transition": "0xbad420" }, "genesis": { "seal": { @@ -251,10 +254,20 @@ "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", - "activate_at": "0x42ae50", "pricing": { - "modexp": { - "divisor": 20 + "0x42ae50": { + "info": "EIP-198: Big integer modular exponentiation. Byzantium hardfork (4_370_000)", + "price": { + "modexp": { + "divisor": 20 + } + } + }, + "0xbad420": { + "info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (12_244_000)", + "price": { + "modexp2565": {} + } } } } diff --git a/crates/ethcore/res/chainspec/goerli.json b/crates/ethcore/res/chainspec/goerli.json index b3ab53730f..01f71a24ac 100644 --- a/crates/ethcore/res/chainspec/goerli.json +++ b/crates/ethcore/res/chainspec/goerli.json @@ -31,6 +31,9 @@ "eip1706Transition": "0x17d433", "eip1884Transition": "0x17d433", "eip2028Transition": "0x17d433", + "eip2315Transition": "0x441064", + "eip2929Transition": "0x441064", + "eip2930Transition": "0x441064", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", "maxCodeSizeTransition": "0x0", @@ -118,10 +121,20 @@ "balance": "0x1", "builtin": { "name": "modexp", - "activate_at": "0x0", "pricing": { - "modexp": { - "divisor": 20 + "0x0": { + "info": "EIP-198: Big integer modular exponentiation. Byzantium hardfork", + "price": { + "modexp": { + "divisor": 20 + } + } + }, + "0x441064": { + "info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (4_460_644)", + "price": { + "modexp2565": {} + } } } } diff --git a/crates/ethcore/res/chainspec/rinkeby.json b/crates/ethcore/res/chainspec/rinkeby.json index ee02408f6c..8a0c59df41 100644 --- a/crates/ethcore/res/chainspec/rinkeby.json +++ b/crates/ethcore/res/chainspec/rinkeby.json @@ -31,6 +31,9 @@ "eip1706Transition": "0x52efd1", "eip1884Transition": "0x52efd1", "eip2028Transition": "0x52efd1", + "eip2315Transition": "0x7e8270", + "eip2929Transition": "0x7e8270", + "eip2930Transition": "0x7e8270", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", "maxCodeSizeTransition": "0x0", @@ -113,10 +116,20 @@ "balance": "0x1", "builtin": { "name": "modexp", - "activate_at": "0xfcc25", "pricing": { - "modexp": { - "divisor": 20 + "0xfcc25": { + "info": "EIP-198: Big integer modular exponentiation. Byzantium hardfork (1_035_301)", + "price": { + "modexp": { + "divisor": 20 + } + } + }, + "0x7e8270": { + "info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (8_290_928)", + "price": { + "modexp2565": {} + } } } } diff --git a/crates/ethcore/res/chainspec/ropsten.json b/crates/ethcore/res/chainspec/ropsten.json index f76cbce3c4..5c7a7a4ed4 100644 --- a/crates/ethcore/res/chainspec/ropsten.json +++ b/crates/ethcore/res/chainspec/ropsten.json @@ -51,7 +51,11 @@ "eip1344Transition": "0x62f756", "eip1706Transition": "0x62f756", "eip1884Transition": "0x62f756", - "eip2028Transition": "0x62f756" + "eip2028Transition": "0x62f756", + "eip2315Transition": "0x95b8dd", + "eip2929Transition": "0x95b8dd", + "eip2930Transition": "0x95b8dd" + }, "genesis": { "seal": { @@ -135,10 +139,20 @@ "nonce": "0x0", "builtin": { "name": "modexp", - "activate_at": "0x19f0a0", "pricing": { - "modexp": { - "divisor": 20 + "0x19f0a0": { + "info": "EIP-198: Big integer modular exponentiation. Byzantium hardfork (1_700_000)", + "price": { + "modexp": { + "divisor": 20 + } + } + }, + "0x95b8dd": { + "info": "EIP-2565: ModExp Gas Cost. Berlin hardfork (9_812_189)", + "price": { + "modexp2565": {} + } } } } diff --git a/crates/ethcore/sync/src/chain/fork_filter.rs b/crates/ethcore/sync/src/chain/fork_filter.rs index b813cbff5f..9baf95d84f 100644 --- a/crates/ethcore/sync/src/chain/fork_filter.rs +++ b/crates/ethcore/sync/src/chain/fork_filter.rs @@ -86,7 +86,7 @@ mod tests { || ethereum::new_foundation(&String::new()), vec![ 1_150_000, 1_920_000, 2_463_000, 2_675_000, 4_370_000, 7_280_000, 9_069_000, - 9_200_000, + 9_200_000, 12_244_000, ], ) } @@ -95,7 +95,9 @@ mod tests { fn ropsten_spec() { test_spec( || ethereum::new_ropsten(&String::new()), - vec![10, 1_700_000, 4_230_000, 4_939_394, 6_485_846, 7_117_117], + vec![ + 10, 1_700_000, 4_230_000, 4_939_394, 6_485_846, 7_117_117, 9_812_189, + ], ) } @@ -103,12 +105,17 @@ mod tests { fn rinkeby_spec() { test_spec( || ethereum::new_rinkeby(&String::new()), - vec![1, 2, 3, 1_035_301, 3_660_663, 4_321_234, 5_435_345], + vec![ + 1, 2, 3, 1_035_301, 3_660_663, 4_321_234, 5_435_345, 8_290_928, + ], ) } #[test] fn goerli_spec() { - test_spec(|| ethereum::new_goerli(&String::new()), vec![1_561_651]) + test_spec( + || ethereum::new_goerli(&String::new()), + vec![1_561_651, 4_460_644], + ) } } From f1dc6821689c7f47d8fd07dfc0a2c5ad557b98ec Mon Sep 17 00:00:00 2001 From: draganrakita Date: Tue, 23 Feb 2021 16:44:55 +0100 Subject: [PATCH 065/107] Bump to 3.2.0-rc.1 --- CHANGELOG.md | 65 +++++++--------------------------- Cargo.lock | 4 +-- Cargo.toml | 2 +- crates/util/version/Cargo.toml | 2 +- docs/CHANGELOG-3.1.md | 56 +++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 docs/CHANGELOG-3.1.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 08cabf8ed4..cda2d5f1d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,56 +1,15 @@ -## OpenEthereum v3.1.1 +## OpenEthereum v3.2.0-rc.1 Bug fixes: -* Ancient target set. InvalidStateRoot bug (#69) (#149) -* Update linked-hash-map to 0.5.3 - +* Update EWF's chains with Istanbul transition block numbers (#11482) (#254) +* fix Supplied instant is later than self (#169) + Enhancements: -* Added additional Sg-1,Ca-2,Ca-3 OE bootnodes -* Add --ws-max-paxload (#155) -* Add flag to disable storage output in openethereum-evm tool #97 (#115) -* ethstore - remove unnecessary dir & tiny-keccak dependencies from the lib (#107) -* Sync block verification (#74) -* Add `wasmDisableTransition` spec option (#60) -* EIP2929 with journaling + Yolov3 (#79) -* EIP2565 impl (#82) -* TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135) - -DevOps: -* Add custom windows runner (#162) -* Remove sscache (#138) -* Fix deprecated set-env declaration (#106) - - -## OpenEthereum v3.1.0 - -OpenEthereum 3.1.0 is a release based on v2.5.13 which is the last stable version known of the client that does not include any of the issues introduced in v2.7. It removes non core features like Ethereum Classic, Private Transactions, Light Client, Updater, IPFS and Swarm support, currently deprecated flags such as expanse, kotti, mordor testnets. - -Database migration utility currently in beta: https://github.com/openethereum/3.1-db-upgrade-tool - -The full list of included changes from v2.5.13 to v3.1.0: - -* Use ubuntu-16.04 for glibc compatibility (#11888) (#73) -* Remove classic, kotti, mordor, expanse (#52) -* Added bad block header hash for ropsten (#49) -* Remove accounts bloom (#33) -* Bump jsonrpc-- to v15 -* Implement eth/64, remove eth/62 (#46) -* No snapshotting by default (#11814) -* Update Ellaism chainspec -* Prometheus, heavy memory calls removed (#27) -* Update ethereum/tests -* Implement JSON test suite (#11801) -* Fix issues during block sync (#11265) -* Fix race same block (#11400) -* EIP-2537: Precompile for BLS12-381 curve operations (#11707) -* Remove private transactions -* Remove GetNodeData -* Remove IPFS integration (#11532) -* Remove updater -* Remove light client -* Remove C and Java bindings (#11346) -* Remove whisper (#10855) -* EIP-2315: Simple Subroutines for the EVM (#11629) -* Remove deprecated flags (removal of --geth flag) -* Remove support for hardware wallets (#10678) -* Update bootnodes +* Berlin hardfork blocks: mainnet (12,244,000), goerli (4,460,644), rinkeby (8,290,928) and ropsten (9,812,189) +* yolo3x spec (#241) +* EIP-2930 RPC support +* Remove eth/63 protocol version (#252) +* Snapshot manifest block added to prometheus (#232) +* EIP-1898: Allow default block parameter to be blockHash +* Change ProtocolId to U64 +* Update ethereum/tests \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 56afaddccc..460fd08c93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2824,7 +2824,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openethereum" -version = "3.1.1" +version = "3.2.0-rc.1" dependencies = [ "ansi_term 0.10.2", "atty", @@ -3187,7 +3187,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "3.1.1" +version = "3.2.0-rc.1" dependencies = [ "parity-bytes", "rlp 0.3.0", diff --git a/Cargo.toml b/Cargo.toml index a9106e73e6..5035c20d92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "OpenEthereum" name = "openethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "3.1.1" +version = "3.2.0-rc.1" license = "GPL-3.0" authors = [ "OpenEthereum developers", diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index 8e67657f9e..83d92c6757 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "parity-version" # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) -version = "3.1.1" +version = "3.2.0-rc.1" authors = ["Parity Technologies "] build = "build.rs" diff --git a/docs/CHANGELOG-3.1.md b/docs/CHANGELOG-3.1.md new file mode 100644 index 0000000000..08cabf8ed4 --- /dev/null +++ b/docs/CHANGELOG-3.1.md @@ -0,0 +1,56 @@ +## OpenEthereum v3.1.1 + +Bug fixes: +* Ancient target set. InvalidStateRoot bug (#69) (#149) +* Update linked-hash-map to 0.5.3 + +Enhancements: +* Added additional Sg-1,Ca-2,Ca-3 OE bootnodes +* Add --ws-max-paxload (#155) +* Add flag to disable storage output in openethereum-evm tool #97 (#115) +* ethstore - remove unnecessary dir & tiny-keccak dependencies from the lib (#107) +* Sync block verification (#74) +* Add `wasmDisableTransition` spec option (#60) +* EIP2929 with journaling + Yolov3 (#79) +* EIP2565 impl (#82) +* TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135) + +DevOps: +* Add custom windows runner (#162) +* Remove sscache (#138) +* Fix deprecated set-env declaration (#106) + + +## OpenEthereum v3.1.0 + +OpenEthereum 3.1.0 is a release based on v2.5.13 which is the last stable version known of the client that does not include any of the issues introduced in v2.7. It removes non core features like Ethereum Classic, Private Transactions, Light Client, Updater, IPFS and Swarm support, currently deprecated flags such as expanse, kotti, mordor testnets. + +Database migration utility currently in beta: https://github.com/openethereum/3.1-db-upgrade-tool + +The full list of included changes from v2.5.13 to v3.1.0: + +* Use ubuntu-16.04 for glibc compatibility (#11888) (#73) +* Remove classic, kotti, mordor, expanse (#52) +* Added bad block header hash for ropsten (#49) +* Remove accounts bloom (#33) +* Bump jsonrpc-- to v15 +* Implement eth/64, remove eth/62 (#46) +* No snapshotting by default (#11814) +* Update Ellaism chainspec +* Prometheus, heavy memory calls removed (#27) +* Update ethereum/tests +* Implement JSON test suite (#11801) +* Fix issues during block sync (#11265) +* Fix race same block (#11400) +* EIP-2537: Precompile for BLS12-381 curve operations (#11707) +* Remove private transactions +* Remove GetNodeData +* Remove IPFS integration (#11532) +* Remove updater +* Remove light client +* Remove C and Java bindings (#11346) +* Remove whisper (#10855) +* EIP-2315: Simple Subroutines for the EVM (#11629) +* Remove deprecated flags (removal of --geth flag) +* Remove support for hardware wallets (#10678) +* Update bootnodes From 1d2b640834a015db9b92fc4b3401c922095b1612 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 24 Feb 2021 22:10:33 +0100 Subject: [PATCH 066/107] chocolate -y confirmation steps --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9dda2d4aa8..e10ff88f0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,7 @@ jobs: - name: Install LLVM for Windows if: matrix.platform == 'windows2019' - run: choco install llvm + run: choco install llvm -y - name: Build OpenEthereum for Windows if: matrix.platform == 'windows2019' From 142b63a4f9516552b8048faf50e05d5dd730022b Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 25 Feb 2021 17:04:21 +0100 Subject: [PATCH 067/107] Backport github actions from old main --- .github/workflows/build-test-windows.yml | 33 -------- .github/workflows/build.yml | 102 +++++++++++------------ .github/workflows/check.yml | 4 +- .github/workflows/deploy-docker.yml | 30 +++++++ 4 files changed, 83 insertions(+), 86 deletions(-) delete mode 100644 .github/workflows/build-test-windows.yml create mode 100644 .github/workflows/deploy-docker.yml diff --git a/.github/workflows/build-test-windows.yml b/.github/workflows/build-test-windows.yml deleted file mode 100644 index a3983eec3f..0000000000 --- a/.github/workflows/build-test-windows.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Build and Test Suite on Windows - -on: - push: - branches: - - main - - dev -jobs: - build-tests: - name: Test and Build - strategy: - matrix: - platform: - - windows2019 # custom runner - toolchain: - - stable - runs-on: ${{ matrix.platform }} - steps: - - name: Checkout sources - uses: actions/checkout@main - with: - submodules: true - - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.toolchain }} - profile: minimal - override: true - - name: Build tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --locked --all --release --features "json-tests" --verbose --no-run diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e10ff88f0f..fae328913b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,7 @@ on: env: AWS_REGION: "us-east-1" AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases" + ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: build: @@ -18,7 +19,6 @@ jobs: platform: - ubuntu-16.04 - macos-latest - - windows2019 toolchain: - stable runs-on: ${{ matrix.platform }} @@ -36,25 +36,25 @@ jobs: # Windows Build # ============================== - - name: Install LLVM for Windows - if: matrix.platform == 'windows2019' - run: choco install llvm -y + # - name: Install LLVM for Windows + # if: matrix.platform == 'windows2019' + # run: choco install llvm - - name: Build OpenEthereum for Windows - if: matrix.platform == 'windows2019' - run: sh scripts/actions/build-windows.sh ${{matrix.platform}} + # - name: Build OpenEthereum for Windows + # if: matrix.platform == 'windows2019' + # run: sh scripts/actions/build-windows.sh ${{matrix.platform}} - - name: Upload Windows build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'windows2019' - with: - name: windows-artifacts - path: artifacts + # - name: Upload Windows build + # uses: actions/upload-artifact@v2 + # if: matrix.platform == 'windows2019' + # with: + # name: windows-artifacts + # path: artifacts # ============================== # Linux/Macos Build # ============================== - + - name: Build OpenEthereum for ${{matrix.platform}} if: matrix.platform != 'windows2019' run: sh scripts/actions/build-linux.sh ${{matrix.platform}} @@ -85,11 +85,11 @@ jobs: # Create ZIP files # ============================== - - name: Download Windows artifacts - uses: actions/download-artifact@v2 - with: - name: windows-artifacts - path: windows-artifacts + # - name: Download Windows artifacts + # uses: actions/download-artifact@v2 + # with: + # name: windows-artifacts + # path: windows-artifacts - name: Download Linux artifacts uses: actions/download-artifact@v2 @@ -132,18 +132,18 @@ jobs: echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - name: Create zip Windows - id: create_zip_windows - run: | - cd windows-artifacts/ - zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - cd .. - mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + # - name: Create zip Windows + # id: create_zip_windows + # run: | + # cd windows-artifacts/ + # zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + # ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # cd .. + # mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - echo "Setting outputs..." - echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + # echo "Setting outputs..." + # echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') # ======================================================================= # Upload artifacts @@ -162,11 +162,11 @@ jobs: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Upload artifacts + # uses: actions/upload-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip # ======================================================================= # Upload artifacts to S3 @@ -191,8 +191,8 @@ jobs: linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + # windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + # windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} draft-release: name: Draft Release @@ -216,10 +216,10 @@ jobs: with: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Download artifacts + # uses: actions/download-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - name: Display structure of downloaded files run: ls @@ -273,13 +273,13 @@ jobs: asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip asset_content_type: application/zip - - name: Upload Release Asset - Windows - id: upload_release_asset_windows - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip + # - name: Upload Release Asset - Windows + # id: upload_release_asset_windows + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + # asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_content_type: application/zip diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 7c9b9c6e04..06d660c1eb 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -30,12 +30,12 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path crates/runtime/io/Cargo.toml --no-default-features --verbose + args: --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose - name: Run cargo check 3/3 uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path crates/runtime/io/Cargo.toml --features "mio" --verbose + args: --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose - name: Run cargo check evmbin uses: actions-rs/cargo@v1 with: diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml new file mode 100644 index 0000000000..44c70a8042 --- /dev/null +++ b/.github/workflows/deploy-docker.yml @@ -0,0 +1,30 @@ +name: Docker Image Release + +on: + push: + branches: + - main + tags: + - v* + +jobs: + deploy-docker: + name: Build Release + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@master + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Deploy to docker hub + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: openethereum/openethereum + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: scripts/docker/alpine/Dockerfile + tag_names: true From f0fd88aa1257652f1d21433d3cd12dec6f943319 Mon Sep 17 00:00:00 2001 From: draganrakita Date: Thu, 25 Feb 2021 17:21:02 +0100 Subject: [PATCH 068/107] Github action path for folder structure --- .github/workflows/check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 06d660c1eb..7c9b9c6e04 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -30,12 +30,12 @@ jobs: uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose + args: --locked --manifest-path crates/runtime/io/Cargo.toml --no-default-features --verbose - name: Run cargo check 3/3 uses: actions-rs/cargo@v1 with: command: check - args: --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose + args: --locked --manifest-path crates/runtime/io/Cargo.toml --features "mio" --verbose - name: Run cargo check evmbin uses: actions-rs/cargo@v1 with: From efb80e10324973223a8d7e64941b795aa6156e48 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Fri, 26 Feb 2021 10:35:17 +0100 Subject: [PATCH 069/107] Enable CI on windows2019 machine (#283) Enable CI on windows2019 machine * Add -y for choco install --- .github/workflows/build-test-windows.yml | 33 +++++++++ .github/workflows/build.yml | 92 ++++++++++++------------ 2 files changed, 79 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/build-test-windows.yml diff --git a/.github/workflows/build-test-windows.yml b/.github/workflows/build-test-windows.yml new file mode 100644 index 0000000000..a3983eec3f --- /dev/null +++ b/.github/workflows/build-test-windows.yml @@ -0,0 +1,33 @@ +name: Build and Test Suite on Windows + +on: + push: + branches: + - main + - dev +jobs: + build-tests: + name: Test and Build + strategy: + matrix: + platform: + - windows2019 # custom runner + toolchain: + - stable + runs-on: ${{ matrix.platform }} + steps: + - name: Checkout sources + uses: actions/checkout@main + with: + submodules: true + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + profile: minimal + override: true + - name: Build tests + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked --all --release --features "json-tests" --verbose --no-run diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fae328913b..0cdce51201 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,6 +19,7 @@ jobs: platform: - ubuntu-16.04 - macos-latest + - windows2019 toolchain: - stable runs-on: ${{ matrix.platform }} @@ -36,25 +37,25 @@ jobs: # Windows Build # ============================== - # - name: Install LLVM for Windows - # if: matrix.platform == 'windows2019' - # run: choco install llvm + - name: Install LLVM for Windows + if: matrix.platform == 'windows2019' + run: choco install llvm -y - # - name: Build OpenEthereum for Windows - # if: matrix.platform == 'windows2019' - # run: sh scripts/actions/build-windows.sh ${{matrix.platform}} + - name: Build OpenEthereum for Windows + if: matrix.platform == 'windows2019' + run: sh scripts/actions/build-windows.sh ${{matrix.platform}} - # - name: Upload Windows build - # uses: actions/upload-artifact@v2 - # if: matrix.platform == 'windows2019' - # with: - # name: windows-artifacts - # path: artifacts + - name: Upload Windows build + uses: actions/upload-artifact@v2 + if: matrix.platform == 'windows2019' + with: + name: windows-artifacts + path: artifacts # ============================== # Linux/Macos Build # ============================== - + - name: Build OpenEthereum for ${{matrix.platform}} if: matrix.platform != 'windows2019' run: sh scripts/actions/build-linux.sh ${{matrix.platform}} @@ -132,18 +133,17 @@ jobs: echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - # - name: Create zip Windows - # id: create_zip_windows - # run: | - # cd windows-artifacts/ - # zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - # ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # cd .. - # mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - - # echo "Setting outputs..." - # echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + - name: Create zip Windows + id: create_zip_windows + run: | + cd windows-artifacts/ + zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + cd .. + mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + echo "Setting outputs..." + echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') # ======================================================================= # Upload artifacts @@ -162,11 +162,11 @@ jobs: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - # - name: Upload artifacts - # uses: actions/upload-artifact@v2 - # with: - # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + - name: Upload artifacts + uses: actions/upload-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip # ======================================================================= # Upload artifacts to S3 @@ -191,8 +191,8 @@ jobs: linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - # windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - # windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} draft-release: name: Draft Release @@ -216,10 +216,10 @@ jobs: with: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - # - name: Download artifacts - # uses: actions/download-artifact@v2 - # with: - # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + - name: Download artifacts + uses: actions/download-artifact@v2 + with: + name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - name: Display structure of downloaded files run: ls @@ -273,13 +273,13 @@ jobs: asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip asset_content_type: application/zip - # - name: Upload Release Asset - Windows - # id: upload_release_asset_windows - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # with: - # upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - # asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - # asset_content_type: application/zip + - name: Upload Release Asset - Windows + id: upload_release_asset_windows + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip From 0947261cf2c21fd4bf253dc8beabeb976fc3ac3b Mon Sep 17 00:00:00 2001 From: Dusan Stanivukovic Date: Fri, 26 Feb 2021 15:23:29 +0100 Subject: [PATCH 070/107] Sunce86/rpc module reverted for RPC JSON api (#284) * rpc module reverted for RPC JSON api Co-authored-by: Dusan Stanivukovic --- bin/oe/cli/mod.rs | 18 ++++---- bin/oe/cli/tests/config.full.toml | 6 +-- bin/oe/configuration.rs | 4 +- bin/oe/rpc_apis.rs | 60 +++++++++++++++++++++--- crates/rpc/src/v1/impls/mod.rs | 2 + crates/rpc/src/v1/impls/rpc.rs | 66 +++++++++++++++++++++++++++ crates/rpc/src/v1/mod.rs | 2 +- crates/rpc/src/v1/tests/mocked/mod.rs | 1 + crates/rpc/src/v1/tests/mocked/rpc.rs | 52 +++++++++++++++++++++ crates/rpc/src/v1/traits/mod.rs | 2 + crates/rpc/src/v1/traits/rpc.rs | 36 +++++++++++++++ 11 files changed, 228 insertions(+), 21 deletions(-) create mode 100644 crates/rpc/src/v1/impls/rpc.rs create mode 100644 crates/rpc/src/v1/tests/mocked/rpc.rs create mode 100644 crates/rpc/src/v1/traits/rpc.rs diff --git a/bin/oe/cli/mod.rs b/bin/oe/cli/mod.rs index 54e229957b..f074229404 100644 --- a/bin/oe/cli/mod.rs +++ b/bin/oe/cli/mod.rs @@ -409,9 +409,9 @@ usage! { "--jsonrpc-interface=[IP]", "Specify the hostname portion of the HTTP JSON-RPC API server, IP should be an interface's IP address, or all (all interfaces) or local.", - ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces", or |c: &Config| c.rpc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), + ARG arg_jsonrpc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc", or |c: &Config| c.rpc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), "--jsonrpc-apis=[APIS]", - "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces", + "Specify the APIs available through the HTTP JSON-RPC interface using a comma-delimited list of API names. Possible names are: all, safe, debug, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", ARG arg_jsonrpc_hosts: (String) = "none", or |c: &Config| c.rpc.as_ref()?.hosts.as_ref().map(|vec| vec.join(",")), "--jsonrpc-hosts=[HOSTS]", @@ -450,9 +450,9 @@ usage! { "--ws-interface=[IP]", "Specify the hostname portion of the WebSockets JSON-RPC server, IP should be an interface's IP address, or all (all interfaces) or local.", - ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces", or |c: &Config| c.websockets.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), + ARG arg_ws_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,traces,rpc", or |c: &Config| c.websockets.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), "--ws-apis=[APIS]", - "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces", + "Specify the JSON-RPC APIs available through the WebSockets interface using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", ARG arg_ws_origins: (String) = "parity://*,chrome-extension://*,moz-extension://*", or |c: &Config| c.websockets.as_ref()?.origins.as_ref().map(|vec| vec.join(",")), "--ws-origins=[URL]", @@ -492,9 +492,9 @@ usage! { "--ipc-path=[PATH]", "Specify custom path for JSON-RPC over IPC service.", - ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,traces", or |c: &Config| c.ipc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), + ARG arg_ipc_apis: (String) = "web3,eth,pubsub,net,parity,parity_pubsub,parity_accounts,traces,rpc", or |c: &Config| c.ipc.as_ref()?.apis.as_ref().map(|vec| vec.join(",")), "--ipc-apis=[APIS]", - "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces", + "Specify custom API set available via JSON-RPC over IPC using a comma-delimited list of API names. Possible names are: all, safe, web3, net, eth, pubsub, personal, signer, parity, parity_pubsub, parity_accounts, parity_set, traces, rpc, secretstore. You can also disable a specific API by putting '-' in the front, example: all,-personal. 'safe' enables the following APIs: web3, net, eth, pubsub, parity, parity_pubsub, traces, rpc", ["Secret Store Options"] FLAG flag_no_secretstore: (bool) = false, or |c: &Config| c.secretstore.as_ref()?.disable.clone(), @@ -1312,7 +1312,7 @@ mod tests { arg_jsonrpc_port: 8545u16, arg_jsonrpc_interface: "local".into(), arg_jsonrpc_cors: "null".into(), - arg_jsonrpc_apis: "web3,eth,net,parity,traces,secretstore".into(), + arg_jsonrpc_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), arg_jsonrpc_hosts: "none".into(), arg_jsonrpc_server_threads: None, arg_jsonrpc_threads: 4, @@ -1324,7 +1324,7 @@ mod tests { flag_no_ws: false, arg_ws_port: 8546u16, arg_ws_interface: "local".into(), - arg_ws_apis: "web3,eth,net,parity,traces,secretstore".into(), + arg_ws_apis: "web3,eth,net,parity,traces,rpc,secretstore".into(), arg_ws_origins: "none".into(), arg_ws_hosts: "none".into(), arg_ws_max_connections: 100, @@ -1333,7 +1333,7 @@ mod tests { // IPC flag_no_ipc: false, arg_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(), - arg_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,secretstore" + arg_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc,secretstore" .into(), // METRICS diff --git a/bin/oe/cli/tests/config.full.toml b/bin/oe/cli/tests/config.full.toml index 37b01cafc7..0d0f7aec1d 100644 --- a/bin/oe/cli/tests/config.full.toml +++ b/bin/oe/cli/tests/config.full.toml @@ -39,7 +39,7 @@ disable = false port = 8545 interface = "local" cors = ["null"] -apis = ["web3", "eth", "net", "parity", "traces", "secretstore"] +apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] hosts = ["none"] allow_missing_blocks = false @@ -48,13 +48,13 @@ disable = false port = 8546 interface = "local" origins = ["none"] -apis = ["web3", "eth", "net", "parity", "traces", "secretstore"] +apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"] hosts = ["none"] [ipc] disable = false path = "$HOME/.parity/jsonrpc.ipc" -apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "secretstore"] +apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc", "secretstore"] [secretstore] disable = false diff --git a/bin/oe/configuration.rs b/bin/oe/configuration.rs index fe7a71917c..b0b1b9215a 100644 --- a/bin/oe/configuration.rs +++ b/bin/oe/configuration.rs @@ -1741,7 +1741,7 @@ mod tests { ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), _ => panic!("Incorrect rpc apis"), } - // "web3,eth,net,personal,parity,parity_set,traces,parity_accounts"); + // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); assert_eq!(c.http_conf.hosts, None); } _ => panic!("Should be Cmd::Run"), @@ -1762,7 +1762,7 @@ mod tests { ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), _ => panic!("Incorrect rpc apis"), } - // "web3,eth,net,personal,parity,parity_set,traces,parity_accounts"); + // "web3,eth,net,personal,parity,parity_set,traces,rpc,parity_accounts"); assert_eq!(c.http_conf.hosts, None); } _ => panic!("Should be Cmd::Run"), diff --git a/bin/oe/rpc_apis.rs b/bin/oe/rpc_apis.rs index 0de19f7685..0acb886460 100644 --- a/bin/oe/rpc_apis.rs +++ b/bin/oe/rpc_apis.rs @@ -14,7 +14,12 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use std::{cmp::PartialEq, collections::HashSet, str::FromStr, sync::Arc}; +use std::{ + cmp::PartialEq, + collections::{BTreeMap, HashSet}, + str::FromStr, + sync::Arc, +}; pub use parity_rpc::signer::SignerService; @@ -51,6 +56,8 @@ pub enum Api { Parity, /// Traces (Safe) Traces, + /// Rpc (Safe) + Rpc, /// Parity PubSub - Generic Publish-Subscriber (Safety depends on other APIs exposed). ParityPubSub, /// Parity Accounts extensions (UNSAFE: Passwords, Side Effects (new account)) @@ -80,6 +87,7 @@ impl FromStr for Api { "parity_set" => Ok(ParitySet), "personal" => Ok(Personal), "pubsub" => Ok(EthPubSub), + "rpc" => Ok(Rpc), "secretstore" => Ok(SecretStore), "signer" => Ok(Signer), "traces" => Ok(Traces), @@ -146,6 +154,30 @@ impl FromStr for ApiSet { } } +fn to_modules(apis: &HashSet) -> BTreeMap { + let mut modules = BTreeMap::new(); + for api in apis { + let (name, version) = match *api { + Api::Debug => ("debug", "1.0"), + Api::Eth => ("eth", "1.0"), + Api::EthPubSub => ("pubsub", "1.0"), + Api::Net => ("net", "1.0"), + Api::Parity => ("parity", "1.0"), + Api::ParityAccounts => ("parity_accounts", "1.0"), + Api::ParityPubSub => ("parity_pubsub", "1.0"), + Api::ParitySet => ("parity_set", "1.0"), + Api::Personal => ("personal", "1.0"), + Api::Rpc => ("rpc", "1.0"), + Api::SecretStore => ("secretstore", "1.0"), + Api::Signer => ("signer", "1.0"), + Api::Traces => ("traces", "1.0"), + Api::Web3 => ("web3", "1.0"), + }; + modules.insert(name.into(), version.into()); + } + modules +} + macro_rules! add_signing_methods { ($namespace:ident, $handler:expr, $deps:expr, $dispatch:expr) => {{ let deps = &$deps; @@ -376,6 +408,10 @@ impl FullDependencies { ); } Api::Traces => handler.extend_with(TracesClient::new(&self.client).to_delegate()), + Api::Rpc => { + let modules = to_modules(&apis); + handler.extend_with(RpcClient::new(modules).to_delegate()); + } Api::SecretStore => { #[cfg(feature = "accounts")] handler.extend_with(SecretStoreClient::new(&self.accounts).to_delegate()); @@ -409,11 +445,17 @@ impl ApiSet { } pub fn list_apis(&self) -> HashSet { - let mut public_list: HashSet = - [Api::Web3, Api::Net, Api::Eth, Api::EthPubSub, Api::Parity] - .iter() - .cloned() - .collect(); + let mut public_list: HashSet = [ + Api::Web3, + Api::Net, + Api::Eth, + Api::EthPubSub, + Api::Parity, + Api::Rpc, + ] + .iter() + .cloned() + .collect(); match *self { ApiSet::List(ref apis) => apis.clone(), @@ -470,6 +512,7 @@ mod test { assert_eq!(Api::ParityAccounts, "parity_accounts".parse().unwrap()); assert_eq!(Api::ParitySet, "parity_set".parse().unwrap()); assert_eq!(Api::Traces, "traces".parse().unwrap()); + assert_eq!(Api::Rpc, "rpc".parse().unwrap()); assert_eq!(Api::SecretStore, "secretstore".parse().unwrap()); assert!("rp".parse::().is_err()); } @@ -498,6 +541,7 @@ mod test { Api::Parity, Api::ParityPubSub, Api::Traces, + Api::Rpc, ] .into_iter() .collect(); @@ -515,6 +559,7 @@ mod test { Api::Parity, Api::ParityPubSub, Api::Traces, + Api::Rpc, // semi-safe Api::ParityAccounts, ] @@ -536,6 +581,7 @@ mod test { Api::Parity, Api::ParityPubSub, Api::Traces, + Api::Rpc, Api::SecretStore, Api::ParityAccounts, Api::ParitySet, @@ -562,6 +608,7 @@ mod test { Api::Parity, Api::ParityPubSub, Api::Traces, + Api::Rpc, Api::SecretStore, Api::ParityAccounts, Api::ParitySet, @@ -587,6 +634,7 @@ mod test { Api::Parity, Api::ParityPubSub, Api::Traces, + Api::Rpc, ] .into_iter() .collect() diff --git a/crates/rpc/src/v1/impls/mod.rs b/crates/rpc/src/v1/impls/mod.rs index c8a1c64bc7..5d7aa04d48 100644 --- a/crates/rpc/src/v1/impls/mod.rs +++ b/crates/rpc/src/v1/impls/mod.rs @@ -28,6 +28,7 @@ mod parity_set; #[cfg(any(test, feature = "accounts"))] mod personal; mod pubsub; +mod rpc; #[cfg(any(test, feature = "accounts"))] mod secretstore; mod signer; @@ -53,6 +54,7 @@ pub use self::{ parity::ParityClient, parity_set::ParitySetClient, pubsub::PubSubClient, + rpc::RpcClient, signer::SignerClient, signing::SigningQueueClient, signing_unsafe::SigningUnsafeClient, diff --git a/crates/rpc/src/v1/impls/rpc.rs b/crates/rpc/src/v1/impls/rpc.rs new file mode 100644 index 0000000000..5218186208 --- /dev/null +++ b/crates/rpc/src/v1/impls/rpc.rs @@ -0,0 +1,66 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! RPC generic methods implementation. +use jsonrpc_core::Result; +use std::collections::BTreeMap; +use v1::traits::Rpc; + +/// RPC generic methods implementation. +pub struct RpcClient { + modules: BTreeMap, + valid_apis: Vec, +} + +impl RpcClient { + /// Creates new `RpcClient`. + pub fn new(modules: BTreeMap) -> Self { + // geth 1.3.6 fails upon receiving unknown api + let valid_apis = vec!["web3", "eth", "net", "personal", "rpc"]; + + RpcClient { + modules, + valid_apis: valid_apis.into_iter().map(ToOwned::to_owned).collect(), + } + } +} + +impl Rpc for RpcClient { + fn rpc_modules(&self) -> Result> { + let modules = self + .modules + .iter() + .fold(BTreeMap::new(), |mut map, (k, v)| { + map.insert(k.to_owned(), v.to_owned()); + map + }); + + Ok(modules) + } + + fn modules(&self) -> Result> { + let modules = self + .modules + .iter() + .filter(|&(k, _v)| self.valid_apis.contains(k)) + .fold(BTreeMap::new(), |mut map, (k, v)| { + map.insert(k.to_owned(), v.to_owned()); + map + }); + + Ok(modules) + } +} diff --git a/crates/rpc/src/v1/mod.rs b/crates/rpc/src/v1/mod.rs index 1645cecd8b..fe4357c153 100644 --- a/crates/rpc/src/v1/mod.rs +++ b/crates/rpc/src/v1/mod.rs @@ -48,7 +48,7 @@ pub use self::{ metadata::Metadata, traits::{ Debug, Eth, EthFilter, EthPubSub, EthSigning, Net, Parity, ParityAccounts, - ParityAccountsInfo, ParitySet, ParitySetAccounts, ParitySigning, Personal, PubSub, + ParityAccountsInfo, ParitySet, ParitySetAccounts, ParitySigning, Personal, PubSub, Rpc, SecretStore, Signer, Traces, Web3, }, types::Origin, diff --git a/crates/rpc/src/v1/tests/mocked/mod.rs b/crates/rpc/src/v1/tests/mocked/mod.rs index 878e0b0500..82d08e2caf 100644 --- a/crates/rpc/src/v1/tests/mocked/mod.rs +++ b/crates/rpc/src/v1/tests/mocked/mod.rs @@ -29,6 +29,7 @@ mod parity_set; #[cfg(any(test, feature = "accounts"))] mod personal; mod pubsub; +mod rpc; #[cfg(any(test, feature = "accounts"))] mod secretstore; mod signer; diff --git a/crates/rpc/src/v1/tests/mocked/rpc.rs b/crates/rpc/src/v1/tests/mocked/rpc.rs new file mode 100644 index 0000000000..6dc677c619 --- /dev/null +++ b/crates/rpc/src/v1/tests/mocked/rpc.rs @@ -0,0 +1,52 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +use jsonrpc_core::IoHandler; +use std::collections::BTreeMap; +use v1::{Rpc, RpcClient}; + +fn rpc_client() -> RpcClient { + let mut modules = BTreeMap::new(); + modules.insert("rpc".to_owned(), "1.0".to_owned()); + modules.insert("web3".to_owned(), "1.0".to_owned()); + modules.insert("ethcore".to_owned(), "1.0".to_owned()); + RpcClient::new(modules) +} + +#[test] +fn modules() { + let rpc = rpc_client().to_delegate(); + let mut io = IoHandler::new(); + io.extend_with(rpc); + + let request = r#"{"jsonrpc": "2.0", "method": "modules", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"rpc":"1.0","web3":"1.0"},"id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); +} + +#[test] +fn rpc_modules() { + let rpc = rpc_client().to_delegate(); + let mut io = IoHandler::new(); + io.extend_with(rpc); + + let request = r#"{"jsonrpc": "2.0", "method": "rpc_modules", "params": [], "id": 1}"#; + let response = + r#"{"jsonrpc":"2.0","result":{"ethcore":"1.0","rpc":"1.0","web3":"1.0"},"id":1}"#; + + assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); +} diff --git a/crates/rpc/src/v1/traits/mod.rs b/crates/rpc/src/v1/traits/mod.rs index 046d54cb12..37c732b372 100644 --- a/crates/rpc/src/v1/traits/mod.rs +++ b/crates/rpc/src/v1/traits/mod.rs @@ -27,6 +27,7 @@ pub mod parity_set; pub mod parity_signing; pub mod personal; pub mod pubsub; +pub mod rpc; pub mod secretstore; pub mod signer; pub mod traces; @@ -44,6 +45,7 @@ pub use self::{ parity_signing::ParitySigning, personal::Personal, pubsub::PubSub, + rpc::Rpc, secretstore::SecretStore, signer::Signer, traces::Traces, diff --git a/crates/rpc/src/v1/traits/rpc.rs b/crates/rpc/src/v1/traits/rpc.rs new file mode 100644 index 0000000000..1348279f04 --- /dev/null +++ b/crates/rpc/src/v1/traits/rpc.rs @@ -0,0 +1,36 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! RPC interface. + +use std::collections::BTreeMap; + +use jsonrpc_core::Result; +use jsonrpc_derive::rpc; + +/// RPC Interface. +#[rpc(server)] +pub trait Rpc { + /// Returns supported modules for Geth 1.3.6 + /// @ignore + #[rpc(name = "modules")] + fn modules(&self) -> Result>; + + /// Returns supported modules for Geth 1.4.0 + /// @ignore + #[rpc(name = "rpc_modules")] + fn rpc_modules(&self) -> Result>; +} From 63fdad8d86f3e7191a047121ee0d03caefcb131f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 2 Mar 2021 21:27:28 +0800 Subject: [PATCH 071/107] ethcore/snapshot: fix double-lock in Service::feed_chunk (#289) --- crates/ethcore/src/snapshot/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index b94d36199f..556e0609ea 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -766,7 +766,7 @@ impl Service { | Err(Error(SnapshotErrorKind::Snapshot(SnapshotError::RestorationAborted), _)) => (), Err(e) => { warn!("Encountered error during snapshot restoration: {}", e); - *self.restoration.lock() = None; + *restoration = None; *self.status.lock() = RestorationStatus::Failed; let _ = fs::remove_dir_all(self.restoration_dir()); } From 7c9eed8d652077c1c7406c81d73642e2ac1acddc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 2 Mar 2021 21:27:28 +0800 Subject: [PATCH 072/107] ethcore/snapshot: fix double-lock in Service::feed_chunk (#289) --- crates/ethcore/src/snapshot/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index b94d36199f..556e0609ea 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -766,7 +766,7 @@ impl Service { | Err(Error(SnapshotErrorKind::Snapshot(SnapshotError::RestorationAborted), _)) => (), Err(e) => { warn!("Encountered error during snapshot restoration: {}", e); - *self.restoration.lock() = None; + *restoration = None; *self.status.lock() = RestorationStatus::Failed; let _ = fs::remove_dir_all(self.restoration_dir()); } From ba011eba15fcb6419348075b617893c463e42296 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 3 Mar 2021 12:58:10 +0100 Subject: [PATCH 073/107] Send RLPx auth in EIP-8 format (#287) --- crates/net/network-devp2p/src/handshake.rs | 39 ++++++++++------------ 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/crates/net/network-devp2p/src/handshake.rs b/crates/net/network-devp2p/src/handshake.rs index 74b2de0eaf..86ba8f3557 100644 --- a/crates/net/network-devp2p/src/handshake.rs +++ b/crates/net/network-devp2p/src/handshake.rs @@ -20,14 +20,13 @@ use ethkey::{ crypto::{ecdh, ecies}, recover, sign, Generator, KeyPair, Public, Random, Secret, }; -use hash::write_keccak; use host::HostInfo; use io::{IoContext, StreamToken}; use mio::tcp::*; use network::{Error, ErrorKind}; use node_table::NodeId; use parity_bytes::Bytes; -use rand::random; +use rand::{random, Rng}; use rlp::{Rlp, RlpStream}; use std::time::Duration; @@ -314,25 +313,23 @@ impl Handshake { Message: Send + Clone + Sync + 'static, { trace!(target: "network", "Sending handshake auth to {:?}", self.connection.remote_addr_str()); - let mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants - let len = data.len(); - { - data[len - 1] = 0x0; - let (sig, rest) = data.split_at_mut(65); - let (hepubk, rest) = rest.split_at_mut(32); - let (pubk, rest) = rest.split_at_mut(64); - let (nonce, _) = rest.split_at_mut(32); - - // E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0) - let shared = *ecdh::agree(secret, &self.id)?; - sig.copy_from_slice(&*sign(self.ecdhe.secret(), &(shared ^ self.nonce))?); - write_keccak(self.ecdhe.public(), hepubk); - pubk.copy_from_slice(public); - nonce.copy_from_slice(&self.nonce); - } - let message = ecies::encrypt(&self.id, &[], &data)?; - self.auth_cipher = message.clone(); - self.connection.send(io, message); + let mut rlp = RlpStream::new_list(4); + let shared = *ecdh::agree(secret, &self.id)?; + rlp.append(&sign(self.ecdhe.secret(), &(shared ^ self.nonce))?.to_vec()); + rlp.append(public); + rlp.append(&self.nonce); + rlp.append(&PROTOCOL_VERSION); + let mut encoded = rlp.out(); + encoded.resize( + encoded.len() + rand::thread_rng().gen_range::(100, 301), + 0, + ); + let len = (encoded.len() + ECIES_OVERHEAD) as u16; + let prefix = len.to_be_bytes(); + let message = ecies::encrypt(&self.id, &prefix, &encoded)?; + self.auth_cipher.extend_from_slice(&prefix); + self.auth_cipher.extend_from_slice(&message); + self.connection.send(io, self.auth_cipher.clone()); self.connection.expect(V4_ACK_PACKET_SIZE); self.state = HandshakeState::ReadingAck; Ok(()) From 973a5a594b5276a645326ecbe337bea9db76b4d6 Mon Sep 17 00:00:00 2001 From: Dusan Stanivukovic Date: Wed, 3 Mar 2021 15:57:25 +0100 Subject: [PATCH 074/107] Sunce86/add support eip2930 ethereum tests runner (#288) * added support for eip2930 tests Co-authored-by: sunce86 --- Cargo.lock | 3 +- bin/evmbin/src/main.rs | 2 +- crates/ethcore/res/json_tests | 2 +- crates/ethcore/src/json_tests/runner.rs | 2 +- crates/ethcore/src/json_tests/state.rs | 6 +- crates/ethcore/types/Cargo.toml | 1 - crates/ethcore/types/src/lib.rs | 1 - crates/ethcore/types/src/log_entry.rs | 11 --- .../types/src/transaction/transaction.rs | 51 ---------- crates/ethjson/Cargo.toml | 2 + crates/ethjson/src/blockchain/transaction.rs | 2 +- crates/ethjson/src/lib.rs | 2 + crates/ethjson/src/state/test.rs | 98 +++++++++++++++++-- crates/ethjson/src/state/transaction.rs | 1 + 14 files changed, 101 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 460fd08c93..edcfc1fd59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -439,7 +439,6 @@ name = "common-types" version = "0.1.0" dependencies = [ "ethereum-types 0.4.2", - "ethjson", "ethkey", "heapsize", "keccak-hash", @@ -1375,7 +1374,9 @@ dependencies = [ name = "ethjson" version = "0.1.0" dependencies = [ + "common-types", "ethereum-types 0.4.2", + "ethkey", "macros", "maplit", "rustc-hex 1.0.0", diff --git a/bin/evmbin/src/main.rs b/bin/evmbin/src/main.rs index a7a63474b1..45b28f5837 100644 --- a/bin/evmbin/src/main.rs +++ b/bin/evmbin/src/main.rs @@ -204,7 +204,7 @@ fn run_state_test(args: Args) { } for (idx, state) in states.into_iter().enumerate() { let post_root = state.hash.into(); - let transaction = multitransaction.select(&state.indexes).into(); + let transaction = multitransaction.select(&state.indexes); let trie_spec = if args.flag_std_dump_json { TrieSpec::Fat diff --git a/crates/ethcore/res/json_tests b/crates/ethcore/res/json_tests index 1508126ea0..31d663076b 160000 --- a/crates/ethcore/res/json_tests +++ b/crates/ethcore/res/json_tests @@ -1 +1 @@ -Subproject commit 1508126ea04cd61495b60db2f036ac823de274b1 +Subproject commit 31d663076b6678df18983d6da912d7cad4ad3416 diff --git a/crates/ethcore/src/json_tests/runner.rs b/crates/ethcore/src/json_tests/runner.rs index a82af46cc3..1def4f91c4 100644 --- a/crates/ethcore/src/json_tests/runner.rs +++ b/crates/ethcore/src/json_tests/runner.rs @@ -184,7 +184,7 @@ impl TestRunner { return Vec::new(); } } - super::state::json_chain_test(&test, &path, &json, &mut |_, _| {}) + super::state::json_state_test(&test, &path, &json, &mut |_, _| {}) }, ) } diff --git a/crates/ethcore/src/json_tests/state.rs b/crates/ethcore/src/json_tests/state.rs index 2b1c89ebc5..0070b87109 100644 --- a/crates/ethcore/src/json_tests/state.rs +++ b/crates/ethcore/src/json_tests/state.rs @@ -20,7 +20,6 @@ use ethjson; use pod_state::PodState; use std::path::Path; use trace; -use types::transaction::SignedTransaction; use vm::EnvInfo; fn skip_test( @@ -42,7 +41,7 @@ fn skip_test( }) } -pub fn json_chain_test( +pub fn json_state_test( state_test: ðjson::test::StateTests, path: &Path, json_data: &[u8], @@ -91,8 +90,7 @@ pub fn json_chain_test( } let post_root: H256 = state.hash.into(); - let transaction: SignedTransaction = - multitransaction.select(&state.indexes).into(); + let transaction = multitransaction.select(&state.indexes); let result = || -> Result<_, EvmTestError> { Ok(EvmTestClient::from_pod_state(&spec, pre.clone())?.transact( diff --git a/crates/ethcore/types/Cargo.toml b/crates/ethcore/types/Cargo.toml index d6a18bcd1c..9a16ddcb61 100644 --- a/crates/ethcore/types/Cargo.toml +++ b/crates/ethcore/types/Cargo.toml @@ -6,7 +6,6 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.4" -ethjson = { path = "../../ethjson" } ethkey = { path = "../../accounts/ethkey" } heapsize = "0.4" keccak-hash = "0.1" diff --git a/crates/ethcore/types/src/lib.rs b/crates/ethcore/types/src/lib.rs index 833e5a61c3..5c99c105bd 100644 --- a/crates/ethcore/types/src/lib.rs +++ b/crates/ethcore/types/src/lib.rs @@ -35,7 +35,6 @@ #![warn(unused_extern_crates)] extern crate ethereum_types; -extern crate ethjson; extern crate ethkey; extern crate heapsize; extern crate keccak_hash as hash; diff --git a/crates/ethcore/types/src/log_entry.rs b/crates/ethcore/types/src/log_entry.rs index 89b56161b8..129e78a92b 100644 --- a/crates/ethcore/types/src/log_entry.rs +++ b/crates/ethcore/types/src/log_entry.rs @@ -21,7 +21,6 @@ use ethereum_types::{Address, Bloom, BloomInput, H256}; use heapsize::HeapSizeOf; use std::ops::Deref; -use ethjson; use BlockNumber; /// A record of execution for a `LOG` operation. @@ -53,16 +52,6 @@ impl LogEntry { } } -impl From for LogEntry { - fn from(l: ethjson::state::Log) -> Self { - LogEntry { - address: l.address.into(), - topics: l.topics.into_iter().map(Into::into).collect(), - data: l.data.into(), - } - } -} - /// Log localized in a blockchain. #[derive(Default, Debug, PartialEq, Clone)] pub struct LocalizedLogEntry { diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 66f477fd90..892795a6ad 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -17,7 +17,6 @@ //! Transaction data structure. use ethereum_types::{Address, H160, H256, U256}; -use ethjson; use ethkey::{self, public_to_address, recover, Public, Secret, Signature}; use hash::keccak; use heapsize::HeapSizeOf; @@ -606,56 +605,6 @@ impl SignatureComponents { } } -#[cfg(any(test, feature = "test-helpers"))] -impl From for SignedTransaction { - fn from(t: ethjson::state::Transaction) -> Self { - let to: Option = t.to.into(); - let secret = t.secret.map(|s| Secret::from(s.0)); - let tx = TypedTransaction::Legacy(Transaction { - nonce: t.nonce.into(), - gas_price: t.gas_price.into(), - gas: t.gas_limit.into(), - action: match to { - Some(to) => Action::Call(to.into()), - None => Action::Create, - }, - value: t.value.into(), - data: t.data.into(), - }); - match secret { - Some(s) => tx.sign(&s, None), - None => tx.null_sign(1), - } - } -} - -impl From for UnverifiedTransaction { - fn from(t: ethjson::transaction::Transaction) -> Self { - let to: Option = t.to.into(); - UnverifiedTransaction { - unsigned: TypedTransaction::Legacy(Transaction { - nonce: t.nonce.into(), - gas_price: t.gas_price.into(), - gas: t.gas_limit.into(), - action: match to { - Some(to) => Action::Call(to.into()), - None => Action::Create, - }, - value: t.value.into(), - data: t.data.into(), - }), - chain_id: signature::extract_chain_id_from_legacy_v(t.v.into()), - signature: SignatureComponents { - r: t.r.into(), - s: t.s.into(), - standard_v: signature::extract_standard_v(t.v.into()), - }, - hash: 0.into(), - } - .compute_hash() - } -} - /// Signed transaction information without verified signature. #[derive(Debug, Clone, Eq, PartialEq)] pub struct UnverifiedTransaction { diff --git a/crates/ethjson/Cargo.toml b/crates/ethjson/Cargo.toml index 584c046370..b86f34f1d6 100644 --- a/crates/ethjson/Cargo.toml +++ b/crates/ethjson/Cargo.toml @@ -5,6 +5,8 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +common-types = { path = "../ethcore/types", features = ["test-helpers"] } +ethkey = { path = "../accounts/ethkey" } ethereum-types = "0.4" rustc-hex = "1.0" serde = "1.0" diff --git a/crates/ethjson/src/blockchain/transaction.rs b/crates/ethjson/src/blockchain/transaction.rs index 003beb306f..277e520018 100644 --- a/crates/ethjson/src/blockchain/transaction.rs +++ b/crates/ethjson/src/blockchain/transaction.rs @@ -41,7 +41,7 @@ pub struct Transaction { pub type AccessList = Vec; -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, PartialEq, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct AccessListItem { pub address: H160, diff --git a/crates/ethjson/src/lib.rs b/crates/ethjson/src/lib.rs index 2f8b67d19c..f5a6d5f837 100644 --- a/crates/ethjson/src/lib.rs +++ b/crates/ethjson/src/lib.rs @@ -14,7 +14,9 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +extern crate common_types as types; extern crate ethereum_types; +extern crate ethkey; extern crate rustc_hex; extern crate serde; extern crate serde_json; diff --git a/crates/ethjson/src/state/test.rs b/crates/ethjson/src/state/test.rs index 5c2439d3d2..4411ff5866 100644 --- a/crates/ethjson/src/state/test.rs +++ b/crates/ethjson/src/state/test.rs @@ -17,14 +17,18 @@ //! General test deserialization. use bytes::Bytes; +use ethkey::Secret; use hash::{Address, H256}; use maybe::MaybeEmpty; use serde_json::{self, Error}; use spec::ForkSpec; -use state::{AccountState, Env, Transaction}; +use state::{AccountState, Env}; use std::{collections::BTreeMap, io::Read}; +use types::transaction::{AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction}; use uint::Uint; +use crate::blockchain::transaction::AccessList; + /// State test deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct Test(BTreeMap); @@ -69,6 +73,8 @@ pub struct State { pub struct MultiTransaction { /// Transaction data set. pub data: Vec, + /// Optional access list + pub access_lists: Option>>, /// Gas limit set. pub gas_limit: Vec, /// Gas price. @@ -84,18 +90,57 @@ pub struct MultiTransaction { pub value: Vec, } +fn sign_with_secret(tx: TypedTransaction, secret: Option) -> SignedTransaction { + match secret { + Some(s) => tx.sign(&s, None), + None => tx.null_sign(1), + } +} + impl MultiTransaction { /// Build transaction with given indexes. - pub fn select(&self, indexes: &PostStateIndexes) -> Transaction { - Transaction { - data: self.data[indexes.data as usize].clone(), - gas_limit: self.gas_limit[indexes.gas as usize].clone(), - gas_price: self.gas_price.clone(), - nonce: self.nonce.clone(), - secret: self.secret.clone(), - to: self.to.clone(), - value: self.value[indexes.value as usize].clone(), + pub fn select(&self, indexes: &PostStateIndexes) -> SignedTransaction { + let secret = self.secret.clone().map(|s| Secret::from(s.0)); + let to: Option
= self.to.clone().into(); + let transaction = Transaction { + nonce: self.nonce.clone().into(), + gas_price: self.gas_price.clone().into(), + gas: self.gas_limit[indexes.gas as usize].clone().into(), + action: match to { + Some(to) => Action::Call(to.into()), + None => Action::Create, + }, + value: self.value[indexes.value as usize].clone().into(), + data: self.data[indexes.data as usize].clone().into(), + }; + + if let Some(access_lists) = self.access_lists.as_ref() { + if access_lists.len() > indexes.data as usize { + if let Some(access_list) = access_lists[indexes.data as usize].clone() { + //access list type of transaction + + let access_list = access_list + .into_iter() + .map(|elem| { + ( + elem.address.into(), + elem.storage_keys.into_iter().map(Into::into).collect(), + ) + }) + .collect(); + + let tx = TypedTransaction::AccessList(AccessListTx { + transaction, + access_list, + }); + + return sign_with_secret(tx, secret); + } + } } + + let tx = TypedTransaction::Legacy(transaction); + sign_with_secret(tx, secret) } } @@ -138,6 +183,39 @@ mod tests { let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap(); } + #[test] + fn multi_transaction_deserialization_with_access_list() { + let s = r#"{ + "data" : [ "" ], + "accessLists" : [ + null, + [ + ], + [ + { + "address" : "0x0000000000000000000000000000000000000102", + "storageKeys" : [ + ] + }, + { + "address" : "0x0000000000000000000000000000000000000101", + "storageKeys" : [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000010" + ] + } + ] + ], + "gasLimit" : [ "0x2dc6c0", "0x222222" ], + "gasPrice" : "0x01", + "nonce" : "0x00", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "1000000000000000000000000000000000000000", + "value" : [ "0x00", "0x01", "0x02" ] + }"#; + let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap(); + } + #[test] fn state_deserialization() { let s = r#"{ diff --git a/crates/ethjson/src/state/transaction.rs b/crates/ethjson/src/state/transaction.rs index 68e639c9c5..b770a30a42 100644 --- a/crates/ethjson/src/state/transaction.rs +++ b/crates/ethjson/src/state/transaction.rs @@ -51,6 +51,7 @@ mod tests { fn transaction_deserialization() { let s = r#"{ "data" : "", + "accessLists": null, "gasLimit" : "0x2dc6c0", "gasPrice" : "0x01", "nonce" : "0x00", From 0fcb102f033ad2f43d1b89ebcdffd8798b9484bf Mon Sep 17 00:00:00 2001 From: "adria0.eth" <5526331+adria0@users.noreply.github.com> Date: Wed, 3 Mar 2021 22:44:35 +0100 Subject: [PATCH 075/107] Improved metrics (#240) Added db metrics (kvdb_bytes_read, kvdb_bytes_written, kvdb_reads, kvdb_writes) Added --metrics-prefix=[prefix] --- Cargo.lock | 6 + bin/oe/cli/mod.rs | 7 + bin/oe/cli/tests/config.toml | 2 +- bin/oe/configuration.rs | 5 + bin/oe/db/rocksdb/mod.rs | 12 +- bin/oe/metrics.rs | 27 ++- crates/concensus/miner/local-store/Cargo.toml | 1 + crates/concensus/miner/local-store/src/lib.rs | 9 +- crates/db/db/Cargo.toml | 3 + crates/db/db/src/db.rs | 202 +++++++++++++++++- crates/db/db/src/lib.rs | 1 + crates/db/journaldb/Cargo.toml | 1 + crates/db/journaldb/src/archivedb.rs | 25 ++- crates/db/journaldb/src/earlymergedb.rs | 11 +- crates/db/journaldb/src/lib.rs | 3 +- crates/db/journaldb/src/overlaydb.rs | 4 +- crates/db/journaldb/src/overlayrecentdb.rs | 13 +- crates/db/journaldb/src/refcounteddb.rs | 5 +- crates/db/journaldb/src/traits.rs | 4 +- crates/ethcore/blockchain/Cargo.toml | 1 + crates/ethcore/blockchain/src/blockchain.rs | 12 +- crates/ethcore/src/client/client.rs | 69 +++--- crates/ethcore/src/client/evm_test_client.rs | 5 +- crates/ethcore/src/client/test_client.rs | 7 +- crates/ethcore/src/lib.rs | 2 - .../src/snapshot/consensus/authority.rs | 2 +- crates/ethcore/src/snapshot/consensus/work.rs | 2 +- crates/ethcore/src/snapshot/mod.rs | 2 +- crates/ethcore/src/snapshot/tests/state.rs | 28 ++- crates/ethcore/src/spec/spec.rs | 2 +- crates/ethcore/src/test_helpers.rs | 23 +- crates/ethcore/sync/src/api.rs | 42 ++-- .../rpc/src/v1/tests/helpers/sync_provider.rs | 4 +- crates/util/stats/src/lib.rs | 81 ++++--- 34 files changed, 437 insertions(+), 186 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 460fd08c93..0abc8c1c81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,6 +1073,7 @@ dependencies = [ "rlp_compress", "rlp_derive", "rustc-hex 1.0.0", + "stats", "tempdir", "triehash-ethereum", ] @@ -1123,9 +1124,12 @@ dependencies = [ "ethereum-types 0.4.2", "heapsize", "kvdb", + "kvdb-memorydb", + "kvdb-rocksdb", "parking_lot 0.7.1", "rlp 0.3.0", "rlp_derive", + "stats", ] [[package]] @@ -2154,6 +2158,7 @@ name = "journaldb" version = "0.2.0" dependencies = [ "env_logger", + "ethcore-db", "ethereum-types 0.4.2", "fastmap", "hash-db", @@ -2986,6 +2991,7 @@ name = "parity-local-store" version = "0.1.0" dependencies = [ "common-types", + "ethcore-db", "ethcore-io", "ethkey", "kvdb", diff --git a/bin/oe/cli/mod.rs b/bin/oe/cli/mod.rs index f074229404..216b7177cf 100644 --- a/bin/oe/cli/mod.rs +++ b/bin/oe/cli/mod.rs @@ -475,6 +475,10 @@ usage! { "--metrics", "Enable prometheus metrics (only full client).", + ARG arg_metrics_prefix: (String) = "", or |c: &Config| c.metrics.as_ref()?.prefix.clone(), + "--metrics-prefix=[prefix]", + "Prepend the specified prefix to the exported metrics names.", + ARG arg_metrics_port: (u16) = 3000u16, or |c: &Config| c.metrics.as_ref()?.port.clone(), "--metrics-port=[PORT]", "Specify the port portion of the metrics server.", @@ -922,6 +926,7 @@ struct Ipc { #[serde(deny_unknown_fields)] struct Metrics { enable: Option, + prefix: Option, port: Option, interface: Option, } @@ -1338,6 +1343,7 @@ mod tests { // METRICS flag_metrics: false, + arg_metrics_prefix: "".into(), arg_metrics_port: 3000u16, arg_metrics_interface: "local".into(), @@ -1542,6 +1548,7 @@ mod tests { }), metrics: Some(Metrics { enable: Some(true), + prefix: Some("oe".to_string()), interface: Some("local".to_string()), port: Some(4000), }), diff --git a/bin/oe/cli/tests/config.toml b/bin/oe/cli/tests/config.toml index 581a59af53..d9b01a05de 100644 --- a/bin/oe/cli/tests/config.toml +++ b/bin/oe/cli/tests/config.toml @@ -36,7 +36,7 @@ apis = ["rpc", "eth"] enable = true interface = "local" port = 4000 - +prefix = "oe" [secretstore] http_port = 8082 diff --git a/bin/oe/configuration.rs b/bin/oe/configuration.rs index b0b1b9215a..79fc2f5ec0 100644 --- a/bin/oe/configuration.rs +++ b/bin/oe/configuration.rs @@ -958,6 +958,7 @@ impl Configuration { fn metrics_config(&self) -> Result { let conf = MetricsConfiguration { enabled: self.metrics_enabled(), + prefix: self.metrics_prefix(), interface: self.metrics_interface(), port: self.args.arg_ports_shift + self.args.arg_metrics_port, }; @@ -1147,6 +1148,10 @@ impl Configuration { self.args.flag_metrics } + fn metrics_prefix(&self) -> String { + self.args.arg_metrics_prefix.clone() + } + fn secretstore_enabled(&self) -> bool { !self.args.flag_no_secretstore && cfg!(feature = "secretstore") } diff --git a/bin/oe/db/rocksdb/mod.rs b/bin/oe/db/rocksdb/mod.rs index c923cba2fa..e5789f89a9 100644 --- a/bin/oe/db/rocksdb/mod.rs +++ b/bin/oe/db/rocksdb/mod.rs @@ -24,7 +24,8 @@ use self::{ }; use blooms_db; use ethcore::client::ClientConfig; -use kvdb::KeyValueDB; +use ethcore_db::KeyValueDB; +use stats::PrometheusMetrics; use std::{fs, io, path::Path, sync::Arc}; mod blooms; @@ -53,6 +54,10 @@ impl BlockChainDB for AppDB { } } +impl PrometheusMetrics for AppDB { + fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {} +} + /// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path. #[cfg(feature = "secretstore")] pub fn open_secretstore_db(data_path: &str) -> Result, String> { @@ -101,8 +106,11 @@ pub fn open_database( fs::create_dir_all(&blooms_path)?; fs::create_dir_all(&trace_blooms_path)?; + let db = Database::open(&config, client_path)?; + let db_with_metrics = ethcore_db::DatabaseWithMetrics::new(db); + let db = AppDB { - key_value: Arc::new(Database::open(&config, client_path)?), + key_value: Arc::new(db_with_metrics), blooms: blooms_db::Database::open(blooms_path)?, trace_blooms: blooms_db::Database::open(trace_blooms_path)?, }; diff --git a/bin/oe/metrics.rs b/bin/oe/metrics.rs index da083bd8d7..7c7119bcf7 100644 --- a/bin/oe/metrics.rs +++ b/bin/oe/metrics.rs @@ -8,13 +8,15 @@ use hyper::{service::service_fn_ok, Body, Method, Request, Response, Server, Sta use stats::{ prometheus::{self, Encoder}, - prometheus_gauge, PrometheusMetrics, + PrometheusMetrics, PrometheusRegistry, }; #[derive(Debug, Clone, PartialEq)] pub struct MetricsConfiguration { /// Are metrics enabled (default is false)? pub enabled: bool, + /// Prefix + pub prefix: String, /// The IP of the network interface used (default is 127.0.0.1). pub interface: String, /// The network port (default is 3000). @@ -25,6 +27,7 @@ impl Default for MetricsConfiguration { fn default() -> Self { MetricsConfiguration { enabled: false, + prefix: "".into(), interface: "127.0.0.1".into(), port: 3000, } @@ -35,19 +38,22 @@ struct State { rpc_apis: Arc, } -fn handle_request(req: Request, state: Arc>) -> Response { +fn handle_request( + req: Request, + conf: Arc, + state: Arc>, +) -> Response { let (parts, _body) = req.into_parts(); match (parts.method, parts.uri.path()) { (Method::GET, "/metrics") => { let start = Instant::now(); - let mut reg = prometheus::Registry::new(); + let mut reg = PrometheusRegistry::new(conf.prefix.clone()); let state = state.lock(); state.rpc_apis.client.prometheus_metrics(&mut reg); state.rpc_apis.sync.prometheus_metrics(&mut reg); let elapsed = start.elapsed(); - prometheus_gauge( - &mut reg, + reg.register_gauge( "metrics_time", "Time to perform rpc metrics", elapsed.as_millis() as i64, @@ -55,7 +61,7 @@ fn handle_request(req: Request, state: Arc>) -> Response| handle_request(req, state.clone())) + let conf = conf.clone(); + service_fn_ok(move |req: Request| { + handle_request(req, conf.clone(), state.clone()) + }) }) .map_err(|e| eprintln!("server error: {}", e)); - println!("Listening on http://{}", addr); + info!("Started prometeus metrics at http://{}/metrics", addr); deps.executor.spawn(server); diff --git a/crates/concensus/miner/local-store/Cargo.toml b/crates/concensus/miner/local-store/Cargo.toml index db34cd7c7f..463470c869 100644 --- a/crates/concensus/miner/local-store/Cargo.toml +++ b/crates/concensus/miner/local-store/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] [dependencies] common-types = { path = "../../../ethcore/types" } ethcore-io = { path = "../../../runtime/io" } +ethcore-db = { path = "../../../db/db"} kvdb = "0.1" log = "0.4" rlp = { version = "0.3.0", features = ["ethereum"] } diff --git a/crates/concensus/miner/local-store/src/lib.rs b/crates/concensus/miner/local-store/src/lib.rs index 9dd80dc356..0d2a3657cb 100644 --- a/crates/concensus/miner/local-store/src/lib.rs +++ b/crates/concensus/miner/local-store/src/lib.rs @@ -18,14 +18,15 @@ use std::{fmt, sync::Arc, time::Duration}; +use ethcore_db::KeyValueDB; use io::IoHandler; -use kvdb::KeyValueDB; use types::transaction::{ Condition as TransactionCondition, PendingTransaction, SignedTransaction, TypedTransaction, UnverifiedTransaction, }; extern crate common_types as types; +extern crate ethcore_db; extern crate ethcore_io as io; extern crate kvdb; extern crate rlp; @@ -253,7 +254,7 @@ mod tests { #[test] fn twice_empty() { - let db = Arc::new(::kvdb_memorydb::create(0)); + let db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); { let store = super::create(db.clone(), None, Dummy(vec![])); @@ -284,7 +285,7 @@ mod tests { }) .collect(); - let db = Arc::new(::kvdb_memorydb::create(0)); + let db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); { // nothing written yet, will write pending. @@ -325,7 +326,7 @@ mod tests { PendingTransaction::new(signed, None) }); - let db = Arc::new(::kvdb_memorydb::create(0)); + let db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); { // nothing written, will write bad. let store = super::create(db.clone(), None, Dummy(transactions.clone())); diff --git a/crates/db/db/Cargo.toml b/crates/db/db/Cargo.toml index 64f175c24a..7b6ebbfde7 100644 --- a/crates/db/db/Cargo.toml +++ b/crates/db/db/Cargo.toml @@ -12,6 +12,9 @@ common-types = { path = "../../ethcore/types" } ethereum-types = "0.4" heapsize = "0.4" kvdb = "0.1" +kvdb-rocksdb = "0.1.3" +kvdb-memorydb = "0.1" parking_lot = "0.7" rlp = { version = "0.3.0", features = ["ethereum"] } rlp_derive = { path = "../../util/rlp-derive" } +stats = { path = "../../util/stats" } \ No newline at end of file diff --git a/crates/db/db/src/db.rs b/crates/db/db/src/db.rs index 67cba2fbdf..464300a251 100644 --- a/crates/db/db/src/db.rs +++ b/crates/db/db/src/db.rs @@ -16,9 +16,11 @@ //! Database utilities and definitions. -use kvdb::{DBTransaction, KeyValueDB}; +use kvdb::DBTransaction; +use kvdb_rocksdb::Database; use parking_lot::RwLock; -use std::{collections::HashMap, hash::Hash, ops::Deref}; +use stats::{PrometheusMetrics, PrometheusRegistry}; +use std::{collections::HashMap, hash::Hash, io::Read, ops::Deref}; use rlp; @@ -282,7 +284,7 @@ impl Writable for DBTransaction { } } -impl Readable for KVDB { +impl Readable for KVDB { fn read(&self, col: Option, key: &dyn Key) -> Option where T: rlp::Decodable, @@ -311,3 +313,197 @@ impl Readable for KVDB { } } } + +/// Database with enabled statistics +pub struct DatabaseWithMetrics { + db: Database, + reads: std::sync::atomic::AtomicI64, + writes: std::sync::atomic::AtomicI64, + bytes_read: std::sync::atomic::AtomicI64, + bytes_written: std::sync::atomic::AtomicI64, +} + +impl DatabaseWithMetrics { + /// Create a new instance + pub fn new(db: Database) -> Self { + Self { + db, + reads: std::sync::atomic::AtomicI64::new(0), + writes: std::sync::atomic::AtomicI64::new(0), + bytes_read: std::sync::atomic::AtomicI64::new(0), + bytes_written: std::sync::atomic::AtomicI64::new(0), + } + } +} + +/// Ethcore definition of a KeyValueDB with embeeded metrics +pub trait KeyValueDB: kvdb::KeyValueDB + PrometheusMetrics {} + +impl kvdb::KeyValueDB for DatabaseWithMetrics { + fn get(&self, col: Option, key: &[u8]) -> std::io::Result> { + let res = self.db.get(col, key); + let count = res + .as_ref() + .map_or(0, |y| y.as_ref().map_or(0, |x| x.bytes().count())); + + self.reads + .fetch_add(1, std::sync::atomic::Ordering::Relaxed); + self.bytes_read + .fetch_add(count as i64, std::sync::atomic::Ordering::Relaxed); + + res + } + fn get_by_prefix(&self, col: Option, prefix: &[u8]) -> Option> { + let res = self.db.get_by_prefix(col, prefix); + let count = res.as_ref().map_or(0, |x| x.bytes().count()); + + self.reads + .fetch_add(1, std::sync::atomic::Ordering::Relaxed); + self.bytes_read + .fetch_add(count as i64, std::sync::atomic::Ordering::Relaxed); + + res + } + fn write_buffered(&self, transaction: DBTransaction) { + let mut count = 0; + for op in &transaction.ops { + count += match op { + kvdb::DBOp::Insert { value, .. } => value.bytes().count(), + _ => 0, + }; + } + + self.writes.fetch_add( + transaction.ops.len() as i64, + std::sync::atomic::Ordering::Relaxed, + ); + self.bytes_written + .fetch_add(count as i64, std::sync::atomic::Ordering::Relaxed); + + self.db.write_buffered(transaction) + } + fn write(&self, transaction: DBTransaction) -> std::io::Result<()> { + let mut count = 0; + for op in &transaction.ops { + count += match op { + kvdb::DBOp::Insert { value, .. } => value.bytes().count(), + _ => 0, + }; + } + + self.bytes_written + .fetch_add(count as i64, std::sync::atomic::Ordering::Relaxed); + self.writes.fetch_add( + transaction.ops.len() as i64, + std::sync::atomic::Ordering::Relaxed, + ); + self.db.write(transaction) + } + fn flush(&self) -> std::io::Result<()> { + self.db.flush() + } + + fn iter<'a>( + &'a self, + col: Option, + ) -> Box<(dyn Iterator, Box<[u8]>)> + 'a)> { + kvdb::KeyValueDB::iter(&self.db, col) + } + + fn iter_from_prefix<'a>( + &'a self, + col: Option, + prefix: &'a [u8], + ) -> Box, Box<[u8]>)> + 'a> { + self.db.iter_from_prefix(col, prefix) + } + + fn restore(&self, new_db: &str) -> std::io::Result<()> { + self.db.restore(new_db) + } +} + +impl KeyValueDB for DatabaseWithMetrics {} + +impl PrometheusMetrics for DatabaseWithMetrics { + fn prometheus_metrics(&self, p: &mut PrometheusRegistry) { + p.register_counter( + "kvdb_reads", + "db reads", + self.reads.load(std::sync::atomic::Ordering::Relaxed) as i64, + ); + p.register_counter( + "kvdb_writes", + "db writes", + self.writes.load(std::sync::atomic::Ordering::Relaxed) as i64, + ); + p.register_counter( + "kvdb_bytes_read", + "db bytes_reads", + self.bytes_read.load(std::sync::atomic::Ordering::Relaxed) as i64, + ); + p.register_counter( + "kvdb_bytes_written", + "db bytes_written", + self.bytes_written + .load(std::sync::atomic::Ordering::Relaxed) as i64, + ); + } +} + +/// InMemory with disabled statistics +pub struct InMemoryWithMetrics { + db: kvdb_memorydb::InMemory, +} + +impl kvdb::KeyValueDB for InMemoryWithMetrics { + fn get(&self, col: Option, key: &[u8]) -> std::io::Result> { + self.db.get(col, key) + } + fn get_by_prefix(&self, col: Option, prefix: &[u8]) -> Option> { + self.db.get_by_prefix(col, prefix) + } + fn write_buffered(&self, transaction: DBTransaction) { + self.db.write_buffered(transaction) + } + fn write(&self, transaction: DBTransaction) -> std::io::Result<()> { + self.db.write(transaction) + } + fn flush(&self) -> std::io::Result<()> { + self.db.flush() + } + + fn iter<'a>( + &'a self, + col: Option, + ) -> Box<(dyn Iterator, Box<[u8]>)> + 'a)> { + kvdb::KeyValueDB::iter(&self.db, col) + } + + fn iter_from_prefix<'a>( + &'a self, + col: Option, + prefix: &'a [u8], + ) -> Box, Box<[u8]>)> + 'a> { + self.db.iter_from_prefix(col, prefix) + } + + fn restore(&self, new_db: &str) -> std::io::Result<()> { + self.db.restore(new_db) + } +} + +impl PrometheusMetrics for InMemoryWithMetrics { + fn prometheus_metrics(&self, _: &mut PrometheusRegistry) {} +} + +impl KeyValueDB for InMemoryWithMetrics {} + +impl InMemoryWithMetrics { + /// Create new instance + pub fn create(num_cols: u32) -> Self { + Self { + db: kvdb_memorydb::create(num_cols), + } + } +} diff --git a/crates/db/db/src/lib.rs b/crates/db/db/src/lib.rs index 9181b64029..29d33cc02a 100644 --- a/crates/db/db/src/lib.rs +++ b/crates/db/db/src/lib.rs @@ -22,5 +22,6 @@ mod db; pub mod cache_manager; pub mod keys; +pub use kvdb::{DBTransaction, DBValue}; pub use self::db::*; diff --git a/crates/db/journaldb/Cargo.toml b/crates/db/journaldb/Cargo.toml index 5ca9853ab6..9c331e14db 100644 --- a/crates/db/journaldb/Cargo.toml +++ b/crates/db/journaldb/Cargo.toml @@ -11,6 +11,7 @@ ethereum-types = "0.4" hash-db = "0.11.0" heapsize = "0.4" keccak-hasher = { path = "../../util/keccak-hasher" } +ethcore-db = { path = "../../db/db"} kvdb = "0.1" log = "0.4" memory-db = { path = "../memory-db" } diff --git a/crates/db/journaldb/src/archivedb.rs b/crates/db/journaldb/src/archivedb.rs index 53ad461407..79cafcd7bc 100644 --- a/crates/db/journaldb/src/archivedb.rs +++ b/crates/db/journaldb/src/archivedb.rs @@ -25,10 +25,10 @@ use std::{ use super::{ error_key_already_exists, error_negatively_reference_hash, memory_db::*, LATEST_ERA_KEY, }; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; use keccak_hasher::KeccakHasher; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use rlp::{decode, encode}; use traits::JournalDB; @@ -222,13 +222,12 @@ mod tests { use super::*; use hash_db::HashDB; use keccak::keccak; - use kvdb_memorydb; use JournalDB; #[test] fn insert_same_in_fork() { // history is 1 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let x = jdb.insert(b"X"); jdb.commit_batch(1, &keccak(b"1"), None).unwrap(); @@ -256,7 +255,7 @@ mod tests { #[test] fn long_history() { // history is 3 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let h = jdb.insert(b"foo"); jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&h)); @@ -276,7 +275,7 @@ mod tests { #[test] #[should_panic] fn multiple_owed_removal_not_allowed() { - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let h = jdb.insert(b"foo"); jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); assert!(jdb.contains(&h)); @@ -290,7 +289,7 @@ mod tests { #[test] fn complex() { // history is 1 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -326,7 +325,7 @@ mod tests { #[test] fn fork() { // history is 1 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -355,7 +354,7 @@ mod tests { #[test] fn overwrite() { // history is 1 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let foo = jdb.insert(b"foo"); jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); @@ -377,7 +376,7 @@ mod tests { #[test] fn fork_same_key() { // history is 1 - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); jdb.commit_batch(0, &keccak(b"0"), None).unwrap(); let foo = jdb.insert(b"foo"); @@ -396,7 +395,7 @@ mod tests { #[test] fn reopen() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let bar = H256::random(); let foo = { @@ -426,7 +425,7 @@ mod tests { #[test] fn reopen_remove() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let foo = { let mut jdb = ArchiveDB::new(shared_db.clone(), None); @@ -460,7 +459,7 @@ mod tests { #[test] fn reopen_fork() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let (foo, _, _) = { let mut jdb = ArchiveDB::new(shared_db.clone(), None); // history is 1 @@ -488,7 +487,7 @@ mod tests { #[test] fn inject() { - let mut jdb = ArchiveDB::new(Arc::new(kvdb_memorydb::create(0)), None); + let mut jdb = ArchiveDB::new(Arc::new(ethcore_db::InMemoryWithMetrics::create(0)), None); let key = jdb.insert(b"dog"); jdb.inject_batch().unwrap(); diff --git a/crates/db/journaldb/src/earlymergedb.rs b/crates/db/journaldb/src/earlymergedb.rs index cf5ad0a82b..2d1c5be69d 100644 --- a/crates/db/journaldb/src/earlymergedb.rs +++ b/crates/db/journaldb/src/earlymergedb.rs @@ -26,11 +26,11 @@ use super::{ error_key_already_exists, error_negatively_reference_hash, traits::JournalDB, LATEST_ERA_KEY, }; use bytes::Bytes; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use memory_db::*; use parking_lot::RwLock; use rlp::{decode, encode}; @@ -622,7 +622,6 @@ mod tests { use super::{super::traits::JournalDB, *}; use hash_db::HashDB; use keccak::keccak; - use kvdb_memorydb; #[test] fn insert_same_in_fork() { @@ -913,13 +912,13 @@ mod tests { } fn new_db() -> EarlyMergeDB { - let backing = Arc::new(kvdb_memorydb::create(0)); + let backing = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); EarlyMergeDB::new(backing, None) } #[test] fn reopen() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let bar = H256::random(); let foo = { @@ -1105,7 +1104,7 @@ mod tests { fn reopen_remove_three() { let _ = ::env_logger::try_init(); - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let foo = keccak(b"foo"); { @@ -1166,7 +1165,7 @@ mod tests { #[test] fn reopen_fork() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let (foo, bar, baz) = { let mut jdb = EarlyMergeDB::new(shared_db.clone(), None); diff --git a/crates/db/journaldb/src/lib.rs b/crates/db/journaldb/src/lib.rs index b41bb0a35f..1365302f5a 100644 --- a/crates/db/journaldb/src/lib.rs +++ b/crates/db/journaldb/src/lib.rs @@ -20,6 +20,7 @@ extern crate heapsize; #[macro_use] extern crate log; +extern crate ethcore_db; extern crate ethereum_types; extern crate fastmap; extern crate hash_db; @@ -147,7 +148,7 @@ impl fmt::Display for Algorithm { /// Create a new `JournalDB` trait object over a generic key-value database. pub fn new( - backing: Arc, + backing: Arc, algorithm: Algorithm, col: Option, ) -> Box { diff --git a/crates/db/journaldb/src/overlaydb.rs b/crates/db/journaldb/src/overlaydb.rs index 3828842cb9..5df5d0bc4f 100644 --- a/crates/db/journaldb/src/overlaydb.rs +++ b/crates/db/journaldb/src/overlaydb.rs @@ -23,10 +23,10 @@ use std::{ }; use super::error_negatively_reference_hash; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; use keccak_hasher::KeccakHasher; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use memory_db::*; use rlp::{decode, encode, Decodable, DecoderError, Encodable, Rlp, RlpStream}; @@ -88,7 +88,7 @@ impl OverlayDB { /// Create a new instance of OverlayDB with an anonymous temporary database. #[cfg(test)] pub fn new_temp() -> OverlayDB { - let backing = Arc::new(::kvdb_memorydb::create(0)); + let backing = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); Self::new(backing, None) } diff --git a/crates/db/journaldb/src/overlayrecentdb.rs b/crates/db/journaldb/src/overlayrecentdb.rs index 8a51161c74..84ae4b3ad3 100644 --- a/crates/db/journaldb/src/overlayrecentdb.rs +++ b/crates/db/journaldb/src/overlayrecentdb.rs @@ -23,12 +23,12 @@ use std::{ }; use super::{error_negatively_reference_hash, JournalDB, DB_PREFIX_LEN, LATEST_ERA_KEY}; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use fastmap::H256FastMap; use hash_db::HashDB; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use memory_db::*; use parking_lot::RwLock; use rlp::{decode, encode, Decodable, DecoderError, Encodable, Rlp, RlpStream}; @@ -554,11 +554,10 @@ mod tests { use super::*; use hash_db::HashDB; use keccak::keccak; - use kvdb_memorydb; use JournalDB; fn new_db() -> OverlayRecentDB { - let backing = Arc::new(kvdb_memorydb::create(0)); + let backing = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); OverlayRecentDB::new(backing, None) } @@ -832,7 +831,7 @@ mod tests { #[test] fn reopen() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let bar = H256::random(); let foo = { @@ -1015,7 +1014,7 @@ mod tests { fn reopen_remove_three() { let _ = ::env_logger::try_init(); - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let foo = keccak(b"foo"); { @@ -1076,7 +1075,7 @@ mod tests { #[test] fn reopen_fork() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); let (foo, bar, baz) = { let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); @@ -1146,7 +1145,7 @@ mod tests { #[test] fn earliest_era() { - let shared_db = Arc::new(kvdb_memorydb::create(0)); + let shared_db = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); // empty DB let mut jdb = OverlayRecentDB::new(shared_db.clone(), None); diff --git a/crates/db/journaldb/src/refcounteddb.rs b/crates/db/journaldb/src/refcounteddb.rs index ee4d1a0b28..73ac77945c 100644 --- a/crates/db/journaldb/src/refcounteddb.rs +++ b/crates/db/journaldb/src/refcounteddb.rs @@ -23,11 +23,11 @@ use std::{ }; use super::{traits::JournalDB, LATEST_ERA_KEY}; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use memory_db::MemoryDB; use overlaydb::OverlayDB; use rlp::{decode, encode}; @@ -252,11 +252,10 @@ mod tests { use super::*; use hash_db::HashDB; use keccak::keccak; - use kvdb_memorydb; use JournalDB; fn new_db() -> RefCountedDB { - let backing = Arc::new(kvdb_memorydb::create(0)); + let backing = Arc::new(ethcore_db::InMemoryWithMetrics::create(0)); RefCountedDB::new(backing, None) } diff --git a/crates/db/journaldb/src/traits.rs b/crates/db/journaldb/src/traits.rs index 3cc2cdb320..ecd2d556ed 100644 --- a/crates/db/journaldb/src/traits.rs +++ b/crates/db/journaldb/src/traits.rs @@ -18,10 +18,10 @@ use std::{io, sync::Arc}; +use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::{AsHashDB, HashDB}; use keccak_hasher::KeccakHasher; -use kvdb::{self, DBTransaction, DBValue}; use std::collections::{BTreeMap, HashMap}; /// expose keys of a hashDB for debugging or tests (slow). @@ -86,7 +86,7 @@ pub trait JournalDB: KeyedHashDB { } /// Get backing database. - fn backing(&self) -> &Arc; + fn backing(&self) -> &Arc; /// Clear internal strucutres. This should called after changes have been written /// to the backing strage diff --git a/crates/ethcore/blockchain/Cargo.toml b/crates/ethcore/blockchain/Cargo.toml index d20a238895..75f3135a52 100644 --- a/crates/ethcore/blockchain/Cargo.toml +++ b/crates/ethcore/blockchain/Cargo.toml @@ -26,6 +26,7 @@ rlp = { version = "0.3.0", features = ["ethereum"] } rlp_compress = { path = "../../util/rlp-compress" } rlp_derive = { path = "../../util/rlp-derive" } triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" } +stats = { path = "../../util/stats" } [dev-dependencies] env_logger = "0.5" diff --git a/crates/ethcore/blockchain/src/blockchain.rs b/crates/ethcore/blockchain/src/blockchain.rs index a03b25aae6..1363304ff9 100644 --- a/crates/ethcore/blockchain/src/blockchain.rs +++ b/crates/ethcore/blockchain/src/blockchain.rs @@ -41,6 +41,7 @@ use common_types::{ views::{BlockView, HeaderView}, BlockNumber, }; +use db::{DBTransaction, KeyValueDB}; use ethcore_db::{ self as db, cache_manager::CacheManager, @@ -50,13 +51,13 @@ use ethcore_db::{ use ethereum_types::{Bloom, BloomRef, H256, U256}; use heapsize::HeapSizeOf; use itertools::Itertools; -use kvdb::{DBTransaction, KeyValueDB}; use log::{info, trace, warn}; use parity_bytes::Bytes; use parking_lot::{Mutex, RwLock}; use rayon::prelude::*; use rlp::RlpStream; use rlp_compress::{blocks_swapper, compress, decompress}; +use stats::PrometheusMetrics; use crate::{ best_block::{BestAncientBlock, BestBlock}, @@ -66,7 +67,7 @@ use crate::{ }; /// Database backing `BlockChain`. -pub trait BlockChainDB: Send + Sync { +pub trait BlockChainDB: Send + Sync + PrometheusMetrics { /// Generic key value store. fn key_value(&self) -> &Arc; @@ -1950,6 +1951,9 @@ mod tests { &self.trace_blooms } } + impl PrometheusMetrics for TestBlockChainDB { + fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {} + } /// Creates new test instance of `BlockChainDB` pub fn new_db() -> Arc { @@ -1961,7 +1965,9 @@ mod tests { trace_blooms: blooms_db::Database::open(trace_blooms_dir.path()).unwrap(), _blooms_dir: blooms_dir, _trace_blooms_dir: trace_blooms_dir, - key_value: Arc::new(kvdb_memorydb::create(ethcore_db::NUM_COLUMNS.unwrap())), + key_value: Arc::new(ethcore_db::InMemoryWithMetrics::create( + ethcore_db::NUM_COLUMNS.unwrap(), + )), }; Arc::new(db) diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 80531f7211..a9cba475f8 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -33,12 +33,12 @@ use blockchain::{ }; use bytes::{Bytes, ToPretty}; use call_contract::CallContract; +use db::{DBTransaction, DBValue, KeyValueDB}; use error::Error; use ethcore_miner::pool::VerifiedTransaction; use ethereum_types::{Address, H256, H264, U256}; use hash::keccak; use itertools::Itertools; -use kvdb::{DBTransaction, DBValue, KeyValueDB}; use parking_lot::{Mutex, RwLock}; use rand::OsRng; use rlp::{PayloadInfo, Rlp}; @@ -88,7 +88,7 @@ use snapshot::{self, io as snapshot_io, SnapshotClient}; use spec::Spec; use state::{self, State}; use state_db::StateDB; -use stats::{prometheus, prometheus_counter, prometheus_gauge, PrometheusMetrics}; +use stats::{PrometheusMetrics, PrometheusRegistry}; use trace::{ self, Database as TraceDatabase, ImportRequest as TraceImportRequest, LocalizedTrace, TraceDB, }; @@ -3236,41 +3236,36 @@ impl IoChannelQueue { } impl PrometheusMetrics for Client { - fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + fn prometheus_metrics(&self, r: &mut PrometheusRegistry) { // gas, tx & blocks let report = self.report(); for (key, value) in report.item_sizes.iter() { - prometheus_gauge( - r, + r.register_gauge( &key, format!("Total item number of {}", key).as_str(), *value as i64, ); } - prometheus_counter( - r, + r.register_counter( "import_gas", "Gas processed", report.gas_processed.as_u64() as i64, ); - prometheus_counter( - r, + r.register_counter( "import_blocks", "Blocks imported", report.blocks_imported as i64, ); - prometheus_counter( - r, + r.register_counter( "import_txs", "Transactions applied", report.transactions_applied as i64, ); let state_db = self.state_db.read(); - prometheus_gauge( - r, + r.register_gauge( "statedb_cache_size", "State DB cache size", state_db.cache_size() as i64, @@ -3278,32 +3273,27 @@ impl PrometheusMetrics for Client { // blockchain cache let blockchain_cache_info = self.blockchain_cache_info(); - prometheus_gauge( - r, + r.register_gauge( "blockchaincache_block_details", "BlockDetails cache size", blockchain_cache_info.block_details as i64, ); - prometheus_gauge( - r, + r.register_gauge( "blockchaincache_block_recipts", "Block receipts size", blockchain_cache_info.block_receipts as i64, ); - prometheus_gauge( - r, + r.register_gauge( "blockchaincache_blocks", "Blocks cache size", blockchain_cache_info.blocks as i64, ); - prometheus_gauge( - r, + r.register_gauge( "blockchaincache_txaddrs", "Transaction addresses cache size", blockchain_cache_info.transaction_addresses as i64, ); - prometheus_gauge( - r, + r.register_gauge( "blockchaincache_size", "Total blockchain cache size", blockchain_cache_info.total() as i64, @@ -3321,22 +3311,19 @@ impl PrometheusMetrics for Client { .map(|last| (first, U256::from(last))) }); if let Some((first, last)) = gap { - prometheus_gauge( - r, + r.register_gauge( "chain_warpsync_gap_first", "Warp sync gap, first block", first.as_u64() as i64, ); - prometheus_gauge( - r, + r.register_gauge( "chain_warpsync_gap_last", "Warp sync gap, last block", last.as_u64() as i64, ); } - prometheus_gauge( - r, + r.register_gauge( "chain_block", "Best block number", chain.best_block_number as i64, @@ -3344,14 +3331,12 @@ impl PrometheusMetrics for Client { // prunning info let prunning = self.pruning_info(); - prometheus_gauge( - r, + r.register_gauge( "prunning_earliest_chain", "The first block which everything can be served after", prunning.earliest_chain as i64, ); - prometheus_gauge( - r, + r.register_gauge( "prunning_earliest_state", "The first block where state requests may be served", prunning.earliest_state as i64, @@ -3359,36 +3344,34 @@ impl PrometheusMetrics for Client { // queue info let queue = self.queue_info(); - prometheus_gauge( - r, + r.register_gauge( "queue_mem_used", "Queue heap memory used in bytes", queue.mem_used as i64, ); - prometheus_gauge( - r, + r.register_gauge( "queue_size_total", "The total size of the queues", queue.total_queue_size() as i64, ); - prometheus_gauge( - r, + r.register_gauge( "queue_size_unverified", "Number of queued items pending verification", queue.unverified_queue_size as i64, ); - prometheus_gauge( - r, + r.register_gauge( "queue_size_verified", "Number of verified queued items pending import", queue.verified_queue_size as i64, ); - prometheus_gauge( - r, + r.register_gauge( "queue_size_verifying", "Number of items being verified", queue.verifying_queue_size as i64, ); + + // database info + self.db.read().key_value().prometheus_metrics(r); } } diff --git a/crates/ethcore/src/client/evm_test_client.rs b/crates/ethcore/src/client/evm_test_client.rs index a80a7c04a1..bc9eac40d4 100644 --- a/crates/ethcore/src/client/evm_test_client.rs +++ b/crates/ethcore/src/client/evm_test_client.rs @@ -25,7 +25,6 @@ use executive; use factory::{self, Factories}; use journaldb; use kvdb::{self, KeyValueDB}; -use kvdb_memorydb; use pod_state; use spec; use state; @@ -181,7 +180,7 @@ impl<'a> EvmTestClient<'a> { spec: &'a spec::Spec, factories: &Factories, ) -> Result, EvmTestError> { - let db = Arc::new(kvdb_memorydb::create( + let db = Arc::new(ethcore_db::InMemoryWithMetrics::create( db::NUM_COLUMNS.expect("We use column-based DB; qed"), )); let journal_db = @@ -211,7 +210,7 @@ impl<'a> EvmTestClient<'a> { factories: &Factories, pod_state: pod_state::PodState, ) -> Result, EvmTestError> { - let db = Arc::new(kvdb_memorydb::create( + let db = Arc::new(ethcore_db::InMemoryWithMetrics::create( db::NUM_COLUMNS.expect("We use column-based DB; qed"), )); let journal_db = diff --git a/crates/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs index 6e284e6c2e..28195da230 100644 --- a/crates/ethcore/src/client/test_client.rs +++ b/crates/ethcore/src/client/test_client.rs @@ -34,7 +34,6 @@ use ethtrie; use hash::keccak; use itertools::Itertools; use kvdb::DBValue; -use kvdb_memorydb; use parking_lot::RwLock; use rlp::RlpStream; use rustc_hex::FromHex; @@ -75,7 +74,7 @@ use miner::{self, Miner, MinerService}; use spec::Spec; use state::StateInfo; use state_db::StateDB; -use stats::{prometheus, PrometheusMetrics}; +use stats::{PrometheusMetrics, PrometheusRegistry}; use trace::LocalizedTrace; use verification::queue::{kind::blocks::Unverified, QueueInfo}; @@ -409,7 +408,7 @@ impl TestBlockChainClient { /// Get temporary db state1 pub fn get_temp_state_db() -> StateDB { - let db = kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0)); + let db = ethcore_db::InMemoryWithMetrics::create(NUM_COLUMNS.unwrap_or(0)); let journal_db = journaldb::new(Arc::new(db), journaldb::Algorithm::EarlyMerge, COL_STATE); StateDB::new(journal_db, 1024 * 1024) } @@ -1132,5 +1131,5 @@ impl super::traits::EngineClient for TestBlockChainClient { } impl PrometheusMetrics for TestBlockChainClient { - fn prometheus_metrics(&self, _r: &mut prometheus::Registry) {} + fn prometheus_metrics(&self, _r: &mut PrometheusRegistry) {} } diff --git a/crates/ethcore/src/lib.rs b/crates/ethcore/src/lib.rs index 8a95f22139..ba87d3ef48 100644 --- a/crates/ethcore/src/lib.rs +++ b/crates/ethcore/src/lib.rs @@ -73,8 +73,6 @@ extern crate ethcore_accounts as accounts; extern crate ethcore_stratum; #[cfg(feature = "json-tests")] extern crate globset; -#[cfg(any(test, feature = "test-helpers"))] -extern crate kvdb_memorydb; #[cfg(any(test, feature = "kvdb-rocksdb"))] extern crate kvdb_rocksdb; #[cfg(test)] diff --git a/crates/ethcore/src/snapshot/consensus/authority.rs b/crates/ethcore/src/snapshot/consensus/authority.rs index 9c74e9ec02..4b03d6588d 100644 --- a/crates/ethcore/src/snapshot/consensus/authority.rs +++ b/crates/ethcore/src/snapshot/consensus/authority.rs @@ -32,9 +32,9 @@ use snapshot::{Error, ManifestData, Progress}; use blockchain::{BlockChain, BlockChainDB, BlockProvider}; use bytes::Bytes; +use db::KeyValueDB; use ethereum_types::{H256, U256}; use itertools::{Itertools, Position}; -use kvdb::KeyValueDB; use rlp::{Rlp, RlpStream}; use types::{ encoded, header::Header, ids::BlockId, receipt::TypedReceipt, transaction::TypedTransaction, diff --git a/crates/ethcore/src/snapshot/consensus/work.rs b/crates/ethcore/src/snapshot/consensus/work.rs index 46d4edd85a..ae9dc364b2 100644 --- a/crates/ethcore/src/snapshot/consensus/work.rs +++ b/crates/ethcore/src/snapshot/consensus/work.rs @@ -32,9 +32,9 @@ use std::{ use blockchain::{BlockChain, BlockChainDB, BlockProvider}; use bytes::Bytes; +use db::KeyValueDB; use engines::EthEngine; use ethereum_types::H256; -use kvdb::KeyValueDB; use rand::OsRng; use rlp::{Rlp, RlpStream}; use snapshot::{block::AbridgedBlock, Error, ManifestData, Progress}; diff --git a/crates/ethcore/src/snapshot/mod.rs b/crates/ethcore/src/snapshot/mod.rs index 5ffd3cff2d..ca9b7f7b09 100644 --- a/crates/ethcore/src/snapshot/mod.rs +++ b/crates/ethcore/src/snapshot/mod.rs @@ -35,12 +35,12 @@ use engines::EthEngine; use types::{header::Header, ids::BlockId}; use bytes::Bytes; +use db::{DBValue, KeyValueDB}; use ethereum_types::H256; use ethtrie::{TrieDB, TrieDBMut}; use hash_db::HashDB; use journaldb::{self, Algorithm, JournalDB}; use keccak_hasher::KeccakHasher; -use kvdb::{DBValue, KeyValueDB}; use num_cpus; use parking_lot::Mutex; use rlp::{Rlp, RlpStream}; diff --git a/crates/ethcore/src/snapshot/tests/state.rs b/crates/ethcore/src/snapshot/tests/state.rs index 06a7e4afec..03653acf61 100644 --- a/crates/ethcore/src/snapshot/tests/state.rs +++ b/crates/ethcore/src/snapshot/tests/state.rs @@ -82,8 +82,11 @@ fn snap_and_restore() { let db_path = tempdir.path().join("db"); let db = { - let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); + let new_db = Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap(); + let new_db_with_metrics: Arc = + Arc::new(ethcore_db::DatabaseWithMetrics::new(new_db)); + let mut rebuilder = + StateRebuilder::new(new_db_with_metrics.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(true); @@ -98,7 +101,7 @@ fn snap_and_restore() { assert_eq!(rebuilder.state_root(), state_root); rebuilder.finalize(1000, H256::default()).unwrap(); - new_db + new_db_with_metrics }; let new_db = journaldb::new(db, Algorithm::OverlayRecent, ::db::COL_STATE); @@ -163,10 +166,11 @@ fn get_code_from_prev_chunk() { let tempdir = TempDir::new("").unwrap(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let new_db = Arc::new(Database::open(&db_cfg, tempdir.path().to_str().unwrap()).unwrap()); - + let new_db = Database::open(&db_cfg, tempdir.path().to_str().unwrap()).unwrap(); + let new_db_with_metrics = Arc::new(db::DatabaseWithMetrics::new(new_db)); { - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); + let mut rebuilder = + StateRebuilder::new(new_db_with_metrics.clone(), Algorithm::OverlayRecent); let flag = AtomicBool::new(true); rebuilder.feed(&chunk1, &flag).unwrap(); @@ -175,7 +179,11 @@ fn get_code_from_prev_chunk() { rebuilder.finalize(1000, H256::random()).unwrap(); } - let state_db = journaldb::new(new_db, Algorithm::OverlayRecent, ::db::COL_STATE); + let state_db = journaldb::new( + new_db_with_metrics, + Algorithm::OverlayRecent, + ::db::COL_STATE, + ); assert_eq!(state_db.earliest_era(), Some(1000)); } @@ -214,8 +222,10 @@ fn checks_flag() { let tempdir = TempDir::new("").unwrap(); let db_path = tempdir.path().join("db"); { - let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); - let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); + let new_db = Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap(); + let new_db_with_metrics = Arc::new(db::DatabaseWithMetrics::new(new_db)); + let mut rebuilder = + StateRebuilder::new(new_db_with_metrics.clone(), Algorithm::OverlayRecent); let reader = PackedReader::new(&snap_file).unwrap().unwrap(); let flag = AtomicBool::new(false); diff --git a/crates/ethcore/src/spec/spec.rs b/crates/ethcore/src/spec/spec.rs index 0ae5835b92..24688c21d6 100644 --- a/crates/ethcore/src/spec/spec.rs +++ b/crates/ethcore/src/spec/spec.rs @@ -970,7 +970,7 @@ impl Spec { let factories = Default::default(); let mut db = journaldb::new( - Arc::new(kvdb_memorydb::create(0)), + Arc::new(db::InMemoryWithMetrics::create(0)), journaldb::Algorithm::Archive, None, ); diff --git a/crates/ethcore/src/test_helpers.rs b/crates/ethcore/src/test_helpers.rs index a8b54e234e..57652dd3df 100644 --- a/crates/ethcore/src/test_helpers.rs +++ b/crates/ethcore/src/test_helpers.rs @@ -23,12 +23,12 @@ use blockchain::{ }; use blooms_db; use bytes::Bytes; +use db::KeyValueDB; use ethereum_types::{Address, H256, U256}; use ethkey::KeyPair; use evm::Factory as EvmFactory; use hash::keccak; use io::IoChannel; -use kvdb::KeyValueDB; use kvdb_rocksdb::{self, Database, DatabaseConfig}; use parking_lot::RwLock; use rlp::{self, RlpStream}; @@ -350,6 +350,10 @@ impl BlockChainDB for TestBlockChainDB { } } +impl stats::PrometheusMetrics for TestBlockChainDB { + fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {} +} + /// Creates new test instance of `BlockChainDB` pub fn new_db() -> Arc { let blooms_dir = TempDir::new("").unwrap(); @@ -360,7 +364,9 @@ pub fn new_db() -> Arc { trace_blooms: blooms_db::Database::open(trace_blooms_dir.path()).unwrap(), _blooms_dir: blooms_dir, _trace_blooms_dir: trace_blooms_dir, - key_value: Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap())), + key_value: Arc::new(ethcore_db::InMemoryWithMetrics::create( + ::db::NUM_COLUMNS.unwrap(), + )), }; Arc::new(db) @@ -374,13 +380,13 @@ pub fn new_temp_db(tempdir: &Path) -> Arc { let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let key_value_db = Database::open(&db_config, key_value_dir.to_str().unwrap()).unwrap(); - + let key_value_db_with_metrics = ethcore_db::DatabaseWithMetrics::new(key_value_db); let db = TestBlockChainDB { blooms: blooms_db::Database::open(blooms_dir.path()).unwrap(), trace_blooms: blooms_db::Database::open(trace_blooms_dir.path()).unwrap(), _blooms_dir: blooms_dir, _trace_blooms_dir: trace_blooms_dir, - key_value: Arc::new(key_value_db), + key_value: Arc::new(key_value_db_with_metrics), }; Arc::new(db) @@ -413,13 +419,14 @@ pub fn restoration_db_handler( &self.trace_blooms } } + impl stats::PrometheusMetrics for RestorationDB { + fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {} + } impl BlockChainDBHandler for RestorationDBHandler { fn open(&self, db_path: &Path) -> io::Result> { - let key_value = Arc::new(kvdb_rocksdb::Database::open( - &self.config, - &db_path.to_string_lossy(), - )?); + let key_value = kvdb_rocksdb::Database::open(&self.config, &db_path.to_string_lossy())?; + let key_value = Arc::new(db::DatabaseWithMetrics::new(key_value)); let blooms_path = db_path.join("blooms"); let trace_blooms_path = db_path.join("trace_blooms"); fs::create_dir_all(&blooms_path)?; diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index e5576aaebb..e451969865 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -42,7 +42,7 @@ use ethkey::Secret; use io::TimerToken; use network::IpFilter; use parking_lot::{Mutex, RwLock}; -use stats::{prometheus, prometheus_counter, prometheus_gauge, PrometheusMetrics}; +use stats::{PrometheusMetrics, PrometheusRegistry}; use std::{ net::{AddrParseError, SocketAddr}, @@ -323,11 +323,11 @@ impl SyncProvider for EthSync { } impl PrometheusMetrics for EthSync { - fn prometheus_metrics(&self, r: &mut prometheus::Registry) { + fn prometheus_metrics(&self, r: &mut PrometheusRegistry) { let scalar = |b| if b { 1i64 } else { 0i64 }; let sync_status = self.status(); - prometheus_gauge(r, + r.register_gauge( "sync_status", "WaitingPeers(0), SnapshotManifest(1), SnapshotData(2), SnapshotWaiting(3), Blocks(4), Idle(5), Waiting(6), NewBlocks(7)", match self.eth_handler.sync.status().state { @@ -342,59 +342,50 @@ impl PrometheusMetrics for EthSync { }); for (key, value) in sync_status.item_sizes.iter() { - prometheus_gauge( - r, + r.register_gauge( &key, format!("Total item number of {}", key).as_str(), *value as i64, ); } - prometheus_gauge( - r, + r.register_gauge( "net_peers", "Total number of connected peers", sync_status.num_peers as i64, ); - prometheus_gauge( - r, + r.register_gauge( "net_active_peers", "Total number of active peers", sync_status.num_active_peers as i64, ); - prometheus_counter( - r, + r.register_counter( "sync_blocks_recieved", "Number of blocks downloaded so far", sync_status.blocks_received as i64, ); - prometheus_counter( - r, + r.register_counter( "sync_blocks_total", "Total number of blocks for the sync process", sync_status.blocks_total as i64, ); - prometheus_gauge( - r, + r.register_gauge( "sync_blocks_highest", "Highest block number in the download queue", sync_status.highest_block_number.unwrap_or(0) as i64, ); - prometheus_gauge( - r, + r.register_gauge( "snapshot_download_active", "1 if downloading snapshots", scalar(sync_status.is_snapshot_syncing()), ); - prometheus_gauge( - r, + r.register_gauge( "snapshot_download_chunks", "Snapshot chunks", sync_status.num_snapshot_chunks as i64, ); - prometheus_gauge( - r, + r.register_gauge( "snapshot_download_chunks_done", "Snapshot chunks downloaded", sync_status.snapshot_chunks_done as i64, @@ -408,8 +399,7 @@ impl PrometheusMetrics for EthSync { .manifest_block() .unwrap_or((0, H256::zero())); - prometheus_gauge( - r, + r.register_gauge( "snapshot_create_block", "First block of the current snapshot creation", if let CreationStatus::Ongoing { block_number } = creation { @@ -418,8 +408,7 @@ impl PrometheusMetrics for EthSync { 0 }, ); - prometheus_gauge( - r, + r.register_gauge( "snapshot_restore_block", "First block of the current snapshot restoration", if let RestorationStatus::Ongoing { block_number, .. } = restoration { @@ -428,8 +417,7 @@ impl PrometheusMetrics for EthSync { 0 }, ); - prometheus_gauge( - r, + r.register_gauge( "snapshot_manifest_block", "First block number of the present snapshot", manifest_block_num as i64, diff --git a/crates/rpc/src/v1/tests/helpers/sync_provider.rs b/crates/rpc/src/v1/tests/helpers/sync_provider.rs index 6b58bd46f1..c0e87b8935 100644 --- a/crates/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/crates/rpc/src/v1/tests/helpers/sync_provider.rs @@ -19,7 +19,7 @@ use ethereum_types::H256; use network::client_version::ClientVersion; use parking_lot::RwLock; -use stats::{prometheus, PrometheusMetrics}; +use stats::{PrometheusMetrics, PrometheusRegistry}; use std::collections::BTreeMap; use sync::{EthProtocolInfo, PeerInfo, SyncProvider, SyncState, SyncStatus, TransactionStats}; @@ -69,7 +69,7 @@ impl TestSyncProvider { } impl PrometheusMetrics for TestSyncProvider { - fn prometheus_metrics(&self, _: &mut prometheus::Registry) {} + fn prometheus_metrics(&self, _: &mut PrometheusRegistry) {} } impl SyncProvider for TestSyncProvider { diff --git a/crates/util/stats/src/lib.rs b/crates/util/stats/src/lib.rs index b6b351bc1e..633ef42e75 100644 --- a/crates/util/stats/src/lib.rs +++ b/crates/util/stats/src/lib.rs @@ -26,39 +26,64 @@ use std::{ extern crate log; pub extern crate prometheus; -/// Implements a prometheus metrics collector -pub trait PrometheusMetrics { - fn prometheus_metrics(&self, registry: &mut prometheus::Registry); +pub struct PrometheusRegistry { + prefix: String, + registry: prometheus::Registry, } -/// Adds a new prometheus counter with the specified value -pub fn prometheus_counter(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) { - let c = prometheus::IntCounter::new(name, help).expect("name and help must be non-empty"); - c.inc_by(value); - reg.register(Box::new(c)) - .expect("prometheus identifiers must be unique"); -} +impl PrometheusRegistry { + /// Create a new instance with the specified prefix + pub fn new(prefix: String) -> Self { + Self { + prefix, + registry: prometheus::Registry::new(), + } + } + + /// Get internal registry + pub fn registry(&self) -> &prometheus::Registry { + &self.registry + } -/// Adds a new prometheus gauge with the specified gauge -pub fn prometheus_gauge(reg: &mut prometheus::Registry, name: &str, help: &str, value: i64) { - let g = prometheus::IntGauge::new(name, help).expect("name and help must be non-empty"); - g.set(value); - reg.register(Box::new(g)) - .expect("prometheus identifiers must be are unique"); + /// Adds a new prometheus counter with the specified value + pub fn register_counter(&mut self, name: &str, help: &str, value: i64) { + let name = format!("{}{}", self.prefix, name); + let c = prometheus::IntCounter::new(name.as_str(), help) + .expect("name and help must be non-empty"); + c.inc_by(value); + self.registry + .register(Box::new(c)) + .expect("prometheus identifiers must be unique"); + } + + /// Adds a new prometheus gauge with the specified gauge + pub fn register_gauge(&mut self, name: &str, help: &str, value: i64) { + let name = format!("{}{}", self.prefix, name); + let g = prometheus::IntGauge::new(name.as_str(), help) + .expect("name and help must be non-empty"); + g.set(value); + self.registry + .register(Box::new(g)) + .expect("prometheus identifiers must be are unique"); + } + + /// Adds a new prometheus counter with the time spent in running the specified function + pub fn register_optime T, T>(&mut self, name: &str, f: &F) -> T { + let start = Instant::now(); + let t = f(); + let elapsed = start.elapsed(); + self.register_gauge( + &format!("optime_{}", name), + &format!("Time to perform {}", name), + elapsed.as_millis() as i64, + ); + t + } } -/// Adds a new prometheus counter with the time spent in running the specified function -pub fn prometheus_optime T, T>(r: &mut prometheus::Registry, name: &str, f: &F) -> T { - let start = Instant::now(); - let t = f(); - let elapsed = start.elapsed(); - prometheus_gauge( - r, - &format!("optime_{}", name), - &format!("Time to perform {}", name), - elapsed.as_millis() as i64, - ); - t +/// Implements a prometheus metrics collector +pub trait PrometheusMetrics { + fn prometheus_metrics(&self, registry: &mut PrometheusRegistry); } /// Sorted corpus of data. From 91e57c803dd1c46c443866e933cc557362d18259 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 2 Mar 2021 22:48:04 +0100 Subject: [PATCH 076/107] Disable EIP-2315 --- crates/ethcore/res/chainspec/foundation.json | 1 - crates/ethcore/res/chainspec/goerli.json | 1 - crates/ethcore/res/chainspec/rinkeby.json | 1 - crates/ethcore/res/chainspec/ropsten.json | 1 - crates/ethcore/res/chainspec/yolo3.json | 1 - 5 files changed, 5 deletions(-) diff --git a/crates/ethcore/res/chainspec/foundation.json b/crates/ethcore/res/chainspec/foundation.json index 991fe18f57..af2f012581 100644 --- a/crates/ethcore/res/chainspec/foundation.json +++ b/crates/ethcore/res/chainspec/foundation.json @@ -170,7 +170,6 @@ "eip1706Transition": "0x8a61c8", "eip1884Transition": "0x8a61c8", "eip2028Transition": "0x8a61c8", - "eip2315Transition": "0xbad420", "eip2929Transition": "0xbad420", "eip2930Transition": "0xbad420" }, diff --git a/crates/ethcore/res/chainspec/goerli.json b/crates/ethcore/res/chainspec/goerli.json index 01f71a24ac..7f61b10e32 100644 --- a/crates/ethcore/res/chainspec/goerli.json +++ b/crates/ethcore/res/chainspec/goerli.json @@ -31,7 +31,6 @@ "eip1706Transition": "0x17d433", "eip1884Transition": "0x17d433", "eip2028Transition": "0x17d433", - "eip2315Transition": "0x441064", "eip2929Transition": "0x441064", "eip2930Transition": "0x441064", "gasLimitBoundDivisor": "0x400", diff --git a/crates/ethcore/res/chainspec/rinkeby.json b/crates/ethcore/res/chainspec/rinkeby.json index 8a0c59df41..a9c3586d58 100644 --- a/crates/ethcore/res/chainspec/rinkeby.json +++ b/crates/ethcore/res/chainspec/rinkeby.json @@ -31,7 +31,6 @@ "eip1706Transition": "0x52efd1", "eip1884Transition": "0x52efd1", "eip2028Transition": "0x52efd1", - "eip2315Transition": "0x7e8270", "eip2929Transition": "0x7e8270", "eip2930Transition": "0x7e8270", "gasLimitBoundDivisor": "0x400", diff --git a/crates/ethcore/res/chainspec/ropsten.json b/crates/ethcore/res/chainspec/ropsten.json index 5c7a7a4ed4..7ab2ef30e2 100644 --- a/crates/ethcore/res/chainspec/ropsten.json +++ b/crates/ethcore/res/chainspec/ropsten.json @@ -52,7 +52,6 @@ "eip1706Transition": "0x62f756", "eip1884Transition": "0x62f756", "eip2028Transition": "0x62f756", - "eip2315Transition": "0x95b8dd", "eip2929Transition": "0x95b8dd", "eip2930Transition": "0x95b8dd" diff --git a/crates/ethcore/res/chainspec/yolo3.json b/crates/ethcore/res/chainspec/yolo3.json index 114de8c113..e33658c2e9 100644 --- a/crates/ethcore/res/chainspec/yolo3.json +++ b/crates/ethcore/res/chainspec/yolo3.json @@ -28,7 +28,6 @@ "eip2028Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", - "eip2315Transition": "0x0", "eip2929Transition": "0x0", "eip2930Transition": "0x0", "eip658Transition": "0x0", From 0cf0cdbb8638119f52c12fa81f11452ea7e321fc Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 5 Mar 2021 19:25:31 +0100 Subject: [PATCH 077/107] Disable CI on tag for windows2019 machine" This reverts commit efb80e10324973223a8d7e64941b795aa6156e48. --- .github/workflows/build.yml | 92 ++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0cdce51201..fae328913b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,6 @@ jobs: platform: - ubuntu-16.04 - macos-latest - - windows2019 toolchain: - stable runs-on: ${{ matrix.platform }} @@ -37,25 +36,25 @@ jobs: # Windows Build # ============================== - - name: Install LLVM for Windows - if: matrix.platform == 'windows2019' - run: choco install llvm -y + # - name: Install LLVM for Windows + # if: matrix.platform == 'windows2019' + # run: choco install llvm - - name: Build OpenEthereum for Windows - if: matrix.platform == 'windows2019' - run: sh scripts/actions/build-windows.sh ${{matrix.platform}} + # - name: Build OpenEthereum for Windows + # if: matrix.platform == 'windows2019' + # run: sh scripts/actions/build-windows.sh ${{matrix.platform}} - - name: Upload Windows build - uses: actions/upload-artifact@v2 - if: matrix.platform == 'windows2019' - with: - name: windows-artifacts - path: artifacts + # - name: Upload Windows build + # uses: actions/upload-artifact@v2 + # if: matrix.platform == 'windows2019' + # with: + # name: windows-artifacts + # path: artifacts # ============================== # Linux/Macos Build # ============================== - + - name: Build OpenEthereum for ${{matrix.platform}} if: matrix.platform != 'windows2019' run: sh scripts/actions/build-linux.sh ${{matrix.platform}} @@ -133,17 +132,18 @@ jobs: echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') - - name: Create zip Windows - id: create_zip_windows - run: | - cd windows-artifacts/ - zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * - ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip - cd .. - mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . - echo "Setting outputs..." - echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip - echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') + # - name: Create zip Windows + # id: create_zip_windows + # run: | + # cd windows-artifacts/ + # zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip * + # ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # cd .. + # mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip . + + # echo "Setting outputs..." + # echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}') # ======================================================================= # Upload artifacts @@ -162,11 +162,11 @@ jobs: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Upload artifacts + # uses: actions/upload-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip # ======================================================================= # Upload artifacts to S3 @@ -191,8 +191,8 @@ jobs: linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }} macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }} macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }} - windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} - windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} + # windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }} + # windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }} draft-release: name: Draft Release @@ -216,10 +216,10 @@ jobs: with: name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip - - name: Download artifacts - uses: actions/download-artifact@v2 - with: - name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # - name: Download artifacts + # uses: actions/download-artifact@v2 + # with: + # name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - name: Display structure of downloaded files run: ls @@ -273,13 +273,13 @@ jobs: asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip asset_content_type: application/zip - - name: Upload Release Asset - Windows - id: upload_release_asset_windows - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip - asset_content_type: application/zip + # - name: Upload Release Asset - Windows + # id: upload_release_asset_windows + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + # asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip + # asset_content_type: application/zip From dbc5f94241e6f8c55e8f6c1471dd420615995ee2 Mon Sep 17 00:00:00 2001 From: gakada Date: Sat, 6 Mar 2021 19:30:52 +0900 Subject: [PATCH 078/107] Migrate compare_and_swap to compare_exchange (#291) --- bin/oe/run.rs | 10 +++++++++- .../ethcore/src/engines/authority_round/mod.rs | 10 ++++++---- crates/ethcore/src/engines/instant_seal.rs | 16 ++++++++++------ crates/ethcore/src/snapshot/service.rs | 3 ++- crates/ethcore/src/verification/queue/mod.rs | 18 ++++++++++++++---- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/bin/oe/run.rs b/bin/oe/run.rs index e4eae651f7..b1892aebbe 100644 --- a/bin/oe/run.rs +++ b/bin/oe/run.rs @@ -450,7 +450,15 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result for AuthorityRound { /// `Seal::None` will be returned. fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal { // first check to avoid generating signature most of the time - // (but there's still a race to the `compare_and_swap`) + // (but there's still a race to the `compare_exchange`) if !self.step.can_propose.load(AtomicOrdering::SeqCst) { trace!(target: "engine", "Aborting seal generation. Can't propose."); return Seal::None; @@ -1245,7 +1245,8 @@ impl Engine for AuthorityRound { if self .step .can_propose - .compare_and_swap(true, false, AtomicOrdering::SeqCst) + .compare_exchange(true, false, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst) + .is_ok() { self.generate_empty_step(header.parent_hash()); } @@ -1266,11 +1267,12 @@ impl Engine for AuthorityRound { )) { trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step); - // only issue the seal if we were the first to reach the compare_and_swap. + // only issue the seal if we were the first to reach the compare_exchange. if self .step .can_propose - .compare_and_swap(true, false, AtomicOrdering::SeqCst) + .compare_exchange(true, false, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst) + .is_ok() { // we can drop all accumulated empty step messages that are // older than the parent step since we're including them in diff --git a/crates/ethcore/src/engines/instant_seal.rs b/crates/ethcore/src/engines/instant_seal.rs index 0c7749fa06..6d944a52ff 100644 --- a/crates/ethcore/src/engines/instant_seal.rs +++ b/crates/ethcore/src/engines/instant_seal.rs @@ -81,12 +81,16 @@ impl Engine for InstantSeal { // Return a regular seal if the given block is _higher_ than // the last sealed one if block_number > last_sealed_block { - let prev_last_sealed_block = self.last_sealed_block.compare_and_swap( - last_sealed_block, - block_number, - Ordering::SeqCst, - ); - if prev_last_sealed_block == last_sealed_block { + if self + .last_sealed_block + .compare_exchange( + last_sealed_block, + block_number, + Ordering::SeqCst, + Ordering::SeqCst, + ) + .is_ok() + { return Seal::Regular(Vec::new()); } } diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index 556e0609ea..17799b2b17 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -516,7 +516,8 @@ impl Service { pub fn take_snapshot(&self, client: &Client, num: u64) -> Result<(), Error> { if self .taking_snapshot - .compare_and_swap(false, true, Ordering::SeqCst) + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) + .is_err() { info!( "Skipping snapshot at #{} as another one is currently in-progress.", diff --git a/crates/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs index cb67d689c4..b6f2b8bba3 100644 --- a/crates/ethcore/src/verification/queue/mod.rs +++ b/crates/ethcore/src/verification/queue/mod.rs @@ -181,8 +181,13 @@ impl QueueSignal { if self .signalled - .compare_and_swap(false, true, AtomicOrdering::Relaxed) - == false + .compare_exchange( + false, + true, + AtomicOrdering::Relaxed, + AtomicOrdering::Relaxed, + ) + .is_ok() { let channel = self.message_channel.lock().clone(); if let Err(e) = channel.send_sync(ClientIoMessage::BlockVerified) { @@ -199,8 +204,13 @@ impl QueueSignal { if self .signalled - .compare_and_swap(false, true, AtomicOrdering::Relaxed) - == false + .compare_exchange( + false, + true, + AtomicOrdering::Relaxed, + AtomicOrdering::Relaxed, + ) + .is_ok() { let channel = self.message_channel.lock().clone(); if let Err(e) = channel.send(ClientIoMessage::BlockVerified) { From 6f50061f0ca0e81c70fb6bf7f80a5b636b14ff63 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 8 Mar 2021 11:59:04 +0100 Subject: [PATCH 079/107] AuRa multi block reward (#290) * Multi block reward for AuRa * Added test * Better error on wrong config --- .../src/engines/authority_round/mod.rs | 53 +++++++++++++++---- crates/ethcore/src/ethereum/ethash.rs | 19 +++++-- crates/ethjson/src/spec/authority_round.rs | 43 ++++++++++++++- 3 files changed, 99 insertions(+), 16 deletions(-) diff --git a/crates/ethcore/src/engines/authority_round/mod.rs b/crates/ethcore/src/engines/authority_round/mod.rs index 076263d998..dee1a03c0e 100644 --- a/crates/ethcore/src/engines/authority_round/mod.rs +++ b/crates/ethcore/src/engines/authority_round/mod.rs @@ -43,7 +43,7 @@ use engines::{ }; use error::{BlockError, Error, ErrorKind}; use ethereum_types::{Address, H256, H520, U128, U256}; -use ethjson; +use ethjson::{self, uint::Uint}; use ethkey::{self, Signature}; use hash::keccak; use io::{IoContext, IoHandler, IoService, TimerToken}; @@ -80,7 +80,7 @@ pub struct AuthorityRoundParams { /// Immediate transitions. pub immediate_transitions: bool, /// Block reward in base units. - pub block_reward: U256, + pub block_reward: BTreeMap, /// Block reward contract transition block. pub block_reward_contract_transition: u64, /// Block reward contract. @@ -113,7 +113,33 @@ impl From for AuthorityRoundParams { validate_score_transition: p.validate_score_transition.map_or(0, Into::into), validate_step_transition: p.validate_step_transition.map_or(0, Into::into), immediate_transitions: p.immediate_transitions.unwrap_or(false), - block_reward: p.block_reward.map_or_else(Default::default, Into::into), + block_reward: p.block_reward.map_or_else( + || { + let mut ret = BTreeMap::new(); + ret.insert(0, U256::zero()); + ret + }, + |reward| match reward { + ethjson::spec::BlockReward::Single(reward) => { + let mut ret = BTreeMap::new(); + ret.insert(0, reward.into()); + ret + } + ethjson::spec::BlockReward::Multi(mut multi) => { + if multi.is_empty() { + panic!("No block rewards are found in config"); + } + // add block reward from genesis and put reward to zero. + multi + .entry(Uint(U256::from(0))) + .or_insert(Uint(U256::from(0))); + multi + .into_iter() + .map(|(block, reward)| (block.into(), reward.into())) + .collect() + } + }, + ), block_reward_contract_transition: p .block_reward_contract_transition .map_or(0, Into::into), @@ -457,7 +483,7 @@ pub struct AuthorityRound { empty_steps: Mutex>, epoch_manager: Mutex, immediate_transitions: bool, - block_reward: U256, + block_reward: BTreeMap, block_reward_contract_transition: u64, block_reward_contract: Option, maximum_uncle_count_transition: u64, @@ -1374,10 +1400,11 @@ impl Engine for AuthorityRound { } let author = *block.header.author(); + let number = block.header.number(); beneficiaries.push((author, RewardKind::Author)); let rewards: Vec<_> = match self.block_reward_contract { - Some(ref c) if block.header.number() >= self.block_reward_contract_transition => { + Some(ref c) if number >= self.block_reward_contract_transition => { let mut call = super::default_system_or_code_call(&self.machine, block); let rewards = c.reward(&beneficiaries, &mut call)?; @@ -1386,10 +1413,18 @@ impl Engine for AuthorityRound { .map(|(author, amount)| (author, RewardKind::External, amount)) .collect() } - _ => beneficiaries - .into_iter() - .map(|(author, reward_kind)| (author, reward_kind, self.block_reward)) - .collect(), + _ => { + let (_, reward) = self.block_reward.iter() + .rev() + .find(|&(block, _)| *block <= number) + .expect("Current block's reward is not found; this indicates a chain config error; qed"); + let reward = *reward; + + beneficiaries + .into_iter() + .map(|(author, reward_kind)| (author, reward_kind, reward)) + .collect() + } }; block_reward::apply_block_rewards(&rewards, block, &self.machine) diff --git a/crates/ethcore/src/ethereum/ethash.rs b/crates/ethcore/src/ethereum/ethash.rs index f1d0853eaf..be7520f2d8 100644 --- a/crates/ethcore/src/ethereum/ethash.rs +++ b/crates/ethcore/src/ethereum/ethash.rs @@ -17,7 +17,7 @@ use std::{cmp, collections::BTreeMap, path::Path, sync::Arc}; use ethereum_types::{H256, H64, U256}; -use ethjson; +use ethjson::{self, uint::Uint}; use hash::KECCAK_EMPTY_LIST_RLP; use rlp::Rlp; use types::{ @@ -145,10 +145,19 @@ impl From for EthashParams { ret.insert(0, reward.into()); ret } - ethjson::spec::BlockReward::Multi(multi) => multi - .into_iter() - .map(|(block, reward)| (block.into(), reward.into())) - .collect(), + ethjson::spec::BlockReward::Multi(mut multi) => { + if multi.is_empty() { + panic!("No block rewards are found in config"); + } + // add block reward from genesis and put reward to zero. + multi + .entry(Uint(U256::from(0))) + .or_insert(Uint(U256::from(0))); + multi + .into_iter() + .map(|(block, reward)| (block.into(), reward.into())) + .collect() + } }, ), expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into), diff --git a/crates/ethjson/src/spec/authority_round.rs b/crates/ethjson/src/spec/authority_round.rs index 15699c33a7..6a76855d16 100644 --- a/crates/ethjson/src/spec/authority_round.rs +++ b/crates/ethjson/src/spec/authority_round.rs @@ -16,7 +16,7 @@ //! Authority params deserialization. -use super::ValidatorSet; +use super::{BlockReward, ValidatorSet}; use bytes::Bytes; use hash::Address; use uint::Uint; @@ -40,7 +40,7 @@ pub struct AuthorityRoundParams { /// Whether transitions should be immediate. pub immediate_transitions: Option, /// Reward per block in wei. - pub block_reward: Option, + pub block_reward: Option, /// Block at which the block reward contract should start being used. pub block_reward_contract_transition: Option, /// Block reward contract address (setting the block reward contract @@ -70,6 +70,9 @@ pub struct AuthorityRound { #[cfg(test)] mod tests { + use std::collections::BTreeMap; + + use super::BlockReward; use ethereum_types::{H160, U256}; use hash::Address; use serde_json; @@ -110,5 +113,41 @@ mod tests { deserialized.params.maximum_uncle_count, Some(Uint(5.into())) ); + assert_eq!( + deserialized.params.block_reward, + Some(BlockReward::Single(Uint(5000000.into()))) + ) + } + + #[test] + fn authority_round_deserialization_multi_block() { + let s = r#"{ + "params": { + "stepDuration": "0x02", + "validators": { + "contract" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b" + }, + "blockReward": { + "0": 5000000, + "100": 150 + } + } + }"#; + + let deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); + assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); + assert_eq!( + deserialized.params.validators, + ValidatorSet::Contract(Address(H160::from( + "0xc6d9d2cd449a754c494264e1809c50e34d64562b" + ))) + ); + let mut rewards: BTreeMap = BTreeMap::new(); + rewards.insert(Uint(U256::from(0)), Uint(U256::from(5000000))); + rewards.insert(Uint(U256::from(100)), Uint(U256::from(150))); + assert_eq!( + deserialized.params.block_reward, + Some(BlockReward::Multi(rewards)) + ); } } From 458d55559e171873cd662ab0cbaa91aef61f4e74 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 8 Mar 2021 17:49:59 +0100 Subject: [PATCH 080/107] Bump to v3.2.0 --- CHANGELOG.md | 5 +++-- Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/util/version/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cda2d5f1d8..ea086927de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ -## OpenEthereum v3.2.0-rc.1 +## OpenEthereum v3.2.0 Bug fixes: * Update EWF's chains with Istanbul transition block numbers (#11482) (#254) * fix Supplied instant is later than self (#169) - +* ethcore/snapshot: fix double-lock in Service::feed_chunk (#289) + Enhancements: * Berlin hardfork blocks: mainnet (12,244,000), goerli (4,460,644), rinkeby (8,290,928) and ropsten (9,812,189) * yolo3x spec (#241) diff --git a/Cargo.lock b/Cargo.lock index edcfc1fd59..c232f77538 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2825,7 +2825,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openethereum" -version = "3.2.0-rc.1" +version = "3.2.0" dependencies = [ "ansi_term 0.10.2", "atty", @@ -3188,7 +3188,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "3.2.0-rc.1" +version = "3.2.0" dependencies = [ "parity-bytes", "rlp 0.3.0", diff --git a/Cargo.toml b/Cargo.toml index 5035c20d92..2906d1545c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "OpenEthereum" name = "openethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "3.2.0-rc.1" +version = "3.2.0" license = "GPL-3.0" authors = [ "OpenEthereum developers", diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index 83d92c6757..7fdef2e3b7 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "parity-version" # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) -version = "3.2.0-rc.1" +version = "3.2.0" authors = ["Parity Technologies "] build = "build.rs" From 7ea57079041745dab9be08abad53a197931e8c07 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 9 Mar 2021 09:47:49 +0100 Subject: [PATCH 081/107] Freeze pruning while creating snapshot (#205) * Freeze pruning while creating snapshot * Use scopeguard for snapshot generation * Snapshot 1k blocks * Snapshot number correction --- Cargo.lock | 11 ++-- bin/oe/run.rs | 8 +-- crates/ethcore/Cargo.toml | 1 + crates/ethcore/src/client/client.rs | 72 ++++++++++++++++++-------- crates/ethcore/src/ethereum/ethash.rs | 4 +- crates/ethcore/src/snapshot/service.rs | 58 +++++++++++---------- 6 files changed, 93 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0abc8c1c81..a25e0bbf30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -572,7 +572,7 @@ dependencies = [ "crossbeam-utils 0.6.6", "lazy_static", "memoffset", - "scopeguard 1.0.0", + "scopeguard 1.1.0", ] [[package]] @@ -1014,6 +1014,7 @@ dependencies = [ "rlp_compress", "rlp_derive", "rustc-hex 1.0.0", + "scopeguard 1.1.0", "serde", "serde_derive", "serde_json", @@ -1871,7 +1872,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" dependencies = [ - "scopeguard 1.0.0", + "scopeguard 1.1.0", "winapi 0.3.8", ] @@ -2436,7 +2437,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ - "scopeguard 1.0.0", + "scopeguard 1.1.0", ] [[package]] @@ -4126,9 +4127,9 @@ checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" [[package]] name = "scopeguard" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scrypt" diff --git a/bin/oe/run.rs b/bin/oe/run.rs index b1892aebbe..d4aac267c5 100644 --- a/bin/oe/run.rs +++ b/bin/oe/run.rs @@ -60,11 +60,11 @@ use signer; use sync::{self, SyncConfig}; use user_defaults::UserDefaults; -// how often to take periodic snapshots. -const SNAPSHOT_PERIOD: u64 = 5000; +// How often we attempt to take a snapshot: only snapshot on blocknumbers that are multiples of this. +const SNAPSHOT_PERIOD: u64 = 20000; -// how many blocks to wait before starting a periodic snapshot. -const SNAPSHOT_HISTORY: u64 = 100; +// Start snapshoting from `tip`-`history, with this we want to bypass reorgs. Should be smaller than prunning history. +const SNAPSHOT_HISTORY: u64 = 50; // Full client number of DNS threads const FETCH_FULL_NUM_DNS_THREADS: usize = 4; diff --git a/crates/ethcore/Cargo.toml b/crates/ethcore/Cargo.toml index 57c75a9671..ab6eba7a0f 100644 --- a/crates/ethcore/Cargo.toml +++ b/crates/ethcore/Cargo.toml @@ -74,6 +74,7 @@ using_queue = { path = "../concensus/miner/using-queue" } vm = { path = "../vm/vm" } walkdir = "2.3" wasm = { path = "../vm/wasm" } +scopeguard = "1.1.0" [dev-dependencies] blooms-db = { path = "../db/blooms-db" } diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index a9cba475f8..a6c3c7a974 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -21,7 +21,7 @@ use std::{ io::{BufRead, BufReader}, str::{from_utf8, FromStr}, sync::{ - atomic::{AtomicBool, AtomicI64, Ordering as AtomicOrdering}, + atomic::{AtomicBool, AtomicI64, AtomicU64, Ordering as AtomicOrdering}, Arc, Weak, }, time::{Duration, Instant}, @@ -209,6 +209,9 @@ pub struct Client { /// Database pruning strategy to use for StateDB pruning: journaldb::Algorithm, + /// Don't prune the state we're currently snapshotting + snapshotting_at: AtomicU64, + /// Client uses this to store blocks, traces, etc. db: RwLock>, @@ -946,6 +949,7 @@ impl Client { tracedb, engine, pruning: config.pruning.clone(), + snapshotting_at: AtomicU64::new(0), db: RwLock::new(db.clone()), state_db: RwLock::new(state_db), report: RwLock::new(Default::default()), @@ -1137,7 +1141,7 @@ impl Client { mut state_db: StateDB, chain: &BlockChain, ) -> Result<(), ::error::Error> { - let number = match state_db.journal_db().latest_era() { + let latest_era = match state_db.journal_db().latest_era() { Some(n) => n, None => return Ok(()), }; @@ -1152,16 +1156,27 @@ impl Client { break; } match state_db.journal_db().earliest_era() { - Some(era) if era + self.history <= number => { - trace!(target: "client", "Pruning state for ancient era {}", era); - match chain.block_hash(era) { + Some(earliest_era) if earliest_era + self.history <= latest_era => { + let freeze_at = self.snapshotting_at.load(AtomicOrdering::SeqCst); + if freeze_at > 0 && freeze_at == earliest_era { + // Note: journal_db().mem_used() can be used for a more accurate memory + // consumption measurement but it can be expensive so sticking with the + // faster `journal_size()` instead. + trace!(target: "pruning", "Pruning is paused at era {} (snapshot under way); earliest era={}, latest era={}, journal_size={} – Not pruning.", + freeze_at, earliest_era, latest_era, state_db.journal_db().journal_size()); + break; + } + trace!(target: "client", "Pruning state for ancient era {}", earliest_era); + match chain.block_hash(earliest_era) { Some(ancient_hash) => { let mut batch = DBTransaction::new(); - state_db.mark_canonical(&mut batch, era, &ancient_hash)?; + state_db.mark_canonical(&mut batch, earliest_era, &ancient_hash)?; self.db.read().key_value().write_buffered(batch); state_db.journal_db().flush(); } - None => debug!(target: "client", "Missing expected hash for block {}", era), + None => { + debug!(target: "client", "Missing expected hash for block {}", earliest_era) + } } } _ => break, // means that every era is kept, no pruning necessary. @@ -1349,7 +1364,6 @@ impl Client { p: &snapshot::Progress, ) -> Result<(), EthcoreError> { let db = self.state_db.read().journal_db().boxed_clone(); - let best_block_number = self.chain_info().best_block_number; let block_number = self .block_number(at) .ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))?; @@ -1360,19 +1374,23 @@ impl Client { let history = ::std::cmp::min(self.history, 1000); - let start_hash = match at { + let (snapshot_block_number, start_hash) = match at { BlockId::Latest => { + let best_block_number = self.chain_info().best_block_number; let start_num = match db.earliest_era() { Some(era) => ::std::cmp::max(era, best_block_number.saturating_sub(history)), None => best_block_number.saturating_sub(history), }; - self.block_hash(BlockId::Number(start_num)) - .ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))? + match self.block_hash(BlockId::Number(start_num)) { + Some(h) => (start_num, h), + None => return Err(snapshot::Error::InvalidStartingBlock(at).into()), + } } - _ => self - .block_hash(at) - .ok_or_else(|| snapshot::Error::InvalidStartingBlock(at))?, + _ => match self.block_hash(at) { + Some(hash) => (block_number, hash), + None => return Err(snapshot::Error::InvalidStartingBlock(at).into()), + }, }; let processing_threads = self.config.snapshot.processing_threads; @@ -1380,15 +1398,23 @@ impl Client { .engine .snapshot_components() .ok_or(snapshot::Error::SnapshotsUnsupported)?; - snapshot::take_snapshot( - chunker, - &self.chain.read(), - start_hash, - db.as_hash_db(), - writer, - p, - processing_threads, - )?; + self.snapshotting_at + .store(snapshot_block_number, AtomicOrdering::SeqCst); + { + scopeguard::defer! {{ + info!(target: "snapshot", "Re-enabling pruning."); + self.snapshotting_at.store(0, AtomicOrdering::SeqCst) + }}; + snapshot::take_snapshot( + chunker, + &self.chain.read(), + start_hash, + db.as_hash_db(), + writer, + p, + processing_threads, + )?; + } Ok(()) } diff --git a/crates/ethcore/src/ethereum/ethash.rs b/crates/ethcore/src/ethereum/ethash.rs index be7520f2d8..9210d1a4d2 100644 --- a/crates/ethcore/src/ethereum/ethash.rs +++ b/crates/ethcore/src/ethereum/ethash.rs @@ -38,9 +38,9 @@ use machine::EthereumMachine; /// Number of blocks in an ethash snapshot. // make dependent on difficulty incrment divisor? -const SNAPSHOT_BLOCKS: u64 = 5000; +const SNAPSHOT_BLOCKS: u64 = 1000; /// Maximum number of blocks allowed in an ethash snapshot. -const MAX_SNAPSHOT_BLOCKS: u64 = 30000; +const MAX_SNAPSHOT_BLOCKS: u64 = 10000; /// Ethash specific seal #[derive(Debug, PartialEq)] diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index 17799b2b17..c212c3d7f3 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -530,45 +530,49 @@ impl Service { .store(num as usize, Ordering::SeqCst); info!("Taking snapshot at #{}", num); - self.progress.reset(); + { + scopeguard::defer! {{ + self.taking_snapshot.store(false, Ordering::SeqCst); + }} + self.progress.reset(); - let temp_dir = self.temp_snapshot_dir(); - let snapshot_dir = self.snapshot_dir(); + let temp_dir = self.temp_snapshot_dir(); + let snapshot_dir = self.snapshot_dir(); - let _ = fs::remove_dir_all(&temp_dir); + let _ = fs::remove_dir_all(&temp_dir); - let writer = LooseWriter::new(temp_dir.clone())?; + let writer = LooseWriter::new(temp_dir.clone())?; - let guard = Guard::new(temp_dir.clone()); - let res = client.take_snapshot(writer, BlockId::Number(num), &self.progress); - self.taking_snapshot.store(false, Ordering::SeqCst); - if let Err(e) = res { - if client.chain_info().best_block_number >= num + client.pruning_history() { - // The state we were snapshotting was pruned before we could finish. - info!("Periodic snapshot failed: block state pruned. Run with a longer `--pruning-history` or with `--no-periodic-snapshot`"); - return Err(e); - } else { - return Err(e); + let guard = Guard::new(temp_dir.clone()); + let res = client.take_snapshot(writer, BlockId::Number(num), &self.progress); + if let Err(e) = res { + if client.chain_info().best_block_number >= num + client.pruning_history() { + // The state we were snapshotting was pruned before we could finish. + info!("Periodic snapshot failed: block state pruned. Run with a longer `--pruning-history` or with `--no-periodic-snapshot`"); + return Err(e); + } else { + return Err(e); + } } - } - info!("Finished taking snapshot at #{}", num); + info!("Finished taking snapshot at #{}", num); - let mut reader = self.reader.write(); + let mut reader = self.reader.write(); - // destroy the old snapshot reader. - *reader = None; + // destroy the old snapshot reader. + *reader = None; - if snapshot_dir.exists() { - fs::remove_dir_all(&snapshot_dir)?; - } + if snapshot_dir.exists() { + fs::remove_dir_all(&snapshot_dir)?; + } - fs::rename(temp_dir, &snapshot_dir)?; + fs::rename(temp_dir, &snapshot_dir)?; - *reader = Some(LooseReader::new(snapshot_dir)?); + *reader = Some(LooseReader::new(snapshot_dir)?); - guard.disarm(); - Ok(()) + guard.disarm(); + Ok(()) + } } /// Initialize the restoration synchronously. From 5b904476cd5fdcd0ad49d22ba2d647cb0f9e1640 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 9 Mar 2021 11:20:32 +0100 Subject: [PATCH 082/107] Backport: Block sync stopped without any errors. #277 (#286) * Backport: Block sync stopped without any errors. #277 * fmt --- crates/ethcore/sync/src/chain/mod.rs | 38 +++++++++++++------- crates/ethcore/sync/src/chain/supplier.rs | 35 ++++++++++--------- crates/ethcore/sync/src/tests/chain.rs | 11 +++--- crates/ethcore/sync/src/tests/helpers.rs | 42 ++++++++++++++--------- 4 files changed, 76 insertions(+), 50 deletions(-) diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index 60596233ee..f6e6114aed 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -108,14 +108,17 @@ use ethereum_types::{H256, U256}; use fastmap::{H256FastMap, H256FastSet}; use hash::keccak; use network::{self, client_version::ClientVersion, PeerId}; -use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; +use parking_lot::Mutex; use rand::Rng; use rlp::{DecoderError, RlpStream}; use snapshot::Snapshot; use std::{ cmp, collections::{BTreeMap, HashMap, HashSet}, - sync::mpsc, + sync::{ + atomic::{AtomicBool, Ordering}, + mpsc, RwLock as StdRwLock, RwLockWriteGuard as StdRwLockWriteGuard, + }, time::{Duration, Instant}, }; use sync_io::SyncIo; @@ -398,8 +401,10 @@ pub type Peers = HashMap; pub struct ChainSyncApi { /// Priority tasks queue priority_tasks: Mutex>, + /// Gate for executing only one priority timer. + priority_tasks_gate: AtomicBool, /// The rest of sync data - sync: RwLock, + sync: StdRwLock, } impl ChainSyncApi { @@ -411,31 +416,33 @@ impl ChainSyncApi { priority_tasks: mpsc::Receiver, ) -> Self { ChainSyncApi { - sync: RwLock::new(ChainSync::new(config, chain, fork_filter)), + sync: StdRwLock::new(ChainSync::new(config, chain, fork_filter)), priority_tasks: Mutex::new(priority_tasks), + priority_tasks_gate: AtomicBool::new(false), } } /// Gives `write` access to underlying `ChainSync` - pub fn write(&self) -> RwLockWriteGuard { - self.sync.write() + pub fn write(&self) -> StdRwLockWriteGuard { + self.sync.write().unwrap() } /// Returns info about given list of peers pub fn peer_info(&self, ids: &[PeerId]) -> Vec> { - let sync = self.sync.read(); + let sync = self.sync.read().unwrap(); ids.iter().map(|id| sync.peer_info(id)).collect() } /// Returns synchonization status pub fn status(&self) -> SyncStatus { - self.sync.read().status() + self.sync.read().unwrap().status() } /// Returns transactions propagation statistics pub fn transactions_stats(&self) -> BTreeMap { self.sync .read() + .unwrap() .transactions_stats() .iter() .map(|(hash, stats)| (*hash, stats.into())) @@ -449,7 +456,7 @@ impl ChainSyncApi { /// Process the queue with requests, that were delayed with response. pub fn process_delayed_requests(&self, io: &mut dyn SyncIo) { - let requests = self.sync.write().retrieve_delayed_requests(); + let requests = self.sync.write().unwrap().retrieve_delayed_requests(); if !requests.is_empty() { debug!(target: "sync", "Processing {} delayed requests", requests.len()); for (peer_id, packet_id, packet_data) in requests { @@ -480,6 +487,13 @@ impl ChainSyncApi { } } + if self + .priority_tasks_gate + .compare_and_swap(false, true, Ordering::AcqRel) + { + return; + } + // deadline to get the task from the queue let deadline = Instant::now() + ::api::PRIORITY_TIMER_INTERVAL; let mut work = || { @@ -489,9 +503,8 @@ impl ChainSyncApi { tasks.recv_timeout(left).ok()? }; task.starting(); - // wait for the sync lock until deadline, - // note we might drop the task here if we won't manage to acquire the lock. - let mut sync = self.sync.try_write_until(deadline)?; + // wait for the sync lock + let mut sync = self.sync.write().unwrap(); // since we already have everything let's use a different deadline // to do the rest of the job now, so that previous work is not wasted. let deadline = Instant::now() + PRIORITY_TASK_DEADLINE; @@ -538,6 +551,7 @@ impl ChainSyncApi { // Process as many items as we can until the deadline is reached. loop { if work().is_none() { + self.priority_tasks_gate.store(false, Ordering::Release); return; } } diff --git a/crates/ethcore/sync/src/chain/supplier.rs b/crates/ethcore/sync/src/chain/supplier.rs index 4c6092cd24..3746819d5f 100644 --- a/crates/ethcore/sync/src/chain/supplier.rs +++ b/crates/ethcore/sync/src/chain/supplier.rs @@ -24,9 +24,8 @@ pub const PAYLOAD_SOFT_LIMIT: usize = 100_000; use enum_primitive::FromPrimitive; use ethereum_types::H256; use network::{self, PeerId}; -use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; -use std::cmp; +use std::{cmp, sync::RwLock as StdRwLock}; use types::{ids::BlockId, BlockNumber}; use sync_io::SyncIo; @@ -54,7 +53,7 @@ impl SyncSupplier { // Take a u8 and not a SyncPacketId because this is the entry point // to chain sync from the outside world. pub fn dispatch_packet( - sync: &RwLock, + sync: &StdRwLock, io: &mut dyn SyncIo, peer: PeerId, packet_id: u8, @@ -102,12 +101,12 @@ impl SyncSupplier { ), StatusPacket => { - sync.write().on_packet(io, peer, packet_id, data); + sync.write().unwrap().on_packet(io, peer, packet_id, data); Ok(()) } // Packets that require the peer to be confirmed _ => { - if !sync.read().peers.contains_key(&peer) { + if !sync.read().unwrap().peers.contains_key(&peer) { debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_version(peer)); return; } @@ -117,17 +116,17 @@ impl SyncSupplier { ConsensusDataPacket => SyncHandler::on_consensus_packet(io, peer, &rlp), TransactionsPacket => { let res = { - let sync_ro = sync.read(); + let sync_ro = sync.read().unwrap(); SyncHandler::on_peer_transactions(&*sync_ro, io, peer, &rlp) }; if res.is_err() { // peer sent invalid data, disconnect. io.disable_peer(peer); - sync.write().deactivate_peer(io, peer); + sync.write().unwrap().deactivate_peer(io, peer); } } _ => { - sync.write().on_packet(io, peer, packet_id, data); + sync.write().unwrap().on_packet(io, peer, packet_id, data); } } @@ -139,9 +138,10 @@ impl SyncSupplier { Err(PacketProcessError::Decoder(e)) => { debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e) } - Err(PacketProcessError::ClientBusy) => { - sync.write().add_delayed_request(peer, packet_id, data) - } + Err(PacketProcessError::ClientBusy) => sync + .write() + .unwrap() + .add_delayed_request(peer, packet_id, data), Ok(()) => {} } } @@ -150,7 +150,7 @@ impl SyncSupplier { /// Dispatch delayed request /// The main difference with dispatch packet is the direct send of the responses to the peer pub fn dispatch_delayed_request( - sync: &RwLock, + sync: &StdRwLock, io: &mut dyn SyncIo, peer: PeerId, packet_id: u8, @@ -178,9 +178,10 @@ impl SyncSupplier { Err(PacketProcessError::Decoder(e)) => { debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e) } - Err(PacketProcessError::ClientBusy) => { - sync.write().add_delayed_request(peer, packet_id, data) - } + Err(PacketProcessError::ClientBusy) => sync + .write() + .unwrap() + .add_delayed_request(peer, packet_id, data), Ok(()) => {} } } @@ -420,7 +421,7 @@ mod test { use ethereum_types::H256; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; - use std::collections::VecDeque; + use std::{collections::VecDeque, sync::RwLock as StdRwLock}; use tests::{helpers::TestIo, snapshot::TestSnapshotService}; #[test] @@ -644,7 +645,7 @@ mod test { io.sender = Some(2usize); SyncSupplier::dispatch_packet( - &RwLock::new(sync), + &StdRwLock::new(sync), &mut io, 0usize, GetReceiptsPacket.id(), diff --git a/crates/ethcore/sync/src/tests/chain.rs b/crates/ethcore/sync/src/tests/chain.rs index 3cc12729b0..fdcb5e195e 100644 --- a/crates/ethcore/sync/src/tests/chain.rs +++ b/crates/ethcore/sync/src/tests/chain.rs @@ -57,7 +57,7 @@ fn status_after_sync() { net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle); net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle); net.sync(); - let status = net.peer(0).sync.read().status(); + let status = net.peer(0).sync.read().unwrap().status(); assert_eq!(status.state, SyncState::Idle); } @@ -177,19 +177,22 @@ fn restart() { assert!(net.peer(0).chain.chain_info().best_block_number > 100); net.restart_peer(0); - let status = net.peer(0).sync.read().status(); + let status = net.peer(0).sync.read().unwrap().status(); assert_eq!(status.state, SyncState::Idle); } #[test] fn status_empty() { let net = TestNet::new(2); - assert_eq!(net.peer(0).sync.read().status().state, SyncState::Idle); + assert_eq!( + net.peer(0).sync.read().unwrap().status().state, + SyncState::Idle + ); let mut config = SyncConfig::default(); config.warp_sync = WarpSync::Enabled; let net = TestNet::new_with_config(2, config); assert_eq!( - net.peer(0).sync.read().status().state, + net.peer(0).sync.read().unwrap().status().state, SyncState::WaitingPeers ); } diff --git a/crates/ethcore/sync/src/tests/helpers.rs b/crates/ethcore/sync/src/tests/helpers.rs index 4beb7d1f1d..89eb22dd68 100644 --- a/crates/ethcore/sync/src/tests/helpers.rs +++ b/crates/ethcore/sync/src/tests/helpers.rs @@ -37,7 +37,10 @@ use network::{self, client_version::ClientVersion, PacketId, PeerId, ProtocolId, use parking_lot::RwLock; use std::{ collections::{HashMap, HashSet, VecDeque}, - sync::Arc, + sync::{ + Arc, RwLock as StdRwLock, RwLockReadGuard as StdRwLockReadGuard, + RwLockWriteGuard as StdRwLockWriteGuard, + }, }; use sync_io::SyncIo; use tests::snapshot::*; @@ -249,7 +252,7 @@ where pub chain: Arc, pub miner: Arc, pub snapshot_service: Arc, - pub sync: RwLock, + pub sync: StdRwLock, pub queue: RwLock>, pub io_queue: RwLock>, new_blocks_queue: RwLock>, @@ -270,15 +273,17 @@ where fn process_io_message(&self, message: ChainMessageType) { let mut io = TestIo::new(&*self.chain, &self.snapshot_service, &self.queue, None); match message { - ChainMessageType::Consensus(data) => { - self.sync.write().propagate_consensus_packet(&mut io, data) - } + ChainMessageType::Consensus(data) => self + .sync + .write() + .unwrap() + .propagate_consensus_packet(&mut io, data), } } fn process_new_block_message(&self, message: NewBlockMessage) { let mut io = TestIo::new(&*self.chain, &self.snapshot_service, &self.queue, None); - self.sync.write().chain_new_blocks( + self.sync.write().unwrap().chain_new_blocks( &mut io, &message.imported, &message.invalid, @@ -294,8 +299,8 @@ impl Peer for EthPeer { type Message = TestPacket; fn on_connect(&self, other: PeerId) { - self.sync.write().update_targets(&*self.chain); - self.sync.write().on_peer_connected( + self.sync.write().unwrap().update_targets(&*self.chain); + self.sync.write().unwrap().on_peer_connected( &mut TestIo::new( &*self.chain, &self.snapshot_service, @@ -313,7 +318,7 @@ impl Peer for EthPeer { &self.queue, Some(other), ); - self.sync.write().on_peer_aborting(&mut io, other); + self.sync.write().unwrap().on_peer_aborting(&mut io, other); } fn receive_message(&self, from: PeerId, msg: TestPacket) -> HashSet { @@ -340,14 +345,17 @@ impl Peer for EthPeer { fn sync_step(&self) { let mut io = TestIo::new(&*self.chain, &self.snapshot_service, &self.queue, None); self.chain.flush(); - self.sync.write().maintain_peers(&mut io); - self.sync.write().maintain_sync(&mut io); - self.sync.write().continue_sync(&mut io); - self.sync.write().propagate_new_transactions(&mut io); + self.sync.write().unwrap().maintain_peers(&mut io); + self.sync.write().unwrap().maintain_sync(&mut io); + self.sync.write().unwrap().continue_sync(&mut io); + self.sync + .write() + .unwrap() + .propagate_new_transactions(&mut io); } fn restart_sync(&self) { - self.sync.write().restart(&mut TestIo::new( + self.sync.write().unwrap().restart(&mut TestIo::new( &*self.chain, &self.snapshot_service, &self.queue, @@ -400,7 +408,7 @@ impl TestNet> { let ss = Arc::new(TestSnapshotService::new()); let sync = ChainSync::new(config.clone(), &chain, ForkFilterApi::new_dummy(&chain)); net.peers.push(Arc::new(EthPeer { - sync: RwLock::new(sync), + sync: StdRwLock::new(sync), snapshot_service: ss, chain: Arc::new(chain), miner: Arc::new(Miner::new_for_tests(&Spec::new_test(), None)), @@ -449,7 +457,7 @@ impl TestNet> { let ss = Arc::new(TestSnapshotService::new()); let sync = ChainSync::new(config, &*client, ForkFilterApi::new_dummy(&*client)); let peer = Arc::new(EthPeer { - sync: RwLock::new(sync), + sync: StdRwLock::new(sync), snapshot_service: ss, chain: client, miner, @@ -558,7 +566,7 @@ where impl TestNet> { pub fn trigger_chain_new_blocks(&mut self, peer_id: usize) { let peer = &mut self.peers[peer_id]; - peer.sync.write().chain_new_blocks( + peer.sync.write().unwrap().chain_new_blocks( &mut TestIo::new(&*peer.chain, &peer.snapshot_service, &peer.queue, None), &[], &[], From e2024c4b81358454bee9f5f7f8658bfaa2278339 Mon Sep 17 00:00:00 2001 From: Karim Agha Date: Wed, 10 Mar 2021 09:46:34 +0100 Subject: [PATCH 083/107] Fixing a compilation warning (#308) * Fixing a compilation warning --- crates/ethcore/sync/src/chain/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index f6e6114aed..d3854dd209 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -489,7 +489,8 @@ impl ChainSyncApi { if self .priority_tasks_gate - .compare_and_swap(false, true, Ordering::AcqRel) + .compare_exchange(false, true, Ordering::Acquire, Ordering::Release) + .is_err() { return; } From eca8fb74ae515483ec8a8a699249451a0670e8ef Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Mar 2021 12:36:23 +0100 Subject: [PATCH 084/107] Strict memory order (#306) * Make MemoryOrdering more strict * fmt * Strict mem order for priority_tasks_gate --- bin/oe/stratum.rs | 2 +- crates/concensus/miner/price-info/src/lib.rs | 8 ++--- crates/concensus/miner/src/pool/queue.rs | 2 +- crates/ethcore/service/src/stop_guard.rs | 2 +- crates/ethcore/src/client/client.rs | 18 +++++------ crates/ethcore/src/client/test_client.rs | 8 ++--- crates/ethcore/src/snapshot/mod.rs | 18 +++++------ crates/ethcore/src/verification/queue/mod.rs | 32 +++++++------------ crates/ethcore/sync/src/chain/mod.rs | 4 +-- crates/net/network-devp2p/src/host.rs | 10 +++--- crates/net/network-devp2p/tests/tests.rs | 8 ++--- crates/rpc/src/v1/informant.rs | 2 +- crates/runtime/io/src/worker.rs | 6 ++-- .../util/cli-signer/rpc-client/src/client.rs | 2 +- 14 files changed, 56 insertions(+), 66 deletions(-) diff --git a/bin/oe/stratum.rs b/bin/oe/stratum.rs index 14e54aa908..d3bd6cc3a7 100644 --- a/bin/oe/stratum.rs +++ b/bin/oe/stratum.rs @@ -39,7 +39,7 @@ struct StratumControlService { impl ControlService for StratumControlService { fn shutdown(&self) -> bool { trace!(target: "hypervisor", "Received shutdown from control service"); - self.stop.store(true, ::std::sync::atomic::Ordering::Relaxed); + self.stop.store(true, ::std::sync::atomic::Ordering::SeqCst); true } } diff --git a/crates/concensus/miner/price-info/src/lib.rs b/crates/concensus/miner/price-info/src/lib.rs index 51ad6a0bc4..7cb422724b 100644 --- a/crates/concensus/miner/price-info/src/lib.rs +++ b/crates/concensus/miner/price-info/src/lib.rs @@ -207,11 +207,11 @@ mod test { // when let bb = b.clone(); price_info.get(move |_| { - bb.store(true, Ordering::Relaxed); + bb.store(true, Ordering::SeqCst); }); // then - assert_eq!(b.load(Ordering::Relaxed), false); + assert_eq!(b.load(Ordering::SeqCst), false); } #[test] @@ -225,10 +225,10 @@ mod test { // when let bb = b.clone(); price_info.get(move |_| { - bb.store(true, Ordering::Relaxed); + bb.store(true, Ordering::SeqCst); }); // then - assert_eq!(b.load(Ordering::Relaxed), false); + assert_eq!(b.load(Ordering::SeqCst), false); } } diff --git a/crates/concensus/miner/src/pool/queue.rs b/crates/concensus/miner/src/pool/queue.rs index d9a72e3da5..e2e0d15622 100644 --- a/crates/concensus/miner/src/pool/queue.rs +++ b/crates/concensus/miner/src/pool/queue.rs @@ -480,7 +480,7 @@ impl TransactionQueue { // We want to clear stale transactions from the queue as well. // (Transactions that are occuping the queue for a long time without being included) let stale_id = { - let current_id = self.insertion_id.load(atomic::Ordering::Relaxed); + let current_id = self.insertion_id.load(atomic::Ordering::SeqCst); // wait at least for half of the queue to be replaced let gap = self.pool.read().options().max_count / 2; // but never less than 100 transactions diff --git a/crates/ethcore/service/src/stop_guard.rs b/crates/ethcore/service/src/stop_guard.rs index 34438fd59f..ce662ea5d5 100644 --- a/crates/ethcore/service/src/stop_guard.rs +++ b/crates/ethcore/service/src/stop_guard.rs @@ -34,6 +34,6 @@ impl StopGuard { impl Drop for StopGuard { fn drop(&mut self) { - self.flag.store(true, Ordering::Relaxed) + self.flag.store(true, Ordering::SeqCst) } } diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index a6c3c7a974..5f183ba047 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -284,7 +284,7 @@ impl Importer { // t_nb 6.0 This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. - if !client.enabled.load(AtomicOrdering::Relaxed) { + if !client.enabled.load(AtomicOrdering::SeqCst) { return 0; } @@ -1445,18 +1445,18 @@ impl Client { } fn wake_up(&self) { - if !self.liveness.load(AtomicOrdering::Relaxed) { - self.liveness.store(true, AtomicOrdering::Relaxed); + if !self.liveness.load(AtomicOrdering::SeqCst) { + self.liveness.store(true, AtomicOrdering::SeqCst); self.notify(|n| n.start()); info!(target: "mode", "wake_up: Waking."); } } fn sleep(&self, force: bool) { - if self.liveness.load(AtomicOrdering::Relaxed) { + if self.liveness.load(AtomicOrdering::SeqCst) { // only sleep if the import queue is mostly empty. if force || (self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON) { - self.liveness.store(false, AtomicOrdering::Relaxed); + self.liveness.store(false, AtomicOrdering::SeqCst); self.notify(|n| n.stop()); info!(target: "mode", "sleep: Sleeping."); } else { @@ -2058,13 +2058,13 @@ impl BlockChainClient for Client { fn disable(&self) { self.set_mode(Mode::Off); - self.enabled.store(false, AtomicOrdering::Relaxed); + self.enabled.store(false, AtomicOrdering::SeqCst); self.clear_queue(); } fn set_mode(&self, new_mode: Mode) { trace!(target: "mode", "Client::set_mode({:?})", new_mode); - if !self.enabled.load(AtomicOrdering::Relaxed) { + if !self.enabled.load(AtomicOrdering::SeqCst) { return; } { @@ -2095,7 +2095,7 @@ impl BlockChainClient for Client { fn set_spec_name(&self, new_spec_name: String) -> Result<(), ()> { trace!(target: "mode", "Client::set_spec_name({:?})", new_spec_name); - if !self.enabled.load(AtomicOrdering::Relaxed) { + if !self.enabled.load(AtomicOrdering::SeqCst) { return Err(()); } if let Some(ref h) = *self.exit_handler.lock() { @@ -3241,7 +3241,7 @@ impl IoChannelQueue { where F: Fn(&Client) + Send + Sync + 'static, { - let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed); + let queue_size = self.currently_queued.load(AtomicOrdering::SeqCst); if queue_size >= self.limit { let err_limit = usize::try_from(self.limit).unwrap_or(usize::max_value()); bail!("The queue is full ({})", err_limit); diff --git a/crates/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs index 28195da230..c0f62aff64 100644 --- a/crates/ethcore/src/client/test_client.rs +++ b/crates/ethcore/src/client/test_client.rs @@ -237,7 +237,7 @@ impl TestBlockChainClient { /// Set block queue size for testing pub fn set_queue_size(&self, size: usize) { - self.queue_size.store(size, AtomicOrder::Relaxed); + self.queue_size.store(size, AtomicOrder::SeqCst); } /// Set timestamp assigned to latest sealed block @@ -402,7 +402,7 @@ impl TestBlockChainClient { /// Returns true if the client has been disabled. pub fn is_disabled(&self) -> bool { - self.disabled.load(AtomicOrder::Relaxed) + self.disabled.load(AtomicOrder::SeqCst) } } @@ -959,7 +959,7 @@ impl BlockChainClient for TestBlockChainClient { fn queue_info(&self) -> QueueInfo { QueueInfo { - verified_queue_size: self.queue_size.load(AtomicOrder::Relaxed), + verified_queue_size: self.queue_size.load(AtomicOrder::SeqCst), unverified_queue_size: 0, verifying_queue_size: 0, max_queue_size: 0, @@ -1019,7 +1019,7 @@ impl BlockChainClient for TestBlockChainClient { } fn disable(&self) { - self.disabled.store(true, AtomicOrder::Relaxed); + self.disabled.store(true, AtomicOrder::SeqCst); } fn pruning_info(&self) -> PruningInfo { diff --git a/crates/ethcore/src/snapshot/mod.rs b/crates/ethcore/src/snapshot/mod.rs index ca9b7f7b09..444b49429c 100644 --- a/crates/ethcore/src/snapshot/mod.rs +++ b/crates/ethcore/src/snapshot/mod.rs @@ -127,34 +127,34 @@ pub struct Progress { impl Progress { /// Reset the progress. pub fn reset(&self) { - self.accounts.store(0, Ordering::Release); - self.blocks.store(0, Ordering::Release); - self.size.store(0, Ordering::Release); - self.abort.store(false, Ordering::Release); + self.accounts.store(0, Ordering::SeqCst); + self.blocks.store(0, Ordering::SeqCst); + self.size.store(0, Ordering::SeqCst); + self.abort.store(false, Ordering::SeqCst); // atomic fence here to ensure the others are written first? // logs might very rarely get polluted if not. - self.done.store(false, Ordering::Release); + self.done.store(false, Ordering::SeqCst); } /// Get the number of accounts snapshotted thus far. pub fn accounts(&self) -> usize { - self.accounts.load(Ordering::Acquire) + self.accounts.load(Ordering::SeqCst) } /// Get the number of blocks snapshotted thus far. pub fn blocks(&self) -> usize { - self.blocks.load(Ordering::Acquire) + self.blocks.load(Ordering::SeqCst) } /// Get the written size of the snapshot in bytes. pub fn size(&self) -> u64 { - self.size.load(Ordering::Acquire) + self.size.load(Ordering::SeqCst) } /// Whether the snapshot is complete. pub fn done(&self) -> bool { - self.done.load(Ordering::Acquire) + self.done.load(Ordering::SeqCst) } } /// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer. diff --git a/crates/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs index b6f2b8bba3..2928ccc2e7 100644 --- a/crates/ethcore/src/verification/queue/mod.rs +++ b/crates/ethcore/src/verification/queue/mod.rs @@ -175,18 +175,13 @@ struct QueueSignal { impl QueueSignal { fn set_sync(&self) { // Do not signal when we are about to close - if self.deleting.load(AtomicOrdering::Relaxed) { + if self.deleting.load(AtomicOrdering::SeqCst) { return; } if self .signalled - .compare_exchange( - false, - true, - AtomicOrdering::Relaxed, - AtomicOrdering::Relaxed, - ) + .compare_exchange(false, true, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst) .is_ok() { let channel = self.message_channel.lock().clone(); @@ -198,18 +193,13 @@ impl QueueSignal { fn set_async(&self) { // Do not signal when we are about to close - if self.deleting.load(AtomicOrdering::Relaxed) { + if self.deleting.load(AtomicOrdering::SeqCst) { return; } if self .signalled - .compare_exchange( - false, - true, - AtomicOrdering::Relaxed, - AtomicOrdering::Relaxed, - ) + .compare_exchange(false, true, AtomicOrdering::SeqCst, AtomicOrdering::SeqCst) .is_ok() { let channel = self.message_channel.lock().clone(); @@ -220,7 +210,7 @@ impl QueueSignal { } fn reset(&self) { - self.signalled.store(false, AtomicOrdering::Relaxed); + self.signalled.store(false, AtomicOrdering::SeqCst); } } @@ -499,9 +489,9 @@ impl VerificationQueue { verified.clear(); let sizes = &self.verification.sizes; - sizes.unverified.store(0, AtomicOrdering::Release); - sizes.verifying.store(0, AtomicOrdering::Release); - sizes.verified.store(0, AtomicOrdering::Release); + sizes.unverified.store(0, AtomicOrdering::SeqCst); + sizes.verifying.store(0, AtomicOrdering::SeqCst); + sizes.verified.store(0, AtomicOrdering::SeqCst); *self.total_difficulty.write() = 0.into(); self.processing.write().clear(); @@ -728,7 +718,7 @@ impl VerificationQueue { .verification .sizes .unverified - .load(AtomicOrdering::Acquire); + .load(AtomicOrdering::SeqCst); (len, size + len * size_of::()) }; @@ -738,7 +728,7 @@ impl VerificationQueue { .verification .sizes .verifying - .load(AtomicOrdering::Acquire); + .load(AtomicOrdering::SeqCst); (len, size + len * size_of::>()) }; let (verified_len, verified_bytes) = { @@ -747,7 +737,7 @@ impl VerificationQueue { .verification .sizes .verified - .load(AtomicOrdering::Acquire); + .load(AtomicOrdering::SeqCst); (len, size + len * size_of::()) }; diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index d3854dd209..bf6103a2bc 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -489,7 +489,7 @@ impl ChainSyncApi { if self .priority_tasks_gate - .compare_exchange(false, true, Ordering::Acquire, Ordering::Release) + .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst) .is_err() { return; @@ -552,7 +552,7 @@ impl ChainSyncApi { // Process as many items as we can until the deadline is reached. loop { if work().is_none() { - self.priority_tasks_gate.store(false, Ordering::Release); + self.priority_tasks_gate.store(false, Ordering::SeqCst); return; } } diff --git a/crates/net/network-devp2p/src/host.rs b/crates/net/network-devp2p/src/host.rs index cb36da9a90..9ac7221d32 100644 --- a/crates/net/network-devp2p/src/host.rs +++ b/crates/net/network-devp2p/src/host.rs @@ -464,7 +464,7 @@ impl Host { } pub fn stop(&self, io: &IoContext) { - self.stopping.store(true, AtomicOrdering::Release); + self.stopping.store(true, AtomicOrdering::SeqCst); let mut to_kill = Vec::new(); for e in self.sessions.read().iter() { let mut s = e.lock(); @@ -1168,7 +1168,7 @@ impl IoHandler for Host { } fn stream_readable(&self, io: &IoContext, stream: StreamToken) { - if self.stopping.load(AtomicOrdering::Acquire) { + if self.stopping.load(AtomicOrdering::SeqCst) { return; } match stream { @@ -1180,7 +1180,7 @@ impl IoHandler for Host { } fn stream_writable(&self, io: &IoContext, stream: StreamToken) { - if self.stopping.load(AtomicOrdering::Acquire) { + if self.stopping.load(AtomicOrdering::SeqCst) { return; } match stream { @@ -1191,7 +1191,7 @@ impl IoHandler for Host { } fn timeout(&self, io: &IoContext, token: TimerToken) { - if self.stopping.load(AtomicOrdering::Acquire) { + if self.stopping.load(AtomicOrdering::SeqCst) { return; } match token { @@ -1253,7 +1253,7 @@ impl IoHandler for Host { } fn message(&self, io: &IoContext, message: &NetworkIoMessage) { - if self.stopping.load(AtomicOrdering::Acquire) { + if self.stopping.load(AtomicOrdering::SeqCst) { return; } match *message { diff --git a/crates/net/network-devp2p/tests/tests.rs b/crates/net/network-devp2p/tests/tests.rs index ab97c2c157..eec2aad786 100644 --- a/crates/net/network-devp2p/tests/tests.rs +++ b/crates/net/network-devp2p/tests/tests.rs @@ -73,11 +73,11 @@ impl TestProtocol { } pub fn got_timeout(&self) -> bool { - self.got_timeout.load(AtomicOrdering::Relaxed) + self.got_timeout.load(AtomicOrdering::SeqCst) } pub fn got_disconnect(&self) -> bool { - self.got_disconnect.load(AtomicOrdering::Relaxed) + self.got_disconnect.load(AtomicOrdering::SeqCst) } } @@ -101,13 +101,13 @@ impl NetworkProtocolHandler for TestProtocol { } fn disconnected(&self, _io: &dyn NetworkContext, _peer: &PeerId) { - self.got_disconnect.store(true, AtomicOrdering::Relaxed); + self.got_disconnect.store(true, AtomicOrdering::SeqCst); } /// Timer function called after a timeout created with `NetworkContext::timeout`. fn timeout(&self, _io: &dyn NetworkContext, timer: TimerToken) { assert_eq!(timer, 0); - self.got_timeout.store(true, AtomicOrdering::Relaxed); + self.got_timeout.store(true, AtomicOrdering::SeqCst); } } diff --git a/crates/rpc/src/v1/informant.rs b/crates/rpc/src/v1/informant.rs index 0b146969de..7e64dc7563 100644 --- a/crates/rpc/src/v1/informant.rs +++ b/crates/rpc/src/v1/informant.rs @@ -171,7 +171,7 @@ impl RpcStats { /// Returns number of open sessions pub fn sessions(&self) -> usize { - self.active_sessions.load(atomic::Ordering::Relaxed) + self.active_sessions.load(atomic::Ordering::SeqCst) } /// Returns requests rate diff --git a/crates/runtime/io/src/worker.rs b/crates/runtime/io/src/worker.rs index a3b4b77213..7d875121c6 100644 --- a/crates/runtime/io/src/worker.rs +++ b/crates/runtime/io/src/worker.rs @@ -86,13 +86,13 @@ impl Worker { future::loop_fn(ini, |(stealer, channel, wait, wait_mutex, deleting)| { { let mut lock = wait_mutex.lock(); - if deleting.load(AtomicOrdering::Acquire) { + if deleting.load(AtomicOrdering::SeqCst) { return Ok(Loop::Break(())); } wait.wait(&mut lock); } - while !deleting.load(AtomicOrdering::Acquire) { + while !deleting.load(AtomicOrdering::SeqCst) { match stealer.steal() { deque::Steal::Data(work) => { Worker::do_work(work, channel.clone()) @@ -147,7 +147,7 @@ impl Drop for Worker { fn drop(&mut self) { trace!(target: "shutdown", "[IoWorker] Closing..."); let _ = self.wait_mutex.lock(); - self.deleting.store(true, AtomicOrdering::Release); + self.deleting.store(true, AtomicOrdering::SeqCst); self.wait.notify_all(); if let Some(thread) = self.thread.take() { thread.join().ok(); diff --git a/crates/util/cli-signer/rpc-client/src/client.rs b/crates/util/cli-signer/rpc-client/src/client.rs index 30c227bf9e..d278620365 100644 --- a/crates/util/cli-signer/rpc-client/src/client.rs +++ b/crates/util/cli-signer/rpc-client/src/client.rs @@ -259,7 +259,7 @@ impl Rpc { { let (c, p) = oneshot::>(); - let id = self.counter.fetch_add(1, Ordering::Relaxed); + let id = self.counter.fetch_add(1, Ordering::SeqCst); self.pending.insert(id, c); let request = MethodCall { From d7a958129f6e9051d2fe9b857c999cdc8a318107 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Mar 2021 16:39:32 +0100 Subject: [PATCH 085/107] [evmbin] Omit storage output, now for std-json (#311) * [evmbin] Omit storage output, now for std-json * fix tests --- bin/evmbin/src/display/config.rs | 2 +- bin/evmbin/src/display/json.rs | 19 +++++++++++++- bin/evmbin/src/display/std_json.rs | 40 +++++++++++++++++++++++------- bin/evmbin/src/info.rs | 4 +-- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/bin/evmbin/src/display/config.rs b/bin/evmbin/src/display/config.rs index 1080919667..128c2eeccb 100644 --- a/bin/evmbin/src/display/config.rs +++ b/bin/evmbin/src/display/config.rs @@ -16,7 +16,7 @@ //! Config used by display informants -#[derive(Default, Copy, Clone)] +#[derive(Default, Copy, Clone, Debug)] pub struct Config { omit_storage_output: bool, omit_memory_output: bool, diff --git a/bin/evmbin/src/display/json.rs b/bin/evmbin/src/display/json.rs index e3fc820574..55b70f86d8 100644 --- a/bin/evmbin/src/display/json.rs +++ b/bin/evmbin/src/display/json.rs @@ -284,7 +284,7 @@ mod tests { gas_cost: U256, memory: String, stack: Vec, - storage: HashMap, + storage: Option>, depth: usize, } @@ -399,6 +399,23 @@ mod tests { {"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"0x","stack":["0x0"],"storage":{},"depth":1} {"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"0x","stack":["0x0","0xd8"],"storage":{},"depth":1} {"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"0x","stack":[],"storage":{"0x00000000000000000000000000000000000000000000000000000000000000d8":"0x0000000000000000000000000000000000000000000000000000000000000000"},"depth":1} +"#, + ); + } + + #[test] + fn should_omit_storage_and_memory_flag() { + // should omit storage + run_test( + Informant::new(Config::new(true, true)), + &compare_json, + "3260D85554", + 0xffff, + r#" +{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"","stack":[],"storage":null,"depth":1} +{"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"","stack":["0x0"],"storage":null,"depth":1} +{"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"","stack":["0x0","0xd8"],"storage":null,"depth":1} +{"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"","stack":[],"storage":null,"depth":1} "#, ) } diff --git a/bin/evmbin/src/display/std_json.rs b/bin/evmbin/src/display/std_json.rs index b6efa4c0c1..ae7e5a7e0d 100644 --- a/bin/evmbin/src/display/std_json.rs +++ b/bin/evmbin/src/display/std_json.rs @@ -203,6 +203,11 @@ impl trace::VMTracer for Informant { fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { let subdepth = self.subdepth; Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { + let storage = if informant.config.omit_storage_output() { + None + } else { + Some(&informant.storage) + }; let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info()); informant.instruction = instruction; let trace_data = json!({ @@ -211,7 +216,7 @@ impl trace::VMTracer for Informant { "opName": info.map(|i| i.name).unwrap_or(""), "gas": format!("{:#x}", current_gas), "stack": informant.stack, - "storage": informant.storage, + "storage": storage, "depth": informant.depth, }); @@ -307,19 +312,16 @@ pub mod tests { } } - pub fn informant() -> (Informant, Arc>>) { + pub fn informant(config: Config) -> (Informant, Arc>>) { let trace_writer: TestWriter = Default::default(); let out_writer: TestWriter = Default::default(); let res = trace_writer.0.clone(); - ( - Informant::new(trace_writer, out_writer, Config::default()), - res, - ) + (Informant::new(trace_writer, out_writer, config), res) } #[test] fn should_trace_failure() { - let (inf, res) = informant(); + let (inf, res) = informant(Config::default()); run_test( inf, move |_, expected| { @@ -333,7 +335,7 @@ pub mod tests { "#, ); - let (inf, res) = informant(); + let (inf, res) = informant(Config::default()); run_test( inf, move |_, expected| { @@ -349,7 +351,7 @@ pub mod tests { #[test] fn should_trace_create_correctly() { - let (informant, res) = informant(); + let (informant, res) = informant(Config::default()); run_test( informant, move |_, expected| { @@ -382,6 +384,26 @@ pub mod tests { {"depth":2,"gas":"0x2102","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}} {"depth":2,"gas":"0x2100","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}} {"depth":2,"gas":"0x20fe","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{}} +"#, + ) + } + + #[test] + fn should_omit_storage_and_memory_flag() { + // should omit storage + let (informant, res) = informant(Config::new(true, true)); + run_test( + informant, + move |_, expected| { + let bytes = res.lock().unwrap(); + assert_eq!(expected, &String::from_utf8_lossy(&**bytes)) + }, + "3260D85554", + 0xffff, + r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":null} +{"depth":1,"gas":"0xfffd","op":96,"opName":"PUSH1","pc":1,"stack":["0x0"],"storage":null} +{"depth":1,"gas":"0xfffa","op":85,"opName":"SSTORE","pc":3,"stack":["0x0","0xd8"],"storage":null} +{"depth":1,"gas":"0xec72","op":84,"opName":"SLOAD","pc":4,"stack":[],"storage":null} "#, ) } diff --git a/bin/evmbin/src/info.rs b/bin/evmbin/src/info.rs index 9ebe02a4e3..8519e1d4b3 100644 --- a/bin/evmbin/src/info.rs +++ b/bin/evmbin/src/info.rs @@ -287,9 +287,9 @@ pub mod tests { #[test] fn should_call_account_from_spec() { - use display::std_json::tests::informant; + use display::{config::Config, std_json::tests::informant}; - let (inf, res) = informant(); + let (inf, res) = informant(Config::default()); let mut params = ActionParams::default(); params.code_address = 0x20.into(); params.gas = 0xffff.into(); From 187c81b3f16b736cad68f949f0c06bcb6ce71e64 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Mar 2021 17:14:08 +0100 Subject: [PATCH 086/107] Upgrade ethereum/tests to v8.0.1 (#301) --- crates/ethcore/res/chainspec/test/berlin_test.json | 3 +-- crates/ethcore/res/json_tests | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/ethcore/res/chainspec/test/berlin_test.json b/crates/ethcore/res/chainspec/test/berlin_test.json index 1cc68c7b76..acf055033a 100644 --- a/crates/ethcore/res/chainspec/test/berlin_test.json +++ b/crates/ethcore/res/chainspec/test/berlin_test.json @@ -43,7 +43,6 @@ "eip1706Transition": "0x0", "eip1884Transition": "0x0", "eip2028Transition": "0x0", - "eip2315Transition": "0x0", "eip2929Transition": "0x0", "eip2930Transition": "0x0" }, @@ -203,4 +202,4 @@ } } } -} \ No newline at end of file +} diff --git a/crates/ethcore/res/json_tests b/crates/ethcore/res/json_tests index 31d663076b..e431795bf7 160000 --- a/crates/ethcore/res/json_tests +++ b/crates/ethcore/res/json_tests @@ -1 +1 @@ -Subproject commit 31d663076b6678df18983d6da912d7cad4ad3416 +Subproject commit e431795bf750166671afc3516f5e0332af3318f1 From f143ddb75aedfb0a3a3afc8e4e9191591932c51f Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Mar 2021 18:30:25 +0100 Subject: [PATCH 087/107] [devops] Upgrade docker alpine to v1.13.2 --- scripts/docker/alpine/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/docker/alpine/Dockerfile b/scripts/docker/alpine/Dockerfile index 516b30370b..f9a6429fd9 100644 --- a/scripts/docker/alpine/Dockerfile +++ b/scripts/docker/alpine/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.12.3 AS builder +FROM alpine:3.13.2 AS builder # show backtraces ENV RUST_BACKTRACE 1 @@ -18,7 +18,7 @@ COPY . /openethereum RUN cargo build --release --features final --target x86_64-alpine-linux-musl --verbose RUN strip target/x86_64-alpine-linux-musl/release/openethereum -FROM alpine:3.12.3 +FROM alpine:3.13.2 # show backtraces ENV RUST_BACKTRACE 1 From a0f406e26b5585218c94a8066d5f832dfba3b656 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 12 Mar 2021 10:12:42 +0100 Subject: [PATCH 088/107] Ethereum-types and various libs upgrade (#315) * Upgrade Eth types ethereum-types -> 0.9.2 rlp -> 0.4.6 keccak-hash -> 0.5.0 parity-crypto -> 0.6.2 ethabi -> 0.12.0 ethabi-derive -> 0.12.0 ethabi-contract -> 0.11.0 ethbloom -> 0.9.1 rand -> 0.7.3 trie-standardmap -> 0.15.2 triehash -> 0.5.0 * backport #10714. Small changes, merge fixes Co-authored-by: mdben1247 --- Cargo.lock | 828 ++++++++---------- Cargo.toml | 10 +- bin/ethkey/Cargo.toml | 1 + bin/ethkey/src/main.rs | 23 +- bin/evmbin/Cargo.toml | 2 +- bin/evmbin/src/display/json.rs | 7 +- bin/evmbin/src/display/std_json.rs | 7 +- bin/evmbin/src/info.rs | 5 +- bin/evmbin/src/main.rs | 5 +- bin/oe/account_utils.rs | 15 +- bin/oe/configuration.rs | 4 +- bin/oe/helpers.rs | 10 +- bin/oe/lib.rs | 1 + bin/oe/presale.rs | 5 +- bin/oe/run.rs | 6 +- bin/oe/secretstore.rs | 3 +- crates/accounts/Cargo.toml | 3 +- crates/accounts/ethkey/Cargo.toml | 8 +- crates/accounts/ethkey/src/brain.rs | 23 +- crates/accounts/ethkey/src/brain_prefix.rs | 16 +- crates/accounts/ethkey/src/brain_recover.rs | 7 +- crates/accounts/ethkey/src/crypto.rs | 202 ----- crates/accounts/ethkey/src/error.rs | 81 -- crates/accounts/ethkey/src/extended.rs | 589 ------------- crates/accounts/ethkey/src/keccak.rs | 33 - crates/accounts/ethkey/src/keypair.rs | 120 --- crates/accounts/ethkey/src/lib.rs | 54 +- crates/accounts/ethkey/src/math.rs | 134 --- crates/accounts/ethkey/src/prefix.rs | 20 +- crates/accounts/ethkey/src/random.rs | 42 - crates/accounts/ethkey/src/secret.rs | 322 ------- crates/accounts/ethkey/src/signature.rs | 325 ------- crates/accounts/ethstore/Cargo.toml | 6 +- .../accounts/ethstore/src/account/crypto.rs | 18 +- .../ethstore/src/account/safe_account.rs | 19 +- .../ethstore/src/accounts_dir/disk.rs | 8 +- .../ethstore/src/accounts_dir/memory.rs | 4 +- crates/accounts/ethstore/src/error.rs | 30 +- crates/accounts/ethstore/src/ethkey.rs | 1 + crates/accounts/ethstore/src/ethstore.rs | 33 +- crates/accounts/ethstore/src/import.rs | 2 +- crates/accounts/ethstore/src/lib.rs | 2 +- crates/accounts/ethstore/src/presale.rs | 12 +- crates/accounts/ethstore/src/random.rs | 10 +- crates/accounts/ethstore/src/secret_store.rs | 5 +- crates/accounts/ethstore/tests/api.rs | 64 +- .../ethstore/tests/util/transient_dir.rs | 4 +- crates/accounts/src/account_data.rs | 3 +- crates/accounts/src/lib.rs | 67 +- crates/accounts/src/stores.rs | 19 +- crates/concensus/ethash/Cargo.toml | 5 +- crates/concensus/ethash/src/cache.rs | 26 +- crates/concensus/ethash/src/compute.rs | 139 ++- crates/concensus/ethash/src/keccak.rs | 43 +- crates/concensus/ethash/src/lib.rs | 30 +- crates/concensus/miner/Cargo.toml | 15 +- crates/concensus/miner/local-store/Cargo.toml | 3 +- crates/concensus/miner/local-store/src/lib.rs | 7 +- crates/concensus/miner/src/external.rs | 8 +- crates/concensus/miner/src/lib.rs | 6 +- crates/concensus/miner/src/pool/listener.rs | 3 +- .../miner/src/pool/local_transactions.rs | 4 +- crates/concensus/miner/src/pool/mod.rs | 4 +- crates/concensus/miner/src/pool/replace.rs | 18 +- crates/concensus/miner/src/pool/tests/tx.rs | 10 +- crates/concensus/miner/stratum/Cargo.toml | 4 +- crates/db/blooms-db/Cargo.toml | 2 +- crates/db/blooms-db/benches/blooms.rs | 10 +- crates/db/blooms-db/src/db.rs | 50 +- crates/db/blooms-db/src/file.rs | 10 +- crates/db/db/Cargo.toml | 6 +- crates/db/db/src/db.rs | 40 +- crates/db/db/src/keys.rs | 46 +- crates/db/journaldb/Cargo.toml | 8 +- crates/db/journaldb/src/archivedb.rs | 12 +- crates/db/journaldb/src/earlymergedb.rs | 30 +- crates/db/journaldb/src/lib.rs | 2 +- crates/db/journaldb/src/overlaydb.rs | 6 +- crates/db/journaldb/src/overlayrecentdb.rs | 26 +- crates/db/journaldb/src/refcounteddb.rs | 7 +- crates/db/memory-db/Cargo.toml | 12 +- crates/db/memory-db/src/lib.rs | 14 +- crates/db/patricia-trie-ethereum/Cargo.toml | 6 +- crates/db/patricia-trie-ethereum/src/lib.rs | 4 +- crates/ethcore/Cargo.toml | 20 +- crates/ethcore/benches/builtin.rs | 8 +- crates/ethcore/blockchain/Cargo.toml | 11 +- crates/ethcore/blockchain/src/blockchain.rs | 95 +- crates/ethcore/blockchain/src/import_route.rs | 31 +- crates/ethcore/blockchain/src/lib.rs | 2 + crates/ethcore/service/Cargo.toml | 2 +- crates/ethcore/src/account_db.rs | 4 +- crates/ethcore/src/block.rs | 2 +- crates/ethcore/src/client/client.rs | 29 +- crates/ethcore/src/client/test_client.rs | 24 +- .../src/engines/authority_round/mod.rs | 27 +- crates/ethcore/src/engines/basic_authority.rs | 9 +- crates/ethcore/src/engines/block_reward.rs | 19 +- .../ethcore/src/engines/clique/block_state.rs | 2 +- crates/ethcore/src/engines/clique/mod.rs | 8 +- crates/ethcore/src/engines/clique/tests.rs | 11 +- crates/ethcore/src/engines/clique/util.rs | 11 +- crates/ethcore/src/engines/mod.rs | 2 +- crates/ethcore/src/engines/signer.rs | 29 +- .../src/engines/validator_set/contract.rs | 4 +- .../src/engines/validator_set/multi.rs | 2 +- .../engines/validator_set/safe_contract.rs | 2 +- .../src/engines/validator_set/simple_list.rs | 10 +- .../ethcore/src/engines/validator_set/test.rs | 9 +- crates/ethcore/src/error.rs | 2 +- crates/ethcore/src/ethereum/ethash.rs | 26 +- crates/ethcore/src/ethereum/mod.rs | 27 +- crates/ethcore/src/executive.rs | 76 +- crates/ethcore/src/externalities.rs | 29 +- crates/ethcore/src/json_tests/executive.rs | 8 +- crates/ethcore/src/lib.rs | 6 +- crates/ethcore/src/machine/impls.rs | 11 +- crates/ethcore/src/miner/miner.rs | 10 +- crates/ethcore/src/miner/stratum.rs | 10 +- crates/ethcore/src/pod_account.rs | 57 +- crates/ethcore/src/pod_state.rs | 27 +- crates/ethcore/src/snapshot/account.rs | 4 +- crates/ethcore/src/snapshot/block.rs | 25 +- crates/ethcore/src/snapshot/consensus/work.rs | 4 +- crates/ethcore/src/snapshot/mod.rs | 4 +- crates/ethcore/src/snapshot/tests/helpers.rs | 2 +- .../src/snapshot/tests/proof_of_authority.rs | 4 +- crates/ethcore/src/snapshot/tests/service.rs | 2 + crates/ethcore/src/snapshot/tests/state.rs | 11 +- crates/ethcore/src/snapshot/watcher.rs | 4 +- crates/ethcore/src/spec/spec.rs | 24 +- crates/ethcore/src/state/account.rs | 68 +- crates/ethcore/src/state/mod.rs | 542 +++++++----- crates/ethcore/src/state/substate.rs | 15 +- crates/ethcore/src/test_helpers.rs | 6 +- crates/ethcore/src/tests/client.rs | 2 +- crates/ethcore/src/tests/evm.rs | 16 +- crates/ethcore/src/tests/trace.rs | 8 +- crates/ethcore/src/trace/db.rs | 51 +- crates/ethcore/src/trace/types/error.rs | 3 +- crates/ethcore/src/trace/types/filter.rs | 125 +-- crates/ethcore/src/trace/types/flat.rs | 30 +- crates/ethcore/src/trace/types/trace.rs | 14 +- crates/ethcore/src/tx_filter.rs | 99 ++- crates/ethcore/src/verification/queue/kind.rs | 21 +- crates/ethcore/src/verification/queue/mod.rs | 27 +- .../ethcore/src/verification/verification.rs | 25 +- crates/ethcore/sync/Cargo.toml | 13 +- crates/ethcore/sync/src/api.rs | 2 +- crates/ethcore/sync/src/block_sync.rs | 10 +- crates/ethcore/sync/src/blocks.rs | 31 +- crates/ethcore/sync/src/chain/handler.rs | 6 +- crates/ethcore/sync/src/chain/mod.rs | 28 +- crates/ethcore/sync/src/chain/propagator.rs | 4 +- crates/ethcore/sync/src/chain/supplier.rs | 34 +- crates/ethcore/sync/src/lib.rs | 7 +- crates/ethcore/sync/src/snapshot.rs | 16 +- crates/ethcore/sync/src/tests/consensus.rs | 6 +- crates/ethcore/sync/src/tests/helpers.rs | 5 +- crates/ethcore/sync/src/tests/snapshot.rs | 8 +- crates/ethcore/sync/src/transactions_stats.rs | 11 +- crates/ethcore/types/Cargo.toml | 10 +- crates/ethcore/types/src/account_diff.rs | 12 +- crates/ethcore/types/src/encoded.rs | 26 +- crates/ethcore/types/src/filter.rs | 123 ++- crates/ethcore/types/src/header.rs | 10 +- crates/ethcore/types/src/lib.rs | 4 +- crates/ethcore/types/src/log_entry.rs | 21 +- crates/ethcore/types/src/receipt.rs | 34 +- crates/ethcore/types/src/transaction/error.rs | 5 +- .../types/src/transaction/transaction.rs | 144 ++- crates/ethcore/types/src/views/block.rs | 5 +- crates/ethcore/types/src/views/header.rs | 23 +- crates/ethjson/Cargo.toml | 4 +- crates/ethjson/src/hash.rs | 15 +- crates/ethjson/src/lib.rs | 2 +- crates/ethjson/src/spec/authority_round.rs | 13 +- crates/ethjson/src/spec/basic_authority.rs | 7 +- crates/ethjson/src/spec/ethash.rs | 87 +- crates/ethjson/src/spec/genesis.rs | 37 +- crates/ethjson/src/spec/seal.rs | 18 +- crates/ethjson/src/spec/validator_set.rs | 19 +- crates/ethjson/src/state/test.rs | 7 +- crates/ethjson/src/uint.rs | 7 +- crates/net/network-devp2p/Cargo.toml | 10 +- crates/net/network-devp2p/src/connection.rs | 272 +++--- crates/net/network-devp2p/src/discovery.rs | 36 +- crates/net/network-devp2p/src/handshake.rs | 61 +- crates/net/network-devp2p/src/host.rs | 6 +- crates/net/network-devp2p/src/node_table.rs | 7 +- crates/net/network-devp2p/tests/tests.rs | 6 +- crates/net/network/Cargo.toml | 6 +- crates/net/network/src/error.rs | 11 +- crates/net/network/src/lib.rs | 2 +- crates/net/node-filter/Cargo.toml | 10 +- crates/net/node-filter/src/lib.rs | 19 +- crates/rpc/Cargo.toml | 11 +- crates/rpc/src/authcodes.rs | 9 +- crates/rpc/src/v1/extractors.rs | 10 +- crates/rpc/src/v1/helpers/dispatch/mod.rs | 3 +- crates/rpc/src/v1/helpers/dispatch/signing.rs | 3 +- crates/rpc/src/v1/helpers/engine_signer.rs | 7 +- .../helpers/external_signer/signing_queue.rs | 17 +- crates/rpc/src/v1/helpers/secretstore.rs | 32 +- crates/rpc/src/v1/helpers/signature.rs | 8 +- crates/rpc/src/v1/helpers/subscribers.rs | 39 +- .../src/v1/helpers/subscription_manager.rs | 4 +- crates/rpc/src/v1/impls/eth.rs | 17 +- crates/rpc/src/v1/impls/eth_pubsub.rs | 6 +- crates/rpc/src/v1/impls/parity.rs | 9 +- crates/rpc/src/v1/impls/parity_accounts.rs | 7 +- crates/rpc/src/v1/impls/parity_set.rs | 3 +- crates/rpc/src/v1/impls/personal.rs | 4 +- crates/rpc/src/v1/impls/secretstore.rs | 8 +- crates/rpc/src/v1/impls/signer.rs | 24 +- crates/rpc/src/v1/tests/eth.rs | 2 +- .../rpc/src/v1/tests/helpers/sync_provider.rs | 14 +- crates/rpc/src/v1/tests/mocked/eth.rs | 51 +- crates/rpc/src/v1/tests/mocked/eth_pubsub.rs | 38 +- crates/rpc/src/v1/tests/mocked/parity.rs | 36 +- .../src/v1/tests/mocked/parity_accounts.rs | 8 +- crates/rpc/src/v1/tests/mocked/parity_set.rs | 4 +- crates/rpc/src/v1/tests/mocked/personal.rs | 10 +- crates/rpc/src/v1/tests/mocked/pubsub.rs | 8 +- crates/rpc/src/v1/tests/mocked/secretstore.rs | 6 +- crates/rpc/src/v1/tests/mocked/signer.rs | 12 +- crates/rpc/src/v1/tests/mocked/signing.rs | 28 +- .../rpc/src/v1/tests/mocked/signing_unsafe.rs | 2 +- crates/rpc/src/v1/tests/mocked/traces.rs | 9 +- crates/rpc/src/v1/types/call_request.rs | 6 +- crates/rpc/src/v1/types/confirmations.rs | 22 +- crates/rpc/src/v1/types/eth_types.rs | 14 +- crates/rpc/src/v1/types/filter.rs | 12 +- crates/rpc/src/v1/types/provenance.rs | 11 +- crates/rpc/src/v1/types/receipt.rs | 9 +- crates/rpc/src/v1/types/secretstore.rs | 9 +- crates/rpc/src/v1/types/sync.rs | 3 +- crates/rpc/src/v1/types/trace.rs | 49 +- crates/rpc/src/v1/types/trace_filter.rs | 4 +- crates/rpc/src/v1/types/transaction.rs | 7 +- .../rpc/src/v1/types/transaction_request.rs | 6 +- crates/util/EIP-712/Cargo.toml | 6 +- crates/util/EIP-712/src/encode.rs | 12 +- crates/util/cli-signer/Cargo.toml | 2 +- crates/util/cli-signer/rpc-client/Cargo.toml | 4 +- crates/util/dir/Cargo.toml | 2 +- crates/util/dir/src/lib.rs | 8 +- crates/util/fastmap/Cargo.toml | 2 +- crates/util/fastmap/src/lib.rs | 2 +- crates/util/keccak-hasher/Cargo.toml | 2 +- crates/util/memory-cache/Cargo.toml | 2 +- crates/util/memory-cache/src/lib.rs | 12 +- crates/util/rlp-compress/Cargo.toml | 2 +- crates/util/rlp-derive/Cargo.toml | 2 +- crates/util/triehash-ethereum/Cargo.toml | 4 +- crates/util/triehash-ethereum/src/lib.rs | 5 +- crates/util/version/Cargo.toml | 2 +- crates/vm/builtin/Cargo.toml | 6 +- crates/vm/builtin/src/lib.rs | 20 +- crates/vm/call-contract/Cargo.toml | 2 +- crates/vm/evm/Cargo.toml | 6 +- crates/vm/evm/benches/basic.rs | 1 - crates/vm/evm/src/interpreter/gasometer.rs | 10 +- crates/vm/evm/src/interpreter/mod.rs | 40 +- crates/vm/evm/src/interpreter/shared_cache.rs | 15 +- crates/vm/evm/src/lib.rs | 2 +- crates/vm/evm/src/tests.rs | 34 +- crates/vm/vm/Cargo.toml | 6 +- crates/vm/vm/src/access_list.rs | 89 +- crates/vm/vm/src/action_params.rs | 10 +- crates/vm/vm/src/tests.rs | 9 +- crates/vm/wasm/Cargo.toml | 2 +- crates/vm/wasm/src/runtime.rs | 22 +- 273 files changed, 3056 insertions(+), 4780 deletions(-) delete mode 100644 crates/accounts/ethkey/src/crypto.rs delete mode 100644 crates/accounts/ethkey/src/error.rs delete mode 100644 crates/accounts/ethkey/src/extended.rs delete mode 100644 crates/accounts/ethkey/src/keccak.rs delete mode 100644 crates/accounts/ethkey/src/keypair.rs delete mode 100644 crates/accounts/ethkey/src/math.rs delete mode 100644 crates/accounts/ethkey/src/random.rs delete mode 100644 crates/accounts/ethkey/src/secret.rs delete mode 100644 crates/accounts/ethkey/src/signature.rs diff --git a/Cargo.lock b/Cargo.lock index 32155cafde..97cb5d1937 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,21 @@ dependencies = [ "stream-cipher", ] +[[package]] +name = "ahash" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29661b60bec623f0586702976ff4d0c9942dcb6723161c2df0eea78455cfedfb" +dependencies = [ + "const-random", +] + +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" + [[package]] name = "aho-corasick" version = "0.6.10" @@ -89,12 +104,6 @@ dependencies = [ "xdg", ] -[[package]] -name = "arrayref" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" - [[package]] name = "arrayvec" version = "0.4.12" @@ -145,7 +154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" dependencies = [ "backtrace-sys", - "cfg-if", + "cfg-if 0.1.10", "libc", "rustc-demangle", ] @@ -216,16 +225,6 @@ dependencies = [ "radium", ] -[[package]] -name = "block-buffer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -dependencies = [ - "arrayref", - "byte-tools 0.2.0", -] - [[package]] name = "block-buffer" version = "0.7.3" @@ -233,9 +232,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ "block-padding", - "byte-tools 0.3.1", + "byte-tools", "byteorder", - "generic-array 0.12.3", + "generic-array", ] [[package]] @@ -244,7 +243,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" dependencies = [ - "generic-array 0.12.3", + "generic-array", ] [[package]] @@ -263,7 +262,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" dependencies = [ - "byte-tools 0.3.1", + "byte-tools", ] [[package]] @@ -272,7 +271,7 @@ version = "0.1.0" dependencies = [ "byteorder", "criterion 0.3.0", - "ethbloom 0.5.0", + "ethbloom", "parking_lot 0.7.1", "tempdir", "tiny-keccak 1.5.0", @@ -287,7 +286,7 @@ dependencies = [ "crunchy 0.2.2", "lazy_static", "rand 0.5.6", - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", ] [[package]] @@ -314,12 +313,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" - [[package]] name = "byte-tools" version = "0.3.1" @@ -360,9 +353,9 @@ checksum = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" [[package]] name = "cc" -version = "1.0.47" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +checksum = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" [[package]] name = "cfg-if" @@ -370,6 +363,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "chainspec" version = "0.1.0" @@ -409,7 +408,7 @@ dependencies = [ name = "cli-signer" version = "1.4.0" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "futures", "parity-rpc", "parity-rpc-client", @@ -438,12 +437,12 @@ dependencies = [ name = "common-types" version = "0.1.0" dependencies = [ - "ethereum-types 0.4.2", - "ethkey", - "heapsize", + "ethereum-types", "keccak-hash", "parity-bytes", - "rlp 0.3.0", + "parity-crypto", + "parity-util-mem", + "rlp", "rlp_derive", "rustc-hex 1.0.0", "serde", @@ -453,10 +452,26 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.1.4" +name = "const-random" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" +dependencies = [ + "getrandom 0.2.2", + "lazy_static", + "proc-macro-hack", + "tiny-keccak 2.0.2", +] [[package]] name = "crc" @@ -567,7 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ "arrayvec 0.4.12", - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils 0.6.6", "lazy_static", "memoffset", @@ -589,7 +604,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "maybe-uninit", ] @@ -600,7 +615,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -611,7 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg 1.0.0", - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -627,23 +642,13 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "crypto-mac" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7afa06d05a046c7a47c3a849907ec303504608c927f4e85f7bfff22b7180d971" -dependencies = [ - "constant_time_eq", - "generic-array 0.9.0", -] - [[package]] name = "crypto-mac" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" dependencies = [ - "generic-array 0.12.3", + "generic-array", "subtle 1.0.0", ] @@ -715,22 +720,13 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" -[[package]] -name = "digest" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -dependencies = [ - "generic-array 0.9.0", -] - [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3", + "generic-array", ] [[package]] @@ -738,7 +734,7 @@ name = "dir" version = "0.1.2" dependencies = [ "app_dirs", - "ethereum-types 0.4.2", + "ethereum-types", "home 0.3.4", "journaldb", ] @@ -765,7 +761,7 @@ checksum = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b" name = "eip-152" version = "0.1.0" dependencies = [ - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", ] [[package]] @@ -773,7 +769,7 @@ name = "eip-712" version = "0.1.0" dependencies = [ "ethabi", - "ethereum-types 0.4.2", + "ethereum-types", "failure", "indexmap", "itertools 0.7.11", @@ -781,7 +777,7 @@ dependencies = [ "lazy_static", "lunarity-lexer", "regex 1.3.9", - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", "serde", "serde_derive", "serde_json", @@ -839,12 +835,12 @@ dependencies = [ [[package]] name = "eth-secp256k1" version = "0.5.7" -source = "git+https://github.com/paritytech/rust-secp256k1?rev=ccc06e7480148b723eb44ac56cf4d20eec380b6f#ccc06e7480148b723eb44ac56cf4d20eec380b6f" +source = "git+https://github.com/paritytech/rust-secp256k1?rev=9791e79f21a5309dcb6e0bd254b1ef88fca2f1f4#9791e79f21a5309dcb6e0bd254b1ef88fca2f1f4" dependencies = [ "arrayvec 0.4.12", "cc", - "cfg-if", - "rand 0.4.6", + "cfg-if 0.1.10", + "rand 0.6.5", ] [[package]] @@ -875,36 +871,35 @@ dependencies = [ [[package]] name = "ethabi" -version = "6.1.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb362fde43ed0b50b258bb0c72b72b3dccfd29f8de9506295eaf9251c49ca31" +checksum = "052a565e3de82944527d6d10a465697e6bb92476b772ca7141080c901f6a63c6" dependencies = [ - "error-chain", - "ethereum-types 0.4.2", - "rustc-hex 2.0.1", + "ethereum-types", + "rustc-hex 2.1.0", "serde", - "serde_derive", "serde_json", "tiny-keccak 1.5.0", + "uint", ] [[package]] name = "ethabi-contract" -version = "6.0.0" +version = "11.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795e25fd868e12a59ca235dbe1f6cc8f1eba8f67d6a39438b29535e0126e0c27" +checksum = "88d4002f1f77d8233685dafd8589efe1c9dfa63e21ca6c11134372acc7f68032" [[package]] name = "ethabi-derive" -version = "6.0.2" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a587250c8190be9d6ae28d67b8957ed97cb9eee2e272173a20593ab054a075" +checksum = "b7c0fe66618e0cfcf111afc863e7940413f2a88240cf63b38cc61206fe7be025" dependencies = [ "ethabi", "heck", - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.26", + "proc-macro2 1.0.20", + "quote 1.0.7", + "syn 1.0.40", ] [[package]] @@ -914,7 +909,7 @@ dependencies = [ "criterion 0.2.11", "crunchy 0.1.6", "either", - "ethereum-types 0.4.2", + "ethereum-types", "keccak-hash", "log", "memmap", @@ -923,19 +918,7 @@ dependencies = [ "rustc-hex 1.0.0", "serde_json", "tempdir", -] - -[[package]] -name = "ethbloom" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" -dependencies = [ - "crunchy 0.1.6", - "ethereum-types-serialize", - "fixed-hash 0.2.2", - "serde", - "tiny-keccak 1.5.0", + "tiny-keccak 2.0.2", ] [[package]] @@ -945,7 +928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71a6567e6fd35589fea0c63b94b4cf2e55573e413901bdbe60ab15cf0e25e5df" dependencies = [ "crunchy 0.2.2", - "fixed-hash 0.6.1", + "fixed-hash", "impl-rlp", "impl-serde", "tiny-keccak 2.0.2", @@ -976,14 +959,13 @@ dependencies = [ "ethcore-io", "ethcore-miner", "ethcore-stratum", - "ethereum-types 0.4.2", + "ethereum-types", "ethjson", "ethkey", "evm", "fetch", "globset", - "hash-db", - "heapsize", + "hash-db 0.11.0", "hex-literal", "itertools 0.5.10", "journaldb", @@ -1002,14 +984,17 @@ dependencies = [ "memory-db 0.11.0", "num_cpus", "parity-bytes", + "parity-crypto", "parity-runtime", "parity-snappy", + "parity-util-mem", "parking_lot 0.7.1", "patricia-trie-ethereum", - "rand 0.4.6", + "rand 0.7.3", + "rand_xorshift 0.2.0", "rayon", "regex 1.3.9", - "rlp 0.3.0", + "rlp", "rlp_compress", "rlp_derive", "rustc-hex 1.0.0", @@ -1037,10 +1022,11 @@ name = "ethcore-accounts" version = "0.1.0" dependencies = [ "common-types", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "ethstore", "log", + "parity-crypto", "parking_lot 0.7.1", "serde", "serde_derive", @@ -1057,19 +1043,20 @@ dependencies = [ "common-types", "env_logger", "ethcore-db", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", - "heapsize", "itertools 0.5.10", "keccak-hash", "kvdb", "kvdb-memorydb", "log", "parity-bytes", + "parity-crypto", + "parity-util-mem", "parking_lot 0.7.1", - "rand 0.6.5", + "rand 0.7.3", "rayon", - "rlp 0.3.0", + "rlp", "rlp_compress", "rlp_derive", "rustc-hex 1.0.0", @@ -1093,7 +1080,7 @@ dependencies = [ "byteorder", "eip-152", "eth_pairings", - "ethereum-types 0.4.2", + "ethereum-types", "ethjson", "ethkey", "hex-literal", @@ -1103,7 +1090,7 @@ dependencies = [ "maplit", "num", "parity-bytes", - "parity-crypto 0.4.2", + "parity-crypto", "rustc-hex 1.0.0", ] @@ -1112,7 +1099,7 @@ name = "ethcore-call-contract" version = "0.1.0" dependencies = [ "common-types", - "ethereum-types 0.4.2", + "ethereum-types", "parity-bytes", ] @@ -1121,13 +1108,13 @@ name = "ethcore-db" version = "0.1.0" dependencies = [ "common-types", - "ethereum-types 0.4.2", - "heapsize", + "ethereum-types", "kvdb", "kvdb-memorydb", "kvdb-rocksdb", + "parity-util-mem", "parking_lot 0.7.1", - "rlp 0.3.0", + "rlp", "rlp_derive", "stats", ] @@ -1177,19 +1164,20 @@ dependencies = [ "ethabi-derive", "ethash", "ethcore-call-contract", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "fetch", "futures", - "heapsize", "hyper 0.12.35", "keccak-hash", "linked-hash-map", "log", + "parity-crypto", "parity-runtime", + "parity-util-mem", "parking_lot 0.7.1", "price-info", - "rlp 0.3.0", + "rlp", "rustc-hex 1.0.0", "trace-time", "transaction-pool", @@ -1203,14 +1191,14 @@ dependencies = [ "assert_matches", "error-chain", "ethcore-io", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "ipnetwork", "lazy_static", "libc", - "parity-crypto 0.3.1", + "parity-crypto", "parity-snappy", - "rlp 0.3.0", + "rlp", "semver", "serde", "serde_derive", @@ -1227,7 +1215,7 @@ dependencies = [ "error-chain", "ethcore-io", "ethcore-network", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "igd", "ipnetwork", @@ -1237,12 +1225,12 @@ dependencies = [ "lru-cache", "mio", "parity-bytes", - "parity-crypto 0.3.1", + "parity-crypto", "parity-path", "parity-snappy", "parking_lot 0.7.1", - "rand 0.4.6", - "rlp 0.3.0", + "rand 0.7.3", + "rlp", "rust-crypto", "rustc-hex 1.0.0", "serde", @@ -1264,7 +1252,7 @@ dependencies = [ "ethcore-db", "ethcore-io", "ethcore-sync", - "ethereum-types 0.4.2", + "ethereum-types", "kvdb", "kvdb-rocksdb", "log", @@ -1277,7 +1265,7 @@ name = "ethcore-stratum" version = "1.12.0" dependencies = [ "env_logger", - "ethereum-types 0.4.2", + "ethereum-types", "jsonrpc-core", "jsonrpc-tcp-server", "keccak-hash", @@ -1300,12 +1288,11 @@ dependencies = [ "ethcore-network", "ethcore-network-devp2p", "ethereum-forkid", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "ethstore", "fastmap", - "hash-db", - "heapsize", + "hash-db 0.11.0", "keccak-hash", "keccak-hasher 0.1.1", "kvdb", @@ -1313,11 +1300,13 @@ dependencies = [ "log", "macros", "parity-bytes", + "parity-crypto", + "parity-util-mem", "parking_lot 0.7.1", "primitive-types", - "rand 0.4.6", - "rlp 0.3.0", - "rlp 0.4.5", + "rand 0.7.3", + "rand_xorshift 0.2.0", + "rlp", "rustc-hex 1.0.0", "stats", "trace-time", @@ -1331,48 +1320,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3010d8372e3a76d4e2c44de0a080257ab62b6d108857ee7bd70fe8dfb2815f13" dependencies = [ "crc", - "ethereum-types 0.9.2", + "ethereum-types", "maplit", "parity-util-mem", - "rlp 0.4.5", + "rlp", "rlp-derive", ] -[[package]] -name = "ethereum-types" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e742184dc63a01c8ea0637369f8faa27c40f537949908a237f95c05e68d2c96" -dependencies = [ - "crunchy 0.1.6", - "ethbloom 0.5.0", - "ethereum-types-serialize", - "fixed-hash 0.2.2", - "serde", - "uint 0.4.1", -] - [[package]] name = "ethereum-types" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0" dependencies = [ - "ethbloom 0.9.2", - "fixed-hash 0.6.1", + "ethbloom", + "fixed-hash", "impl-rlp", "impl-serde", "primitive-types", - "uint 0.8.5", -] - -[[package]] -name = "ethereum-types-serialize" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d77b32bc1891a79dad925f2acbc318ee942b38b9110f9dbc5fbeffcea350" -dependencies = [ - "serde", + "uint", ] [[package]] @@ -1380,10 +1346,10 @@ name = "ethjson" version = "0.1.0" dependencies = [ "common-types", - "ethereum-types 0.4.2", - "ethkey", + "ethereum-types", "macros", "maplit", + "parity-crypto", "rustc-hex 1.0.0", "serde", "serde_derive", @@ -1396,14 +1362,14 @@ version = "0.3.0" dependencies = [ "edit-distance", "eth-secp256k1", - "ethereum-types 0.4.2", + "ethereum-types", "lazy_static", "log", "memzero", - "parity-crypto 0.3.1", + "parity-crypto", "parity-wordlist", "quick-error", - "rand 0.4.6", + "rand 0.7.3", "rustc-hex 1.0.0", "serde", "serde_derive", @@ -1418,6 +1384,7 @@ dependencies = [ "env_logger", "ethkey", "panic_hook", + "parity-crypto", "parity-wordlist", "rustc-hex 1.0.0", "serde", @@ -1429,17 +1396,17 @@ dependencies = [ name = "ethstore" version = "0.2.1" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "itertools 0.5.10", "lazy_static", "libc", "log", "matches", - "parity-crypto 0.3.1", + "parity-crypto", "parity-wordlist", "parking_lot 0.7.1", - "rand 0.4.6", + "rand 0.7.3", "rustc-hex 1.0.0", "serde", "serde_derive", @@ -1473,8 +1440,7 @@ dependencies = [ "bit-set", "criterion 0.2.11", "ethcore-builtin", - "ethereum-types 0.4.2", - "heapsize", + "ethereum-types", "hex-literal", "keccak-hash", "lazy_static", @@ -1482,6 +1448,7 @@ dependencies = [ "memory-cache", "num-bigint 0.2.3", "parity-bytes", + "parity-util-mem", "parking_lot 0.7.1", "rustc-hex 1.0.0", "vm", @@ -1496,7 +1463,7 @@ dependencies = [ "docopt", "env_logger", "ethcore", - "ethereum-types 0.4.2", + "ethereum-types", "ethjson", "evm", "panic_hook", @@ -1529,7 +1496,7 @@ dependencies = [ "proc-macro2 1.0.20", "quote 1.0.7", "syn 1.0.40", - "synstructure 0.12.2", + "synstructure", ] [[package]] @@ -1551,7 +1518,7 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" name = "fastmap" version = "0.1.0" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "plain_hasher", ] @@ -1578,18 +1545,6 @@ dependencies = [ "url 2.1.0", ] -[[package]] -name = "fixed-hash" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de" -dependencies = [ - "heapsize", - "libc", - "rand 0.4.6", - "rustc-hex 1.0.0", -] - [[package]] name = "fixed-hash" version = "0.6.1" @@ -1597,8 +1552,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c" dependencies = [ "byteorder", - "rand 0.7.2", - "rustc-hex 2.0.1", + "rand 0.7.3", + "rustc-hex 2.1.0", "static_assertions", ] @@ -1642,12 +1597,6 @@ dependencies = [ "winapi 0.3.8", ] -[[package]] -name = "fs_extra" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" - [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1701,15 +1650,6 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -[[package]] -name = "generic-array" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.12.3" @@ -1734,9 +1674,20 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", - "wasi", + "wasi 0.7.0", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -1782,6 +1733,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03501f6e1a2a97f1618879aba3156f14ca2847faa530c4e28859638bd11483" +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + [[package]] name = "hash256-std-hasher" version = "0.11.0" @@ -1791,12 +1748,41 @@ dependencies = [ "crunchy 0.2.2", ] +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy 0.2.2", +] + +[[package]] +name = "hashbrown" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" +dependencies = [ + "ahash 0.2.19", + "autocfg 0.1.7", +] + +[[package]] +name = "hashbrown" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" +dependencies = [ + "ahash 0.3.8", + "autocfg 1.0.0", +] + [[package]] name = "heapsize" version = "0.4.2" -source = "git+https://github.com/cheme/heapsize.git?branch=ec-macfix#c07ffe843acb9da570682e290a48540741afdce1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" dependencies = [ - "jemallocator", "winapi 0.3.8", ] @@ -1837,24 +1823,14 @@ dependencies = [ "proc-macro-hack", ] -[[package]] -name = "hmac" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" -dependencies = [ - "crypto-mac 0.6.2", - "digest 0.7.6", -] - [[package]] name = "hmac" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" dependencies = [ - "crypto-mac 0.7.0", - "digest 0.8.1", + "crypto-mac", + "digest", ] [[package]] @@ -2048,7 +2024,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f7a72f11830b52333f36e3b09a288333888bf54380fd0ac0790a3c31ab0f3c5" dependencies = [ - "rlp 0.4.5", + "rlp", ] [[package]] @@ -2134,37 +2110,15 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -[[package]] -name = "jemalloc-sys" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae" -dependencies = [ - "cc", - "fs_extra", - "libc", -] - -[[package]] -name = "jemallocator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0cd42ac65f758063fea55126b0148b1ce0a6354ff78e07a4d6806bc65c4ab3" -dependencies = [ - "jemalloc-sys", - "libc", -] - [[package]] name = "journaldb" version = "0.2.0" dependencies = [ "env_logger", "ethcore-db", - "ethereum-types 0.4.2", + "ethereum-types", "fastmap", - "hash-db", - "heapsize", + "hash-db 0.11.0", "keccak-hash", "keccak-hasher 0.1.1", "kvdb", @@ -2172,8 +2126,9 @@ dependencies = [ "log", "memory-db 0.11.0", "parity-bytes", + "parity-util-mem", "parking_lot 0.7.1", - "rlp 0.3.0", + "rlp", ] [[package]] @@ -2239,7 +2194,7 @@ dependencies = [ "jsonrpc-core", "log", "parking_lot 0.10.2", - "rand 0.7.2", + "rand 0.7.3", "serde", ] @@ -2288,20 +2243,20 @@ dependencies = [ [[package]] name = "keccak-hash" -version = "0.1.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "253bbe643c32c816bf58fa5a88248fafedeebb139705ad17a62add3517854a86" +checksum = "1f58a51ef3df9398cf2434bea8d4eb61fb748d0feb1571f87388579a120a4c8f" dependencies = [ - "ethereum-types 0.4.2", - "tiny-keccak 1.5.0", + "primitive-types", + "tiny-keccak 2.0.2", ] [[package]] name = "keccak-hasher" version = "0.1.1" dependencies = [ - "ethereum-types 0.4.2", - "hash-db", + "ethereum-types", + "hash-db 0.11.0", "plain_hasher", "tiny-keccak 1.5.0", ] @@ -2312,11 +2267,22 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb9d3670023f4c04153d90b8a557a822d1b27ed702bb015a87cf7bffead5b611" dependencies = [ - "hash-db", - "hash256-std-hasher", + "hash-db 0.11.0", + "hash256-std-hasher 0.11.0", "tiny-keccak 1.5.0", ] +[[package]] +name = "keccak-hasher" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711adba9940a039f4374fc5724c0a5eaca84a2d558cce62256bfe26f0dbef05e" +dependencies = [ + "hash-db 0.15.2", + "hash256-std-hasher 0.15.2", + "tiny-keccak 2.0.2", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -2447,7 +2413,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -2473,6 +2439,15 @@ dependencies = [ "utf8-ranges", ] +[[package]] +name = "lru" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34" +dependencies = [ + "hashbrown 0.6.3", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -2545,8 +2520,8 @@ dependencies = [ name = "memory-cache" version = "0.1.0" dependencies = [ - "heapsize", "lru-cache", + "parity-util-mem", ] [[package]] @@ -2554,9 +2529,9 @@ name = "memory-db" version = "0.11.0" dependencies = [ "criterion 0.2.11", - "hash-db", - "heapsize", + "hash-db 0.11.0", "keccak-hasher 0.11.0", + "parity-util-mem", ] [[package]] @@ -2565,7 +2540,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" dependencies = [ - "hash-db", + "hash-db 0.11.0", "heapsize", ] @@ -2602,7 +2577,7 @@ version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -2684,7 +2659,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "winapi 0.3.8", ] @@ -2700,7 +2675,7 @@ dependencies = [ "ethcore-io", "ethcore-network", "ethcore-network-devp2p", - "ethereum-types 0.4.2", + "ethereum-types", "kvdb-memorydb", "log", "lru-cache", @@ -2853,7 +2828,7 @@ dependencies = [ "ethcore-network", "ethcore-service", "ethcore-sync", - "ethereum-types 0.4.2", + "ethereum-types", "ethkey", "ethstore", "fake-fetch", @@ -2875,6 +2850,7 @@ dependencies = [ "number_prefix", "panic_hook", "parity-bytes", + "parity-crypto", "parity-daemonize", "parity-local-store", "parity-path", @@ -2885,7 +2861,7 @@ dependencies = [ "pretty_assertions", "prometheus", "regex 1.3.9", - "rlp 0.3.0", + "rlp", "rpassword", "rustc-hex 1.0.0", "rustc_version", @@ -2937,41 +2913,26 @@ checksum = "0c276d76c5333b8c2579e02d49a06733a55b8282d2d9b13e8d53b6406bd7e30a" [[package]] name = "parity-crypto" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1b9c063d87e1507cb3807493c8d21859ef23b5414b39f81c53f0ba267d64c1" -dependencies = [ - "aes", - "aes-ctr", - "block-modes", - "digest 0.8.1", - "quick-error", - "ring", - "ripemd160", - "scrypt 0.1.2", - "sha2 0.8.0", - "tiny-keccak 1.5.0", -] - -[[package]] -name = "parity-crypto" -version = "0.4.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27a9c2b525c93d717a234eb220c26474f8d97b08ac50d79faeac4cb6c74bf0b9" +checksum = "88e15b5e11d7a4829490630a797c537a68c9e864a139f56fe7a1e6a51f0da25d" dependencies = [ "aes", "aes-ctr", "block-modes", - "digest 0.8.1", - "hmac 0.7.1", - "pbkdf2 0.3.0", - "rand 0.7.2", + "digest", + "ethereum-types", + "hmac", + "lazy_static", + "pbkdf2", + "rand 0.7.3", "ripemd160", - "rustc-hex 2.0.1", - "scrypt 0.2.0", - "sha2 0.8.0", + "rustc-hex 2.1.0", + "scrypt", + "secp256k1", + "sha2", "subtle 2.3.0", - "tiny-keccak 1.5.0", + "tiny-keccak 2.0.2", "zeroize", ] @@ -2999,7 +2960,8 @@ dependencies = [ "kvdb", "kvdb-memorydb", "log", - "rlp 0.3.0", + "parity-crypto", + "rlp", "serde", "serde_derive", "serde_json", @@ -3052,7 +3014,7 @@ dependencies = [ "ethcore-miner", "ethcore-network", "ethcore-sync", - "ethereum-types 0.4.2", + "ethereum-types", "ethjson", "ethkey", "ethstore", @@ -3071,13 +3033,14 @@ dependencies = [ "macros", "order-stat", "parity-bytes", - "parity-crypto 0.3.1", + "parity-crypto", "parity-runtime", "parity-version", "parking_lot 0.7.1", "pretty_assertions", - "rand 0.4.6", - "rlp 0.3.0", + "rand 0.7.3", + "rand_xorshift 0.2.0", + "rlp", "rustc-hex 1.0.0", "serde", "serde_derive", @@ -3095,7 +3058,7 @@ dependencies = [ name = "parity-rpc-client" version = "1.4.0" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "futures", "jsonrpc-core", "jsonrpc-ws-server", @@ -3161,7 +3124,7 @@ dependencies = [ "log", "mio-named-pipes", "miow 0.3.3", - "rand 0.7.2", + "rand 0.7.3", "tokio", "tokio-named-pipes", "tokio-uds", @@ -3174,11 +3137,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297ff91fa36aec49ce183484b102f6b75b46776822bd81525bfc4cc9b0dd0f5c" dependencies = [ - "cfg-if", - "ethereum-types 0.9.2", + "cfg-if 0.1.10", + "ethereum-types", + "hashbrown 0.8.2", "impl-trait-for-tuples", + "lru", "parity-util-mem-derive", + "parking_lot 0.10.2", "primitive-types", + "smallvec 1.4.2", "winapi 0.3.8", ] @@ -3190,7 +3157,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2 1.0.20", "syn 1.0.40", - "synstructure 0.12.2", + "synstructure", ] [[package]] @@ -3198,7 +3165,7 @@ name = "parity-version" version = "3.2.0" dependencies = [ "parity-bytes", - "rlp 0.3.0", + "rlp", "rustc_version", "target_info", "toml 0.4.10", @@ -3236,7 +3203,7 @@ dependencies = [ "log", "mio", "mio-extras", - "rand 0.7.2", + "rand 0.7.3", "sha-1", "slab 0.4.2", "url 2.1.0", @@ -3318,7 +3285,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall", @@ -3333,7 +3300,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall", @@ -3346,28 +3313,17 @@ name = "patricia-trie-ethereum" version = "0.1.0" dependencies = [ "elastic-array", - "ethereum-types 0.4.2", - "hash-db", + "ethereum-types", + "hash-db 0.11.0", "journaldb", "keccak-hash", "keccak-hasher 0.1.1", "memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes", - "rlp 0.3.0", + "rlp", "trie-db", ] -[[package]] -name = "pbkdf2" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09cddfbfc98de7f76931acf44460972edb4023eb14d0c6d4018800e552d8e0" -dependencies = [ - "byteorder", - "crypto-mac 0.6.2", - "generic-array 0.9.0", -] - [[package]] name = "pbkdf2" version = "0.3.0" @@ -3376,10 +3332,10 @@ checksum = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" dependencies = [ "base64 0.9.3", "byteorder", - "crypto-mac 0.7.0", - "hmac 0.7.1", + "crypto-mac", + "hmac", "rand 0.5.6", - "sha2 0.8.0", + "sha2", "subtle 1.0.0", ] @@ -3495,11 +3451,11 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c55c21c64d0eaa4d7ed885d959ef2d62d9e488c27c0e02d9aa5ce6c877b7d5f8" dependencies = [ - "fixed-hash 0.6.1", + "fixed-hash", "impl-codec", "impl-rlp", "impl-serde", - "uint 0.8.5", + "uint", ] [[package]] @@ -3513,14 +3469,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.11" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2 1.0.20", - "quote 1.0.7", - "syn 1.0.40", -] +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" @@ -3546,7 +3497,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0ced56dee39a6e960c15c74dc48849d614586db2eaada6497477af7c7811cd" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fnv", "lazy_static", "protobuf", @@ -3661,17 +3612,17 @@ dependencies = [ "rand_jitter", "rand_os 0.1.3", "rand_pcg", - "rand_xorshift", + "rand_xorshift 0.1.1", "winapi 0.3.8", ] [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.13", "libc", "rand_chacha 0.2.1", "rand_core 0.5.1", @@ -3719,7 +3670,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.13", ] [[package]] @@ -3780,7 +3731,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" dependencies = [ - "getrandom", + "getrandom 0.1.13", "rand_core 0.5.1", ] @@ -3803,6 +3754,15 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "rand_xorshift" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_xoshiro" version = "0.1.0" @@ -3948,41 +3908,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", + "block-buffer", + "digest", "opaque-debug", ] [[package]] name = "rlp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524c5ad554859785dfc8469df3ed5e0b5784d4d335877ed47c8d90fc0eb238fe" -dependencies = [ - "byteorder", - "elastic-array", - "ethereum-types 0.4.2", - "rustc-hex 2.0.1", -] - -[[package]] -name = "rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d1effe9845d54f90e7be8420ee49e5c94623140b97ee4bc6fb5bfddb745720" -dependencies = [ - "byteorder", - "ethereum-types 0.4.2", - "rustc-hex 2.0.1", -] - -[[package]] -name = "rlp" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a7d3f9bed94764eac15b8f14af59fac420c236adaff743b7bcc88e265cb4345" +checksum = "1190dcc8c3a512f1eef5d09bb8c84c7f39e1054e174d1795482e18f5272f2e73" dependencies = [ - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", ] [[package]] @@ -4002,7 +3939,7 @@ version = "0.1.0" dependencies = [ "elastic-array", "lazy_static", - "rlp 0.3.0", + "rlp", ] [[package]] @@ -4011,7 +3948,7 @@ version = "0.1.0" dependencies = [ "proc-macro2 0.4.30", "quote 0.6.13", - "rlp 0.3.0", + "rlp", "syn 0.15.26", ] @@ -4060,9 +3997,9 @@ checksum = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" [[package]] name = "rustc-hex" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc-serialize" @@ -4132,30 +4069,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "scrypt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8570c5e2fa69cb29d492fd4e9974b6b5facb5a888e1c6da630d4a3cd7ebfef4a" -dependencies = [ - "byte-tools 0.3.1", - "byteorder", - "hmac 0.6.3", - "pbkdf2 0.2.3", - "sha2 0.7.1", -] - [[package]] name = "scrypt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" dependencies = [ - "byte-tools 0.3.1", + "byte-tools", "byteorder", - "hmac 0.7.1", - "pbkdf2 0.3.0", - "sha2 0.8.0", + "hmac", + "pbkdf2", + "sha2", ] [[package]] @@ -4168,6 +4092,25 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secp256k1" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056" +dependencies = [ + "rand 0.6.5", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220" +dependencies = [ + "cc", +] + [[package]] name = "semver" version = "0.9.0" @@ -4232,32 +4175,20 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", + "block-buffer", + "digest", "fake-simd", "opaque-debug", ] -[[package]] -name = "sha2" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" -dependencies = [ - "block-buffer 0.3.3", - "byte-tools 0.2.0", - "digest 0.7.6", - "fake-simd", -] - [[package]] name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", + "block-buffer", + "digest", "fake-simd", "opaque-debug", ] @@ -4279,7 +4210,7 @@ source = "git+https://github.com/matter-labs/eip1962.git?rev=ece6cbabc41948db420 dependencies = [ "byteorder", "crunchy 0.2.2", - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", "static_assertions", ] @@ -4338,7 +4269,7 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", "winapi 0.3.8", @@ -4376,7 +4307,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c" dependencies = [ - "generic-array 0.12.3", + "generic-array", ] [[package]] @@ -4434,18 +4365,6 @@ dependencies = [ "unicode-xid 0.2.0", ] -[[package]] -name = "synstructure" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.26", - "unicode-xid 0.1.0", -] - [[package]] name = "synstructure" version = "0.12.2" @@ -4480,9 +4399,9 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", - "rand 0.7.2", + "rand 0.7.3", "redox_syscall", "remove_dir_all", "winapi 0.3.8", @@ -4964,38 +4883,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c7319e28ca295f27359d944a682f7f65b419158bf1590c92cadc0000258d788" dependencies = [ "elastic-array", - "hash-db", + "hash-db 0.11.0", "log", "rand 0.6.5", ] [[package]] name = "trie-standardmap" -version = "0.1.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e26f52976a57a0859616d6fcec87092ac35d08eabbd78dc3dabee93b480ea5f" +checksum = "c3161ba520ab28cd8e6b68e1126f1009f6e335339d1a73b978139011703264c8" dependencies = [ - "ethereum-types 0.4.2", - "keccak-hash", - "parity-bytes", - "rlp 0.2.4", + "hash-db 0.15.2", + "keccak-hasher 0.15.3", ] [[package]] name = "triehash" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d26efb4ddf87870fc08dc9a6580dc3061be350d7b9d0eb30aef1c8b4227aa46" +checksum = "92148b4d8d55eff71bc8c9e3c5f714e266c2a05e724dce5405a10deabbf449a8" dependencies = [ - "hash-db", - "rlp 0.3.0", + "hash-db 0.11.0", + "rlp", ] [[package]] name = "triehash-ethereum" version = "0.2.0" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "keccak-hasher 0.1.1", "triehash", ] @@ -5024,18 +4941,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236" -[[package]] -name = "uint" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754ba11732b9161b94c41798e5197e5e75388d012f760c42adb5000353e98646" -dependencies = [ - "byteorder", - "crunchy 0.1.6", - "heapsize", - "rustc-hex 2.0.1", -] - [[package]] name = "uint" version = "0.8.5" @@ -5044,7 +4949,7 @@ checksum = "9db035e67dfaf7edd9aebfe8676afcd63eed53c8a4044fed514c8cccf1835177" dependencies = [ "byteorder", "crunchy 0.2.2", - "rustc-hex 2.0.1", + "rustc-hex 2.1.0", "static_assertions", ] @@ -5197,12 +5102,12 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" name = "vm" version = "0.1.0" dependencies = [ - "ethereum-types 0.4.2", + "ethereum-types", "ethjson", "keccak-hash", "parity-bytes", "patricia-trie-ethereum", - "rlp 0.3.0", + "rlp", ] [[package]] @@ -5244,13 +5149,19 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "wasm" version = "0.1.0" dependencies = [ "byteorder", "env_logger", - "ethereum-types 0.4.2", + "ethereum-types", "libc", "log", "parity-wasm", @@ -5380,21 +5291,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "0.9.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080616bd0e31f36095288bb0acdf1f78ef02c2fa15527d7e993f2a6c7591643e" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.26", - "synstructure 0.10.1", -] +checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" diff --git a/Cargo.toml b/Cargo.toml index 2906d1545c..0d42b6342a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,12 +47,13 @@ ethcore-miner = { path = "crates/concensus/miner" } ethcore-network = { path = "crates/net/network" } ethcore-service = { path = "crates/ethcore/service" } ethcore-sync = { path = "crates/ethcore/sync" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethkey = { path = "crates/accounts/ethkey" } ethstore = { path = "crates/accounts/ethstore" } fetch = { path = "crates/net/fetch" } node-filter = { path = "crates/net/node-filter" } -rlp = { version = "0.3.0", features = ["ethereum"] } +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +rlp = { version = "0.4.6" } cli-signer= { path = "crates/util/cli-signer" } parity-daemonize = "0.3" parity-local-store = { path = "crates/concensus/miner/local-store" } @@ -62,7 +63,7 @@ parity-version = { path = "crates/util/version" } parity-path = "0.1" dir = { path = "crates/util/dir" } panic_hook = { path = "crates/util/panic-hook" } -keccak-hash = "0.1" +keccak-hash = "0.5.0" migration-rocksdb = { path = "crates/db/migration-rocksdb" } kvdb = "0.1" kvdb-rocksdb = "0.1.3" @@ -130,6 +131,3 @@ members = [ "bin/evmbin", "bin/chainspec" ] - -[patch.crates-io] -heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" } diff --git a/bin/ethkey/Cargo.toml b/bin/ethkey/Cargo.toml index e649202e0c..d5af93f26b 100644 --- a/bin/ethkey/Cargo.toml +++ b/bin/ethkey/Cargo.toml @@ -9,6 +9,7 @@ docopt = "1.0" env_logger = "0.5" ethkey = { path = "../../crates/accounts/ethkey" } panic_hook = { path = "../../crates/util/panic-hook" } +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } parity-wordlist="1.3" rustc-hex = "1.0" serde = "1.0" diff --git a/bin/ethkey/src/main.rs b/bin/ethkey/src/main.rs index 7327553e19..230351ef4d 100644 --- a/bin/ethkey/src/main.rs +++ b/bin/ethkey/src/main.rs @@ -18,6 +18,7 @@ extern crate docopt; extern crate env_logger; extern crate ethkey; extern crate panic_hook; +extern crate parity_crypto as crypto; extern crate parity_wordlist; extern crate rustc_hex; extern crate serde; @@ -28,11 +29,11 @@ extern crate serde_derive; use std::{env, fmt, io, num::ParseIntError, process, sync}; -use docopt::Docopt; -use ethkey::{ - brain_recover, sign, verify_address, verify_public, Brain, BrainPrefix, Error as EthkeyError, - Generator, KeyPair, Prefix, Random, +use crypto::publickey::{ + sign, verify_address, verify_public, Error as EthkeyError, Generator, KeyPair, Random, }; +use docopt::Docopt; +use ethkey::{brain_recover, Brain, BrainPrefix, Prefix}; use rustc_hex::{FromHex, FromHexError}; const USAGE: &'static str = r#" @@ -202,15 +203,13 @@ where let result = if args.flag_brain { let phrase = args.arg_secret_or_phrase; let phrase_info = validate_phrase(&phrase); - let keypair = Brain::new(phrase) - .generate() - .expect("Brain wallet generator is infallible; qed"); + let keypair = Brain::new(phrase).generate(); (keypair, Some(phrase_info)) } else { let secret = args .arg_secret_or_phrase .parse() - .map_err(|_| EthkeyError::InvalidSecret)?; + .map_err(|_| EthkeyError::InvalidSecretKey)?; (KeyPair::from_secret(secret)?, None) }; Ok(display(result, display_mode)) @@ -223,7 +222,7 @@ where let phrase = format!("recovery phrase: {}", brain.phrase()); (keypair, Some(phrase)) } else { - (Random.generate()?, None) + (Random.generate(), None) } } else if args.cmd_prefix { let prefix = args.arg_prefix.from_hex()?; @@ -254,7 +253,7 @@ where let secret = args .arg_secret .parse() - .map_err(|_| EthkeyError::InvalidSecret)?; + .map_err(|_| EthkeyError::InvalidSecretKey)?; let message = args .arg_message .parse() @@ -274,7 +273,7 @@ where let public = args .arg_public .parse() - .map_err(|_| EthkeyError::InvalidPublic)?; + .map_err(|_| EthkeyError::InvalidPublicKey)?; verify_public(&public, &signature, &message)? } else if args.cmd_address { let address = args @@ -301,7 +300,7 @@ where while let Some(phrase) = it.next() { i += 1; - let keypair = Brain::new(phrase.clone()).generate().unwrap(); + let keypair = Brain::new(phrase.clone()).generate(); if keypair.address() == address { return Ok(Some((phrase, keypair))); } diff --git a/bin/evmbin/Cargo.toml b/bin/evmbin/Cargo.toml index 1e0ac33ad4..d6b8960519 100644 --- a/bin/evmbin/Cargo.toml +++ b/bin/evmbin/Cargo.toml @@ -13,7 +13,7 @@ common-types = { path = "../../crates/ethcore/types", features = ["test-helpers" docopt = "1.0" env_logger = "0.5" ethcore = { path = "../../crates/ethcore", features = ["test-helpers", "json-tests", "to-pod-full"] } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethjson = { path = "../../crates/ethjson" } evm = { path = "../../crates/vm/evm" } panic_hook = { path = "../../crates/util/panic-hook" } diff --git a/bin/evmbin/src/display/json.rs b/bin/evmbin/src/display/json.rs index 55b70f86d8..08658abf0f 100644 --- a/bin/evmbin/src/display/json.rs +++ b/bin/evmbin/src/display/json.rs @@ -22,7 +22,7 @@ use super::config::Config; use bytes::ToPretty; use display; use ethcore::trace; -use ethereum_types::{H256, U256}; +use ethereum_types::{BigEndianHash, H256, U256}; use info as vm; /// JSON formatting informant. @@ -208,7 +208,10 @@ impl trace::VMTracer for Informant { } if let Some((pos, val)) = store_diff { - informant.storage.insert(pos.into(), val.into()); + informant.storage.insert( + BigEndianHash::from_uint(&pos), + BigEndianHash::from_uint(&val), + ); } if !informant.subtraces.is_empty() { diff --git a/bin/evmbin/src/display/std_json.rs b/bin/evmbin/src/display/std_json.rs index ae7e5a7e0d..4114f719cc 100644 --- a/bin/evmbin/src/display/std_json.rs +++ b/bin/evmbin/src/display/std_json.rs @@ -22,7 +22,7 @@ use super::config::Config; use bytes::ToPretty; use display; use ethcore::{pod_state, trace}; -use ethereum_types::{H256, U256}; +use ethereum_types::{BigEndianHash, H256, U256}; use info as vm; pub trait Writer: io::Write + Send + Sized { @@ -237,7 +237,10 @@ impl trace::VMTracer for Informant { let subdepth = self.subdepth; Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { if let Some((pos, val)) = store_written { - informant.storage.insert(pos.into(), val.into()); + informant.storage.insert( + BigEndianHash::from_uint(&pos), + BigEndianHash::from_uint(&val), + ); } }); } diff --git a/bin/evmbin/src/info.rs b/bin/evmbin/src/info.rs index 8519e1d4b3..4e308d264f 100644 --- a/bin/evmbin/src/info.rs +++ b/bin/evmbin/src/info.rs @@ -103,7 +103,7 @@ pub fn run_action( Ok(r) => (Ok(r.return_data.to_vec()), Some(r.gas_left)), Err(err) => (Err(err), None), }; - (result.0, 0.into(), None, result.1, informant.drain()) + (result.0, H256::zero(), None, result.1, informant.drain()) }, ) } @@ -262,6 +262,7 @@ where #[cfg(test)] pub mod tests { use super::*; + use ethereum_types::Address; use rustc_hex::FromHex; use std::sync::Arc; use tempdir::TempDir; @@ -291,7 +292,7 @@ pub mod tests { let (inf, res) = informant(Config::default()); let mut params = ActionParams::default(); - params.code_address = 0x20.into(); + params.code_address = Address::from_low_u64_be(0x20); params.gas = 0xffff.into(); let spec = ::ethcore::ethereum::load(None, include_bytes!("../res/testchain.json")); diff --git a/bin/evmbin/src/main.rs b/bin/evmbin/src/main.rs index 45b28f5837..c6a7f987ec 100644 --- a/bin/evmbin/src/main.rs +++ b/bin/evmbin/src/main.rs @@ -429,6 +429,7 @@ fn die(msg: T) -> ! { mod tests { use super::{Args, USAGE}; use docopt::Docopt; + use ethereum_types::Address; fn run>(args: &[T]) -> Args { Docopt::new(USAGE) @@ -468,8 +469,8 @@ mod tests { assert_eq!(args.flag_std_out_only, true); assert_eq!(args.gas(), Ok(1.into())); assert_eq!(args.gas_price(), Ok(2.into())); - assert_eq!(args.from(), Ok(3.into())); - assert_eq!(args.to(), Ok(4.into())); + assert_eq!(args.from(), Ok(Address::from_low_u64_be(3))); + assert_eq!(args.to(), Ok(Address::from_low_u64_be(4))); assert_eq!(args.code(), Ok(Some(vec![05]))); assert_eq!(args.data(), Ok(Some(vec![06]))); assert_eq!(args.flag_chain, Some("./testfile".to_owned())); diff --git a/bin/oe/account_utils.rs b/bin/oe/account_utils.rs index 36a91a06e1..902e557ccd 100644 --- a/bin/oe/account_utils.rs +++ b/bin/oe/account_utils.rs @@ -16,8 +16,9 @@ use std::sync::Arc; +use crypto::publickey; use dir::Directories; -use ethereum_types::Address; +use ethereum_types::{Address, H160}; use ethkey::Password; use params::{AccountsConfig, SpecType}; @@ -70,6 +71,7 @@ mod accounts { #[cfg(feature = "accounts")] mod accounts { use super::*; + use std::str::FromStr; use upgrade::upgrade_key_location; pub use accounts::AccountProvider; @@ -103,7 +105,8 @@ mod accounts { | SpecType::Goerli | SpecType::Sokol | SpecType::Dev => vec![], - _ => vec!["00a329c0648769a73afac7f9381e08fb43dbea72".into()], + _ => vec![H160::from_str("00a329c0648769a73afac7f9381e08fb43dbea72") + .expect("the string is valid hex; qed")], }, }; @@ -216,9 +219,11 @@ mod accounts { } fn insert_dev_account(account_provider: &AccountProvider) { - let secret: ethkey::Secret = - "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into(); - let dev_account = ethkey::KeyPair::from_secret(secret.clone()) + let secret = publickey::Secret::from_str( + "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7", + ) + .expect("Valid account;qed"); + let dev_account = publickey::KeyPair::from_secret(secret.clone()) .expect("Valid secret produces valid key;qed"); if !account_provider.has_account(dev_account.address()) { match account_provider.insert_account(secret, &Password::from(String::new())) { diff --git a/bin/oe/configuration.rs b/bin/oe/configuration.rs index 79fc2f5ec0..84c83bca81 100644 --- a/bin/oe/configuration.rs +++ b/bin/oe/configuration.rs @@ -17,6 +17,7 @@ use ansi_term::Colour; use bytes::Bytes; use cli::{Args, ArgsError}; +use crypto::publickey::{Public, Secret}; use ethcore::{ client::VMType, miner::{stratum, MinerOptions}, @@ -24,7 +25,6 @@ use ethcore::{ verification::queue::VerifierSettings, }; use ethereum_types::{Address, H256, U256}; -use ethkey::{Public, Secret}; use hash::keccak; use metrics::MetricsConfiguration; use miner::pool; @@ -810,7 +810,7 @@ impl Configuration { ret.public_address = public.map(|p| format!("{}", p)); ret.use_secret = match self.args.arg_node_key.as_ref().map(|s| { s.parse::() - .or_else(|_| Secret::from_unsafe_slice(&keccak(s))) + .or_else(|_| Secret::import_key(keccak(s).as_bytes())) .map_err(|e| format!("Invalid key: {:?}", e)) }) { None => None, diff --git a/bin/oe/helpers.rs b/bin/oe/helpers.rs index 01f8310736..e9cdf93df4 100644 --- a/bin/oe/helpers.rs +++ b/bin/oe/helpers.rs @@ -21,7 +21,7 @@ use ethcore::{ client::{BlockId, ClientConfig, DatabaseCompactionProfile, Mode, VMType, VerifierType}, miner::{Penalization, PendingSet}, }; -use ethereum_types::{clean_0x, Address, U256}; +use ethereum_types::{Address, U256}; use ethkey::Password; use journaldb::Algorithm; use miner::pool::PrioritizationStrategy; @@ -39,6 +39,14 @@ pub fn to_duration(s: &str) -> Result { to_seconds(s).map(Duration::from_secs) } +fn clean_0x(s: &str) -> &str { + if s.starts_with("0x") { + &s[2..] + } else { + s + } +} + fn to_seconds(s: &str) -> Result { let bad = |_| { format!( diff --git a/bin/oe/lib.rs b/bin/oe/lib.rs index 09d8ae5d0b..ed9a7166ec 100644 --- a/bin/oe/lib.rs +++ b/bin/oe/lib.rs @@ -61,6 +61,7 @@ extern crate keccak_hash as hash; extern crate kvdb; extern crate node_filter; extern crate parity_bytes as bytes; +extern crate parity_crypto as crypto; extern crate parity_local_store as local_store; extern crate parity_path as path; extern crate parity_rpc; diff --git a/bin/oe/presale.rs b/bin/oe/presale.rs index b160ab7744..5a5fecf0c1 100644 --- a/bin/oe/presale.rs +++ b/bin/oe/presale.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey; use ethkey::Password; use ethstore::PresaleWallet; use helpers::{password_from_file, password_prompt}; @@ -44,7 +45,7 @@ pub fn execute(cmd: ImportWallet) -> Result { } #[cfg(feature = "accounts")] -pub fn import_account(cmd: &ImportWallet, kp: ethkey::KeyPair, password: Password) { +pub fn import_account(cmd: &ImportWallet, kp: publickey::KeyPair, password: Password) { use accounts::{AccountProvider, AccountProviderSettings}; use ethstore::{accounts_dir::RootDiskDirectory, EthStore}; @@ -57,4 +58,4 @@ pub fn import_account(cmd: &ImportWallet, kp: ethkey::KeyPair, password: Passwor } #[cfg(not(feature = "accounts"))] -pub fn import_account(_cmd: &ImportWallet, _kp: ethkey::KeyPair, _password: Password) {} +pub fn import_account(_cmd: &ImportWallet, _kp: publickey::KeyPair, _password: Password) {} diff --git a/bin/oe/run.rs b/bin/oe/run.rs index d4aac267c5..91d274a67e 100644 --- a/bin/oe/run.rs +++ b/bin/oe/run.rs @@ -16,6 +16,7 @@ use std::{ any::Any, + str::FromStr, sync::{atomic, Arc, Weak}, thread, time::{Duration, Instant}, @@ -606,7 +607,10 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result Vec { match *spec { SpecType::Ropsten => { - vec!["1eac3d16c642411f13c287e29144c6f58fda859407c8f24c38deb168e1040714".into()] + vec![ + H256::from_str("1eac3d16c642411f13c287e29144c6f58fda859407c8f24c38deb168e1040714") + .expect("Valid hex string"), + ] } _ => vec![], } diff --git a/bin/oe/secretstore.rs b/bin/oe/secretstore.rs index a55bfd90b0..6ef0b23e1f 100644 --- a/bin/oe/secretstore.rs +++ b/bin/oe/secretstore.rs @@ -15,10 +15,11 @@ // along with OpenEthereum. If not, see . use account_utils::AccountProvider; +use crypto::publickey::{Public, Secret}; use dir::{default_data_path, helpers::replace_home}; use ethcore::{client::Client, miner::Miner}; use ethereum_types::Address; -use ethkey::{Password, Public, Secret}; +use ethkey::Password; use parity_runtime::Executor; use std::{collections::BTreeMap, sync::Arc}; use sync::SyncProvider; diff --git a/crates/accounts/Cargo.toml b/crates/accounts/Cargo.toml index e88d77683a..56ad94278f 100644 --- a/crates/accounts/Cargo.toml +++ b/crates/accounts/Cargo.toml @@ -12,11 +12,12 @@ common-types = { path = "../ethcore/types" } ethkey = { path = "ethkey" } ethstore = { path = "ethstore" } log = "0.4" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } parking_lot = "0.7" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" [dev-dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" tempdir = "0.3" diff --git a/crates/accounts/ethkey/Cargo.toml b/crates/accounts/ethkey/Cargo.toml index 6348230d3e..5b32bbaa2e 100644 --- a/crates/accounts/ethkey/Cargo.toml +++ b/crates/accounts/ethkey/Cargo.toml @@ -6,15 +6,15 @@ authors = ["Parity Technologies "] [dependencies] edit-distance = "2.0" -parity-crypto = "0.3.0" -eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "ccc06e7480148b723eb44ac56cf4d20eec380b6f" } -ethereum-types = "0.4" +parity-crypto = { version = "0.6.2", features = ["publickey"] } +eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "9791e79f21a5309dcb6e0bd254b1ef88fca2f1f4" } +ethereum-types = "0.9.2" lazy_static = "1.0" log = "0.4" memzero = { path = "../../../crates/util/memzero" } parity-wordlist = "1.3" quick-error = "1.2.2" -rand = "0.4" +rand = "0.7.3" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" diff --git a/crates/accounts/ethkey/src/brain.rs b/crates/accounts/ethkey/src/brain.rs index 9d835f1180..2cb6806fc5 100644 --- a/crates/accounts/ethkey/src/brain.rs +++ b/crates/accounts/ethkey/src/brain.rs @@ -14,8 +14,10 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use super::{Generator, KeyPair, Secret}; -use keccak::Keccak256; +use parity_crypto::{ + publickey::{KeyPair, Secret}, + Keccak256, +}; use parity_wordlist; /// Simple brainwallet. @@ -29,12 +31,8 @@ impl Brain { pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> { parity_wordlist::validate_phrase(phrase, expected_words) } -} - -impl Generator for Brain { - type Error = ::Void; - fn generate(&mut self) -> Result { + pub fn generate(&mut self) -> KeyPair { let seed = self.0.clone(); let mut secret = seed.into_bytes().keccak256(); @@ -45,12 +43,10 @@ impl Generator for Brain { match i > 16384 { false => i += 1, true => { - if let Ok(pair) = - Secret::from_unsafe_slice(&secret).and_then(KeyPair::from_secret) - { + if let Ok(pair) = Secret::import_key(&secret).and_then(KeyPair::from_secret) { if pair.address()[0] == 0 { trace!("Testing: {}, got: {:?}", self.0, pair.address()); - return Ok(pair); + return pair; } } } @@ -62,13 +58,12 @@ impl Generator for Brain { #[cfg(test)] mod tests { use Brain; - use Generator; #[test] fn test_brain() { let words = "this is sparta!".to_owned(); - let first_keypair = Brain::new(words.clone()).generate().unwrap(); - let second_keypair = Brain::new(words.clone()).generate().unwrap(); + let first_keypair = Brain::new(words.clone()).generate(); + let second_keypair = Brain::new(words.clone()).generate(); assert_eq!(first_keypair.secret(), second_keypair.secret()); } } diff --git a/crates/accounts/ethkey/src/brain_prefix.rs b/crates/accounts/ethkey/src/brain_prefix.rs index cc25a03f21..819dce564e 100644 --- a/crates/accounts/ethkey/src/brain_prefix.rs +++ b/crates/accounts/ethkey/src/brain_prefix.rs @@ -14,7 +14,8 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use super::{Brain, Error, Generator, KeyPair}; +use super::Brain; +use parity_crypto::publickey::{Error, KeyPair}; use parity_wordlist as wordlist; /// Tries to find brain-seed keypair with address starting with given prefix. @@ -38,16 +39,12 @@ impl BrainPrefix { pub fn phrase(&self) -> &str { &self.last_phrase } -} - -impl Generator for BrainPrefix { - type Error = Error; - fn generate(&mut self) -> Result { + pub fn generate(&mut self) -> Result { for _ in 0..self.iterations { let phrase = wordlist::random_phrase(self.no_of_words); - let keypair = Brain::new(phrase.clone()).generate().unwrap(); - if keypair.address().starts_with(&self.prefix) { + let keypair = Brain::new(phrase.clone()).generate(); + if keypair.address().as_ref().starts_with(&self.prefix) { self.last_phrase = phrase; return Ok(keypair); } @@ -60,7 +57,6 @@ impl Generator for BrainPrefix { #[cfg(test)] mod tests { use BrainPrefix; - use Generator; #[test] fn prefix_generator() { @@ -68,6 +64,6 @@ mod tests { let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12) .generate() .unwrap(); - assert!(keypair.address().starts_with(&prefix)); + assert!(keypair.address().as_bytes().starts_with(&prefix)); } } diff --git a/crates/accounts/ethkey/src/brain_recover.rs b/crates/accounts/ethkey/src/brain_recover.rs index 92cd7df1e3..611893f4ab 100644 --- a/crates/accounts/ethkey/src/brain_recover.rs +++ b/crates/accounts/ethkey/src/brain_recover.rs @@ -17,9 +17,10 @@ use std::collections::HashSet; use edit_distance::edit_distance; +use parity_crypto::publickey::Address; use parity_wordlist; -use super::{Address, Brain, Generator}; +use super::Brain; /// Tries to find a phrase for address, given the number /// of expected words and a partial phrase. @@ -32,9 +33,7 @@ pub fn brain_recover( ) -> Option { let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words); for phrase in it { - let keypair = Brain::new(phrase.clone()) - .generate() - .expect("Brain wallets are infallible; qed"); + let keypair = Brain::new(phrase.clone()).generate(); trace!("Testing: {}, got: {:?}", phrase, keypair.address()); if &keypair.address() == address { return Some(phrase); diff --git a/crates/accounts/ethkey/src/crypto.rs b/crates/accounts/ethkey/src/crypto.rs deleted file mode 100644 index 4fa1ee6900..0000000000 --- a/crates/accounts/ethkey/src/crypto.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -#![allow(deprecated)] - -use parity_crypto::error::SymmError; -use secp256k1; -use std::io; - -quick_error! { - #[derive(Debug)] - pub enum Error { - Secp(e: secp256k1::Error) { - display("secp256k1 error: {}", e) - cause(e) - from() - } - Io(e: io::Error) { - display("i/o error: {}", e) - cause(e) - from() - } - InvalidMessage { - display("invalid message") - } - Symm(e: SymmError) { - cause(e) - from() - } - } -} - -/// ECDH functions -pub mod ecdh { - use super::Error; - use secp256k1::{self, ecdh, key}; - use Public; - use Secret; - use SECP256K1; - - /// Agree on a shared secret - pub fn agree(secret: &Secret, public: &Public) -> Result { - let context = &SECP256K1; - let pdata = { - let mut temp = [4u8; 65]; - (&mut temp[1..65]).copy_from_slice(&public[0..64]); - temp - }; - - let publ = key::PublicKey::from_slice(context, &pdata)?; - let sec = key::SecretKey::from_slice(context, &secret)?; - let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec); - - Secret::from_unsafe_slice(&shared[0..32]) - .map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey)) - } -} - -/// ECIES function -pub mod ecies { - use super::{ecdh, Error}; - use ethereum_types::H128; - use parity_crypto::{aes, digest, hmac, is_equal}; - use Generator; - use Public; - use Random; - use Secret; - - /// Encrypt a message with a public key, writing an HMAC covering both - /// the plaintext and authenticated data. - /// - /// Authenticated data may be empty. - pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result, Error> { - let r = Random.generate()?; - let z = ecdh::agree(r.secret(), public)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - - let ekey = &key[0..16]; - let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); - - let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32]; - msg[0] = 0x04u8; - { - let msgd = &mut msg[1..]; - msgd[0..64].copy_from_slice(r.public()); - let iv = H128::random(); - msgd[64..80].copy_from_slice(&iv); - { - let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())]; - aes::encrypt_128_ctr(ekey, &iv, plain, cipher)?; - } - let mut hmac = hmac::Signer::with(&mkey); - { - let cipher_iv = &msgd[64..(64 + 16 + plain.len())]; - hmac.update(cipher_iv); - } - hmac.update(auth_data); - let sig = hmac.sign(); - msgd[(64 + 16 + plain.len())..].copy_from_slice(&sig); - } - Ok(msg) - } - - /// Decrypt a message with a secret key, checking HMAC for ciphertext - /// and authenticated data validity. - pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result, Error> { - let meta_len = 1 + 64 + 16 + 32; - if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 { - return Err(Error::InvalidMessage); //invalid message: publickey - } - - let e = &encrypted[1..]; - let p = Public::from_slice(&e[0..64]); - let z = ecdh::agree(secret, &p)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - - let ekey = &key[0..16]; - let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); - - let clen = encrypted.len() - meta_len; - let cipher_with_iv = &e[64..(64 + 16 + clen)]; - let cipher_iv = &cipher_with_iv[0..16]; - let cipher_no_iv = &cipher_with_iv[16..]; - let msg_mac = &e[(64 + 16 + clen)..]; - - // Verify tag - let mut hmac = hmac::Signer::with(&mkey); - hmac.update(cipher_with_iv); - hmac.update(auth_data); - let mac = hmac.sign(); - - if !is_equal(&mac.as_ref()[..], msg_mac) { - return Err(Error::InvalidMessage); - } - - let mut msg = vec![0u8; clen]; - aes::decrypt_128_ctr(ekey, cipher_iv, cipher_no_iv, &mut msg[..])?; - Ok(msg) - } - - fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) { - // SEC/ISO/Shoup specify counter size SHOULD be equivalent - // to size of hash output, however, it also notes that - // the 4 bytes is okay. NIST specifies 4 bytes. - let mut ctr = 1u32; - let mut written = 0usize; - while written < dest.len() { - let mut hasher = digest::Hasher::sha256(); - let ctrs = [ - (ctr >> 24) as u8, - (ctr >> 16) as u8, - (ctr >> 8) as u8, - ctr as u8, - ]; - hasher.update(&ctrs); - hasher.update(secret); - hasher.update(s1); - let d = hasher.finish(); - &mut dest[written..(written + 32)].copy_from_slice(&d); - written += 32; - ctr += 1; - } - } -} - -#[cfg(test)] -mod tests { - use super::ecies; - use Generator; - use Random; - - #[test] - fn ecies_shared() { - let kp = Random.generate().unwrap(); - let message = b"So many books, so little time"; - - let shared = b"shared"; - let wrong_shared = b"incorrect"; - let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap(); - assert!(encrypted[..] != message[..]); - assert_eq!(encrypted[0], 0x04); - - assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err()); - let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); - assert_eq!(decrypted[..message.len()], message[..]); - } -} diff --git a/crates/accounts/ethkey/src/error.rs b/crates/accounts/ethkey/src/error.rs deleted file mode 100644 index 3e66a905d2..0000000000 --- a/crates/accounts/ethkey/src/error.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use std::{error, fmt}; - -#[derive(Debug)] -/// Crypto error -pub enum Error { - /// Invalid secret key - InvalidSecret, - /// Invalid public key - InvalidPublic, - /// Invalid address - InvalidAddress, - /// Invalid EC signature - InvalidSignature, - /// Invalid AES message - InvalidMessage, - /// IO Error - Io(::std::io::Error), - /// Custom - Custom(String), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let msg = match *self { - Error::InvalidSecret => "Invalid secret".into(), - Error::InvalidPublic => "Invalid public".into(), - Error::InvalidAddress => "Invalid address".into(), - Error::InvalidSignature => "Invalid EC signature".into(), - Error::InvalidMessage => "Invalid AES message".into(), - Error::Io(ref err) => format!("I/O error: {}", err), - Error::Custom(ref s) => s.clone(), - }; - - f.write_fmt(format_args!("Crypto error ({})", msg)) - } -} - -impl error::Error for Error { - fn description(&self) -> &str { - "Crypto error" - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } -} - -impl From<::secp256k1::Error> for Error { - fn from(e: ::secp256k1::Error) -> Error { - match e { - ::secp256k1::Error::InvalidMessage => Error::InvalidMessage, - ::secp256k1::Error::InvalidPublicKey => Error::InvalidPublic, - ::secp256k1::Error::InvalidSecretKey => Error::InvalidSecret, - _ => Error::InvalidSignature, - } - } -} - -impl From<::std::io::Error> for Error { - fn from(err: ::std::io::Error) -> Error { - Error::Io(err) - } -} diff --git a/crates/accounts/ethkey/src/extended.rs b/crates/accounts/ethkey/src/extended.rs deleted file mode 100644 index 663f555e7a..0000000000 --- a/crates/accounts/ethkey/src/extended.rs +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -//! Extended keys - -pub use self::derivation::Error as DerivationError; -use ethereum_types::H256; -use secret::Secret; -use Public; - -/// Represents label that can be stored as a part of key derivation -pub trait Label { - /// Length of the data that label occupies - fn len() -> usize; - - /// Store label data to the key derivation sequence - /// Must not use more than `len()` bytes from slice - fn store(&self, target: &mut [u8]); -} - -impl Label for u32 { - fn len() -> usize { - 4 - } - - fn store(&self, target: &mut [u8]) { - let bytes = self.to_be_bytes(); - target[0..4].copy_from_slice(&bytes); - } -} - -/// Key derivation over generic label `T` -pub enum Derivation { - /// Soft key derivation (allow proof of parent) - Soft(T), - /// Hard key derivation (does not allow proof of parent) - Hard(T), -} - -impl From for Derivation { - fn from(index: u32) -> Self { - if index < (2 << 30) { - Derivation::Soft(index) - } else { - Derivation::Hard(index) - } - } -} - -impl Label for H256 { - fn len() -> usize { - 32 - } - - fn store(&self, target: &mut [u8]) { - self.copy_to(&mut target[0..32]); - } -} - -/// Extended secret key, allows deterministic derivation of subsequent keys. -pub struct ExtendedSecret { - secret: Secret, - chain_code: H256, -} - -impl ExtendedSecret { - /// New extended key from given secret and chain code. - pub fn with_code(secret: Secret, chain_code: H256) -> ExtendedSecret { - ExtendedSecret { - secret: secret, - chain_code: chain_code, - } - } - - /// New extended key from given secret with the random chain code. - pub fn new_random(secret: Secret) -> ExtendedSecret { - ExtendedSecret::with_code(secret, H256::random()) - } - - /// New extended key from given secret. - /// Chain code will be derived from the secret itself (in a deterministic way). - pub fn new(secret: Secret) -> ExtendedSecret { - let chain_code = derivation::chain_code(*secret); - ExtendedSecret::with_code(secret, chain_code) - } - - /// Derive new private key - pub fn derive(&self, index: Derivation) -> ExtendedSecret - where - T: Label, - { - let (derived_key, next_chain_code) = - derivation::private(*self.secret, self.chain_code, index); - - let derived_secret = Secret::from(derived_key.0); - - ExtendedSecret::with_code(derived_secret, next_chain_code) - } - - /// Private key component of the extended key. - pub fn as_raw(&self) -> &Secret { - &self.secret - } -} - -/// Extended public key, allows deterministic derivation of subsequent keys. -pub struct ExtendedPublic { - public: Public, - chain_code: H256, -} - -impl ExtendedPublic { - /// New extended public key from known parent and chain code - pub fn new(public: Public, chain_code: H256) -> Self { - ExtendedPublic { - public: public, - chain_code: chain_code, - } - } - - /// Create new extended public key from known secret - pub fn from_secret(secret: &ExtendedSecret) -> Result { - Ok(ExtendedPublic::new( - derivation::point(**secret.as_raw())?, - secret.chain_code.clone(), - )) - } - - /// Derive new public key - /// Operation is defined only for index belongs [0..2^31) - pub fn derive(&self, index: Derivation) -> Result - where - T: Label, - { - let (derived_key, next_chain_code) = - derivation::public(self.public, self.chain_code, index)?; - Ok(ExtendedPublic::new(derived_key, next_chain_code)) - } - - pub fn public(&self) -> &Public { - &self.public - } -} - -pub struct ExtendedKeyPair { - secret: ExtendedSecret, - public: ExtendedPublic, -} - -impl ExtendedKeyPair { - pub fn new(secret: Secret) -> Self { - let extended_secret = ExtendedSecret::new(secret); - let extended_public = ExtendedPublic::from_secret(&extended_secret) - .expect("Valid `Secret` always produces valid public; qed"); - ExtendedKeyPair { - secret: extended_secret, - public: extended_public, - } - } - - pub fn with_code(secret: Secret, public: Public, chain_code: H256) -> Self { - ExtendedKeyPair { - secret: ExtendedSecret::with_code(secret, chain_code.clone()), - public: ExtendedPublic::new(public, chain_code), - } - } - - pub fn with_secret(secret: Secret, chain_code: H256) -> Self { - let extended_secret = ExtendedSecret::with_code(secret, chain_code); - let extended_public = ExtendedPublic::from_secret(&extended_secret) - .expect("Valid `Secret` always produces valid public; qed"); - ExtendedKeyPair { - secret: extended_secret, - public: extended_public, - } - } - - pub fn with_seed(seed: &[u8]) -> Result { - let (master_key, chain_code) = derivation::seed_pair(seed); - Ok(ExtendedKeyPair::with_secret( - Secret::from_unsafe_slice(&*master_key).map_err(|_| DerivationError::InvalidSeed)?, - chain_code, - )) - } - - pub fn secret(&self) -> &ExtendedSecret { - &self.secret - } - - pub fn public(&self) -> &ExtendedPublic { - &self.public - } - - pub fn derive(&self, index: Derivation) -> Result - where - T: Label, - { - let derived = self.secret.derive(index); - - Ok(ExtendedKeyPair { - public: ExtendedPublic::from_secret(&derived)?, - secret: derived, - }) - } -} - -// Derivation functions for private and public keys -// Work is based on BIP0032 -// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -mod derivation { - use super::{Derivation, Label}; - use ethereum_types::{H256, H512, U256, U512}; - use keccak; - use math::curve_order; - use parity_crypto::hmac; - use secp256k1::key::{PublicKey, SecretKey}; - use SECP256K1; - - #[derive(Debug)] - pub enum Error { - InvalidHardenedUse, - InvalidPoint, - MissingIndex, - InvalidSeed, - } - - // Deterministic derivation of the key using secp256k1 elliptic curve. - // Derivation can be either hardened or not. - // For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum - // - // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_order()]) field - pub fn private(private_key: H256, chain_code: H256, index: Derivation) -> (H256, H256) - where - T: Label, - { - match index { - Derivation::Soft(index) => private_soft(private_key, chain_code, index), - Derivation::Hard(index) => private_hard(private_key, chain_code, index), - } - } - - fn hmac_pair(data: &[u8], private_key: H256, chain_code: H256) -> (H256, H256) { - let private: U256 = private_key.into(); - - // produces 512-bit derived hmac (I) - let skey = hmac::SigKey::sha512(&*chain_code); - let i_512 = hmac::sign(&skey, &data[..]); - - // left most 256 bits are later added to original private key - let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into(); - // right most 256 bits are new chain code for later derivations - let next_chain_code = H256::from(&i_512[32..64]); - - let child_key = private_add(hmac_key, private).into(); - (child_key, next_chain_code) - } - - // Can panic if passed `private_key` is not a valid secp256k1 private key - // (outside of (0..curve_order()]) field - fn private_soft(private_key: H256, chain_code: H256, index: T) -> (H256, H256) - where - T: Label, - { - let mut data = vec![0u8; 33 + T::len()]; - - let sec_private = SecretKey::from_slice(&SECP256K1, &*private_key) - .expect("Caller should provide valid private key"); - let sec_public = PublicKey::from_secret_key(&SECP256K1, &sec_private) - .expect("Caller should provide valid private key"); - let public_serialized = sec_public.serialize_vec(&SECP256K1, true); - - // curve point (compressed public key) -- index - // 0.33 -- 33..end - data[0..33].copy_from_slice(&public_serialized); - index.store(&mut data[33..]); - - hmac_pair(&data, private_key, chain_code) - } - - // Deterministic derivation of the key using secp256k1 elliptic curve - // This is hardened derivation and does not allow to associate - // corresponding public keys of the original and derived private keys - fn private_hard(private_key: H256, chain_code: H256, index: T) -> (H256, H256) - where - T: Label, - { - let mut data: Vec = vec![0u8; 33 + T::len()]; - let private: U256 = private_key.into(); - - // 0x00 (padding) -- private_key -- index - // 0 -- 1..33 -- 33..end - private.to_big_endian(&mut data[1..33]); - index.store(&mut data[33..(33 + T::len())]); - - hmac_pair(&data, private_key, chain_code) - } - - fn private_add(k1: U256, k2: U256) -> U256 { - let sum = U512::from(k1) + U512::from(k2); - modulo(sum, curve_order()) - } - - // todo: surely can be optimized - fn modulo(u1: U512, u2: U256) -> U256 { - let dv = u1 / U512::from(u2); - let md = u1 - (dv * U512::from(u2)); - md.into() - } - - pub fn public( - public_key: H512, - chain_code: H256, - derivation: Derivation, - ) -> Result<(H512, H256), Error> - where - T: Label, - { - let index = match derivation { - Derivation::Soft(index) => index, - Derivation::Hard(_) => { - return Err(Error::InvalidHardenedUse); - } - }; - - let mut public_sec_raw = [0u8; 65]; - public_sec_raw[0] = 4; - public_sec_raw[1..65].copy_from_slice(&*public_key); - let public_sec = - PublicKey::from_slice(&SECP256K1, &public_sec_raw).map_err(|_| Error::InvalidPoint)?; - let public_serialized = public_sec.serialize_vec(&SECP256K1, true); - - let mut data = vec![0u8; 33 + T::len()]; - // curve point (compressed public key) -- index - // 0.33 -- 33..end - data[0..33].copy_from_slice(&public_serialized); - index.store(&mut data[33..(33 + T::len())]); - - // HMAC512SHA produces [derived private(256); new chain code(256)] - let skey = hmac::SigKey::sha512(&*chain_code); - let i_512 = hmac::sign(&skey, &data[..]); - - let new_private = H256::from(&i_512[0..32]); - let new_chain_code = H256::from(&i_512[32..64]); - - // Generated private key can (extremely rarely) be out of secp256k1 key field - if curve_order() <= new_private.clone().into() { - return Err(Error::MissingIndex); - } - let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private) - .expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed"); - let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec) - .expect("Valid private key produces valid public key"); - - // Adding two points on the elliptic curves (combining two public keys) - new_public - .add_assign(&SECP256K1, &public_sec) - .expect("Addition of two valid points produce valid point"); - - let serialized = new_public.serialize_vec(&SECP256K1, false); - - Ok((H512::from(&serialized[1..65]), new_chain_code)) - } - - fn sha3(slc: &[u8]) -> H256 { - keccak::Keccak256::keccak256(slc).into() - } - - pub fn chain_code(secret: H256) -> H256 { - // 10,000 rounds of sha3 - let mut running_sha3 = sha3(&*secret); - for _ in 0..99999 { - running_sha3 = sha3(&*running_sha3); - } - running_sha3 - } - - pub fn point(secret: H256) -> Result { - let sec = SecretKey::from_slice(&SECP256K1, &*secret).map_err(|_| Error::InvalidPoint)?; - let public_sec = - PublicKey::from_secret_key(&SECP256K1, &sec).map_err(|_| Error::InvalidPoint)?; - let serialized = public_sec.serialize_vec(&SECP256K1, false); - Ok(H512::from(&serialized[1..65])) - } - - pub fn seed_pair(seed: &[u8]) -> (H256, H256) { - let skey = hmac::SigKey::sha512(b"Bitcoin seed"); - let i_512 = hmac::sign(&skey, seed); - - let master_key = H256::from_slice(&i_512[0..32]); - let chain_code = H256::from_slice(&i_512[32..64]); - - (master_key, chain_code) - } -} - -#[cfg(test)] -mod tests { - use super::{derivation, Derivation, ExtendedKeyPair, ExtendedPublic, ExtendedSecret}; - use ethereum_types::{H128, H256}; - use secret::Secret; - use std::str::FromStr; - - fn master_chain_basic() -> (H256, H256) { - let seed = H128::from_str("000102030405060708090a0b0c0d0e0f") - .expect("Seed should be valid H128") - .to_vec(); - - derivation::seed_pair(&*seed) - } - - fn test_extended(f: F, test_private: H256) - where - F: Fn(ExtendedSecret) -> ExtendedSecret, - { - let (private_seed, chain_code) = master_chain_basic(); - let extended_secret = ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code); - let derived = f(extended_secret); - assert_eq!(**derived.as_raw(), test_private); - } - - #[test] - fn smoky() { - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into()); - - // hardened - assert_eq!(&**extended_secret.as_raw(), &*secret); - assert_eq!( - &**extended_secret.derive(2147483648.into()).as_raw(), - &"0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6".into() - ); - assert_eq!( - &**extended_secret.derive(2147483649.into()).as_raw(), - &"44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f".into() - ); - - // normal - assert_eq!( - &**extended_secret.derive(0.into()).as_raw(), - &"bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6".into() - ); - assert_eq!( - &**extended_secret.derive(1.into()).as_raw(), - &"bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc".into() - ); - assert_eq!( - &**extended_secret.derive(2.into()).as_raw(), - &"86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268".into() - ); - - let extended_public = ExtendedPublic::from_secret(&extended_secret) - .expect("Extended public should be created"); - let derived_public = extended_public - .derive(0.into()) - .expect("First derivation of public should succeed"); - assert_eq!(&*derived_public.public(), &"f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94".into()); - - let keypair = ExtendedKeyPair::with_secret( - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(), - 064.into(), - ); - assert_eq!( - &**keypair - .derive(2147483648u32.into()) - .expect("Derivation of keypair should succeed") - .secret() - .as_raw(), - &"edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c".into() - ); - } - - #[test] - fn h256_soft_match() { - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let derivation_secret = - H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015") - .unwrap(); - - let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into()); - let extended_public = ExtendedPublic::from_secret(&extended_secret) - .expect("Extended public should be created"); - - let derived_secret0 = extended_secret.derive(Derivation::Soft(derivation_secret)); - let derived_public0 = extended_public - .derive(Derivation::Soft(derivation_secret)) - .expect("First derivation of public should succeed"); - - let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0) - .expect("Extended public should be created"); - - assert_eq!(public_from_secret0.public(), derived_public0.public()); - } - - #[test] - fn h256_hard() { - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let derivation_secret = - H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015") - .unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), 1u64.into()); - - assert_eq!( - &**extended_secret - .derive(Derivation::Hard(derivation_secret)) - .as_raw(), - &"2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486".into() - ); - } - - #[test] - fn match_() { - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let extended_secret = ExtendedSecret::with_code(secret.clone(), 1.into()); - let extended_public = ExtendedPublic::from_secret(&extended_secret) - .expect("Extended public should be created"); - - let derived_secret0 = extended_secret.derive(0.into()); - let derived_public0 = extended_public - .derive(0.into()) - .expect("First derivation of public should succeed"); - - let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0) - .expect("Extended public should be created"); - - assert_eq!(public_from_secret0.public(), derived_public0.public()); - } - - #[test] - fn test_seeds() { - let seed = H128::from_str("000102030405060708090a0b0c0d0e0f") - .expect("Seed should be valid H128") - .to_vec(); - - // private key from bitcoin test vector - // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs - let test_private = - H256::from_str("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35") - .expect("Private should be decoded ok"); - - let (private_seed, _) = derivation::seed_pair(&*seed); - - assert_eq!(private_seed, test_private); - } - - #[test] - fn test_vector_1() { - // xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 - // H(0) - test_extended( - |secret| secret.derive(2147483648.into()), - H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea") - .expect("Private should be decoded ok"), - ); - } - - #[test] - fn test_vector_2() { - // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs - // H(0)/1 - test_extended( - |secret| secret.derive(2147483648.into()).derive(1.into()), - H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368") - .expect("Private should be decoded ok"), - ); - } -} diff --git a/crates/accounts/ethkey/src/keccak.rs b/crates/accounts/ethkey/src/keccak.rs deleted file mode 100644 index e3c67b34d1..0000000000 --- a/crates/accounts/ethkey/src/keccak.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use tiny_keccak::Keccak; - -pub trait Keccak256 { - fn keccak256(&self) -> T - where - T: Sized; -} - -impl Keccak256<[u8; 32]> for [u8] { - fn keccak256(&self) -> [u8; 32] { - let mut keccak = Keccak::new_keccak256(); - let mut result = [0u8; 32]; - keccak.update(self); - keccak.finalize(&mut result); - result - } -} diff --git a/crates/accounts/ethkey/src/keypair.rs b/crates/accounts/ethkey/src/keypair.rs deleted file mode 100644 index 7f97e03fb8..0000000000 --- a/crates/accounts/ethkey/src/keypair.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::{Address, Error, Public, Secret, SECP256K1}; -use keccak::Keccak256; -use rustc_hex::ToHex; -use secp256k1::key; -use std::fmt; - -pub fn public_to_address(public: &Public) -> Address { - let hash = public.keccak256(); - let mut result = Address::default(); - result.copy_from_slice(&hash[12..]); - result -} - -#[derive(Debug, Clone, PartialEq)] -/// secp256k1 key pair -pub struct KeyPair { - secret: Secret, - public: Public, -} - -impl fmt::Display for KeyPair { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - writeln!(f, "secret: {}", self.secret.to_hex())?; - writeln!(f, "public: {}", self.public.to_hex())?; - write!(f, "address: {}", self.address().to_hex()) - } -} - -impl KeyPair { - /// Create a pair from secret key - pub fn from_secret(secret: Secret) -> Result { - let context = &SECP256K1; - let s: key::SecretKey = key::SecretKey::from_slice(context, &secret[..])?; - let pub_key = key::PublicKey::from_secret_key(context, &s)?; - let serialized = pub_key.serialize_vec(context, false); - - let mut public = Public::default(); - public.copy_from_slice(&serialized[1..65]); - - let keypair = KeyPair { - secret: secret, - public: public, - }; - - Ok(keypair) - } - - pub fn from_secret_slice(slice: &[u8]) -> Result { - Self::from_secret(Secret::from_unsafe_slice(slice)?) - } - - pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self { - let context = &SECP256K1; - let serialized = publ.serialize_vec(context, false); - let secret = Secret::from(sec); - let mut public = Public::default(); - public.copy_from_slice(&serialized[1..65]); - - KeyPair { - secret: secret, - public: public, - } - } - - pub fn secret(&self) -> &Secret { - &self.secret - } - - pub fn public(&self) -> &Public { - &self.public - } - - pub fn address(&self) -> Address { - public_to_address(&self.public) - } -} - -#[cfg(test)] -mod tests { - use std::str::FromStr; - use KeyPair; - use Secret; - - #[test] - fn from_secret() { - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let _ = KeyPair::from_secret(secret).unwrap(); - } - - #[test] - fn keypair_display() { - let expected = -"secret: a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65 -public: 8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4 -address: 5b073e9233944b5e729e46d618f0d8edf3d9c34a".to_owned(); - let secret = - Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65") - .unwrap(); - let kp = KeyPair::from_secret(secret).unwrap(); - assert_eq!(format!("{}", kp), expected); - } -} diff --git a/crates/accounts/ethkey/src/lib.rs b/crates/accounts/ethkey/src/lib.rs index 4aa436dc25..19accc4e1a 100644 --- a/crates/accounts/ethkey/src/lib.rs +++ b/crates/accounts/ethkey/src/lib.rs @@ -17,20 +17,10 @@ // #![warn(missing_docs)] extern crate edit_distance; -extern crate ethereum_types; -extern crate memzero; extern crate parity_crypto; extern crate parity_wordlist; -#[macro_use] -extern crate quick_error; -extern crate rand; -extern crate rustc_hex; -extern crate secp256k1; extern crate serde; -extern crate tiny_keccak; -#[macro_use] -extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] @@ -38,52 +28,12 @@ extern crate serde_derive; mod brain; mod brain_prefix; -mod error; -mod extended; -mod keccak; -mod keypair; mod password; mod prefix; -mod random; -mod secret; -mod signature; pub mod brain_recover; -pub mod crypto; -pub mod math; pub use self::{ - brain::Brain, - brain_prefix::BrainPrefix, - error::Error, - extended::{Derivation, DerivationError, ExtendedKeyPair, ExtendedPublic, ExtendedSecret}, - keypair::{public_to_address, KeyPair}, - math::public_is_valid, - parity_wordlist::Error as WordlistError, - password::Password, - prefix::Prefix, - random::Random, - secret::Secret, - signature::{recover, sign, verify_address, verify_public, Signature}, + brain::Brain, brain_prefix::BrainPrefix, parity_wordlist::Error as WordlistError, + password::Password, prefix::Prefix, }; - -use ethereum_types::H256; - -pub use ethereum_types::{Address, Public}; -pub type Message = H256; - -lazy_static! { - pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new(); -} - -/// Uninstantiatable error type for infallible generators. -#[derive(Debug)] -pub enum Void {} - -/// Generates new keypair. -pub trait Generator { - type Error; - - /// Should be called to generate new keypair. - fn generate(&mut self) -> Result; -} diff --git a/crates/accounts/ethkey/src/math.rs b/crates/accounts/ethkey/src/math.rs deleted file mode 100644 index 5b61cd05dd..0000000000 --- a/crates/accounts/ethkey/src/math.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::{Error, Public, Secret, SECP256K1}; -use ethereum_types::{H256, U256}; -use secp256k1::{ - constants::{CURVE_ORDER, GENERATOR_X, GENERATOR_Y}, - key, -}; - -/// Whether the public key is valid. -pub fn public_is_valid(public: &Public) -> bool { - to_secp256k1_public(public) - .ok() - .map_or(false, |p| p.is_valid()) -} - -/// Inplace multiply public key by secret key (EC point * scalar) -pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> { - let key_secret = secret.to_secp256k1_secret()?; - let mut key_public = to_secp256k1_public(public)?; - key_public.mul_assign(&SECP256K1, &key_secret)?; - set_public(public, &key_public); - Ok(()) -} - -/// Inplace add one public key to another (EC point + EC point) -pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> { - let mut key_public = to_secp256k1_public(public)?; - let other_public = to_secp256k1_public(other)?; - key_public.add_assign(&SECP256K1, &other_public)?; - set_public(public, &key_public); - Ok(()) -} - -/// Inplace sub one public key from another (EC point - EC point) -pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> { - let mut key_neg_other = to_secp256k1_public(other)?; - key_neg_other.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - - let mut key_public = to_secp256k1_public(public)?; - key_public.add_assign(&SECP256K1, &key_neg_other)?; - set_public(public, &key_public); - Ok(()) -} - -/// Replace public key with its negation (EC point = - EC point) -pub fn public_negate(public: &mut Public) -> Result<(), Error> { - let mut key_public = to_secp256k1_public(public)?; - key_public.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - set_public(public, &key_public); - Ok(()) -} - -/// Return base point of secp256k1 -pub fn generation_point() -> Public { - let mut public_sec_raw = [0u8; 65]; - public_sec_raw[0] = 4; - public_sec_raw[1..33].copy_from_slice(&GENERATOR_X); - public_sec_raw[33..65].copy_from_slice(&GENERATOR_Y); - - let public_key = key::PublicKey::from_slice(&SECP256K1, &public_sec_raw) - .expect("constructing using predefined constants; qed"); - let mut public = Public::default(); - set_public(&mut public, &public_key); - public -} - -/// Return secp256k1 elliptic curve order -pub fn curve_order() -> U256 { - H256::from_slice(&CURVE_ORDER).into() -} - -fn to_secp256k1_public(public: &Public) -> Result { - let public_data = { - let mut temp = [4u8; 65]; - (&mut temp[1..65]).copy_from_slice(&public[0..64]); - temp - }; - - Ok(key::PublicKey::from_slice(&SECP256K1, &public_data)?) -} - -fn set_public(public: &mut Public, key_public: &key::PublicKey) { - let key_public_serialized = key_public.serialize_vec(&SECP256K1, false); - public.copy_from_slice(&key_public_serialized[1..65]); -} - -#[cfg(test)] -mod tests { - use super::{ - super::{Generator, Random}, - public_add, public_sub, - }; - - #[test] - fn public_addition_is_commutative() { - let public1 = Random.generate().unwrap().public().clone(); - let public2 = Random.generate().unwrap().public().clone(); - - let mut left = public1.clone(); - public_add(&mut left, &public2).unwrap(); - - let mut right = public2.clone(); - public_add(&mut right, &public1).unwrap(); - - assert_eq!(left, right); - } - - #[test] - fn public_addition_is_reversible_with_subtraction() { - let public1 = Random.generate().unwrap().public().clone(); - let public2 = Random.generate().unwrap().public().clone(); - - let mut sum = public1.clone(); - public_add(&mut sum, &public2).unwrap(); - public_sub(&mut sum, &public2).unwrap(); - - assert_eq!(sum, public1); - } -} diff --git a/crates/accounts/ethkey/src/prefix.rs b/crates/accounts/ethkey/src/prefix.rs index 61382e721f..e037c41fe2 100644 --- a/crates/accounts/ethkey/src/prefix.rs +++ b/crates/accounts/ethkey/src/prefix.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use super::{Error, Generator, KeyPair, Random}; +use parity_crypto::publickey::{Error, Generator, KeyPair, Random}; /// Tries to find keypair with address starting with given prefix. pub struct Prefix { @@ -24,20 +24,13 @@ pub struct Prefix { impl Prefix { pub fn new(prefix: Vec, iterations: usize) -> Self { - Prefix { - prefix: prefix, - iterations: iterations, - } + Prefix { prefix, iterations } } -} - -impl Generator for Prefix { - type Error = Error; - fn generate(&mut self) -> Result { + pub fn generate(&mut self) -> Result { for _ in 0..self.iterations { - let keypair = Random.generate()?; - if keypair.address().starts_with(&self.prefix) { + let keypair = Random.generate(); + if keypair.address().as_ref().starts_with(&self.prefix) { return Ok(keypair); } } @@ -48,7 +41,6 @@ impl Generator for Prefix { #[cfg(test)] mod tests { - use Generator; use Prefix; #[test] @@ -57,6 +49,6 @@ mod tests { let keypair = Prefix::new(prefix.clone(), usize::max_value()) .generate() .unwrap(); - assert!(keypair.address().starts_with(&prefix)); + assert!(keypair.address().as_bytes().starts_with(&prefix)); } } diff --git a/crates/accounts/ethkey/src/random.rs b/crates/accounts/ethkey/src/random.rs deleted file mode 100644 index 3efc4df97e..0000000000 --- a/crates/accounts/ethkey/src/random.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use super::{Generator, KeyPair, SECP256K1}; -use rand::os::OsRng; - -/// Randomly generates new keypair, instantiating the RNG each time. -pub struct Random; - -impl Generator for Random { - type Error = ::std::io::Error; - - fn generate(&mut self) -> Result { - let mut rng = OsRng::new()?; - rng.generate().or_else(|void| match void {}) - } -} - -impl Generator for OsRng { - type Error = ::Void; - - fn generate(&mut self) -> Result { - let (sec, publ) = SECP256K1 - .generate_keypair(self) - .expect("context always created with full capabilities; qed"); - - Ok(KeyPair::from_keypair(sec, publ)) - } -} diff --git a/crates/accounts/ethkey/src/secret.rs b/crates/accounts/ethkey/src/secret.rs deleted file mode 100644 index ab78e494d6..0000000000 --- a/crates/accounts/ethkey/src/secret.rs +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::H256; -use memzero::Memzero; -use rustc_hex::ToHex; -use secp256k1::{constants::SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE, key}; -use std::{fmt, ops::Deref, str::FromStr}; -use Error; -use SECP256K1; - -#[derive(Clone, PartialEq, Eq)] -pub struct Secret { - inner: Memzero, -} - -impl ToHex for Secret { - fn to_hex(&self) -> String { - format!("{:x}", *self.inner) - } -} - -impl fmt::LowerHex for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(fmt) - } -} - -impl fmt::Debug for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(fmt) - } -} - -impl fmt::Display for Secret { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!( - fmt, - "Secret: 0x{:x}{:x}..{:x}{:x}", - self.inner[0], self.inner[1], self.inner[30], self.inner[31] - ) - } -} - -impl Secret { - /// Creates a `Secret` from the given slice, returning `None` if the slice length != 32. - pub fn from_slice(key: &[u8]) -> Option { - if key.len() != 32 { - return None; - } - let mut h = H256::default(); - h.copy_from_slice(&key[0..32]); - Some(Secret { - inner: Memzero::from(h), - }) - } - - /// Creates zero key, which is invalid for crypto operations, but valid for math operation. - pub fn zero() -> Self { - Secret { - inner: Memzero::from(H256::default()), - } - } - - /// Imports and validates the key. - pub fn from_unsafe_slice(key: &[u8]) -> Result { - let secret = key::SecretKey::from_slice(&super::SECP256K1, key)?; - Ok(secret.into()) - } - - /// Checks validity of this key. - pub fn check_validity(&self) -> Result<(), Error> { - self.to_secp256k1_secret().map(|_| ()) - } - - /// Inplace add one secret key to another (scalar + scalar) - pub fn add(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (false, true) => Ok(()), - (true, false) => { - *self = other.clone(); - Ok(()) - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.add_assign(&SECP256K1, &other_secret)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace subtract one secret key from another (scalar - scalar) - pub fn sub(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (false, true) => Ok(()), - (true, false) => { - *self = other.clone(); - self.neg() - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let mut other_secret = other.to_secp256k1_secret()?; - other_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - key_secret.add_assign(&SECP256K1, &other_secret)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace decrease secret key (scalar - 1) - pub fn dec(&mut self) -> Result<(), Error> { - match self.is_zero() { - true => { - *self = key::MINUS_ONE_KEY.into(); - Ok(()) - } - false => { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace multiply one secret key to another (scalar * scalar) - pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { - match (self.is_zero(), other.is_zero()) { - (true, true) | (true, false) => Ok(()), - (false, true) => { - *self = Self::zero(); - Ok(()) - } - (false, false) => { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.mul_assign(&SECP256K1, &other_secret)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace negate secret key (-scalar) - pub fn neg(&mut self) -> Result<(), Error> { - match self.is_zero() { - true => Ok(()), - false => { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - - *self = key_secret.into(); - Ok(()) - } - } - } - - /// Inplace inverse secret key (1 / scalar) - pub fn inv(&mut self) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.inv_assign(&SECP256K1)?; - - *self = key_secret.into(); - Ok(()) - } - - /// Compute power of secret key inplace (secret ^ pow). - /// This function is not intended to be used with large powers. - pub fn pow(&mut self, pow: usize) -> Result<(), Error> { - if self.is_zero() { - return Ok(()); - } - - match pow { - 0 => *self = key::ONE_KEY.into(), - 1 => (), - _ => { - let c = self.clone(); - for _ in 1..pow { - self.mul(&c)?; - } - } - } - - Ok(()) - } - - /// Create `secp256k1::key::SecretKey` based on this secret - pub fn to_secp256k1_secret(&self) -> Result { - Ok(key::SecretKey::from_slice(&SECP256K1, &self[..])?) - } -} - -impl FromStr for Secret { - type Err = Error; - fn from_str(s: &str) -> Result { - Ok(H256::from_str(s) - .map_err(|e| Error::Custom(format!("{:?}", e)))? - .into()) - } -} - -impl From<[u8; 32]> for Secret { - fn from(k: [u8; 32]) -> Self { - Secret { - inner: Memzero::from(H256(k)), - } - } -} - -impl From for Secret { - fn from(s: H256) -> Self { - s.0.into() - } -} - -impl From<&'static str> for Secret { - fn from(s: &'static str) -> Self { - s.parse().expect(&format!( - "invalid string literal for {}: '{}'", - stringify!(Self), - s - )) - } -} - -impl From for Secret { - fn from(key: key::SecretKey) -> Self { - let mut a = [0; SECP256K1_SECRET_KEY_SIZE]; - a.copy_from_slice(&key[0..SECP256K1_SECRET_KEY_SIZE]); - a.into() - } -} - -impl Deref for Secret { - type Target = H256; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -#[cfg(test)] -mod tests { - use super::{ - super::{Generator, Random}, - Secret, - }; - use std::str::FromStr; - - #[test] - fn multiplicating_secret_inversion_with_secret_gives_one() { - let secret = Random.generate().unwrap().secret().clone(); - let mut inversion = secret.clone(); - inversion.inv().unwrap(); - inversion.mul(&secret).unwrap(); - assert_eq!( - inversion, - Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001") - .unwrap() - ); - } - - #[test] - fn secret_inversion_is_reversible_with_inversion() { - let secret = Random.generate().unwrap().secret().clone(); - let mut inversion = secret.clone(); - inversion.inv().unwrap(); - inversion.inv().unwrap(); - assert_eq!(inversion, secret); - } - - #[test] - fn secret_pow() { - let secret = Random.generate().unwrap().secret().clone(); - - let mut pow0 = secret.clone(); - pow0.pow(0).unwrap(); - assert_eq!( - pow0, - Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001") - .unwrap() - ); - - let mut pow1 = secret.clone(); - pow1.pow(1).unwrap(); - assert_eq!(pow1, secret); - - let mut pow2 = secret.clone(); - pow2.pow(2).unwrap(); - let mut pow2_expected = secret.clone(); - pow2_expected.mul(&secret).unwrap(); - assert_eq!(pow2, pow2_expected); - - let mut pow3 = secret.clone(); - pow3.pow(3).unwrap(); - let mut pow3_expected = secret.clone(); - pow3_expected.mul(&secret).unwrap(); - pow3_expected.mul(&secret).unwrap(); - assert_eq!(pow3, pow3_expected); - } -} diff --git a/crates/accounts/ethkey/src/signature.rs b/crates/accounts/ethkey/src/signature.rs deleted file mode 100644 index fdb7b4c106..0000000000 --- a/crates/accounts/ethkey/src/signature.rs +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright 2015-2020 Parity Technologies (UK) Ltd. -// This file is part of OpenEthereum. - -// OpenEthereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// OpenEthereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with OpenEthereum. If not, see . - -use ethereum_types::{H256, H520}; -use public_to_address; -use rustc_hex::{FromHex, ToHex}; -use secp256k1::{ - key::{PublicKey, SecretKey}, - Error as SecpError, Message as SecpMessage, RecoverableSignature, RecoveryId, -}; -use std::{ - cmp::PartialEq, - fmt, - hash::{Hash, Hasher}, - ops::{Deref, DerefMut}, - str::FromStr, -}; -use Address; -use Error; -use Message; -use Public; -use Secret; -use SECP256K1; - -/// Signature encoded as RSV components -#[repr(C)] -pub struct Signature([u8; 65]); - -impl Signature { - /// Get a slice into the 'r' portion of the data. - pub fn r(&self) -> &[u8] { - &self.0[0..32] - } - - /// Get a slice into the 's' portion of the data. - pub fn s(&self) -> &[u8] { - &self.0[32..64] - } - - /// Get the recovery byte. - pub fn v(&self) -> u8 { - self.0[64] - } - - /// Encode the signature into RSV array (V altered to be in "Electrum" notation). - pub fn into_electrum(mut self) -> [u8; 65] { - self.0[64] += 27; - self.0 - } - - /// Parse bytes as a signature encoded as RSV (V in "Electrum" notation). - /// May return empty (invalid) signature if given data has invalid length. - pub fn from_electrum(data: &[u8]) -> Self { - if data.len() != 65 || data[64] < 27 { - // fallback to empty (invalid) signature - return Signature::default(); - } - - let mut sig = [0u8; 65]; - sig.copy_from_slice(data); - sig[64] -= 27; - Signature(sig) - } - - /// Create a signature object from the sig. - pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self { - let mut sig = [0u8; 65]; - sig[0..32].copy_from_slice(&r); - sig[32..64].copy_from_slice(&s); - sig[64] = v; - Signature(sig) - } - - /// Check if this is a "low" signature. - pub fn is_low_s(&self) -> bool { - H256::from_slice(self.s()) - <= "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0".into() - } - - /// Check if each component of the signature is in range. - pub fn is_valid(&self) -> bool { - self.v() <= 1 - && H256::from_slice(self.r()) - < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() - && H256::from_slice(self.r()) >= 1.into() - && H256::from_slice(self.s()) - < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() - && H256::from_slice(self.s()) >= 1.into() - } -} - -// manual implementation large arrays don't have trait impls by default. -// remove when integer generics exist -impl PartialEq for Signature { - fn eq(&self, other: &Self) -> bool { - &self.0[..] == &other.0[..] - } -} - -// manual implementation required in Rust 1.13+, see `std::cmp::AssertParamIsEq`. -impl Eq for Signature {} - -// also manual for the same reason, but the pretty printing might be useful. -impl fmt::Debug for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.debug_struct("Signature") - .field("r", &self.0[0..32].to_hex()) - .field("s", &self.0[32..64].to_hex()) - .field("v", &self.0[64..65].to_hex()) - .finish() - } -} - -impl fmt::Display for Signature { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{}", self.to_hex()) - } -} - -impl FromStr for Signature { - type Err = Error; - - fn from_str(s: &str) -> Result { - match s.from_hex() { - Ok(ref hex) if hex.len() == 65 => { - let mut data = [0; 65]; - data.copy_from_slice(&hex[0..65]); - Ok(Signature(data)) - } - _ => Err(Error::InvalidSignature), - } - } -} - -impl Default for Signature { - fn default() -> Self { - Signature([0; 65]) - } -} - -impl Hash for Signature { - fn hash(&self, state: &mut H) { - H520::from(self.0).hash(state); - } -} - -impl Clone for Signature { - fn clone(&self) -> Self { - Signature(self.0) - } -} - -impl From<[u8; 65]> for Signature { - fn from(s: [u8; 65]) -> Self { - Signature(s) - } -} - -impl Into<[u8; 65]> for Signature { - fn into(self) -> [u8; 65] { - self.0 - } -} - -impl From for H520 { - fn from(s: Signature) -> Self { - H520::from(s.0) - } -} - -impl From for Signature { - fn from(bytes: H520) -> Self { - Signature(bytes.into()) - } -} - -impl Deref for Signature { - type Target = [u8; 65]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Signature { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -pub fn sign(secret: &Secret, message: &Message) -> Result { - let context = &SECP256K1; - let sec = SecretKey::from_slice(context, &secret)?; - let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?; - let (rec_id, data) = s.serialize_compact(context); - let mut data_arr = [0; 65]; - - // no need to check if s is low, it always is - data_arr[0..64].copy_from_slice(&data[0..64]); - data_arr[64] = rec_id.to_i32() as u8; - Ok(Signature(data_arr)) -} - -pub fn verify_public( - public: &Public, - signature: &Signature, - message: &Message, -) -> Result { - let context = &SECP256K1; - let rsig = RecoverableSignature::from_compact( - context, - &signature[0..64], - RecoveryId::from_i32(signature[64] as i32)?, - )?; - let sig = rsig.to_standard(context); - - let pdata: [u8; 65] = { - let mut temp = [4u8; 65]; - temp[1..65].copy_from_slice(&**public); - temp - }; - - let publ = PublicKey::from_slice(context, &pdata)?; - match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) { - Ok(_) => Ok(true), - Err(SecpError::IncorrectSignature) => Ok(false), - Err(x) => Err(Error::from(x)), - } -} - -pub fn verify_address( - address: &Address, - signature: &Signature, - message: &Message, -) -> Result { - let public = recover(signature, message)?; - let recovered_address = public_to_address(&public); - Ok(address == &recovered_address) -} - -pub fn recover(signature: &Signature, message: &Message) -> Result { - let context = &SECP256K1; - let rsig = RecoverableSignature::from_compact( - context, - &signature[0..64], - RecoveryId::from_i32(signature[64] as i32)?, - )?; - let pubkey = context.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?; - let serialized = pubkey.serialize_vec(context, false); - - let mut public = Public::default(); - public.copy_from_slice(&serialized[1..65]); - Ok(public) -} - -#[cfg(test)] -mod tests { - use super::{recover, sign, verify_address, verify_public, Signature}; - use std::str::FromStr; - use Generator; - use Message; - use Random; - - #[test] - fn vrs_conversion() { - // given - let keypair = Random.generate().unwrap(); - let message = Message::default(); - let signature = sign(keypair.secret(), &message).unwrap(); - - // when - let vrs = signature.clone().into_electrum(); - let from_vrs = Signature::from_electrum(&vrs); - - // then - assert_eq!(signature, from_vrs); - } - - #[test] - fn signature_to_and_from_str() { - let keypair = Random.generate().unwrap(); - let message = Message::default(); - let signature = sign(keypair.secret(), &message).unwrap(); - let string = format!("{}", signature); - let deserialized = Signature::from_str(&string).unwrap(); - assert_eq!(signature, deserialized); - } - - #[test] - fn sign_and_recover_public() { - let keypair = Random.generate().unwrap(); - let message = Message::default(); - let signature = sign(keypair.secret(), &message).unwrap(); - assert_eq!(keypair.public(), &recover(&signature, &message).unwrap()); - } - - #[test] - fn sign_and_verify_public() { - let keypair = Random.generate().unwrap(); - let message = Message::default(); - let signature = sign(keypair.secret(), &message).unwrap(); - assert!(verify_public(keypair.public(), &signature, &message).unwrap()); - } - - #[test] - fn sign_and_verify_address() { - let keypair = Random.generate().unwrap(); - let message = Message::default(); - let signature = sign(keypair.secret(), &message).unwrap(); - assert!(verify_address(&keypair.address(), &signature, &message).unwrap()); - } -} diff --git a/crates/accounts/ethstore/Cargo.toml b/crates/accounts/ethstore/Cargo.toml index cdcae98e43..3f2f22f1f4 100644 --- a/crates/accounts/ethstore/Cargo.toml +++ b/crates/accounts/ethstore/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Parity Technologies "] [dependencies] log = "0.4" libc = "0.2" -rand = "0.4" +rand = "0.7.3" ethkey = { path = "../ethkey" } serde = "1.0" serde_json = "1.0" @@ -16,8 +16,8 @@ rustc-hex = "1.0" time = "0.1.34" itertools = "0.5" parking_lot = "0.7" -parity-crypto = "0.3.0" -ethereum-types = "0.4" +parity-crypto = { version = "0.6.2", features = [ "publickey"] } +ethereum-types = "0.9.2" smallvec = "0.6" parity-wordlist = "1.3" tempdir = "0.3" diff --git a/crates/accounts/ethstore/src/account/crypto.rs b/crates/accounts/ethstore/src/account/crypto.rs index 5b30dbbba0..ea5149c8ff 100644 --- a/crates/accounts/ethstore/src/account/crypto.rs +++ b/crates/accounts/ethstore/src/account/crypto.rs @@ -15,8 +15,8 @@ // along with OpenEthereum. If not, see . use account::{Aes128Ctr, Cipher, Kdf, Pbkdf2, Prf}; -use crypto::{self, Keccak256}; -use ethkey::{Password, Secret}; +use crypto::{self, publickey::Secret, Keccak256}; +use ethkey::Password; use json; use random::Random; use smallvec::SmallVec; @@ -79,7 +79,7 @@ impl Crypto { password: &Password, iterations: NonZeroU32, ) -> Result { - Crypto::with_plain(&*secret, password, iterations) + Crypto::with_plain(secret.as_bytes(), password, iterations) } /// Encrypt custom plain data @@ -94,7 +94,7 @@ impl Crypto { // two parts of derived key // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] let (derived_left_bits, derived_right_bits) = - crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); + crypto::derive_key_iterations(password.as_bytes(), &salt, iterations.get()); // preallocated (on-stack in case of `Secret`) buffer to hold cipher // length = length(plain) as we are using CTR-approach @@ -127,7 +127,7 @@ impl Crypto { } let secret = self.do_decrypt(password, 32)?; - Ok(Secret::from_unsafe_slice(&secret)?) + Ok(Secret::import_key(&secret)?) } /// Try to decrypt and return result as is @@ -139,7 +139,7 @@ impl Crypto { fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result, Error> { let (derived_left_bits, derived_right_bits) = match self.kdf { Kdf::Pbkdf2(ref params) => { - crypto::derive_key_iterations(password.as_bytes(), ¶ms.salt, params.c) + crypto::derive_key_iterations(password.as_bytes(), ¶ms.salt, params.c.get()) } Kdf::Scrypt(ref params) => crypto::scrypt::derive_key( password.as_bytes(), @@ -179,7 +179,7 @@ impl Crypto { #[cfg(test)] mod tests { use super::{Crypto, Error, NonZeroU32}; - use ethkey::{Generator, Random}; + use crypto::publickey::{Generator, Random}; lazy_static! { static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); @@ -187,7 +187,7 @@ mod tests { #[test] fn crypto_with_secret_create() { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let passwd = "this is sparta".into(); let crypto = Crypto::with_secret(keypair.secret(), &passwd, *ITERATIONS).unwrap(); let secret = crypto.secret(&passwd).unwrap(); @@ -196,7 +196,7 @@ mod tests { #[test] fn crypto_with_secret_invalid_password() { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), *ITERATIONS).unwrap(); assert_matches!( diff --git a/crates/accounts/ethstore/src/account/safe_account.rs b/crates/accounts/ethstore/src/account/safe_account.rs index a6f3d007d7..89b4d17a51 100644 --- a/crates/accounts/ethstore/src/account/safe_account.rs +++ b/crates/accounts/ethstore/src/account/safe_account.rs @@ -16,10 +16,11 @@ use super::crypto::Crypto; use account::Version; -use crypto; -use ethkey::{ - self, crypto::ecdh::agree, sign, Address, KeyPair, Message, Password, Public, Secret, Signature, +use crypto::{ + self, + publickey::{ecdh::agree, sign, Address, KeyPair, Message, Public, Secret, Signature}, }; +use ethkey::Password; use json; use std::num::NonZeroU32; use Error; @@ -193,7 +194,7 @@ impl SafeAccount { message: &[u8], ) -> Result, Error> { let secret = self.crypto.secret(password)?; - ethkey::crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from) + crypto::publickey::ecies::decrypt(&secret, shared_mac, message).map_err(From::from) } /// Agree on shared key. @@ -237,7 +238,7 @@ impl SafeAccount { #[cfg(test)] mod tests { use super::{NonZeroU32, SafeAccount}; - use ethkey::{verify_public, Generator, Message, Random}; + use crypto::publickey::{verify_public, Generator, Random}; lazy_static! { static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed"); @@ -245,9 +246,9 @@ mod tests { #[test] fn sign_and_verify_public() { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let password = "hello world".into(); - let message = Message::default(); + let message = [1u8; 32].into(); let account = SafeAccount::create( &keypair, [0u8; 16], @@ -262,10 +263,10 @@ mod tests { #[test] fn change_password() { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let first_password = "hello world".into(); let sec_password = "this is sparta".into(); - let message = Message::default(); + let message = [1u8; 32].into(); let account = SafeAccount::create( &keypair, [0u8; 16], diff --git a/crates/accounts/ethstore/src/accounts_dir/disk.rs b/crates/accounts/ethstore/src/accounts_dir/disk.rs index c981f6949c..13a8b7c288 100644 --- a/crates/accounts/ethstore/src/accounts_dir/disk.rs +++ b/crates/accounts/ethstore/src/accounts_dir/disk.rs @@ -420,7 +420,7 @@ mod test { use self::tempdir::TempDir; use super::{KeyDirectory, RootDiskDirectory, VaultKey}; use account::SafeAccount; - use ethkey::{Generator, Random}; + use crypto::publickey::{Generator, Random}; use std::{env, fs, num::NonZeroU32}; lazy_static! { @@ -432,7 +432,7 @@ mod test { // given let mut dir = env::temp_dir(); dir.push("ethstore_should_create_new_account"); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let password = "hello world".into(); let directory = RootDiskDirectory::create(dir.clone()).unwrap(); @@ -463,7 +463,7 @@ mod test { // given let mut dir = env::temp_dir(); dir.push("ethstore_should_handle_duplicate_filenames"); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let password = "hello world".into(); let directory = RootDiskDirectory::create(dir.clone()).unwrap(); @@ -582,7 +582,7 @@ mod test { .expect("Files hash should be calculated ok"); assert_eq!(hash, 15130871412783076140); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let password = "test pass".into(); let account = SafeAccount::create( &keypair, diff --git a/crates/accounts/ethstore/src/accounts_dir/memory.rs b/crates/accounts/ethstore/src/accounts_dir/memory.rs index 80ecb66764..73f48ef7c3 100644 --- a/crates/accounts/ethstore/src/accounts_dir/memory.rs +++ b/crates/accounts/ethstore/src/accounts_dir/memory.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use ethkey::Address; +use crypto::publickey::Address; use itertools; use parking_lot::RwLock; use std::collections::HashMap; @@ -70,7 +70,7 @@ impl KeyDirectory for MemoryDirectory { let mut val = 0u64; let accounts = self.accounts.read(); for acc in accounts.keys() { - val = val ^ acc.low_u64() + val = val ^ acc.to_low_u64_be() } Ok(val) } diff --git a/crates/accounts/ethstore/src/error.rs b/crates/accounts/ethstore/src/error.rs index 72372db87d..646f47339a 100644 --- a/crates/accounts/ethstore/src/error.rs +++ b/crates/accounts/ethstore/src/error.rs @@ -14,8 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use crypto::{self, Error as EthCryptoError}; -use ethkey::{self, DerivationError, Error as EthKeyError}; +use crypto::publickey::DerivationError; use std::{fmt, io::Error as IoError}; /// Account-related errors. @@ -45,12 +44,10 @@ pub enum Error { VaultNotFound, /// Account creation failed. CreationFailed, - /// `EthKey` error - EthKey(EthKeyError), - /// `ethkey::crypto::Error` - EthKeyCrypto(ethkey::crypto::Error), + /// `crypto::publickey::Error` + EthCrypto(crypto::Error), /// `EthCrypto` error - EthCrypto(EthCryptoError), + EthCryptoPublicKey(crypto::publickey::Error), /// Derivation error Derivation(DerivationError), /// Custom error @@ -72,9 +69,8 @@ impl fmt::Display for Error { Error::InvalidVaultName => "Invalid vault name".into(), Error::VaultNotFound => "Vault not found".into(), Error::CreationFailed => "Account creation failed".into(), - Error::EthKey(ref err) => err.to_string(), - Error::EthKeyCrypto(ref err) => err.to_string(), Error::EthCrypto(ref err) => err.to_string(), + Error::EthCryptoPublicKey(ref err) => err.to_string(), Error::Derivation(ref err) => format!("Derivation error: {:?}", err), Error::Custom(ref s) => s.clone(), }; @@ -89,20 +85,14 @@ impl From for Error { } } -impl From for Error { - fn from(err: EthKeyError) -> Self { - Error::EthKey(err) +impl From for Error { + fn from(err: crypto::publickey::Error) -> Self { + Error::EthCryptoPublicKey(err) } } -impl From for Error { - fn from(err: ethkey::crypto::Error) -> Self { - Error::EthKeyCrypto(err) - } -} - -impl From for Error { - fn from(err: EthCryptoError) -> Self { +impl From for Error { + fn from(err: crypto::Error) -> Self { Error::EthCrypto(err) } } diff --git a/crates/accounts/ethstore/src/ethkey.rs b/crates/accounts/ethstore/src/ethkey.rs index dc08af4191..aed0695bb3 100644 --- a/crates/accounts/ethstore/src/ethkey.rs +++ b/crates/accounts/ethstore/src/ethkey.rs @@ -16,6 +16,7 @@ //! ethkey reexport to make documentation look pretty. pub use _ethkey::*; +pub use crypto::publickey::Address; use json; impl Into for Address { diff --git a/crates/accounts/ethstore/src/ethstore.rs b/crates/accounts/ethstore/src/ethstore.rs index 3de0d13802..bf674e4581 100644 --- a/crates/accounts/ethstore/src/ethstore.rs +++ b/crates/accounts/ethstore/src/ethstore.rs @@ -24,9 +24,10 @@ use std::{ use account::SafeAccount; use accounts_dir::{KeyDirectory, SetKeyError, VaultKey, VaultKeyDirectory}; -use ethkey::{ - self, Address, ExtendedKeyPair, KeyPair, Message, Password, Public, Secret, Signature, +use crypto::publickey::{ + self, Address, ExtendedKeyPair, KeyPair, Message, Public, Secret, Signature, }; +use ethkey::Password; use json::{self, OpaqueKeyFile, Uuid}; use presale::PresaleWallet; use random::Random; @@ -554,17 +555,17 @@ impl EthMultiStore { Derivation::Hierarchical(path) => { for path_item in path { extended = extended.derive(if path_item.soft { - ethkey::Derivation::Soft(path_item.index) + publickey::Derivation::Soft(path_item.index) } else { - ethkey::Derivation::Hard(path_item.index) + publickey::Derivation::Hard(path_item.index) })?; } } Derivation::SoftHash(h256) => { - extended = extended.derive(ethkey::Derivation::Soft(h256))?; + extended = extended.derive(publickey::Derivation::Soft(h256))?; } Derivation::HardHash(h256) => { - extended = extended.derive(ethkey::Derivation::Hard(h256))?; + extended = extended.derive(publickey::Derivation::Hard(h256))?; } } Ok(extended) @@ -615,7 +616,7 @@ impl SimpleSecretStore for EthMultiStore { let accounts = self.get_matching(&account_ref, password)?; for account in accounts { let extended = self.generate(account.crypto.secret(password)?, derivation)?; - return Ok(ethkey::public_to_address(extended.public().public())); + return Ok(publickey::public_to_address(extended.public().public())); } Err(Error::InvalidPassword) } @@ -631,7 +632,7 @@ impl SimpleSecretStore for EthMultiStore { for account in accounts { let extended = self.generate(account.crypto.secret(password)?, derivation)?; let secret = extended.secret().as_raw(); - return Ok(ethkey::sign(&secret, message)?); + return Ok(publickey::sign(&secret, message)?); } Err(Error::InvalidPassword) } @@ -898,14 +899,14 @@ mod tests { use self::tempdir::TempDir; use super::{EthMultiStore, EthStore}; use accounts_dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory}; + use crypto::publickey::{Generator, KeyPair, Random}; use ethereum_types::H256; - use ethkey::{Generator, KeyPair, Random}; use secret_store::{ Derivation, SecretStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef, }; fn keypair() -> KeyPair { - Random.generate().unwrap() + Random.generate() } fn store() -> EthStore { @@ -1051,6 +1052,7 @@ mod tests { let passwd2 = "xzy".into(); let multi_store = multi_store(); let keypair = keypair(); + let message = [1u8; 32].into(); let address = store .insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd1) .unwrap(); @@ -1073,9 +1075,7 @@ mod tests { "First password should work for store." ); assert!( - multi_store - .sign(&address, &passwd2, &Default::default()) - .is_ok(), + multi_store.sign(&address, &passwd2, &message).is_ok(), "Second password should work for second store." ); assert_eq!(multi_store.accounts().unwrap().len(), 1); @@ -1462,7 +1462,7 @@ mod tests { SecretVaultRef::Root, &address, &"test".into(), - Derivation::HardHash(H256::from(0)), + Derivation::HardHash(H256::zero()), ) .unwrap(); @@ -1470,11 +1470,10 @@ mod tests { let accounts = store.accounts().unwrap(); assert_eq!(accounts.len(), 2); + let message = [1u8; 32].into(); // and we can sign with the derived contract assert!( - store - .sign(&derived, &"test".into(), &Default::default()) - .is_ok(), + store.sign(&derived, &"test".into(), &message).is_ok(), "Second password should work for second store." ); } diff --git a/crates/accounts/ethstore/src/import.rs b/crates/accounts/ethstore/src/import.rs index 949d37db7b..20cbcd787b 100644 --- a/crates/accounts/ethstore/src/import.rs +++ b/crates/accounts/ethstore/src/import.rs @@ -17,7 +17,7 @@ use std::{collections::HashSet, fs, path::Path}; use accounts_dir::{DiskKeyFileManager, KeyDirectory, KeyFileManager}; -use ethkey::Address; +use crypto::publickey::Address; use Error; /// Import an account from a file. diff --git a/crates/accounts/ethstore/src/lib.rs b/crates/accounts/ethstore/src/lib.rs index 5830ab998d..5abfdf2ae3 100644 --- a/crates/accounts/ethstore/src/lib.rs +++ b/crates/accounts/ethstore/src/lib.rs @@ -74,4 +74,4 @@ pub use self::{ }; /// An opaque wrapper for secret. -pub struct OpaqueSecret(::ethkey::Secret); +pub struct OpaqueSecret(crypto::publickey::Secret); diff --git a/crates/accounts/ethstore/src/presale.rs b/crates/accounts/ethstore/src/presale.rs index 0bf5905a90..45cc0de5d6 100644 --- a/crates/accounts/ethstore/src/presale.rs +++ b/crates/accounts/ethstore/src/presale.rs @@ -14,8 +14,12 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use crypto::{self, pbkdf2, Keccak256}; -use ethkey::{Address, KeyPair, Password, Secret}; +use crypto::{ + self, pbkdf2, + publickey::{Address, KeyPair, Secret}, + Keccak256, +}; +use ethkey::Password; use json; use std::{fs, num::NonZeroU32, path::Path}; use Error; @@ -61,7 +65,7 @@ impl PresaleWallet { let salt = pbkdf2::Salt(password.as_bytes()); let sec = pbkdf2::Secret(password.as_bytes()); let iter = NonZeroU32::new(2000).expect("2000 > 0; qed"); - pbkdf2::sha256(iter, salt, sec, &mut derived_key); + pbkdf2::sha256(iter.get(), salt, sec, &mut derived_key); let mut key = vec![0; self.ciphertext.len()]; let len = @@ -69,7 +73,7 @@ impl PresaleWallet { .map_err(|_| Error::InvalidPassword)?; let unpadded = &key[..len]; - let secret = Secret::from_unsafe_slice(&unpadded.keccak256())?; + let secret = Secret::import_key(&unpadded.keccak256())?; if let Ok(kp) = KeyPair::from_secret(secret) { if kp.address() == self.address { return Ok(kp); diff --git a/crates/accounts/ethstore/src/random.rs b/crates/accounts/ethstore/src/random.rs index c50abf85fd..405873c94e 100644 --- a/crates/accounts/ethstore/src/random.rs +++ b/crates/accounts/ethstore/src/random.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use rand::{OsRng, Rng}; +use rand::{distributions::Alphanumeric, rngs::OsRng, Rng, RngCore}; pub trait Random { fn random() -> Self @@ -25,7 +25,7 @@ pub trait Random { impl Random for [u8; 16] { fn random() -> Self { let mut result = [0u8; 16]; - let mut rng = OsRng::new().unwrap(); + let mut rng = OsRng; rng.fill_bytes(&mut result); result } @@ -34,7 +34,7 @@ impl Random for [u8; 16] { impl Random for [u8; 32] { fn random() -> Self { let mut result = [0u8; 32]; - let mut rng = OsRng::new().unwrap(); + let mut rng = OsRng; rng.fill_bytes(&mut result); result } @@ -42,6 +42,6 @@ impl Random for [u8; 32] { /// Generate a random string of given length. pub fn random_string(length: usize) -> String { - let mut rng = OsRng::new().expect("Not able to operate without random source."); - rng.gen_ascii_chars().take(length).collect() + let rng = OsRng; + rng.sample_iter(&Alphanumeric).take(length).collect() } diff --git a/crates/accounts/ethstore/src/secret_store.rs b/crates/accounts/ethstore/src/secret_store.rs index b9c098c46f..36c6f9ed57 100644 --- a/crates/accounts/ethstore/src/secret_store.rs +++ b/crates/accounts/ethstore/src/secret_store.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{Address, Message, Public, Secret, Signature}; use ethereum_types::H256; -use ethkey::{Address, Message, Password, Public, Secret, Signature}; +use ethkey::Password; use json::{OpaqueKeyFile, Uuid}; use std::{ cmp::Ordering, @@ -174,7 +175,7 @@ pub trait SecretStore: SimpleSecretStore { secret: &OpaqueSecret, message: &Message, ) -> Result { - Ok(::ethkey::sign(&secret.0, message)?) + Ok(crypto::publickey::sign(&secret.0, message)?) } /// Imports presale wallet diff --git a/crates/accounts/ethstore/tests/api.rs b/crates/accounts/ethstore/tests/api.rs index c37100c223..1eb2fa7f0e 100644 --- a/crates/accounts/ethstore/tests/api.rs +++ b/crates/accounts/ethstore/tests/api.rs @@ -14,15 +14,19 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +extern crate ethereum_types; extern crate ethstore; +extern crate parity_crypto as crypto; extern crate rand; mod util; +use std::str::FromStr; + +use crypto::publickey::{verify_address, Generator, KeyPair, Random, Secret}; +use ethereum_types::H160; use ethstore::{ - accounts_dir::RootDiskDirectory, - ethkey::{verify_address, Generator, KeyPair, Random, Secret}, - EthStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef, + accounts_dir::RootDiskDirectory, EthStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef, }; use util::TransientDir; @@ -40,7 +44,7 @@ fn secret_store_open_not_existing() { } fn random_secret() -> Secret { - Random.generate().unwrap().secret().clone() + Random.generate().secret().clone() } #[test] @@ -66,13 +70,10 @@ fn secret_store_sign() { .insert_account(SecretVaultRef::Root, random_secret(), &"".into()) .is_ok()); let accounts = store.accounts().unwrap(); + let message = [1u8; 32].into(); assert_eq!(accounts.len(), 1); - assert!(store - .sign(&accounts[0], &"".into(), &Default::default()) - .is_ok()); - assert!(store - .sign(&accounts[0], &"1".into(), &Default::default()) - .is_err()); + assert!(store.sign(&accounts[0], &"".into(), &message).is_ok()); + assert!(store.sign(&accounts[0], &"1".into(), &message).is_err()); } #[test] @@ -83,19 +84,14 @@ fn secret_store_change_password() { .insert_account(SecretVaultRef::Root, random_secret(), &"".into()) .is_ok()); let accounts = store.accounts().unwrap(); + let message = [1u8; 32].into(); assert_eq!(accounts.len(), 1); - assert!(store - .sign(&accounts[0], &"".into(), &Default::default()) - .is_ok()); + assert!(store.sign(&accounts[0], &"".into(), &message).is_ok()); assert!(store .change_password(&accounts[0], &"".into(), &"1".into()) .is_ok()); - assert!(store - .sign(&accounts[0], &"".into(), &Default::default()) - .is_err()); - assert!(store - .sign(&accounts[0], &"1".into(), &Default::default()) - .is_ok()); + assert!(store.sign(&accounts[0], &"".into(), &message).is_err()); + assert!(store.sign(&accounts[0], &"1".into(), &message).is_ok()); } #[test] @@ -140,9 +136,15 @@ fn secret_store_laod_geth_files() { assert_eq!( store.accounts().unwrap(), vec![ - StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()), - StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()), - StoreAccountRef::root("63121b431a52f8043c16fcf0d1df9cb7b5f66649".into()), + StoreAccountRef::root( + H160::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap() + ), + StoreAccountRef::root( + H160::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap() + ), + StoreAccountRef::root( + H160::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap() + ), ] ); } @@ -154,8 +156,12 @@ fn secret_store_load_pat_files() { assert_eq!( store.accounts().unwrap(), vec![ - StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()), - StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()), + StoreAccountRef::root( + H160::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap() + ), + StoreAccountRef::root( + H160::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap() + ), ] ); } @@ -182,12 +188,16 @@ fn test_decrypting_files_with_short_ciphertext() { assert_eq!( accounts, vec![ - StoreAccountRef::root("31e9d1e6d844bd3a536800ef8d8be6a9975db509".into()), - StoreAccountRef::root("d1e64e5480bfaf733ba7d48712decb8227797a4e".into()), + StoreAccountRef::root( + H160::from_str("31e9d1e6d844bd3a536800ef8d8be6a9975db509").unwrap() + ), + StoreAccountRef::root( + H160::from_str("d1e64e5480bfaf733ba7d48712decb8227797a4e").unwrap() + ), ] ); - let message = Default::default(); + let message = [1u8; 32].into(); let s1 = store.sign(&accounts[0], &"foo".into(), &message).unwrap(); let s2 = store.sign(&accounts[1], &"foo".into(), &message).unwrap(); diff --git a/crates/accounts/ethstore/tests/util/transient_dir.rs b/crates/accounts/ethstore/tests/util/transient_dir.rs index 88fb755c1b..5f22e7efdf 100644 --- a/crates/accounts/ethstore/tests/util/transient_dir.rs +++ b/crates/accounts/ethstore/tests/util/transient_dir.rs @@ -18,11 +18,11 @@ use ethstore::{ accounts_dir::{KeyDirectory, RootDiskDirectory}, Error, SafeAccount, }; -use rand::{OsRng, Rng}; +use rand::{rngs::OsRng, RngCore}; use std::{env, fs, path::PathBuf}; pub fn random_dir() -> PathBuf { - let mut rng = OsRng::new().unwrap(); + let mut rng = OsRng; let mut dir = env::temp_dir(); dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64())); dir diff --git a/crates/accounts/src/account_data.rs b/crates/accounts/src/account_data.rs index 5bb41daf26..2c9c3bd32f 100644 --- a/crates/accounts/src/account_data.rs +++ b/crates/accounts/src/account_data.rs @@ -18,7 +18,8 @@ use std::{collections::HashMap, time::Instant}; -use ethkey::{Address, Password}; +use crypto::publickey::Address; +use ethkey::Password; use serde_derive::{Deserialize, Serialize}; use serde_json; diff --git a/crates/accounts/src/lib.rs b/crates/accounts/src/lib.rs index d7003d56c9..d68ba61f05 100644 --- a/crates/accounts/src/lib.rs +++ b/crates/accounts/src/lib.rs @@ -18,6 +18,8 @@ //! Account management. +extern crate parity_crypto as crypto; + mod account_data; mod error; mod stores; @@ -32,7 +34,8 @@ use std::{ time::{Duration, Instant}, }; -use ethkey::{Address, Generator, Message, Password, Public, Random, Secret}; +use crypto::publickey::{Address, Generator, Message, Public, Random, Secret}; +use ethkey::Password; use ethstore::{ accounts_dir::MemoryDirectory, random_string, EthMultiStore, EthStore, OpaqueSecret, SecretStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef, @@ -40,7 +43,7 @@ use ethstore::{ use log::*; use parking_lot::RwLock; -pub use ethkey::Signature; +pub use crypto::publickey::Signature; pub use ethstore::{Derivation, Error, IndexDerivation, KeyFile}; pub use self::{account_data::AccountMeta, error::SignError}; @@ -134,9 +137,7 @@ impl AccountProvider { /// Creates new random account and returns address and public key pub fn new_account_and_public(&self, password: &Password) -> Result<(Address, Public), Error> { - let acc = Random - .generate() - .expect("secp context has generation capabilities; qed"); + let acc = Random.generate(); let public = acc.public().clone(); let secret = acc.secret().clone(); let account = self @@ -355,7 +356,8 @@ impl AccountProvider { } else { // verify password by signing dump message // result may be discarded - let _ = self.sstore.sign(&account, &password, &Default::default())?; + let dummy_msg = [1u8; 32].into(); + let _ = self.sstore.sign(&account, &password, &dummy_msg)?; } let data = AccountData { @@ -632,15 +634,16 @@ impl AccountProvider { #[cfg(test)] mod tests { use super::{AccountProvider, Unlock}; + use crypto::publickey::{Address, Generator, Random}; use ethereum_types::H256; - use ethkey::{Address, Generator, Random}; use ethstore::{Derivation, StoreAccountRef}; use std::time::{Duration, Instant}; #[test] fn unlock_account_temp() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); + let dummy_msg = [1u8; 32].into(); assert!(ap .insert_account(kp.secret().clone(), &"test".into()) .is_ok()); @@ -650,13 +653,13 @@ mod tests { assert!(ap .unlock_account_temporarily(kp.address(), "test".into()) .is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_err()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_err()); } #[test] fn derived_account_nosave() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); assert!(ap .insert_account(kp.secret().clone(), &"base".into()) @@ -669,7 +672,7 @@ mod tests { .derive_account( &kp.address(), None, - Derivation::SoftHash(H256::from(999)), + Derivation::SoftHash(H256::from_low_u64_be(999)), false, ) .expect("Derivation should not fail"); @@ -683,7 +686,7 @@ mod tests { #[test] fn derived_account_save() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); assert!(ap .insert_account(kp.secret().clone(), &"base".into()) @@ -696,7 +699,7 @@ mod tests { .derive_account( &kp.address(), None, - Derivation::SoftHash(H256::from(999)), + Derivation::SoftHash(H256::from_low_u64_be(999)), true, ) .expect("Derivation should not fail"); @@ -716,7 +719,7 @@ mod tests { #[test] fn derived_account_sign() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); assert!(ap .insert_account(kp.secret().clone(), &"base".into()) @@ -729,14 +732,14 @@ mod tests { .derive_account( &kp.address(), None, - Derivation::SoftHash(H256::from(1999)), + Derivation::SoftHash(H256::from_low_u64_be(1999)), true, ) .expect("Derivation should not fail"); ap.unlock_account_permanently(derived_addr, "base".into()) .expect("Should be ok because account is saved and password is valid"); - let msg = Default::default(); + let msg = [2u8; 32].into(); let signed_msg1 = ap .sign(derived_addr, None, msg) .expect("Signing with existing unlocked account should not fail"); @@ -744,7 +747,7 @@ mod tests { .sign_derived( &kp.address(), None, - Derivation::SoftHash(H256::from(1999)), + Derivation::SoftHash(H256::from_low_u64_be(1999)), msg, ) .expect("Derived signing with existing unlocked account should not fail"); @@ -754,8 +757,9 @@ mod tests { #[test] fn unlock_account_perm() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); + let dummy_msg = [1u8; 32].into(); assert!(ap .insert_account(kp.secret().clone(), &"test".into()) .is_ok()); @@ -765,19 +769,20 @@ mod tests { assert!(ap .unlock_account_permanently(kp.address(), "test".into()) .is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); assert!(ap .unlock_account_temporarily(kp.address(), "test".into()) .is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); } #[test] fn unlock_account_timer() { - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); + let dummy_msg = [1u8; 32].into(); assert!(ap .insert_account(kp.secret().clone(), &"test".into()) .is_ok()); @@ -787,35 +792,35 @@ mod tests { assert!(ap .unlock_account_timed(kp.address(), "test".into(), Duration::from_secs(60)) .is_ok()); - assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_ok()); ap.unlocked .write() .get_mut(&StoreAccountRef::root(kp.address())) .unwrap() .unlock = Unlock::Timed(Instant::now()); - assert!(ap.sign(kp.address(), None, Default::default()).is_err()); + assert!(ap.sign(kp.address(), None, dummy_msg).is_err()); } #[test] fn should_sign_and_return_token() { // given - let kp = Random.generate().unwrap(); + let kp = Random.generate(); let ap = AccountProvider::transient_provider(); + let dummy_msg = [1u8; 32].into(); assert!(ap .insert_account(kp.secret().clone(), &"test".into()) .is_ok()); // when let (_signature, token) = ap - .sign_with_token(kp.address(), "test".into(), Default::default()) + .sign_with_token(kp.address(), "test".into(), dummy_msg) .unwrap(); // then - ap.sign_with_token(kp.address(), token.clone(), Default::default()) + ap.sign_with_token(kp.address(), token.clone(), dummy_msg) .expect("First usage of token should be correct."); assert!( - ap.sign_with_token(kp.address(), token, Default::default()) - .is_err(), + ap.sign_with_token(kp.address(), token, dummy_msg).is_err(), "Second usage of the same token should fail." ); } diff --git a/crates/accounts/src/stores.rs b/crates/accounts/src/stores.rs index 63a551be1f..f6accb66d8 100644 --- a/crates/accounts/src/stores.rs +++ b/crates/accounts/src/stores.rs @@ -22,7 +22,7 @@ use std::{ path::{Path, PathBuf}, }; -use ethkey::Address; +use crypto::publickey::Address; use log::{trace, warn}; use crate::AccountMeta; @@ -172,6 +172,7 @@ impl DiskMap { mod tests { use super::AddressBook; use crate::account_data::AccountMeta; + use ethereum_types::H160; use std::collections::HashMap; use tempdir::TempDir; @@ -179,8 +180,8 @@ mod tests { fn should_save_and_reload_address_book() { let tempdir = TempDir::new("").unwrap(); let mut b = AddressBook::new(tempdir.path()); - b.set_name(1.into(), "One".to_owned()); - b.set_meta(1.into(), "{1:1}".to_owned()); + b.set_name(H160::from_low_u64_be(1), "One".to_owned()); + b.set_meta(H160::from_low_u64_be(1), "{1:1}".to_owned()); let b = AddressBook::new(tempdir.path()); assert_eq!( b.get(), @@ -193,7 +194,7 @@ mod tests { } )] .into_iter() - .map(|(a, b)| (a.into(), b)) + .map(|(a, b)| (H160::from_low_u64_be(a), b)) .collect::>() ); } @@ -203,10 +204,10 @@ mod tests { let tempdir = TempDir::new("").unwrap(); let mut b = AddressBook::new(tempdir.path()); - b.set_name(1.into(), "One".to_owned()); - b.set_name(2.into(), "Two".to_owned()); - b.set_name(3.into(), "Three".to_owned()); - b.remove(2.into()); + b.set_name(H160::from_low_u64_be(1), "One".to_owned()); + b.set_name(H160::from_low_u64_be(2), "Two".to_owned()); + b.set_name(H160::from_low_u64_be(3), "Three".to_owned()); + b.remove(H160::from_low_u64_be(2)); let b = AddressBook::new(tempdir.path()); assert_eq!( @@ -230,7 +231,7 @@ mod tests { ), ] .into_iter() - .map(|(a, b)| (a.into(), b)) + .map(|(a, b)| (H160::from_low_u64_be(a), b)) .collect::>() ); } diff --git a/crates/concensus/ethash/Cargo.toml b/crates/concensus/ethash/Cargo.toml index 06ee93f889..9ae4ff7f5c 100644 --- a/crates/concensus/ethash/Cargo.toml +++ b/crates/concensus/ethash/Cargo.toml @@ -7,8 +7,9 @@ authors = ["Parity Technologies "] [dependencies] crunchy = "0.1.0" either = "1.0.0" -ethereum-types = "0.4" -keccak-hash = "0.1" +ethereum-types = "0.9.2" +keccak-hash = "0.5.0" +tiny-keccak = "2.0.2" log = "0.4" memmap = "0.6" parking_lot = "0.7" diff --git a/crates/concensus/ethash/src/cache.rs b/crates/concensus/ethash/src/cache.rs index ab3407a07e..38b2b2de65 100644 --- a/crates/concensus/ethash/src/cache.rs +++ b/crates/concensus/ethash/src/cache.rs @@ -21,7 +21,7 @@ use memmap::MmapMut; use parking_lot::Mutex; use seed_compute::SeedHashCompute; -use shared::{epoch, get_cache_size, to_hex, Node, ETHASH_CACHE_ROUNDS, NODE_BYTES, NODE_DWORDS}; +use shared::{epoch, get_cache_size, to_hex, Node, ETHASH_CACHE_ROUNDS, NODE_BYTES}; use std::{ borrow::Cow, @@ -318,27 +318,22 @@ impl AsRef<[Node]> for NodeCache { // out. It counts as a read and causes all writes afterwards to be elided. Yes, really. I know, I // want to refactor this to use less `unsafe` as much as the next rustacean. unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) { - let dst = memory as *mut u8; + // We use raw pointers here, see above + let dst = slice::from_raw_parts_mut(memory as *mut u8, NODE_BYTES); debug_assert_eq!(ident.len(), 32); - keccak_512::unchecked(dst, NODE_BYTES, ident.as_ptr(), ident.len()); + keccak_512::write(&ident[..], dst); for i in 1..num_nodes { // We use raw pointers here, see above - let dst = memory.offset(i as _) as *mut u8; - let src = memory.offset(i as isize - 1) as *mut u8; - - keccak_512::unchecked(dst, NODE_BYTES, src, NODE_BYTES); + let dst = slice::from_raw_parts_mut(memory.offset(i as _) as *mut u8, NODE_BYTES); + let src = slice::from_raw_parts(memory.offset(i as isize - 1) as *mut u8, NODE_BYTES); + keccak_512::write(src, dst); } // Now this is initialized, we can treat it as a slice. let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes); - // For `unroll!`, see below. If the literal in `unroll!` is not the same as the RHS here then - // these have got out of sync! Don't let this happen! - debug_assert_eq!(NODE_DWORDS, 8); - - // This _should_ get unrolled by the compiler, since it's not using the loop variable. for _ in 0..ETHASH_CACHE_ROUNDS { for i in 0..num_nodes { let data_idx = (num_nodes - 1 + i) % num_nodes; @@ -348,11 +343,8 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) { let mut data: Node = nodes.get_unchecked(data_idx).clone(); let rhs: &Node = nodes.get_unchecked(idx); - unroll! { - for w in 0..8 { - *data.as_dwords_mut().get_unchecked_mut(w) ^= - *rhs.as_dwords().get_unchecked(w); - } + for (a, b) in data.as_dwords_mut().iter_mut().zip(rhs.as_dwords()) { + *a ^= *b; } data diff --git a/crates/concensus/ethash/src/compute.rs b/crates/concensus/ethash/src/compute.rs index 648b157b1d..00bbcd96d8 100644 --- a/crates/concensus/ethash/src/compute.rs +++ b/crates/concensus/ethash/src/compute.rs @@ -26,7 +26,7 @@ use seed_compute::SeedHashCompute; use shared::*; use std::io; -use std::{mem, path::Path, ptr}; +use std::{mem, path::Path}; const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4; const MIX_NODES: usize = MIX_WORDS / NODE_WORDS; @@ -141,31 +141,24 @@ pub fn quick_get_difficulty( mix_hash: &H256, progpow: bool, ) -> H256 { - unsafe { - if progpow { - let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]); - keccak_f800_long(*header_hash, seed, mem::transmute(*mix_hash)) - } else { - // This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set - // with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write - // the next 32 bytes before we read the whole thing with `keccak_256`. - // - // This cannot be elided by the compiler as it doesn't know the implementation of - // `keccak_512`. - let mut buf: [u8; 64 + 32] = ::mem::MaybeUninit::uninit().assume_init(); + if progpow { + let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]); + keccak_f800_long(*header_hash, seed, unsafe { mem::transmute(*mix_hash) }) + } else { + let mut buf = [0u8; 64 + 32]; - ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32); - ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8); + let hash_len = header_hash.len(); + buf[..hash_len].copy_from_slice(header_hash); + let end = hash_len + mem::size_of::(); + buf[hash_len..end].copy_from_slice(&nonce.to_ne_bytes()); - keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40); - ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32); + keccak_512::inplace_range(&mut buf, 0..end); + buf[64..].copy_from_slice(mix_hash); - // This is initialized in `keccak_256` - let mut hash: [u8; 32] = ::mem::MaybeUninit::uninit().assume_init(); - keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()); + let mut hash = [0u8; 32]; + keccak_256::write(&buf, &mut hash); - hash - } + hash } } @@ -214,32 +207,21 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) // improvements, since I can't imagine that 3-5% of our runtime is taken up by catting two // arrays together. let mut buf: MixBuf = MixBuf { - half_mix: unsafe { + half_mix: { // Pack `header_hash` and `nonce` together - // We explicitly write the first 40 bytes, leaving the last 24 as uninitialized. Then - // `keccak_512` reads the first 40 bytes (4th parameter) and overwrites the entire array, - // leaving it fully initialized. - let mut out: [u8; NODE_BYTES] = ::mem::MaybeUninit::uninit().assume_init(); - - ptr::copy_nonoverlapping(header_hash.as_ptr(), out.as_mut_ptr(), header_hash.len()); - ptr::copy_nonoverlapping( - &nonce as *const u64 as *const u8, - out[header_hash.len()..].as_mut_ptr(), - mem::size_of::(), - ); + let mut out = [0u8; NODE_BYTES]; + + let hash_len = header_hash.len(); + out[..hash_len].copy_from_slice(header_hash); + let end = hash_len + mem::size_of::(); + out[hash_len..end].copy_from_slice(&nonce.to_ne_bytes()); // compute keccak-512 hash and replicate across mix - keccak_512::unchecked( - out.as_mut_ptr(), - NODE_BYTES, - out.as_ptr(), - header_hash.len() + mem::size_of::(), - ); + keccak_512::inplace_range(&mut out, 0..end); Node { bytes: out } }, - // This is fully initialized before being read, see `let mut compress = ...` below - compress_bytes: unsafe { ::mem::MaybeUninit::uninit().assume_init() }, + compress_bytes: [0u8; MIX_WORDS], }; let mut mix: [_; MIX_NODES] = [buf.half_mix.clone(), buf.half_mix.clone()]; @@ -263,24 +245,13 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages }; - unroll! { - // MIX_NODES - for n in 0..2 { - let tmp_node = calculate_dag_item( - index * MIX_NODES as u32 + n as u32, - cache, - ); + // MIX_NODES + for n in 0..2 { + let tmp_node = calculate_dag_item(index * MIX_NODES as u32 + n as u32, cache); - unroll! { - // NODE_WORDS - for w in 0..16 { - mix[n].as_words_mut()[w] = - fnv_hash( - mix[n].as_words()[w], - tmp_node.as_words()[w], - ); - } - } + // NODE_WORDS + for (a, b) in mix[n].as_words_mut().iter_mut().zip(tmp_node.as_words()) { + *a = fnv_hash(*a, *b); } } } @@ -288,25 +259,27 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) let mix_words: [u32; MIX_WORDS] = unsafe { mem::transmute(mix) }; { - // This is an uninitialized buffer to begin with, but we iterate precisely `compress.len()` - // times and set each index, leaving the array fully initialized. THIS ONLY WORKS ON LITTLE- - // ENDIAN MACHINES. See a future PR to make this and the rest of the code work correctly on + // We iterate precisely `compress.len()` times and set each index, + // leaving the array fully initialized. THIS ONLY WORKS ON LITTLE-ENDIAN MACHINES. + // See a future PR to make this and the rest of the code work correctly on // big-endian arches like mips. let compress: &mut [u32; MIX_WORDS / 4] = unsafe { make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes) }; + #[cfg(target_endian = "big")] + { + compile_error!("OpenEthereum currently only supports little-endian targets"); + } // Compress mix debug_assert_eq!(MIX_WORDS / 4, 8); - unroll! { - for i in 0..8 { - let w = i * 4; - - let mut reduction = mix_words[w + 0]; - reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1]; - reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2]; - reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3]; - compress[i] = reduction; - } + for i in 0..8 { + let w = i * 4; + + let mut reduction = mix_words[w + 0]; + reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1]; + reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2]; + reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3]; + compress[i] = reduction; } } @@ -315,24 +288,20 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) let value: H256 = { // We can interpret the buffer as an array of `u8`s, since it's `repr(C)`. let read_ptr: *const u8 = &buf as *const MixBuf as *const u8; - // We overwrite the second half since `keccak_256` has an internal buffer and so allows - // overlapping arrays as input. - let write_ptr: *mut u8 = &mut buf.compress_bytes as *mut [u8; 32] as *mut u8; - unsafe { - keccak_256::unchecked( - write_ptr, - buf.compress_bytes.len(), + let buffer = unsafe { + core::slice::from_raw_parts( read_ptr, buf.half_mix.bytes.len() + buf.compress_bytes.len(), - ); - } + ) + }; + // We overwrite the buf.compress_bytes since `keccak_256` has an internal buffer and so allows + // overlapping arrays as input. + keccak_256::write(buffer, &mut buf.compress_bytes); + buf.compress_bytes }; - ProofOfWork { - mix_hash: mix_hash, - value: value, - } + ProofOfWork { mix_hash, value } } // TODO: Use the `simd` crate diff --git a/crates/concensus/ethash/src/keccak.rs b/crates/concensus/ethash/src/keccak.rs index f09ce56f87..134a11fb2a 100644 --- a/crates/concensus/ethash/src/keccak.rs +++ b/crates/concensus/ethash/src/keccak.rs @@ -21,46 +21,15 @@ pub type H256 = [u8; 32]; pub mod keccak_512 { use super::hash; - pub use self::hash::keccak_512_unchecked as unchecked; - - pub fn write(input: &[u8], output: &mut [u8]) { - hash::keccak_512(input, output); - } - - pub fn inplace(input: &mut [u8]) { - // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This - // means that we can reuse the input buffer for both input and output. - unsafe { - hash::keccak_512_unchecked( - input.as_mut_ptr(), - input.len(), - input.as_ptr(), - input.len(), - ); - } - } + pub use self::hash::{ + keccak512 as inplace, keccak512_range as inplace_range, keccak_512 as write, + }; } pub mod keccak_256 { use super::hash; - pub use self::hash::keccak_256_unchecked as unchecked; - - #[allow(dead_code)] - pub fn write(input: &[u8], output: &mut [u8]) { - hash::keccak_256(input, output); - } - - pub fn inplace(input: &mut [u8]) { - // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This - // means that we can reuse the input buffer for both input and output. - unsafe { - hash::keccak_256_unchecked( - input.as_mut_ptr(), - input.len(), - input.as_ptr(), - input.len(), - ); - } - } + pub use self::hash::{ + keccak256 as inplace, keccak256_range as inplace_range, keccak_256 as write, + }; } diff --git a/crates/concensus/ethash/src/lib.rs b/crates/concensus/ethash/src/lib.rs index e56b09358e..2232d24319 100644 --- a/crates/concensus/ethash/src/lib.rs +++ b/crates/concensus/ethash/src/lib.rs @@ -19,6 +19,7 @@ extern crate ethereum_types; extern crate memmap; extern crate parking_lot; extern crate primal; +extern crate tiny_keccak; #[macro_use] extern crate crunchy; @@ -52,12 +53,13 @@ mod progpow; pub use cache::{NodeCacheBuilder, OptimizeFor}; use compute::Light; pub use compute::{quick_get_difficulty, slow_hash_block_number, ProofOfWork}; -use ethereum_types::{U256, U512}; +use ethereum_types::{BigEndianHash, U256, U512}; use keccak::H256; use parking_lot::Mutex; pub use seed_compute::SeedHashCompute; pub use shared::ETHASH_EPOCH_LENGTH; use std::{ + convert::TryFrom, mem, path::{Path, PathBuf}, }; @@ -168,12 +170,12 @@ impl EthashManager { /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`. pub fn boundary_to_difficulty(boundary: ðereum_types::H256) -> U256 { - difficulty_to_boundary_aux(&**boundary) + difficulty_to_boundary_aux(&boundary.into_uint()) } /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`. pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 { - difficulty_to_boundary_aux(difficulty).into() + BigEndianHash::from_uint(&difficulty_to_boundary_aux(difficulty)) } fn difficulty_to_boundary_aux>(difficulty: T) -> ethereum_types::U256 { @@ -184,8 +186,8 @@ fn difficulty_to_boundary_aux>(difficulty: T) -> ethereum_types::U if difficulty == U512::one() { U256::max_value() } else { - // difficulty > 1, so result should never overflow 256 bits - U256::from((U512::one() << 256) / difficulty) + const PROOF: &str = "difficulty > 1, so result never overflows 256 bits; qed"; + U256::try_from((U512::one() << 256) / difficulty).expect(PROOF) } } @@ -210,12 +212,12 @@ fn test_lru() { #[test] fn test_difficulty_to_boundary() { - use ethereum_types::H256; + use ethereum_types::{BigEndianHash, H256}; use std::str::FromStr; assert_eq!( difficulty_to_boundary(&U256::from(1)), - H256::from(U256::max_value()) + BigEndianHash::from_uint(&U256::max_value()) ); assert_eq!( difficulty_to_boundary(&U256::from(2)), @@ -243,16 +245,18 @@ fn test_difficulty_to_boundary_regression() { boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())) ); assert_eq!( - H256::from(difficulty), - difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())) + H256::from_low_u64_be(difficulty), + difficulty_to_boundary(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty))) ); assert_eq!( U256::from(difficulty), - boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()) + boundary_to_difficulty(&BigEndianHash::from_uint(&boundary_to_difficulty( + &H256::from_low_u64_be(difficulty) + ))), ); assert_eq!( - H256::from(difficulty), - difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()) + H256::from_low_u64_be(difficulty), + difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into_uint()) ); } } @@ -266,5 +270,5 @@ fn test_difficulty_to_boundary_panics_on_zero() { #[test] #[should_panic] fn test_boundary_to_difficulty_panics_on_zero() { - boundary_to_difficulty(ðereum_types::H256::from(0)); + boundary_to_difficulty(ðereum_types::H256::zero()); } diff --git a/crates/concensus/miner/Cargo.toml b/crates/concensus/miner/Cargo.toml index d7bb02b56f..0fae0fa7b7 100644 --- a/crates/concensus/miner/Cargo.toml +++ b/crates/concensus/miner/Cargo.toml @@ -17,20 +17,21 @@ url = { version = "2", optional = true } ansi_term = "0.10" common-types = { path = "../../ethcore/types" } error-chain = "0.12" -ethabi = "6.0" -ethabi-derive = "6.0" -ethabi-contract = "6.0" +ethabi = "12.0.0" +ethabi-derive = "12.0.0" +ethabi-contract = "11.0.0" ethcore-call-contract = { path = "../../vm/call-contract" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" futures = "0.1" -heapsize = "0.4" -keccak-hash = "0.1" +keccak-hash = "0.5.0" linked-hash-map = "0.5" log = "0.4" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } parity-runtime = { path = "../../runtime/runtime" } +parity-util-mem = "0.7" parking_lot = "0.7" price-info = { path = "./price-info", optional = true } -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } trace-time = "0.1" transaction-pool = "2.0.1" diff --git a/crates/concensus/miner/local-store/Cargo.toml b/crates/concensus/miner/local-store/Cargo.toml index 463470c869..554ea93015 100644 --- a/crates/concensus/miner/local-store/Cargo.toml +++ b/crates/concensus/miner/local-store/Cargo.toml @@ -10,7 +10,8 @@ ethcore-io = { path = "../../../runtime/io" } ethcore-db = { path = "../../../db/db"} kvdb = "0.1" log = "0.4" -rlp = { version = "0.3.0", features = ["ethereum"] } +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +rlp = { version = "0.4.6" } serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/crates/concensus/miner/local-store/src/lib.rs b/crates/concensus/miner/local-store/src/lib.rs index 0d2a3657cb..d1aee10651 100644 --- a/crates/concensus/miner/local-store/src/lib.rs +++ b/crates/concensus/miner/local-store/src/lib.rs @@ -29,6 +29,7 @@ extern crate common_types as types; extern crate ethcore_db; extern crate ethcore_io as io; extern crate kvdb; +extern crate parity_crypto as crypto; extern crate rlp; extern crate serde; extern crate serde_json; @@ -238,7 +239,7 @@ impl Drop for LocalDataStore { mod tests { use super::NodeInfo; - use ethkey::{Brain, Generator}; + use ethkey::Brain; use std::sync::Arc; use types::transaction::{Condition, PendingTransaction, Transaction, TypedTransaction}; @@ -269,7 +270,7 @@ mod tests { #[test] fn with_condition() { - let keypair = Brain::new("abcd".into()).generate().unwrap(); + let keypair = Brain::new("abcd".into()).generate(); let transactions: Vec<_> = (0..10u64) .map(|nonce| { let mut tx = TypedTransaction::Legacy(Transaction::default()); @@ -306,7 +307,7 @@ mod tests { #[test] fn skips_bad_transactions() { - let keypair = Brain::new("abcd".into()).generate().unwrap(); + let keypair = Brain::new("abcd".into()).generate(); let mut transactions: Vec<_> = (0..10u64) .map(|nonce| { let mut tx = TypedTransaction::Legacy(Transaction::default()); diff --git a/crates/concensus/miner/src/external.rs b/crates/concensus/miner/src/external.rs index 403f6949d8..2a68b4e35c 100644 --- a/crates/concensus/miner/src/external.rs +++ b/crates/concensus/miner/src/external.rs @@ -92,7 +92,7 @@ mod tests { // given let m = miner(); assert_eq!(m.hashrate(), U256::from(0)); - m.submit_hashrate(U256::from(10), H256::from(1)); + m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1)); assert_eq!(m.hashrate(), U256::from(10)); // when @@ -107,12 +107,12 @@ mod tests { // given let m = miner(); assert_eq!(m.hashrate(), U256::from(0)); - m.submit_hashrate(U256::from(10), H256::from(1)); + m.submit_hashrate(U256::from(10), H256::from_low_u64_be(1)); assert_eq!(m.hashrate(), U256::from(10)); // when - m.submit_hashrate(U256::from(15), H256::from(1)); - m.submit_hashrate(U256::from(20), H256::from(2)); + m.submit_hashrate(U256::from(15), H256::from_low_u64_be(1)); + m.submit_hashrate(U256::from(20), H256::from_low_u64_be(2)); // then assert_eq!(m.hashrate(), U256::from(35)); diff --git a/crates/concensus/miner/src/lib.rs b/crates/concensus/miner/src/lib.rs index 89bd18c4f3..46280c1520 100644 --- a/crates/concensus/miner/src/lib.rs +++ b/crates/concensus/miner/src/lib.rs @@ -22,13 +22,15 @@ extern crate ansi_term; extern crate common_types as types; extern crate ethabi; +extern crate ethabi_derive; extern crate ethcore_call_contract as call_contract; extern crate ethereum_types; extern crate futures; -extern crate heapsize; extern crate keccak_hash as hash; extern crate linked_hash_map; +extern crate parity_crypto as crypto; extern crate parity_runtime; +extern crate parity_util_mem; extern crate parking_lot; #[cfg(feature = "price-info")] extern crate price_info; @@ -38,8 +40,6 @@ extern crate transaction_pool as txpool; #[macro_use] extern crate ethabi_contract; #[macro_use] -extern crate ethabi_derive; -#[macro_use] extern crate error_chain; #[macro_use] extern crate log; diff --git a/crates/concensus/miner/src/pool/listener.rs b/crates/concensus/miner/src/pool/listener.rs index 6cb190ca9c..5d1b936b99 100644 --- a/crates/concensus/miner/src/pool/listener.rs +++ b/crates/concensus/miner/src/pool/listener.rs @@ -124,6 +124,7 @@ impl txpool::Listener for Logger { #[cfg(test)] mod tests { use super::*; + use ethereum_types::H160; use parking_lot::Mutex; use txpool::Listener; use types::transaction; @@ -166,7 +167,7 @@ mod tests { gas_price: 5.into(), value: 0.into(), }) - .fake_sign(5.into()); + .fake_sign(H160::from_low_u64_be(5)); Arc::new(Transaction::from_pending_block_transaction(signed)) } diff --git a/crates/concensus/miner/src/pool/local_transactions.rs b/crates/concensus/miner/src/pool/local_transactions.rs index 8c0037c58d..bb86f76f93 100644 --- a/crates/concensus/miner/src/pool/local_transactions.rs +++ b/crates/concensus/miner/src/pool/local_transactions.rs @@ -254,8 +254,8 @@ impl txpool::Listener for LocalTransactionsList { #[cfg(test)] mod tests { use super::*; + use crypto::publickey::{Generator, Random}; use ethereum_types::U256; - use ethkey::{Generator, Random}; use txpool::Listener; use types::transaction; @@ -339,7 +339,7 @@ mod tests { } fn new_tx>(nonce: T) -> Arc { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let signed = transaction::TypedTransaction::Legacy(transaction::Transaction { action: transaction::Action::Create, value: U256::from(100), diff --git a/crates/concensus/miner/src/pool/mod.rs b/crates/concensus/miner/src/pool/mod.rs index 8d11c43d93..1467a1f235 100644 --- a/crates/concensus/miner/src/pool/mod.rs +++ b/crates/concensus/miner/src/pool/mod.rs @@ -17,7 +17,7 @@ //! Transaction Pool use ethereum_types::{Address, H256, U256}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOfExt; use txpool; use types::transaction; @@ -177,7 +177,7 @@ impl txpool::VerifiedTransaction for VerifiedTransaction { } fn mem_usage(&self) -> usize { - self.transaction.heap_size_of_children() + self.transaction.malloc_size_of() } fn sender(&self) -> &Address { diff --git a/crates/concensus/miner/src/pool/replace.rs b/crates/concensus/miner/src/pool/replace.rs index 0e2b7cc95e..d7d9ac1d96 100644 --- a/crates/concensus/miner/src/pool/replace.rs +++ b/crates/concensus/miner/src/pool/replace.rs @@ -117,7 +117,7 @@ where mod tests { use super::*; - use ethkey::{Generator, KeyPair, Random}; + use crypto::publickey::{Generator, KeyPair, Random}; use pool::{ scoring::*, tests::{ @@ -160,7 +160,7 @@ mod tests { let replace = ReplaceByScoreAndReadiness::new(scoring, client); // same sender txs - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let same_sender_tx1 = local_tx_verified( Tx { @@ -190,7 +190,7 @@ mod tests { ); // different sender txs - let sender1 = Random.generate().unwrap(); + let sender1 = Random.generate(); let different_sender_tx1 = local_tx_verified( Tx { nonce: 2, @@ -200,7 +200,7 @@ mod tests { &sender1, ); - let sender2 = Random.generate().unwrap(); + let sender2 = Random.generate(); let different_sender_tx2 = local_tx_verified( Tx { nonce: 1, @@ -274,7 +274,7 @@ mod tests { ..Default::default() }; - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let txs = vec![tx1, tx2, tx3, tx4] .into_iter() .map(|tx| tx.unsigned().sign(keypair.secret(), None).verified()) @@ -440,7 +440,7 @@ mod tests { let client = TestClient::new().with_nonce(1); let replace = ReplaceByScoreAndReadiness::new(scoring, client); - let old_sender = Random.generate().unwrap(); + let old_sender = Random.generate(); let tx_old_ready_1 = { let tx = Tx { nonce: 1, @@ -518,7 +518,7 @@ mod tests { tx.signed().verified() }; - let new_sender = Random.generate().unwrap(); + let new_sender = Random.generate(); let tx_new_ready_1 = { let tx = Tx { nonce: 1, @@ -586,7 +586,7 @@ mod tests { tx.signed().verified() }; - let new_sender = Random.generate().unwrap(); + let new_sender = Random.generate(); let tx_new_ready_1 = local_tx_verified( Tx { nonce: 1, @@ -641,7 +641,7 @@ mod tests { tx.signed().verified() }; - let new_sender = Random.generate().unwrap(); + let new_sender = Random.generate(); let tx_new_ready_1 = local_tx_verified( Tx { nonce: 1, diff --git a/crates/concensus/miner/src/pool/tests/tx.rs b/crates/concensus/miner/src/pool/tests/tx.rs index 51c276d445..84187cbd1d 100644 --- a/crates/concensus/miner/src/pool/tests/tx.rs +++ b/crates/concensus/miner/src/pool/tests/tx.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{Generator, Random}; use ethereum_types::{H256, U256}; -use ethkey::{Generator, Random}; use rustc_hex::FromHex; use types::transaction::{ self, SignedTransaction, Transaction, TypedTransaction, UnverifiedTransaction, @@ -49,7 +49,7 @@ impl Tx { } pub fn signed(self) -> SignedTransaction { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); self.unsigned().sign(keypair.secret(), None) } @@ -59,7 +59,7 @@ impl Tx { } pub fn signed_triple(mut self) -> (SignedTransaction, SignedTransaction, SignedTransaction) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let tx1 = self.clone().unsigned().sign(keypair.secret(), None); self.nonce += 1; let tx2 = self.clone().unsigned().sign(keypair.secret(), None); @@ -70,7 +70,7 @@ impl Tx { } pub fn signed_replacement(mut self) -> (SignedTransaction, SignedTransaction) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let tx1 = self.clone().unsigned().sign(keypair.secret(), None); self.gas_price += 1; let tx2 = self.unsigned().sign(keypair.secret(), None); @@ -90,7 +90,7 @@ impl Tx { } pub fn big_one(self) -> SignedTransaction { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let tx = TypedTransaction::Legacy(Transaction { action: transaction::Action::Create, value: U256::from(100), diff --git a/crates/concensus/miner/stratum/Cargo.toml b/crates/concensus/miner/stratum/Cargo.toml index a4977555e5..2b1248576b 100644 --- a/crates/concensus/miner/stratum/Cargo.toml +++ b/crates/concensus/miner/stratum/Cargo.toml @@ -6,8 +6,8 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] -ethereum-types = "0.4" -keccak-hash = "0.1" +ethereum-types = "0.9.2" +keccak-hash = "0.5.0" jsonrpc-core = "15.0.0" jsonrpc-tcp-server = "15.0.0" log = "0.4" diff --git a/crates/db/blooms-db/Cargo.toml b/crates/db/blooms-db/Cargo.toml index 543a798772..a531ca5d60 100644 --- a/crates/db/blooms-db/Cargo.toml +++ b/crates/db/blooms-db/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.2" -ethbloom = "=0.5.0" +ethbloom = "0.9.1" parking_lot = "0.7" tiny-keccak = "1.4" diff --git a/crates/db/blooms-db/benches/blooms.rs b/crates/db/blooms-db/benches/blooms.rs index 42f59c37b4..9713a676ae 100644 --- a/crates/db/blooms-db/benches/blooms.rs +++ b/crates/db/blooms-db/benches/blooms.rs @@ -40,7 +40,7 @@ fn bench_blooms_filter_1_million_ok(c: &mut Criterion) { database .insert_blooms(999_999, iter::once(&Bloom::zero())) .unwrap(); - let bloom = Bloom::from(0x001); + let bloom = Bloom::from_low_u64_be(0x001); database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); @@ -60,8 +60,8 @@ fn bench_blooms_filter_1_million_miss(c: &mut Criterion) { database .insert_blooms(999_999, iter::once(&Bloom::zero())) .unwrap(); - let bloom = Bloom::from(0x001); - let bad_bloom = Bloom::from(0x0001); + let bloom = Bloom::from_low_u64_be(0x001); + let bad_bloom = Bloom::from_low_u64_be(0x0001); database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); @@ -81,8 +81,8 @@ fn bench_blooms_filter_1_million_miss_and_ok(c: &mut Criterion) { database .insert_blooms(999_999, iter::once(&Bloom::zero())) .unwrap(); - let bloom = Bloom::from(0x001); - let bad_bloom = Bloom::from(0x0001); + let bloom = Bloom::from_low_u64_be(0x001); + let bad_bloom = Bloom::from_low_u64_be(0x0001); database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); diff --git a/crates/db/blooms-db/src/db.rs b/crates/db/blooms-db/src/db.rs index 752120b269..f174ffeb13 100644 --- a/crates/db/blooms-db/src/db.rs +++ b/crates/db/blooms-db/src/db.rs @@ -346,59 +346,59 @@ mod tests { .insert_blooms( 0, vec![ - Bloom::from(0), - Bloom::from(0x01), - Bloom::from(0x10), - Bloom::from(0x11), + Bloom::zero(), + Bloom::from_low_u64_be(0x01), + Bloom::from_low_u64_be(0x10), + Bloom::from_low_u64_be(0x11), ] .iter(), ) .unwrap(); let matches = database - .iterate_matching(0, 3, Some(&Bloom::from(0))) + .iterate_matching(0, 3, Some(&Bloom::zero())) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![0, 1, 2, 3]); let matches = database - .iterate_matching(0, 4, Some(&Bloom::from(0))) + .iterate_matching(0, 4, Some(&Bloom::zero())) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![0, 1, 2, 3]); let matches = database - .iterate_matching(1, 3, Some(&Bloom::from(0))) + .iterate_matching(1, 3, Some(&Bloom::zero())) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![1, 2, 3]); let matches = database - .iterate_matching(1, 2, Some(&Bloom::from(0))) + .iterate_matching(1, 2, Some(&Bloom::zero())) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![1, 2]); let matches = database - .iterate_matching(0, 3, Some(&Bloom::from(0x01))) + .iterate_matching(0, 3, Some(&Bloom::from_low_u64_be(0x01))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![1, 3]); let matches = database - .iterate_matching(0, 3, Some(&Bloom::from(0x10))) + .iterate_matching(0, 3, Some(&Bloom::from_low_u64_be(0x10))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![2, 3]); let matches = database - .iterate_matching(2, 2, Some(&Bloom::from(0x10))) + .iterate_matching(2, 2, Some(&Bloom::from_low_u64_be(0x10))) .unwrap() .collect::, _>>() .unwrap(); @@ -413,52 +413,52 @@ mod tests { .insert_blooms( 254, vec![ - Bloom::from(0x100), - Bloom::from(0x01), - Bloom::from(0x10), - Bloom::from(0x11), + Bloom::from_low_u64_be(0x100), + Bloom::from_low_u64_be(0x01), + Bloom::from_low_u64_be(0x10), + Bloom::from_low_u64_be(0x11), ] .iter(), ) .unwrap(); let matches = database - .iterate_matching(0, 257, Some(&Bloom::from(0x01))) + .iterate_matching(0, 257, Some(&Bloom::from_low_u64_be(0x01))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![255, 257]); let matches = database - .iterate_matching(0, 258, Some(&Bloom::from(0x100))) + .iterate_matching(0, 258, Some(&Bloom::from_low_u64_be(0x100))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![254]); let matches = database - .iterate_matching(0, 256, Some(&Bloom::from(0x01))) + .iterate_matching(0, 256, Some(&Bloom::from_low_u64_be(0x01))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![255]); let matches = database - .iterate_matching(255, 255, Some(&Bloom::from(0x01))) + .iterate_matching(255, 255, Some(&Bloom::from_low_u64_be(0x01))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![255]); let matches = database - .iterate_matching(256, 256, Some(&Bloom::from(0x10))) + .iterate_matching(256, 256, Some(&Bloom::from_low_u64_be(0x10))) .unwrap() .collect::, _>>() .unwrap(); assert_eq!(matches, vec![256]); let matches = database - .iterate_matching(256, 257, Some(&Bloom::from(0x10))) + .iterate_matching(256, 257, Some(&Bloom::from_low_u64_be(0x10))) .unwrap() .collect::, _>>() .unwrap(); @@ -469,10 +469,10 @@ mod tests { fn test_db_close() { let tempdir = TempDir::new("").unwrap(); let blooms = vec![ - Bloom::from(0x100), - Bloom::from(0x01), - Bloom::from(0x10), - Bloom::from(0x11), + Bloom::from_low_u64_be(0x100), + Bloom::from_low_u64_be(0x01), + Bloom::from_low_u64_be(0x10), + Bloom::from_low_u64_be(0x11), ]; let mut database = Database::open(tempdir.path()).unwrap(); diff --git a/crates/db/blooms-db/src/file.rs b/crates/db/blooms-db/src/file.rs index edb236d929..1d1efaebcb 100644 --- a/crates/db/blooms-db/src/file.rs +++ b/crates/db/blooms-db/src/file.rs @@ -66,7 +66,7 @@ impl File { let mut file_ref = &self.file; file_ref.seek(SeekFrom::Start(pos * 256))?; let mut bloom = ethbloom::Bloom::default(); - file_ref.read_exact(&mut bloom)?; + file_ref.read_exact(bloom.as_bytes_mut())?; Ok(bloom) } @@ -80,7 +80,7 @@ impl File { old_bloom.accrue_bloom(bloom); let mut file_ref = &self.file; file_ref.seek(SeekFrom::Start(pos * 256))?; - file_ref.write_all(&old_bloom) + file_ref.write_all(old_bloom.as_bytes()) } /// Replace bloom at given position with a new one. @@ -133,7 +133,7 @@ impl<'a> Iterator for FileIterator<'a> { fn next(&mut self) -> Option { let mut bloom = ethbloom::Bloom::default(); - match self.file.read_exact(&mut bloom) { + match self.file.read_exact(bloom.as_bytes_mut()) { Ok(_) => Some(Ok(bloom)), Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => None, Err(err) => Some(Err(err)), @@ -151,8 +151,8 @@ mod tests { fn test_file() { let tempdir = TempDir::new("").unwrap(); let mut file = File::open(tempdir.path().join("file")).unwrap(); - file.accrue_bloom(0, &Bloom::from(1)).unwrap(); + file.accrue_bloom(0, &Bloom::from_low_u64_be(1)).unwrap(); file.flush().unwrap(); - assert_eq!(file.read_bloom(0).unwrap(), Bloom::from(1)); + assert_eq!(file.read_bloom(0).unwrap(), Bloom::from_low_u64_be(1)); } } diff --git a/crates/db/db/Cargo.toml b/crates/db/db/Cargo.toml index 7b6ebbfde7..6cfd27ce66 100644 --- a/crates/db/db/Cargo.toml +++ b/crates/db/db/Cargo.toml @@ -9,12 +9,12 @@ edition = "2018" [dependencies] common-types = { path = "../../ethcore/types" } -ethereum-types = "0.4" -heapsize = "0.4" +ethereum-types = "0.9.2" kvdb = "0.1" kvdb-rocksdb = "0.1.3" kvdb-memorydb = "0.1" +parity-util-mem = "0.7" parking_lot = "0.7" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } rlp_derive = { path = "../../util/rlp-derive" } stats = { path = "../../util/stats" } \ No newline at end of file diff --git a/crates/db/db/src/db.rs b/crates/db/db/src/db.rs index 464300a251..170ab9863e 100644 --- a/crates/db/db/src/db.rs +++ b/crates/db/db/src/db.rs @@ -20,7 +20,7 @@ use kvdb::DBTransaction; use kvdb_rocksdb::Database; use parking_lot::RwLock; use stats::{PrometheusMetrics, PrometheusRegistry}; -use std::{collections::HashMap, hash::Hash, io::Read, ops::Deref}; +use std::{collections::HashMap, hash::Hash, io::Read}; use rlp; @@ -84,7 +84,7 @@ where /// Should be used to get database key associated with given value. pub trait Key { /// The db key associated with this value. - type Target: Deref; + type Target: AsRef<[u8]>; /// Returns db key. fn key(&self) -> Self::Target; @@ -96,13 +96,13 @@ pub trait Writable { fn write(&mut self, col: Option, key: &dyn Key, value: &T) where T: rlp::Encodable, - R: Deref; + R: AsRef<[u8]>; /// Deletes key from the databse. fn delete(&mut self, col: Option, key: &dyn Key) where T: rlp::Encodable, - R: Deref; + R: AsRef<[u8]>; /// Writes the value into the database and updates the cache. fn write_with_cache( @@ -115,7 +115,7 @@ pub trait Writable { ) where K: Key + Hash + Eq, T: rlp::Encodable, - R: Deref, + R: AsRef<[u8]>, { self.write(col, &key, &value); match policy { @@ -138,7 +138,7 @@ pub trait Writable { ) where K: Key + Hash + Eq, T: rlp::Encodable, - R: Deref, + R: AsRef<[u8]>, { match policy { CacheUpdatePolicy::Overwrite => { @@ -166,7 +166,7 @@ pub trait Writable { ) where K: Key + Hash + Eq, T: rlp::Encodable, - R: Deref, + R: AsRef<[u8]>, { match policy { CacheUpdatePolicy::Overwrite => { @@ -197,7 +197,7 @@ pub trait Readable { fn read(&self, col: Option, key: &dyn Key) -> Option where T: rlp::Decodable, - R: Deref; + R: AsRef<[u8]>; /// Returns value for given key either in cache or in database. fn read_with_cache(&self, col: Option, cache: &RwLock, key: &K) -> Option @@ -246,13 +246,13 @@ pub trait Readable { /// Returns true if given value exists. fn exists(&self, col: Option, key: &dyn Key) -> bool where - R: Deref; + R: AsRef<[u8]>; /// Returns true if given value exists either in cache or in database. fn exists_with_cache(&self, col: Option, cache: &RwLock, key: &K) -> bool where K: Eq + Hash + Key, - R: Deref, + R: AsRef<[u8]>, C: Cache, { { @@ -270,17 +270,17 @@ impl Writable for DBTransaction { fn write(&mut self, col: Option, key: &dyn Key, value: &T) where T: rlp::Encodable, - R: Deref, + R: AsRef<[u8]>, { - self.put(col, &key.key(), &rlp::encode(value)); + self.put(col, key.key().as_ref(), &rlp::encode(value)); } fn delete(&mut self, col: Option, key: &dyn Key) where T: rlp::Encodable, - R: Deref, + R: AsRef<[u8]>, { - self.delete(col, &key.key()); + self.delete(col, key.key().as_ref()); } } @@ -288,25 +288,25 @@ impl Readable for KVDB { fn read(&self, col: Option, key: &dyn Key) -> Option where T: rlp::Decodable, - R: Deref, + R: AsRef<[u8]>, { - self.get(col, &key.key()) - .expect(&format!("db get failed, key: {:?}", &key.key() as &[u8])) + self.get(col, key.key().as_ref()) + .expect(&format!("db get failed, key: {:?}", key.key().as_ref())) .map(|v| rlp::decode(&v).expect("decode db value failed")) } fn exists(&self, col: Option, key: &dyn Key) -> bool where - R: Deref, + R: AsRef<[u8]>, { - let result = self.get(col, &key.key()); + let result = self.get(col, key.key().as_ref()); match result { Ok(v) => v.is_some(), Err(err) => { panic!( "db get failed, key: {:?}, err: {:?}", - &key.key() as &[u8], + key.key().as_ref(), err ); } diff --git a/crates/db/db/src/keys.rs b/crates/db/db/src/keys.rs index ded42045f3..e3c26df3f3 100644 --- a/crates/db/db/src/keys.rs +++ b/crates/db/db/src/keys.rs @@ -16,14 +16,14 @@ //! Blockchain DB extras. -use std::{io::Write, ops}; +use std::io::Write; use common_types::{ engines::epoch::Transition as EpochTransition, receipt::TypedReceipt, BlockNumber, }; use ethereum_types::{H256, H264, U256}; -use heapsize::HeapSizeOf; use kvdb::PREFIX_LEN as DB_PREFIX_LEN; +use parity_util_mem::MallocSizeOf; use rlp; use rlp_derive::{RlpDecodable, RlpEncodable}; @@ -48,19 +48,17 @@ pub enum ExtrasIndex { fn with_index(hash: &H256, i: ExtrasIndex) -> H264 { let mut result = H264::default(); - result[0] = i as u8; - (*result)[1..].clone_from_slice(hash); + result.as_bytes_mut()[0] = i as u8; + result.as_bytes_mut()[1..].clone_from_slice(hash.as_bytes()); result } /// Wrapper for block number used as a DB key. pub struct BlockNumberKey([u8; 5]); -impl ops::Deref for BlockNumberKey { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 +impl AsRef<[u8]> for BlockNumberKey { + fn as_ref(&self) -> &[u8] { + &self.0[..] } } @@ -133,10 +131,8 @@ pub const EPOCH_KEY_PREFIX: &'static [u8; DB_PREFIX_LEN] = &[ /// Epoch transitions key pub struct EpochTransitionsKey([u8; EPOCH_KEY_LEN]); -impl ops::Deref for EpochTransitionsKey { - type Target = [u8]; - - fn deref(&self) -> &[u8] { +impl AsRef<[u8]> for EpochTransitionsKey { + fn as_ref(&self) -> &[u8] { &self.0[..] } } @@ -156,7 +152,7 @@ impl Key for u64 { } /// Familial details concerning a block -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MallocSizeOf)] pub struct BlockDetails { /// Block number pub number: BlockNumber, @@ -215,14 +211,8 @@ impl rlp::Decodable for BlockDetails { } } -impl HeapSizeOf for BlockDetails { - fn heap_size_of_children(&self) -> usize { - self.children.heap_size_of_children() - } -} - /// Represents address of certain transaction within block -#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable)] +#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable, MallocSizeOf)] pub struct TransactionAddress { /// Block hash pub block_hash: H256, @@ -230,14 +220,8 @@ pub struct TransactionAddress { pub index: usize, } -impl HeapSizeOf for TransactionAddress { - fn heap_size_of_children(&self) -> usize { - 0 - } -} - /// Contains all block receipts. -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] pub struct BlockReceipts { /// Block receipts pub receipts: Vec, @@ -262,12 +246,6 @@ impl BlockReceipts { } } -impl HeapSizeOf for BlockReceipts { - fn heap_size_of_children(&self) -> usize { - self.receipts.heap_size_of_children() - } -} - /// Candidate transitions to an epoch with specific number. #[derive(Clone, RlpEncodable, RlpDecodable)] pub struct EpochTransitions { diff --git a/crates/db/journaldb/Cargo.toml b/crates/db/journaldb/Cargo.toml index 9c331e14db..7bd8abf405 100644 --- a/crates/db/journaldb/Cargo.toml +++ b/crates/db/journaldb/Cargo.toml @@ -7,19 +7,19 @@ license = "GPL3" [dependencies] parity-bytes = "0.1" -ethereum-types = "0.4" +ethereum-types = "0.9.2" hash-db = "0.11.0" -heapsize = "0.4" keccak-hasher = { path = "../../util/keccak-hasher" } ethcore-db = { path = "../../db/db"} kvdb = "0.1" log = "0.4" memory-db = { path = "../memory-db" } +parity-util-mem = "0.7" parking_lot = "0.7" fastmap = { path = "../../util/fastmap" } -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } [dev-dependencies] env_logger = "0.5" -keccak-hash = "0.1" +keccak-hash = "0.5.0" kvdb-memorydb = "=0.1.0" diff --git a/crates/db/journaldb/src/archivedb.rs b/crates/db/journaldb/src/archivedb.rs index 79cafcd7bc..5d4ddfe443 100644 --- a/crates/db/journaldb/src/archivedb.rs +++ b/crates/db/journaldb/src/archivedb.rs @@ -63,7 +63,7 @@ impl ArchiveDB { fn payload(&self, key: &H256) -> Option { self.backing - .get(self.column, key) + .get(self.column, key.as_bytes()) .expect("Low-level database error. Some issue with your hard disk?") } } @@ -147,7 +147,7 @@ impl JournalDB for ArchiveDB { for i in self.overlay.drain() { let (key, (value, rc)) = i; if rc > 0 { - batch.put(self.column, &key, &value); + batch.put(self.column, key.as_bytes(), &value); inserts += 1; } if rc < 0 { @@ -180,18 +180,18 @@ impl JournalDB for ArchiveDB { for i in self.overlay.drain() { let (key, (value, rc)) = i; if rc > 0 { - if self.backing.get(self.column, &key)?.is_some() { + if self.backing.get(self.column, key.as_bytes())?.is_some() { return Err(error_key_already_exists(&key)); } - batch.put(self.column, &key, &value); + batch.put(self.column, key.as_bytes(), &value); inserts += 1; } if rc < 0 { assert!(rc == -1); - if self.backing.get(self.column, &key)?.is_none() { + if self.backing.get(self.column, key.as_bytes())?.is_none() { return Err(error_negatively_reference_hash(&key)); } - batch.delete(self.column, &key); + batch.delete(self.column, key.as_bytes()); deletes += 1; } } diff --git a/crates/db/journaldb/src/earlymergedb.rs b/crates/db/journaldb/src/earlymergedb.rs index 2d1c5be69d..4455ff43ef 100644 --- a/crates/db/journaldb/src/earlymergedb.rs +++ b/crates/db/journaldb/src/earlymergedb.rs @@ -29,25 +29,19 @@ use bytes::Bytes; use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; -use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use memory_db::*; +use parity_util_mem::MallocSizeOf; use parking_lot::RwLock; use rlp::{decode, encode}; use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView}; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] struct RefInfo { queue_refs: usize, in_archive: bool, } -impl HeapSizeOf for RefInfo { - fn heap_size_of_children(&self) -> usize { - 0 - } -} - #[derive(Clone, PartialEq, Eq)] enum RemoveFrom { Queue, @@ -133,7 +127,7 @@ impl EarlyMergeDB { } fn morph_key(key: &H256, index: u8) -> Bytes { - let mut ret = (&**key).to_owned(); + let mut ret = key.as_bytes().to_owned(); ret.push(index); ret } @@ -170,7 +164,7 @@ impl EarlyMergeDB { Entry::Vacant(entry) => { // this is the first entry for this node in the journal. let in_archive = backing - .get(col, h) + .get(col, h.as_bytes()) .expect("Low-level database error. Some issue with your hard disk?") .is_some(); if in_archive { @@ -182,7 +176,7 @@ impl EarlyMergeDB { //Self::reset_already_in(&h); assert!(!Self::is_already_in(backing, col, h)); trace!(target: "jdb.fine", " insert({}): New to queue, not in DB: Inserting into queue and DB", h); - batch.put(col, h, d); + batch.put(col, h.as_bytes(), d); } entry.insert(RefInfo { queue_refs: 1, @@ -258,7 +252,7 @@ impl EarlyMergeDB { } (1, false) => { entry.remove(); - batch.delete(col, h); + batch.delete(col, h.as_bytes()); trace!(target: "jdb.fine", " remove({}): Not in archive, only 1 ref in queue: Removing from queue and DB", h); } _ => panic!("Invalid value in refs: {:?}", entry.get()), @@ -267,7 +261,7 @@ impl EarlyMergeDB { Entry::Vacant(_entry) => { // Gets removed when moving from 1 to 0 additional refs. Should never be here at 0 additional refs. //assert!(!Self::is_already_in(db, &h)); - batch.delete(col, h); + batch.delete(col, h.as_bytes()); trace!(target: "jdb.fine", " remove({}): Not in queue - MUST BE IN ARCHIVE: Removing from DB", h); } } @@ -308,7 +302,7 @@ impl EarlyMergeDB { fn payload(&self, key: &H256) -> Option { self.backing - .get(self.column, key) + .get(self.column, key.as_bytes()) .expect("Low-level database error. Some issue with your hard disk?") } @@ -593,16 +587,16 @@ impl JournalDB for EarlyMergeDB { match rc { 0 => {} 1 => { - if self.backing.get(self.column, &key)?.is_some() { + if self.backing.get(self.column, key.as_bytes())?.is_some() { return Err(error_key_already_exists(&key)); } - batch.put(self.column, &key, &value) + batch.put(self.column, key.as_bytes(), &value) } -1 => { - if self.backing.get(self.column, &key)?.is_none() { + if self.backing.get(self.column, key.as_bytes())?.is_none() { return Err(error_negatively_reference_hash(&key)); } - batch.delete(self.column, &key) + batch.delete(self.column, key.as_bytes()) } _ => panic!("Attempted to inject invalid state."), } diff --git a/crates/db/journaldb/src/lib.rs b/crates/db/journaldb/src/lib.rs index 1365302f5a..4ac6da48c9 100644 --- a/crates/db/journaldb/src/lib.rs +++ b/crates/db/journaldb/src/lib.rs @@ -16,7 +16,6 @@ //! `JournalDB` interface and implementation. -extern crate heapsize; #[macro_use] extern crate log; @@ -28,6 +27,7 @@ extern crate keccak_hasher; extern crate kvdb; extern crate memory_db; extern crate parity_bytes as bytes; +extern crate parity_util_mem; extern crate parking_lot; extern crate rlp; diff --git a/crates/db/journaldb/src/overlaydb.rs b/crates/db/journaldb/src/overlaydb.rs index 5df5d0bc4f..c11db5a3b4 100644 --- a/crates/db/journaldb/src/overlaydb.rs +++ b/crates/db/journaldb/src/overlaydb.rs @@ -149,7 +149,7 @@ impl OverlayDB { /// Get the refs and value of the given key. fn payload(&self, key: &H256) -> Option { self.backing - .get(self.column, key) + .get(self.column, key.as_bytes()) .expect("Low-level database error. Some issue with your hard disk?") .map(|ref d| decode(d).expect("decoding db value failed")) } @@ -162,10 +162,10 @@ impl OverlayDB { payload: &Payload, ) -> bool { if payload.count > 0 { - batch.put(self.column, key, &encode(payload)); + batch.put(self.column, key.as_bytes(), &encode(payload)); false } else { - batch.delete(self.column, key); + batch.delete(self.column, key.as_bytes()); true } } diff --git a/crates/db/journaldb/src/overlayrecentdb.rs b/crates/db/journaldb/src/overlayrecentdb.rs index 84ae4b3ad3..cd7eb171ad 100644 --- a/crates/db/journaldb/src/overlayrecentdb.rs +++ b/crates/db/journaldb/src/overlayrecentdb.rs @@ -27,9 +27,9 @@ use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use fastmap::H256FastMap; use hash_db::HashDB; -use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use memory_db::*; +use parity_util_mem::MallocSizeOf; use parking_lot::RwLock; use rlp::{decode, encode, Decodable, DecoderError, Encodable, Rlp, RlpStream}; use util::DatabaseKey; @@ -132,19 +132,13 @@ struct JournalOverlay { cumulative_size: usize, // cumulative size of all entries. } -#[derive(PartialEq)] +#[derive(PartialEq, MallocSizeOf)] struct JournalEntry { id: H256, insertions: Vec, deletions: Vec, } -impl HeapSizeOf for JournalEntry { - fn heap_size_of_children(&self) -> usize { - self.insertions.heap_size_of_children() + self.deletions.heap_size_of_children() - } -} - impl Clone for OverlayRecentDB { fn clone(&self) -> OverlayRecentDB { OverlayRecentDB { @@ -181,7 +175,7 @@ impl OverlayRecentDB { fn payload(&self, key: &H256) -> Option { self.backing - .get(self.column, key) + .get(self.column, key.as_bytes()) .expect("Low-level database error. Some issue with your hard disk?") } @@ -256,7 +250,7 @@ impl OverlayRecentDB { #[inline] fn to_short_key(key: &H256) -> H256 { - let mut k = H256::new(); + let mut k = H256::zero(); k[0..DB_PREFIX_LEN].copy_from_slice(&key[0..DB_PREFIX_LEN]); k } @@ -453,7 +447,7 @@ impl JournalDB for OverlayRecentDB { // apply canon inserts first for (k, v) in canon_insertions { - batch.put(self.column, &k, &v); + batch.put(self.column, k.as_bytes(), &v); journal_overlay.pending_overlay.insert(to_short_key(&k), v); } // update the overlay @@ -468,7 +462,7 @@ impl JournalDB for OverlayRecentDB { // apply canon deletions for k in canon_deletions { if !journal_overlay.backing_overlay.contains(&to_short_key(&k)) { - batch.delete(self.column, &k); + batch.delete(self.column, k.as_bytes()); } } } @@ -496,12 +490,14 @@ impl JournalDB for OverlayRecentDB { match rc { 0 => {} - _ if rc > 0 => batch.put(self.column, &key, &value), + _ if rc > 0 => batch.put(self.column, key.as_bytes(), &value), -1 => { - if cfg!(debug_assertions) && self.backing.get(self.column, &key)?.is_none() { + if cfg!(debug_assertions) + && self.backing.get(self.column, key.as_bytes())?.is_none() + { return Err(error_negatively_reference_hash(&key)); } - batch.delete(self.column, &key) + batch.delete(self.column, key.as_bytes()) } _ => panic!("Attempted to inject invalid state ({})", rc), } diff --git a/crates/db/journaldb/src/refcounteddb.rs b/crates/db/journaldb/src/refcounteddb.rs index 73ac77945c..15b353c6e9 100644 --- a/crates/db/journaldb/src/refcounteddb.rs +++ b/crates/db/journaldb/src/refcounteddb.rs @@ -26,10 +26,10 @@ use super::{traits::JournalDB, LATEST_ERA_KEY}; use ethcore_db::{DBTransaction, DBValue, KeyValueDB}; use ethereum_types::H256; use hash_db::HashDB; -use heapsize::HeapSizeOf; use keccak_hasher::KeccakHasher; use memory_db::MemoryDB; use overlaydb::OverlayDB; +use parity_util_mem::{allocators::new_malloc_size_ops, MallocSizeOf}; use rlp::{decode, encode}; use util::{DatabaseKey, DatabaseValueRef, DatabaseValueView}; @@ -121,13 +121,14 @@ impl JournalDB for RefCountedDB { } fn get_sizes(&self, sizes: &mut BTreeMap) { + let mut ops = new_malloc_size_ops(); sizes.insert( String::from("db_ref_counted_inserts"), - self.inserts.heap_size_of_children(), + self.inserts.size_of(&mut ops), ); sizes.insert( String::from("db_ref_counted_removes"), - self.removes.heap_size_of_children(), + self.removes.size_of(&mut ops), ); } diff --git a/crates/db/memory-db/Cargo.toml b/crates/db/memory-db/Cargo.toml index 03af7f22aa..90c3cd8954 100644 --- a/crates/db/memory-db/Cargo.toml +++ b/crates/db/memory-db/Cargo.toml @@ -21,13 +21,15 @@ repository = "https://github.com/paritytech/parity-common" [[bench]] name = "bench" harness = false -[dependencies.hash-db] -version = "0.11.0" -[dependencies.heapsize] -version = "0.4" +[dependencies] +hash-db = "0.11.0" + [dev-dependencies.criterion] version = "0.2.8" [dev-dependencies.keccak-hasher] -version = "0.11.0" \ No newline at end of file +version = "0.11.0" + +[dependencies.parity-util-mem] +version = "0.7" diff --git a/crates/db/memory-db/src/lib.rs b/crates/db/memory-db/src/lib.rs index c7bf97eb83..7baa58cabc 100644 --- a/crates/db/memory-db/src/lib.rs +++ b/crates/db/memory-db/src/lib.rs @@ -15,12 +15,13 @@ //! Reference-counted memory-based `HashDB` implementation. extern crate hash_db; -extern crate heapsize; +extern crate parity_util_mem; + #[cfg(test)] extern crate keccak_hasher; use hash_db::{AsHashDB, AsPlainDB, HashDB, HashDBRef, Hasher as KeyHasher, PlainDB, PlainDBRef}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use std::{ collections::{hash_map::Entry, HashMap}, hash, mem, @@ -233,12 +234,15 @@ where impl MemoryDB where H: KeyHasher, - T: HeapSizeOf, + T: MallocSizeOf, { /// Returns the size of allocated heap memory pub fn mem_used(&self) -> usize { - 0 //self.data.heap_size_of_children() - // TODO Reenable above when HeapSizeOf supports arrays. + // TODO: figure out how to call malloc_size_of() + //let mut ops = new_malloc_size_ops(); + //self.data.size_of(&mut ops) + //self.data.malloc_size_of() + 0 } } diff --git a/crates/db/patricia-trie-ethereum/Cargo.toml b/crates/db/patricia-trie-ethereum/Cargo.toml index 1a2bdf3446..1064bdb303 100644 --- a/crates/db/patricia-trie-ethereum/Cargo.toml +++ b/crates/db/patricia-trie-ethereum/Cargo.toml @@ -9,12 +9,12 @@ license = "GPL-3.0" trie-db = "0.11.0" keccak-hasher = { version = "0.1.1", path = "../../util/keccak-hasher" } hash-db = "0.11.0" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } parity-bytes = "0.1" -ethereum-types = "0.4" +ethereum-types = "0.9.2" elastic-array = "0.10" [dev-dependencies] memory-db = "0.11.0" -keccak-hash = "0.1.2" +keccak-hash = "0.5.0" journaldb = { path = "../journaldb" } diff --git a/crates/db/patricia-trie-ethereum/src/lib.rs b/crates/db/patricia-trie-ethereum/src/lib.rs index 4dc474853e..d6828ee701 100644 --- a/crates/db/patricia-trie-ethereum/src/lib.rs +++ b/crates/db/patricia-trie-ethereum/src/lib.rs @@ -63,7 +63,7 @@ pub type RlpCodec = RlpNodeCodec; /// /// fn main() { /// let mut memdb = journaldb::new_memory_db(); -/// let mut root = H256::new(); +/// let mut root = H256::default(); /// TrieDBMut::new(&mut memdb, &mut root).insert(b"foo", b"bar").unwrap(); /// let t = TrieDB::new(&memdb, &root).unwrap(); /// assert!(t.contains(b"foo").unwrap()); @@ -107,7 +107,7 @@ pub type FatDB<'db> = trie::FatDB<'db, KeccakHasher, RlpCodec>; /// /// fn main() { /// let mut memdb = journaldb::new_memory_db(); -/// let mut root = H256::new(); +/// let mut root = H256::default(); /// let mut t = TrieDBMut::new(&mut memdb, &mut root); /// assert!(t.is_empty()); /// assert_eq!(*t.root(), KECCAK_NULL_RLP); diff --git a/crates/ethcore/Cargo.toml b/crates/ethcore/Cargo.toml index ab6eba7a0f..1d18f16489 100644 --- a/crates/ethcore/Cargo.toml +++ b/crates/ethcore/Cargo.toml @@ -14,9 +14,9 @@ crossbeam-utils = "0.6" eip-152 = { version = "0.1", path = "../util/EIP-152" } env_logger = { version = "0.5", optional = true } error-chain = { version = "0.12", default-features = false } -ethabi = "6.0" -ethabi-contract = "6.0" -ethabi-derive = "6.0" +ethabi = "12.0.0" +ethabi-contract = "11.0.0" +ethabi-derive = "12.0.0" ethash = { path = "../concensus/ethash" } ethcore-blockchain = { path = "./blockchain" } ethcore-bloom-journal = { path = "../db/bloom" } @@ -26,16 +26,15 @@ ethcore-db = { path = "../db/db" } ethcore-io = { path = "../runtime/io" } ethcore-miner = { path = "../concensus/miner" } ethcore-stratum = { path = "../concensus/miner/stratum", optional = true } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethjson = { path = "../ethjson" } ethkey = { path = "../accounts/ethkey" } evm = { path = "../vm/evm" } globset = "0.4" hash-db = "0.11.0" -heapsize = "0.4" itertools = "0.5" journaldb = { path = "../db/journaldb" } -keccak-hash = "0.1" +keccak-hash = "0.5.0" keccak-hasher = { path = "../util/keccak-hasher" } kvdb = "0.1" kvdb-memorydb = "0.1" @@ -50,14 +49,17 @@ memory-cache = { path = "../util/memory-cache" } memory-db = { path = "../db/memory-db" } num_cpus = "1.2" parity-bytes = "0.1" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } parity-snappy = "0.1" +parity-util-mem = "0.7" parking_lot = "0.7" trie-db = "0.11.0" patricia-trie-ethereum = { path = "../db/patricia-trie-ethereum" } -rand = "0.4" +rand = "0.7.3" +rand_xorshift = "0.2.0" rayon = "1.1" regex = "1.3.9" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } rlp_derive = { path = "../util/rlp-derive" } rustc-hex = "1.0" serde = "1.0" @@ -87,7 +89,7 @@ kvdb-rocksdb = "0.1.3" parity-runtime = { path = "../runtime/runtime" } rlp_compress = { path = "../util/rlp-compress" } tempdir = "0.3" -trie-standardmap = "0.1" +trie-standardmap = "0.15.2" [features] parity = ["work-notify", "price-info", "stratum"] diff --git a/crates/ethcore/benches/builtin.rs b/crates/ethcore/benches/builtin.rs index 6eaf50562f..47c6cd568f 100644 --- a/crates/ethcore/benches/builtin.rs +++ b/crates/ethcore/benches/builtin.rs @@ -25,10 +25,13 @@ extern crate ethereum_types; extern crate parity_bytes as bytes; extern crate rustc_hex; +use std::str::FromStr; + use bytes::BytesRef; use criterion::{Bencher, Criterion}; use ethcore::{ethereum::new_byzantium_test_machine, machine::EthereumMachine}; use ethcore_builtin::Builtin; +use ethereum_types::H160; use rustc_hex::FromHex; lazy_static! { @@ -45,7 +48,10 @@ impl<'a> BuiltinBenchmark<'a> { fn new(builtin_address: &'static str, input: &str, expected: &str) -> BuiltinBenchmark<'a> { let builtins = BYZANTIUM_MACHINE.builtins(); - let builtin = builtins.get(&builtin_address.into()).unwrap().clone(); + let builtin = builtins + .get(&H160::from_str(builtin_address).unwrap()) + .unwrap() + .clone(); let input = FromHex::from_hex(input).unwrap(); let expected = FromHex::from_hex(expected).unwrap(); diff --git a/crates/ethcore/blockchain/Cargo.toml b/crates/ethcore/blockchain/Cargo.toml index 75f3135a52..4c93eb8a49 100644 --- a/crates/ethcore/blockchain/Cargo.toml +++ b/crates/ethcore/blockchain/Cargo.toml @@ -12,17 +12,18 @@ ansi_term = "0.11" blooms-db = { path = "../../db/blooms-db" } common-types = { path = "../types" } ethcore-db = { path = "../../db/db" } -ethereum-types = "0.4" -heapsize = "0.4" +ethereum-types = "0.9.2" itertools = "0.5" -keccak-hash = "0.1" +keccak-hash = "0.5.0" kvdb = "0.1" log = "0.4" parity-bytes = "0.1" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +parity-util-mem = "0.7" parking_lot = "0.7" -rand = "0.6" +rand = "0.7.3" rayon = "1.1" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } rlp_compress = { path = "../../util/rlp-compress" } rlp_derive = { path = "../../util/rlp-derive" } triehash-ethereum = { version = "0.2", path = "../../util/triehash-ethereum" } diff --git a/crates/ethcore/blockchain/src/blockchain.rs b/crates/ethcore/blockchain/src/blockchain.rs index 1363304ff9..76778d34bb 100644 --- a/crates/ethcore/blockchain/src/blockchain.rs +++ b/crates/ethcore/blockchain/src/blockchain.rs @@ -49,10 +49,10 @@ use ethcore_db::{ CacheUpdatePolicy, Readable, Writable, }; use ethereum_types::{Bloom, BloomRef, H256, U256}; -use heapsize::HeapSizeOf; use itertools::Itertools; use log::{info, trace, warn}; use parity_bytes::Bytes; +use parity_util_mem::{allocators::new_malloc_size_ops, MallocSizeOf}; use parking_lot::{Mutex, RwLock}; use rayon::prelude::*; use rlp::RlpStream; @@ -324,9 +324,13 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let b = self.db.key_value().get(db::COL_HEADERS, hash).expect( - "Low level database error when fetching block header data. Some issue with disk?", - )?; + let b = self + .db + .key_value() + .get(db::COL_HEADERS, hash.as_bytes()) + .expect( + "Low level database error when fetching block header data. Some issue with disk?", + )?; let header = encoded::Header::new(decompress(&b, blocks_swapper()).into_vec()); let mut write = self.block_headers.write(); @@ -357,9 +361,13 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let b = self.db.key_value().get(db::COL_BODIES, hash).expect( - "Low level database error when fetching block body data. Some issue with disk?", - )?; + let b = self + .db + .key_value() + .get(db::COL_BODIES, hash.as_bytes()) + .expect( + "Low level database error when fetching block body data. Some issue with disk?", + )?; let body = encoded::Body::new(decompress(&b, blocks_swapper()).into_vec()); let mut write = self.block_bodies.write(); @@ -672,13 +680,21 @@ impl BlockChain { }; let mut batch = DBTransaction::new(); - batch.put(db::COL_HEADERS, &hash, block.header_rlp().as_raw()); - batch.put(db::COL_BODIES, &hash, &Self::block_to_body(genesis)); + batch.put( + db::COL_HEADERS, + hash.as_bytes(), + block.header_rlp().as_raw(), + ); + batch.put( + db::COL_BODIES, + hash.as_bytes(), + &Self::block_to_body(genesis), + ); batch.write(db::COL_EXTRA, &hash, &details); batch.write(db::COL_EXTRA, &header.number(), &hash); - batch.put(db::COL_EXTRA, b"best", &hash); + batch.put(db::COL_EXTRA, b"best", hash.as_bytes()); bc.db.key_value().write(batch).expect( "Low level database error when fetching 'best' block. Some issue with disk?", ); @@ -752,7 +768,7 @@ impl BlockChain { if hash != bc.genesis_hash() { info!("First new block calculated: {:?}", hash); let mut batch = db.key_value().transaction(); - batch.put(db::COL_EXTRA, b"first", &hash); + batch.put(db::COL_EXTRA, b"first", hash.as_bytes()); db.key_value().write(batch).expect("Low level database error when writing 'first' block. Some issue with disk?"); bc.first_block = Some(hash); } @@ -916,8 +932,8 @@ impl BlockChain { let compressed_body = compress(&Self::block_to_body(block.raw()), blocks_swapper()); // store block in db - batch.put(db::COL_HEADERS, &hash, &compressed_header); - batch.put(db::COL_BODIES, &hash, &compressed_body); + batch.put(db::COL_HEADERS, hash.as_bytes(), &compressed_header); + batch.put(db::COL_BODIES, hash.as_bytes(), &compressed_body); let maybe_parent = self.uncommitted_block_details(&block_parent_hash); @@ -1115,7 +1131,7 @@ impl BlockChain { *pending_best_ancient_block = Some(None); } else if block_number > ancient_number { trace!(target: "blockchain", "Updating the best ancient block to {}.", block_number); - batch.put(db::COL_EXTRA, b"ancient", &block_hash); + batch.put(db::COL_EXTRA, b"ancient", block_hash.as_bytes()); *pending_best_ancient_block = Some(Some(BestAncientBlock { hash: *block_hash, number: block_number, @@ -1301,8 +1317,8 @@ impl BlockChain { let compressed_body = compress(&Self::block_to_body(block.raw()), blocks_swapper()); // store block in db - batch.put(db::COL_HEADERS, &hash, &compressed_header); - batch.put(db::COL_BODIES, &hash, &compressed_body); + batch.put(db::COL_HEADERS, hash.as_bytes(), &compressed_header); + batch.put(db::COL_BODIES, hash.as_bytes(), &compressed_body); let info = self.block_info(&block.header_view(), route, &extras); @@ -1444,7 +1460,7 @@ impl BlockChain { { let mut best_block = self.pending_best_block.write(); if is_best && update.info.location != BlockLocation::Branch { - batch.put(db::COL_EXTRA, b"best", &update.info.hash); + batch.put(db::COL_EXTRA, b"best", update.info.hash.as_bytes()); *best_block = Some(BestBlock { total_difficulty: update.info.total_difficulty, header: update.block.decode_header(), @@ -1818,12 +1834,13 @@ impl BlockChain { /// Get current cache size. pub fn cache_size(&self) -> CacheSize { + let mut ops = new_malloc_size_ops(); CacheSize { - blocks: self.block_headers.read().heap_size_of_children() - + self.block_bodies.read().heap_size_of_children(), - block_details: self.block_details.read().heap_size_of_children(), - transaction_addresses: self.transaction_addresses.read().heap_size_of_children(), - block_receipts: self.block_receipts.read().heap_size_of_children(), + blocks: self.block_headers.read().size_of(&mut ops) + + self.block_bodies.read().size_of(&mut ops), + block_details: self.block_details.read().size_of(&mut ops), + transaction_addresses: self.transaction_addresses.read().size_of(&mut ops), + block_receipts: self.block_receipts.read().size_of(&mut ops), } } @@ -1870,12 +1887,13 @@ impl BlockChain { transaction_addresses.shrink_to_fit(); block_receipts.shrink_to_fit(); - block_headers.heap_size_of_children() - + block_bodies.heap_size_of_children() - + block_details.heap_size_of_children() - + block_hashes.heap_size_of_children() - + transaction_addresses.heap_size_of_children() - + block_receipts.heap_size_of_children() + let mut ops = new_malloc_size_ops(); + block_headers.size_of(&mut ops) + + block_bodies.size_of(&mut ops) + + block_details.size_of(&mut ops) + + block_hashes.size_of(&mut ops) + + transaction_addresses.size_of(&mut ops) + + block_receipts.size_of(&mut ops) }); } @@ -1918,14 +1936,14 @@ impl BlockChain { mod tests { use super::*; - use std::iter; + use std::{iter, str::FromStr}; use crate::generator::{BlockBuilder, BlockGenerator, BlockOptions}; use common_types::{ receipt::{LegacyReceipt, TransactionOutcome, TypedReceipt}, transaction::{Action, Transaction, TypedTransaction}, }; - use ethkey::Secret; + use crypto::publickey::Secret; use keccak_hash::keccak; use rustc_hex::FromHex; use tempdir::TempDir; @@ -2492,8 +2510,9 @@ mod tests { fn find_transaction_by_hash() { let genesis = "f901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0af81e09f8c46ca322193edfda764fa7e88e81923f802f1d325ec0b0308ac2cd0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008083023e38808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0".from_hex().unwrap(); let b1 = "f904a8f901faa0ce1f26f798dd03c8782d63b3e42e79a64eaea5694ea686ac5d7ce3df5171d1aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0a65c2364cd0f1542d761823dc0109c6b072f14c20459598c5455c274601438f4a070616ebd7ad2ed6fb7860cf7e9df00163842351c38a87cac2c1cb193895035a2a05c5b4fc43c2d45787f54e1ae7d27afdb4ad16dfc567c5692070d5c4556e0b1d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000183023ec683021536845685109780a029f07836e4e59229b3a065913afc27702642c683bba689910b2b2fd45db310d3888957e6d004a31802f902a7f85f800a8255f094aaaf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca0575da4e21b66fa764be5f74da9389e67693d066fb0d1312e19e17e501da00ecda06baf5a5327595f6619dfc2fcb3f2e6fb410b5810af3cb52d0e7508038e91a188f85f010a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba04fa966bf34b93abc1bcd665554b7f316b50f928477b50be0f3285ead29d18c5ba017bba0eeec1625ab433746955e125d46d80b7fdc97386c51266f842d8e02192ef85f020a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca004377418ae981cc32b1312b4a427a1d69a821b28db8584f5f2bd8c6d42458adaa053a1dba1af177fac92f3b6af0a9fa46a22adf56e686c93794b6a012bf254abf5f85f030a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ca04fe13febd28a05f4fcb2f451d7ddc2dda56486d9f8c79a62b0ba4da775122615a0651b2382dd402df9ebc27f8cb4b2e0f3cea68dda2dca0ee9603608f0b6f51668f85f040a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba078e6a0ba086a08f8450e208a399bb2f2d2a0d984acd2517c7c7df66ccfab567da013254002cd45a97fac049ae00afbc43ed0d9961d0c56a3b2382c80ce41c198ddf85f050a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba0a7174d8f43ea71c8e3ca9477691add8d80ac8e0ed89d8d8b572041eef81f4a54a0534ea2e28ec4da3b5b944b18c51ec84a5cf35f5b3343c5fb86521fd2d388f506f85f060a82520894bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba034bd04065833536a10c77ee2a43a5371bc6d34837088b861dd9d4b7f44074b59a078807715786a13876d3455716a6b9cb2186b7a4887a5c31160fc877454958616c0".from_hex().unwrap(); - let b1_hash: H256 = - "f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3".into(); + let b1_hash = + H256::from_str("f53f268d23a71e85c7d6d83a9504298712b84c1a2ba220441c86eeda0bf0b6e3") + .unwrap(); let db = new_db(); let bc = new_chain(encoded::Block::new(genesis), db.clone()); @@ -2745,11 +2764,11 @@ mod tests { #[test] fn test_bloom_filter_simple() { - let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); + let bloom_b1 = Bloom::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap(); - let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_b2 = Bloom::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let bloom_ba: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_ba = Bloom::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let genesis = BlockBuilder::genesis(); let b1 = genesis.add_block_with(|| BlockOptions { @@ -2813,11 +2832,11 @@ mod tests { #[test] fn test_insert_unordered() { - let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); + let bloom_b1 = Bloom::from_str("00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000").unwrap(); - let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_b2 = Bloom::from_str("00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let bloom_b3: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_b3 = Bloom::from_str("00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); let genesis = BlockBuilder::genesis(); let b1 = genesis.add_block_with_bloom(bloom_b1); diff --git a/crates/ethcore/blockchain/src/import_route.rs b/crates/ethcore/blockchain/src/import_route.rs index 126b5068a4..6519eb653f 100644 --- a/crates/ethcore/blockchain/src/import_route.rs +++ b/crates/ethcore/blockchain/src/import_route.rs @@ -70,7 +70,7 @@ impl From for ImportRoute { mod tests { use super::ImportRoute; use crate::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData}; - use ethereum_types::{H256, U256}; + use ethereum_types::{BigEndianHash, U256}; #[test] fn import_route_none() { @@ -87,7 +87,7 @@ mod tests { #[test] fn import_route_branch() { let info = BlockInfo { - hash: H256::from(U256::from(1)), + hash: BigEndianHash::from_uint(&U256::from(1)), number: 0, total_difficulty: U256::from(0), location: BlockLocation::Branch, @@ -98,7 +98,7 @@ mod tests { ImportRoute { retracted: vec![], enacted: vec![], - omitted: vec![H256::from(U256::from(1))], + omitted: vec![BigEndianHash::from_uint(&U256::from(1))], } ); } @@ -106,7 +106,7 @@ mod tests { #[test] fn import_route_canon_chain() { let info = BlockInfo { - hash: H256::from(U256::from(1)), + hash: BigEndianHash::from_uint(&U256::from(1)), number: 0, total_difficulty: U256::from(0), location: BlockLocation::CanonChain, @@ -116,7 +116,7 @@ mod tests { ImportRoute::from(info), ImportRoute { retracted: vec![], - enacted: vec![H256::from(U256::from(1))], + enacted: vec![BigEndianHash::from_uint(&U256::from(1))], omitted: vec![], } ); @@ -125,21 +125,30 @@ mod tests { #[test] fn import_route_branch_becoming_canon_chain() { let info = BlockInfo { - hash: H256::from(U256::from(2)), + hash: BigEndianHash::from_uint(&U256::from(2)), number: 0, total_difficulty: U256::from(0), location: BlockLocation::BranchBecomingCanonChain(BranchBecomingCanonChainData { - ancestor: H256::from(U256::from(0)), - enacted: vec![H256::from(U256::from(1))], - retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))], + ancestor: BigEndianHash::from_uint(&U256::from(0)), + enacted: vec![BigEndianHash::from_uint(&U256::from(1))], + retracted: vec![ + BigEndianHash::from_uint(&U256::from(3)), + BigEndianHash::from_uint(&U256::from(4)), + ], }), }; assert_eq!( ImportRoute::from(info), ImportRoute { - retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))], - enacted: vec![H256::from(U256::from(1)), H256::from(U256::from(2))], + retracted: vec![ + BigEndianHash::from_uint(&U256::from(3)), + BigEndianHash::from_uint(&U256::from(4)) + ], + enacted: vec![ + BigEndianHash::from_uint(&U256::from(1)), + BigEndianHash::from_uint(&U256::from(2)) + ], omitted: vec![], } ); diff --git a/crates/ethcore/blockchain/src/lib.rs b/crates/ethcore/blockchain/src/lib.rs index 943bc3c89a..38284cd40c 100644 --- a/crates/ethcore/blockchain/src/lib.rs +++ b/crates/ethcore/blockchain/src/lib.rs @@ -18,6 +18,8 @@ #![warn(missing_docs)] +extern crate parity_crypto as crypto; + mod best_block; mod block_info; mod blockchain; diff --git a/crates/ethcore/service/Cargo.toml b/crates/ethcore/service/Cargo.toml index cd0f9e1122..bab7124834 100644 --- a/crates/ethcore/service/Cargo.toml +++ b/crates/ethcore/service/Cargo.toml @@ -11,7 +11,7 @@ ethcore = { path = ".." } ethcore-blockchain = { path = "../blockchain" } ethcore-io = { path = "../../runtime/io" } ethcore-sync = { path = "../sync" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" kvdb = "0.1" log = "0.4" trace-time = "0.1" diff --git a/crates/ethcore/src/account_db.rs b/crates/ethcore/src/account_db.rs index d0464cf2e6..b3e50b1635 100644 --- a/crates/ethcore/src/account_db.rs +++ b/crates/ethcore/src/account_db.rs @@ -31,8 +31,8 @@ use ethereum_types::Address; fn combine_key<'a>(address_hash: &'a H256, key: &'a H256) -> H256 { let mut dst = key.clone(); { - let last_src: &[u8] = &*address_hash; - let last_dst: &mut [u8] = &mut *dst; + let last_src: &[u8] = address_hash.as_bytes(); + let last_dst: &mut [u8] = dst.as_bytes_mut(); for (k, a) in last_dst[12..].iter_mut().zip(&last_src[12..]) { *k ^= *a } diff --git a/crates/ethcore/src/block.rs b/crates/ethcore/src/block.rs index eee50c46d9..9c31849f6b 100644 --- a/crates/ethcore/src/block.rs +++ b/crates/ethcore/src/block.rs @@ -662,7 +662,7 @@ mod tests { db, parent, last_hashes, - Address::new(), + Address::default(), (3141562.into(), 31415620.into()), vec![], false, diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 5f183ba047..46b8eb4190 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -40,7 +40,7 @@ use ethereum_types::{Address, H256, H264, U256}; use hash::keccak; use itertools::Itertools; use parking_lot::{Mutex, RwLock}; -use rand::OsRng; +use rand::rngs::OsRng; use rlp::{PayloadInfo, Rlp}; use rustc_hex::FromHex; use trie::{Trie, TrieFactory, TrieSpec}; @@ -541,7 +541,7 @@ impl Importer { { trace_time!("import_old_block"); // verify the block, passing the chain for updating the epoch verifier. - let mut rng = OsRng::new()?; + let mut rng = OsRng; self.ancient_verifier .verify(&mut rng, &unverified.header, &chain)?; @@ -1641,8 +1641,8 @@ impl BlockChainReset for Client { best_block_hash = current_header.parent_hash(); let (number, hash) = (current_header.number(), current_header.hash()); - batch.delete(::db::COL_HEADERS, &hash); - batch.delete(::db::COL_BODIES, &hash); + batch.delete(::db::COL_HEADERS, hash.as_bytes()); + batch.delete(::db::COL_BODIES, hash.as_bytes()); Writable::delete::(&mut batch, ::db::COL_EXTRA, &hash); Writable::delete::(&mut batch, ::db::COL_EXTRA, &number); @@ -1673,7 +1673,7 @@ impl BlockChainReset for Client { best_block_details.children.retain(|h| *h != *last_hash); batch.write(::db::COL_EXTRA, &best_block_hash, &best_block_details); // update the new best block hash - batch.put(::db::COL_EXTRA, b"best", &best_block_hash); + batch.put(::db::COL_EXTRA, b"best", best_block_hash.as_bytes()); self.db .read() @@ -2203,7 +2203,7 @@ impl BlockChainClient for Client { }; if let Some(after) = after { - if let Err(e) = iter.seek(after) { + if let Err(e) = iter.seek(after.as_bytes()) { trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e); } else { // Position the iterator after the `after` element @@ -2261,7 +2261,7 @@ impl BlockChainClient for Client { }; if let Some(after) = after { - if let Err(e) = iter.seek(after) { + if let Err(e) = iter.seek(after.as_bytes()) { trace!(target: "fatdb", "list_storage: Couldn't seek the DB: {:?}", e); } else { // Position the iterator after the `after` element @@ -3404,6 +3404,7 @@ impl PrometheusMetrics for Client { #[cfg(test)] mod tests { use blockchain::{BlockProvider, ExtrasInsert}; + use ethereum_types::{H160, H256}; use spec::Spec; use test_helpers::generate_dummy_client_with_spec_and_data; @@ -3484,7 +3485,7 @@ mod tests { #[test] fn should_return_correct_log_index() { use super::transaction_receipt; - use ethkey::KeyPair; + use crypto::publickey::KeyPair; use hash::keccak; use types::{ log_entry::{LocalizedLogEntry, LogEntry}, @@ -3493,19 +3494,19 @@ mod tests { }; // given - let key = KeyPair::from_secret_slice(&keccak("test")).unwrap(); + let key = KeyPair::from_secret_slice(keccak("test").as_bytes()).unwrap(); let secret = key.secret(); let machine = ::ethereum::new_frontier_test_machine(); let block_number = 1; - let block_hash = 5.into(); - let state_root = 99.into(); + let block_hash = H256::from_low_u64_be(5); + let state_root = H256::from_low_u64_be(99); let gas_used = 10.into(); let raw_tx = TypedTransaction::Legacy(Transaction { nonce: 0.into(), gas_price: 0.into(), gas: 21000.into(), - action: Action::Call(10.into()), + action: Action::Call(H160::from_low_u64_be(10)), value: 0.into(), data: vec![], }); @@ -3519,12 +3520,12 @@ mod tests { }; let logs = vec![ LogEntry { - address: 5.into(), + address: H160::from_low_u64_be(5), topics: vec![], data: vec![], }, LogEntry { - address: 15.into(), + address: H160::from_low_u64_be(15), topics: vec![], data: vec![], }, diff --git a/crates/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs index c0f62aff64..e59b186314 100644 --- a/crates/ethcore/src/client/test_client.rs +++ b/crates/ethcore/src/client/test_client.rs @@ -18,6 +18,7 @@ use std::{ collections::{BTreeMap, HashMap}, + str::FromStr, sync::{ atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrder}, Arc, @@ -26,10 +27,10 @@ use std::{ use blockchain::{BlockReceipts, TreeRoute}; use bytes::Bytes; +use crypto::publickey::{Generator, Random}; use db::{COL_STATE, NUM_COLUMNS}; use ethcore_miner::pool::VerifiedTransaction; use ethereum_types::{Address, H256, U256}; -use ethkey::{Generator, Random}; use ethtrie; use hash::keccak; use itertools::Itertools; @@ -174,9 +175,9 @@ impl TestBlockChainClient { let mut client = TestBlockChainClient { blocks: RwLock::new(HashMap::new()), numbers: RwLock::new(HashMap::new()), - genesis_hash: H256::new(), + genesis_hash: H256::default(), extra_data: extra_data, - last_hash: RwLock::new(H256::new()), + last_hash: RwLock::new(H256::default()), difficulty: RwLock::new(spec.genesis_header().difficulty().clone()), balances: RwLock::new(HashMap::new()), nonces: RwLock::new(HashMap::new()), @@ -293,7 +294,7 @@ impl TestBlockChainClient { _ => 1, }; let mut txs = RlpStream::new_list(num_transactions); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let mut nonce = U256::zero(); for _ in 0..num_transactions { @@ -340,7 +341,7 @@ impl TestBlockChainClient { .unwrap() .decode() .expect("decoding failed"); - header.set_parent_hash(H256::from(42)); + header.set_parent_hash(H256::from_low_u64_be(42)); let mut rlp = RlpStream::new_list(3); rlp.append(&header); rlp.append_raw(&::rlp::NULL_RLP, 1); @@ -370,7 +371,7 @@ impl TestBlockChainClient { /// Inserts a transaction with given gas price to miners transactions queue. pub fn insert_transaction_with_gas_price_to_queue(&self, gas_price: U256) -> H256 { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let tx = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(100), @@ -753,7 +754,7 @@ impl BlockChainClient for TestBlockChainClient { .clone() .unwrap() .into_iter() - .map(|t| t.transaction_hash.unwrap_or(H256::new())) + .map(|t| t.transaction_hash.unwrap_or(H256::default())) .zip(self.execution_result.read().clone().unwrap().into_iter()), )) } @@ -784,7 +785,7 @@ impl BlockChainClient for TestBlockChainClient { .read() .get(&(address.clone(), position.clone())) .cloned() - .unwrap_or_else(H256::new), + .unwrap_or_else(H256::default), ), _ => None, } @@ -902,7 +903,7 @@ impl BlockChainClient for TestBlockChainClient { // works only if blocks are one after another 1 -> 2 -> 3 fn tree_route(&self, from: &H256, to: &H256) -> Option { Some(TreeRoute { - ancestor: H256::new(), + ancestor: H256::default(), index: 0, blocks: { let numbers_read = self.numbers.read(); @@ -943,7 +944,10 @@ impl BlockChainClient for TestBlockChainClient { fn block_receipts(&self, hash: &H256) -> Option { // starts with 'f' ? - if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { + if *hash + > H256::from_str("f000000000000000000000000000000000000000000000000000000000000000") + .unwrap() + { let receipt = BlockReceipts::new(vec![TypedReceipt::new( TypedTxId::Legacy, LegacyReceipt::new( diff --git a/crates/ethcore/src/engines/authority_round/mod.rs b/crates/ethcore/src/engines/authority_round/mod.rs index dee1a03c0e..9afdedfc03 100644 --- a/crates/ethcore/src/engines/authority_round/mod.rs +++ b/crates/ethcore/src/engines/authority_round/mod.rs @@ -36,6 +36,7 @@ use super::{ }; use block::*; use client::{traits::ForceUpdateSealing, EngineClient}; +use crypto::publickey::{self, Signature}; use engines::{ block_reward, block_reward::{BlockRewardContract, RewardKind}, @@ -43,8 +44,8 @@ use engines::{ }; use error::{BlockError, Error, ErrorKind}; use ethereum_types::{Address, H256, H520, U128, U256}; + use ethjson::{self, uint::Uint}; -use ethkey::{self, Signature}; use hash::keccak; use io::{IoContext, IoHandler, IoService, TimerToken}; use itertools::{self, Itertools}; @@ -378,14 +379,14 @@ impl EmptyStep { let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); let correct_proposer = step_proposer(validators, &self.parent_hash, self.step); - ethkey::verify_address(&correct_proposer, &self.signature.into(), &message) + publickey::verify_address(&correct_proposer, &self.signature.into(), &message) .map_err(|e| e.into()) } fn author(&self) -> Result { let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); - let public = ethkey::recover(&self.signature.into(), &message)?; - Ok(ethkey::public_to_address(&public)) + let public = publickey::recover(&self.signature.into(), &message)?; + Ok(publickey::public_to_address(&public)) } fn sealed(&self) -> SealedEmptyStep { @@ -583,7 +584,7 @@ impl super::EpochVerifier for EpochVerifier { fn header_seal_hash(header: &Header, empty_steps_rlp: Option<&[u8]>) -> H256 { match empty_steps_rlp { Some(empty_steps_rlp) => { - let mut message = header.bare_hash().to_vec(); + let mut message = header.bare_hash().as_bytes().to_vec(); message.extend_from_slice(empty_steps_rlp); keccak(message) } @@ -717,7 +718,7 @@ fn verify_external( }; let header_seal_hash = header_seal_hash(header, empty_steps_rlp); - !ethkey::verify_address(&correct_proposer, &proposer_signature, &header_seal_hash)? + !publickey::verify_address(&correct_proposer, &proposer_signature, &header_seal_hash)? }; if is_invalid_proposer { @@ -1312,7 +1313,7 @@ impl Engine for AuthorityRound { } let mut fields = - vec![encode(&step), encode(&(&H520::from(signature) as &[u8]))]; + vec![encode(&step), encode(&(H520::from(signature).as_bytes()))]; if let Some(empty_steps_rlp) = empty_steps_rlp { fields.push(empty_steps_rlp); @@ -1738,7 +1739,7 @@ impl Engine for AuthorityRound { .signer .read() .as_ref() - .ok_or(ethkey::Error::InvalidAddress)? + .ok_or(publickey::Error::InvalidAddress)? .sign(hash)?) } @@ -1782,13 +1783,13 @@ mod tests { }; use accounts::AccountProvider; use block::*; + use crypto::publickey::Signature; use engines::{ validator_set::{SimpleList, TestSet}, Engine, EngineError, EthEngine, Seal, }; use error::{Error, ErrorKind}; use ethereum_types::{Address, H256, H520, U256}; - use ethkey::Signature; use hash::keccak; use rlp::encode; use spec::Spec; @@ -2187,7 +2188,7 @@ mod tests { fn set_empty_steps_seal( header: &mut Header, step: u64, - block_signature: ðkey::Signature, + block_signature: &crypto::publickey::Signature, empty_steps: &[SealedEmptyStep], ) { header.set_seal(vec![ @@ -2539,7 +2540,7 @@ mod tests { // empty step with invalid step let empty_steps = vec![SealedEmptyStep { - signature: 0.into(), + signature: H520::zero(), step: 2, }]; set_empty_steps_seal(&mut header, 2, &signature, &empty_steps); @@ -2551,7 +2552,7 @@ mod tests { // empty step with invalid signature let empty_steps = vec![SealedEmptyStep { - signature: 0.into(), + signature: H520::zero(), step: 1, }]; set_empty_steps_seal(&mut header, 2, &signature, &empty_steps); @@ -2703,7 +2704,7 @@ mod tests { p.maximum_empty_steps = 0; }); - let parent_hash: H256 = 1.into(); + let parent_hash = H256::from_low_u64_be(1); let signature = H520::default(); let step = |step: u64| EmptyStep { step, diff --git a/crates/ethcore/src/engines/basic_authority.rs b/crates/ethcore/src/engines/basic_authority.rs index 8164e65a6b..f1b9e7baf9 100644 --- a/crates/ethcore/src/engines/basic_authority.rs +++ b/crates/ethcore/src/engines/basic_authority.rs @@ -19,11 +19,11 @@ use super::validator_set::{new_validator_set, SimpleList, ValidatorSet}; use block::*; use client::EngineClient; +use crypto::publickey::{self, Signature}; use engines::{signer::EngineSigner, ConstructedVerifier, Engine, EngineError, Seal}; use error::{BlockError, Error}; use ethereum_types::{H256, H520}; use ethjson; -use ethkey::{self, Signature}; use machine::{AuxiliaryData, Call, EthereumMachine}; use parking_lot::RwLock; use std::sync::Weak; @@ -59,7 +59,8 @@ fn verify_external(header: &Header, validators: &dyn ValidatorSet) -> Result<(), // Check if the signature belongs to a validator, can depend on parent state. let sig = Rlp::new(&header.seal()[0]).as_val::()?; - let signer = ethkey::public_to_address(ðkey::recover(&sig.into(), &header.bare_hash())?); + let signer = + publickey::public_to_address(&publickey::recover(&sig.into(), &header.bare_hash())?); if *header.author() != signer { return Err(EngineError::NotAuthorized(*header.author()).into()); @@ -114,7 +115,7 @@ impl Engine for BasicAuthority { if self.validators.contains(header.parent_hash(), author) { // account should be pernamently unlocked, otherwise sealing will fail if let Ok(signature) = self.sign(header.bare_hash()) { - return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8]))]); + return Seal::Regular(vec![::rlp::encode(&(H520::from(signature).as_bytes()))]); } else { trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable"); } @@ -205,7 +206,7 @@ impl Engine for BasicAuthority { .signer .read() .as_ref() - .ok_or_else(|| ethkey::Error::InvalidAddress)? + .ok_or_else(|| publickey::Error::InvalidAddress)? .sign(hash)?) } diff --git a/crates/ethcore/src/engines/block_reward.rs b/crates/ethcore/src/engines/block_reward.rs index 1cdd2cc959..90c05a8a7e 100644 --- a/crates/ethcore/src/engines/block_reward.rs +++ b/crates/ethcore/src/engines/block_reward.rs @@ -196,12 +196,13 @@ pub fn apply_block_rewards( #[cfg(test)] mod test { use client::PrepareOpenBlock; - use ethereum_types::U256; + use ethereum_types::{H160, U256}; use spec::Spec; use test_helpers::generate_dummy_client_with_spec; use super::{BlockRewardContract, RewardKind}; use engines::SystemOrCodeCallKind; + use std::str::FromStr; #[test] fn block_reward_contract() { @@ -211,13 +212,13 @@ mod test { // the spec has a block reward contract defined at the given address let block_reward_contract = BlockRewardContract::new_from_address( - "0000000000000000000000000000000000000042".into(), + H160::from_str("0000000000000000000000000000000000000042").unwrap(), ); let mut call = |to, data| { let mut block = client .prepare_open_block( - "0000000000000000000000000000000000000001".into(), + H160::from_str("0000000000000000000000000000000000000001").unwrap(), (3141562.into(), 31415620.into()), vec![], ) @@ -244,15 +245,15 @@ mod test { // the contract rewards (1000 + kind) for each benefactor let beneficiaries = vec![ ( - "0000000000000000000000000000000000000033".into(), + H160::from_str("0000000000000000000000000000000000000033").unwrap(), RewardKind::Author, ), ( - "0000000000000000000000000000000000000034".into(), + H160::from_str("0000000000000000000000000000000000000034").unwrap(), RewardKind::Uncle(1), ), ( - "0000000000000000000000000000000000000035".into(), + H160::from_str("0000000000000000000000000000000000000035").unwrap(), RewardKind::EmptyStep, ), ]; @@ -262,15 +263,15 @@ mod test { .unwrap(); let expected = vec![ ( - "0000000000000000000000000000000000000033".into(), + H160::from_str("0000000000000000000000000000000000000033").unwrap(), U256::from(1000), ), ( - "0000000000000000000000000000000000000034".into(), + H160::from_str("0000000000000000000000000000000000000034").unwrap(), U256::from(1000 + 101), ), ( - "0000000000000000000000000000000000000035".into(), + H160::from_str("0000000000000000000000000000000000000035").unwrap(), U256::from(1000 + 2), ), ]; diff --git a/crates/ethcore/src/engines/clique/block_state.rs b/crates/ethcore/src/engines/clique/block_state.rs index 424911cf9c..53565693dc 100644 --- a/crates/ethcore/src/engines/clique/block_state.rs +++ b/crates/ethcore/src/engines/clique/block_state.rs @@ -221,7 +221,7 @@ impl CliqueBlockState { }))? } - let nonce: H64 = decoded_seal[1].into(); + let nonce = H64::from_slice(decoded_seal[1]); self.update_signers_on_vote( VoteType::from_nonce(nonce)?, creator, diff --git a/crates/ethcore/src/engines/clique/mod.rs b/crates/ethcore/src/engines/clique/mod.rs index 1839f1f827..9952e87a17 100644 --- a/crates/ethcore/src/engines/clique/mod.rs +++ b/crates/ethcore/src/engines/clique/mod.rs @@ -68,13 +68,13 @@ use std::{ use super::signer::EngineSigner; use block::ExecutedBlock; use client::{traits::ForceUpdateSealing, BlockId, EngineClient}; +use crypto::publickey::Signature; use engines::{ clique::util::{extract_signers, recover_creator}, Engine, EngineError, Seal, }; use error::{BlockError, Error}; use ethereum_types::{Address, H160, H256, H64, U256}; -use ethkey::Signature; use hash::KECCAK_EMPTY_LIST_RLP; use itertools::Itertools; use lru_cache::LruCache; @@ -590,7 +590,7 @@ impl Engine for Clique { if is_checkpoint && *header.author() != NULL_AUTHOR { return Err(EngineError::CliqueWrongAuthorCheckpoint(Mismatch { - expected: 0.into(), + expected: H160::zero(), found: *header.author(), }))?; } @@ -603,8 +603,8 @@ impl Engine for Clique { }))? } - let mixhash: H256 = seal_fields[0].into(); - let nonce: H64 = seal_fields[1].into(); + let mixhash = H256::from_slice(seal_fields[0]); + let nonce = H64::from_slice(seal_fields[1]); // Nonce must be 0x00..0 or 0xff..f if nonce != NONCE_DROP_VOTE && nonce != NONCE_AUTH_VOTE { diff --git a/crates/ethcore/src/engines/clique/tests.rs b/crates/ethcore/src/engines/clique/tests.rs index a243a38931..22135731f4 100644 --- a/crates/ethcore/src/engines/clique/tests.rs +++ b/crates/ethcore/src/engines/clique/tests.rs @@ -18,10 +18,10 @@ use super::*; use block::*; +use crypto::publickey::{KeyPair, Secret}; use engines::Engine; use error::{Error, ErrorKind}; use ethereum_types::{Address, H256}; -use ethkey::{KeyPair, Secret}; use state_db::StateDB; use test_helpers::get_temp_state_db; @@ -72,10 +72,10 @@ impl CliqueTester { let mut extra_data = vec![0; VANITY_LENGTH]; for &signer in SIGNER_TAGS.iter() { - let secret = Secret::from(H256::from(signer as u64)); + let secret = Secret::from(H256::from_low_u64_be(signer as u64)); let keypair = KeyPair::from_secret(secret).unwrap(); if initial_signers.contains(&signer) { - extra_data.extend(&*keypair.address()); + extra_data.extend(keypair.address().as_bytes()); } signers.insert(signer, keypair); } @@ -167,7 +167,7 @@ impl CliqueTester { CliqueBlockType::Checkpoint => { let signers = self.clique.state(&last_header).unwrap().signers().clone(); for signer in signers { - extra_data.extend(&*signer); + extra_data.extend(signer.as_bytes()); } } CliqueBlockType::Vote(v) => seal = v.as_rlp(), @@ -203,7 +203,8 @@ impl CliqueTester { b.header.set_difficulty(difficulty); b.header.set_seal(seal); - let sign = ethkey::sign(self.signers[&signer].secret(), &b.header.hash()).unwrap(); + let sign = + crypto::publickey::sign(self.signers[&signer].secret(), &b.header.hash()).unwrap(); let mut extra_data = b.header.extra_data().clone(); extra_data.extend_from_slice(&*sign); b.header.set_extra_data(extra_data); diff --git a/crates/ethcore/src/engines/clique/util.rs b/crates/ethcore/src/engines/clique/util.rs index 81751fa045..a5fd9f14a8 100644 --- a/crates/ethcore/src/engines/clique/util.rs +++ b/crates/ethcore/src/engines/clique/util.rs @@ -16,13 +16,13 @@ use std::collections::BTreeSet; +use crypto::publickey::{public_to_address, recover as ec_recover, Signature}; use engines::{ clique::{ADDRESS_LENGTH, NULL_MIXHASH, NULL_NONCE, SIGNATURE_LENGTH, VANITY_LENGTH}, EngineError, }; use error::Error; -use ethereum_types::{Address, H256}; -use ethkey::{public_to_address, recover as ec_recover, Signature}; +use ethereum_types::{Address, H160, H256}; use lru_cache::LruCache; use parking_lot::RwLock; use rlp::encode; @@ -106,7 +106,7 @@ pub fn extract_signers(header: &Header) -> Result, Error> { .map(|i| { let start = i * ADDRESS_LENGTH; let end = start + ADDRESS_LENGTH; - signers_raw[start..end].into() + H160::from_slice(&signers_raw[start..end]) }) .collect(); @@ -115,5 +115,8 @@ pub fn extract_signers(header: &Header) -> Result, Error> { /// Retrieve `null_seal` pub fn null_seal() -> Vec> { - vec![encode(&NULL_MIXHASH.to_vec()), encode(&NULL_NONCE.to_vec())] + vec![ + encode(&NULL_MIXHASH.as_bytes().to_vec()), + encode(&NULL_NONCE.as_bytes().to_vec()), + ] } diff --git a/crates/ethcore/src/engines/mod.rs b/crates/ethcore/src/engines/mod.rs index 7c49fea562..f2c2f66aec 100644 --- a/crates/ethcore/src/engines/mod.rs +++ b/crates/ethcore/src/engines/mod.rs @@ -60,8 +60,8 @@ use vm::{ActionValue, CallType, CreateContractAddress, EnvInfo, Schedule}; use block::ExecutedBlock; use bytes::Bytes; +use crypto::publickey::Signature; use ethereum_types::{Address, H256, H64, U256}; -use ethkey::Signature; use machine::{self, AuxiliaryData, AuxiliaryRequest, Machine}; use types::ancestry_action::AncestryAction; use unexpected::{Mismatch, OutOfBounds}; diff --git a/crates/ethcore/src/engines/signer.rs b/crates/ethcore/src/engines/signer.rs index d4a31802df..74fb61f9c4 100644 --- a/crates/ethcore/src/engines/signer.rs +++ b/crates/ethcore/src/engines/signer.rs @@ -16,28 +16,28 @@ //! A signer used by Engines which need to sign messages. +use crypto::publickey::{self, Signature}; use ethereum_types::{Address, H256}; -use ethkey::{self, Signature}; /// Everything that an Engine needs to sign messages. pub trait EngineSigner: Send + Sync { /// Sign a consensus message hash. - fn sign(&self, hash: H256) -> Result; + fn sign(&self, hash: H256) -> Result; /// Signing address fn address(&self) -> Address; } /// Creates a new `EngineSigner` from given key pair. -pub fn from_keypair(keypair: ethkey::KeyPair) -> Box { +pub fn from_keypair(keypair: publickey::KeyPair) -> Box { Box::new(Signer(keypair)) } -struct Signer(ethkey::KeyPair); +struct Signer(publickey::KeyPair); impl EngineSigner for Signer { - fn sign(&self, hash: H256) -> Result { - ethkey::sign(self.0.secret(), &hash) + fn sign(&self, hash: H256) -> Result { + publickey::sign(self.0.secret(), &hash) } fn address(&self) -> Address { @@ -47,26 +47,29 @@ impl EngineSigner for Signer { #[cfg(test)] mod test_signer { + + extern crate ethkey; + use std::sync::Arc; + use self::ethkey::Password; use accounts::{self, AccountProvider, SignError}; - use ethkey::Password; use super::*; impl EngineSigner for (Arc, Address, Password) { - fn sign(&self, hash: H256) -> Result { + fn sign(&self, hash: H256) -> Result { match self.0.sign(self.1, Some(self.2.clone()), hash) { Err(SignError::NotUnlocked) => unreachable!(), - Err(SignError::NotFound) => Err(ethkey::Error::InvalidAddress), - Err(SignError::SStore(accounts::Error::EthKey(err))) => Err(err), - Err(SignError::SStore(accounts::Error::EthKeyCrypto(err))) => { + Err(SignError::NotFound) => Err(crypto::publickey::Error::InvalidAddress), + Err(SignError::SStore(accounts::Error::EthCryptoPublicKey(err))) => Err(err), + Err(SignError::SStore(accounts::Error::EthCrypto(err))) => { warn!("Low level crypto error: {:?}", err); - Err(ethkey::Error::InvalidSecret) + Err(crypto::publickey::Error::InvalidSecretKey) } Err(SignError::SStore(err)) => { warn!("Error signing for engine: {:?}", err); - Err(ethkey::Error::InvalidSignature) + Err(crypto::publickey::Error::InvalidSignature) } Ok(ok) => Ok(ok), } diff --git a/crates/ethcore/src/engines/validator_set/contract.rs b/crates/ethcore/src/engines/validator_set/contract.rs index b742120f2a..451d8e39ce 100644 --- a/crates/ethcore/src/engines/validator_set/contract.rs +++ b/crates/ethcore/src/engines/validator_set/contract.rs @@ -211,7 +211,7 @@ mod tests { // Check a block that is a bit in future, reject it but don't report the validator. let mut header = Header::default(); - let seal = vec![encode(&4u8), encode(&(&H520::default() as &[u8]))]; + let seal = vec![encode(&4u8), encode(&(H520::default().as_bytes()))]; header.set_seal(seal); header.set_author(v1); header.set_number(2); @@ -222,7 +222,7 @@ mod tests { // Now create one that is more in future. That one should be rejected and validator should be reported. let mut header = Header::default(); - let seal = vec![encode(&8u8), encode(&(&H520::default() as &[u8]))]; + let seal = vec![encode(&8u8), encode(&(H520::default().as_bytes()))]; header.set_seal(seal); header.set_author(v1); header.set_number(2); diff --git a/crates/ethcore/src/engines/validator_set/multi.rs b/crates/ethcore/src/engines/validator_set/multi.rs index b5b2901679..01618e5af4 100644 --- a/crates/ethcore/src/engines/validator_set/multi.rs +++ b/crates/ethcore/src/engines/validator_set/multi.rs @@ -183,9 +183,9 @@ impl ValidatorSet for Multi { mod tests { use accounts::AccountProvider; use client::{traits::ForceUpdateSealing, BlockChainClient, BlockInfo, ChainInfo, ImportBlock}; + use crypto::publickey::Secret; use engines::{validator_set::ValidatorSet, EpochChange}; use ethereum_types::Address; - use ethkey::Secret; use hash::keccak; use miner::{self, MinerService}; use spec::Spec; diff --git a/crates/ethcore/src/engines/validator_set/safe_contract.rs b/crates/ethcore/src/engines/validator_set/safe_contract.rs index 6e36015aa8..30e8403f11 100644 --- a/crates/ethcore/src/engines/validator_set/safe_contract.rs +++ b/crates/ethcore/src/engines/validator_set/safe_contract.rs @@ -481,8 +481,8 @@ mod tests { traits::{EngineClient, ForceUpdateSealing}, BlockInfo, ChainInfo, ImportBlock, }; + use crypto::publickey::Secret; use ethereum_types::Address; - use ethkey::Secret; use hash::keccak; use miner::{self, MinerService}; use rustc_hex::FromHex; diff --git a/crates/ethcore/src/engines/validator_set/simple_list.rs b/crates/ethcore/src/engines/validator_set/simple_list.rs index 5911d749c5..8e44204625 100644 --- a/crates/ethcore/src/engines/validator_set/simple_list.rs +++ b/crates/ethcore/src/engines/validator_set/simple_list.rs @@ -16,14 +16,14 @@ use ethereum_types::{Address, H256}; /// Preconfigured validator list. -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use super::ValidatorSet; use machine::{AuxiliaryData, Call, EthereumMachine}; use types::{header::Header, BlockNumber}; /// Validator set containing a known set of addresses. -#[derive(Clone, Debug, PartialEq, Eq, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Default, MallocSizeOf)] pub struct SimpleList { validators: Vec
, } @@ -58,12 +58,6 @@ impl From> for SimpleList { } } -impl HeapSizeOf for SimpleList { - fn heap_size_of_children(&self) -> usize { - self.validators.heap_size_of_children() - } -} - impl ValidatorSet for SimpleList { fn default_caller(&self, _block_id: ::types::ids::BlockId) -> Box { Box::new(|_, _| Err("Simple list doesn't require calls.".into())) diff --git a/crates/ethcore/src/engines/validator_set/test.rs b/crates/ethcore/src/engines/validator_set/test.rs index afc4cb1d05..ab96a42e69 100644 --- a/crates/ethcore/src/engines/validator_set/test.rs +++ b/crates/ethcore/src/engines/validator_set/test.rs @@ -23,13 +23,14 @@ use std::sync::{ use bytes::Bytes; use ethereum_types::{Address, H256}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use types::{header::Header, BlockNumber}; use super::{SimpleList, ValidatorSet}; use machine::{AuxiliaryData, Call, EthereumMachine}; /// Set used for testing with a single validator. +#[derive(MallocSizeOf)] pub struct TestSet { validator: SimpleList, last_malicious: Arc, @@ -55,12 +56,6 @@ impl TestSet { } } -impl HeapSizeOf for TestSet { - fn heap_size_of_children(&self) -> usize { - self.validator.heap_size_of_children() - } -} - impl ValidatorSet for TestSet { fn default_caller(&self, _block_id: ::types::ids::BlockId) -> Box { Box::new(|_, _| Err("Test set doesn't require calls.".into())) diff --git a/crates/ethcore/src/error.rs b/crates/ethcore/src/error.rs index 5081c85bf3..5a246f12c2 100644 --- a/crates/ethcore/src/error.rs +++ b/crates/ethcore/src/error.rs @@ -22,8 +22,8 @@ use std::{error, fmt, time::SystemTime}; +use crypto::publickey::Error as EthkeyError; use ethereum_types::{Address, Bloom, H256, U256}; -use ethkey::Error as EthkeyError; use ethtrie::TrieError; use rlp; use snappy::InvalidInput; diff --git a/crates/ethcore/src/ethereum/ethash.rs b/crates/ethcore/src/ethereum/ethash.rs index 9210d1a4d2..ffd55eb847 100644 --- a/crates/ethcore/src/ethereum/ethash.rs +++ b/crates/ethcore/src/ethereum/ethash.rs @@ -362,7 +362,7 @@ impl Engine for Arc { let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty( &header.bare_hash().0, - seal.nonce.low_u64(), + seal.nonce.to_low_u64_be(), &seal.mix_hash.0, header.number() >= self.ethash_params.progpow_transition, ))); @@ -384,7 +384,7 @@ impl Engine for Arc { let result = self.pow.compute_light( header.number() as u64, &header.bare_hash().0, - seal.nonce.low_u64(), + seal.nonce.to_low_u64_be(), ); let mix = H256(result.mix_hash); let difficulty = ethash::boundary_to_difficulty(&H256(result.value)); @@ -392,7 +392,7 @@ impl Engine for Arc { num = header.number() as u64, seed = H256(slow_hash_block_number(header.number() as u64)), h = header.bare_hash(), - non = seal.nonce.low_u64(), + non = seal.nonce.to_low_u64_be(), mix = H256(result.mix_hash), res = H256(result.value)); if mix != seal.mix_hash { @@ -692,7 +692,7 @@ mod tests { ) .unwrap(); let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + let uncle_author = Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(); uncle.set_author(uncle_author); b.push_uncle(uncle).unwrap(); @@ -732,8 +732,8 @@ mod tests { .unwrap(); let b = b.close().unwrap(); - let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into(); - let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into(); + let ubi_contract = Address::from_str("00efdd5883ec628983e9063c7d969fe268bbf310").unwrap(); + let dev_contract = Address::from_str("00756cf8159095948496617f5fb17ed95059f536").unwrap(); assert_eq!( b.state.balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap() @@ -888,9 +888,10 @@ mod tests { let engine = test_spec().engine; let mut header: Header = Header::default(); header.set_seal(vec![ - rlp::encode(&H256::from( - "b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d", - )), + rlp::encode( + &H256::from_str("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d") + .unwrap(), + ), rlp::encode(&H64::zero()), ]); header.set_difficulty( @@ -1025,9 +1026,10 @@ mod tests { let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut header = Header::default(); header.set_seal(vec![ - rlp::encode(&H256::from( - "b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d", - )), + rlp::encode( + &H256::from_str("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d") + .unwrap(), + ), rlp::encode(&H64::zero()), ]); let info = ethash.extra_info(&header); diff --git a/crates/ethcore/src/ethereum/mod.rs b/crates/ethcore/src/ethereum/mod.rs index b527ff9c91..0b412b12ef 100644 --- a/crates/ethcore/src/ethereum/mod.rs +++ b/crates/ethcore/src/ethereum/mod.rs @@ -346,8 +346,9 @@ pub fn new_kovan_wasm_test_machine() -> EthereumMachine { #[cfg(test)] mod tests { use super::*; - use ethereum_types::U256; + use ethereum_types::{H160, H256, U256}; use state::*; + use std::str::FromStr; use test_helpers::get_temp_state_db; use types::{view, views::BlockView}; @@ -367,32 +368,32 @@ mod tests { ) .unwrap(); assert_eq!( - s.balance(&"0000000000000000000000000000000000000001".into()) + s.balance(&H160::from_str("0000000000000000000000000000000000000001").unwrap()) .unwrap(), 1u64.into() ); assert_eq!( - s.balance(&"0000000000000000000000000000000000000002".into()) + s.balance(&H160::from_str("0000000000000000000000000000000000000002").unwrap()) .unwrap(), 1u64.into() ); assert_eq!( - s.balance(&"0000000000000000000000000000000000000003".into()) + s.balance(&H160::from_str("0000000000000000000000000000000000000003").unwrap()) .unwrap(), 1u64.into() ); assert_eq!( - s.balance(&"0000000000000000000000000000000000000004".into()) + s.balance(&H160::from_str("0000000000000000000000000000000000000004").unwrap()) .unwrap(), 1u64.into() ); assert_eq!( - s.balance(&"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c".into()) + s.balance(&H160::from_str("102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c").unwrap()) .unwrap(), U256::from(1u64) << 200 ); assert_eq!( - s.balance(&"0000000000000000000000000000000000000000".into()) + s.balance(&H160::from_str("0000000000000000000000000000000000000000").unwrap()) .unwrap(), 0u64.into() ); @@ -404,12 +405,14 @@ mod tests { assert_eq!( morden.state_root(), - "f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9".into() + H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9") + .unwrap() ); let genesis = morden.genesis_block(); assert_eq!( view!(BlockView, &genesis).header_view().hash(), - "0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303".into() + H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303") + .unwrap() ); let _ = morden.engine; @@ -421,12 +424,14 @@ mod tests { assert_eq!( frontier.state_root(), - "d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544".into() + H256::from_str("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544") + .unwrap() ); let genesis = frontier.genesis_block(); assert_eq!( view!(BlockView, &genesis).header_view().hash(), - "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3".into() + H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") + .unwrap() ); let _ = frontier.engine; diff --git a/crates/ethcore/src/executive.rs b/crates/ethcore/src/executive.rs index 485bb4275e..6834c17234 100644 --- a/crates/ethcore/src/executive.rs +++ b/crates/ethcore/src/executive.rs @@ -25,7 +25,7 @@ use factory::VmFactory; use hash::keccak; use machine::EthereumMachine as Machine; use state::{Backend as StateBackend, CleanupMode, State, Substate}; -use std::{cmp, sync::Arc}; +use std::{cmp, convert::TryFrom, sync::Arc}; use trace::{self, Tracer, VMTracer}; use transaction_ext::Transaction; use types::transaction::{Action, SignedTransaction, TypedTransaction}; @@ -1220,7 +1220,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { } self.state.sub_balance( &sender, - &U256::from(gas_cost), + &U256::try_from(gas_cost).expect("Total cost (value + gas_cost) is lower than max allowed balance (U256); gas_cost has to fit U256; qed"), &mut substate.to_cleanup_mode(&schedule), )?; @@ -1561,9 +1561,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { #[allow(dead_code)] mod tests { use super::*; + use crypto::publickey::{Generator, Random}; use error::ExecutionError; - use ethereum_types::{Address, H256, U256, U512}; - use ethkey::{Generator, Random}; + use ethereum_types::{Address, BigEndianHash, H160, H256, U256, U512}; use evm::{Factory, VMType}; use machine::EthereumMachine; use rustc_hex::FromHex; @@ -1640,8 +1640,8 @@ mod tests { assert_eq!(gas_left, U256::from(79_975)); assert_eq!( - state.storage_at(&address, &H256::new()).unwrap(), - H256::from(&U256::from(0xf9u64)) + state.storage_at(&address, &H256::default()).unwrap(), + BigEndianHash::from_uint(&U256::from(0xf9u64)) ); assert_eq!(state.balance(&sender).unwrap(), U256::from(0xf9)); assert_eq!(state.balance(&address).unwrap(), U256::from(0x7)); @@ -1759,8 +1759,8 @@ mod tests { vec![ FlatTrace { action: trace::Action::Call(trace::Call { - from: "4444444444444444444444444444444444444444".into(), - to: "5555555555555555555555555555555555555555".into(), + from: H160::from_str("4444444444444444444444444444444444444444").unwrap(), + to: H160::from_str("5555555555555555555555555555555555555555").unwrap(), value: 100.into(), gas: 100_000.into(), input: vec![], @@ -1775,8 +1775,8 @@ mod tests { }, FlatTrace { action: trace::Action::Call(trace::Call { - from: "5555555555555555555555555555555555555555".into(), - to: "0000000000000000000000000000000000000003".into(), + from: H160::from_str("5555555555555555555555555555555555555555").unwrap(), + to: H160::from_str("0000000000000000000000000000000000000003").unwrap(), value: 1.into(), gas: 66560.into(), input: vec![], @@ -1866,8 +1866,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "cd1722f3947def4cf144679da39c4c32bdc35681".into(), - to: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + from: H160::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(), + to: H160::from_str("b010143a42d5980c7e5ef0e4a4416dc098a4fed3").unwrap(), value: 100.into(), gas: 100000.into(), input: vec![], @@ -1882,7 +1882,7 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Create(trace::Create { - from: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + from: H160::from_str("b010143a42d5980c7e5ef0e4a4416dc098a4fed3").unwrap(), value: 23.into(), gas: 67979.into(), init: vec![ @@ -1997,8 +1997,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "cd1722f3947def4cf144679da39c4c32bdc35681".into(), - to: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + from: H160::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(), + to: H160::from_str("b010143a42d5980c7e5ef0e4a4416dc098a4fed3").unwrap(), value: 100.into(), gas: 100_000.into(), input: vec![], @@ -2013,7 +2013,7 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Create(trace::Create { - from: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + from: H160::from_str("b010143a42d5980c7e5ef0e4a4416dc098a4fed3").unwrap(), value: 23.into(), gas: 66_917.into(), init: vec![0x60, 0x01, 0x60, 0x00, 0xfd], @@ -2392,9 +2392,9 @@ mod tests { assert_eq!(gas_left, U256::from(73_237)); assert_eq!( state - .storage_at(&address_a, &H256::from(&U256::from(0x23))) + .storage_at(&address_a, &BigEndianHash::from_uint(&U256::from(0x23))) .unwrap(), - H256::from(&U256::from(1)) + BigEndianHash::from_uint(&U256::from(1)) ); } @@ -2451,15 +2451,15 @@ mod tests { assert_eq!(gas_left, U256::from(59_870)); assert_eq!( state - .storage_at(&address, &H256::from(&U256::zero())) + .storage_at(&address, &BigEndianHash::from_uint(&U256::zero())) .unwrap(), - H256::from(&U256::from(1)) + BigEndianHash::from_uint(&U256::from(1)) ); assert_eq!( state - .storage_at(&address, &H256::from(&U256::one())) + .storage_at(&address, &BigEndianHash::from_uint(&U256::one())) .unwrap(), - H256::from(&U256::from(1)) + BigEndianHash::from_uint(&U256::from(1)) ); } @@ -2467,7 +2467,7 @@ mod tests { // TODO: fix (preferred) or remove evm_test_ignore! {test_transact_simple: test_transact_simple_int} fn test_transact_simple(factory: Factory) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), @@ -2511,14 +2511,14 @@ mod tests { assert_eq!(state.balance(&contract).unwrap(), U256::from(17)); assert_eq!(state.nonce(&sender).unwrap(), U256::from(1)); assert_eq!( - state.storage_at(&contract, &H256::new()).unwrap(), - H256::from(&U256::from(1)) + state.storage_at(&contract, &H256::zero()).unwrap(), + BigEndianHash::from_uint(&U256::from(1)) ); } evm_test! {test_transact_invalid_nonce: test_transact_invalid_nonce_int} fn test_transact_invalid_nonce(factory: Factory) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), @@ -2557,7 +2557,7 @@ mod tests { evm_test! {test_transact_gas_limit_reached: test_transact_gas_limit_reached_int} fn test_transact_gas_limit_reached(factory: Factory) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(17), @@ -2602,7 +2602,7 @@ mod tests { evm_test! {test_not_enough_cash: test_not_enough_cash_int} fn test_not_enough_cash(factory: Factory) { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::from(18), @@ -2730,20 +2730,20 @@ mod tests { assert_eq!(output[..], returns[..]); assert_eq!( state - .storage_at(&contract_address, &H256::from(&U256::zero())) + .storage_at(&contract_address, &BigEndianHash::from_uint(&U256::zero())) .unwrap(), - H256::from(&U256::from(0)) + BigEndianHash::from_uint(&U256::from(0)) ); } evm_test! {test_eip1283: test_eip1283_int} fn test_eip1283(factory: Factory) { - let x1 = Address::from(0x1000); - let x2 = Address::from(0x1001); - let y1 = Address::from(0x2001); - let y2 = Address::from(0x2002); - let operating_address = Address::from(0); - let k = H256::new(); + let x1 = Address::from_low_u64_be(0x1000); + let x2 = Address::from_low_u64_be(0x1001); + let y1 = Address::from_low_u64_be(0x2001); + let y2 = Address::from_low_u64_be(0x2002); + let operating_address = Address::from_low_u64_be(0); + let k = H256::default(); let mut state = get_temp_state_with_factory(factory.clone()); state @@ -2777,7 +2777,7 @@ mod tests { assert_eq!( state.storage_at(&operating_address, &k).unwrap(), - H256::from(U256::from(0)) + BigEndianHash::from_uint(&U256::from(0)) ); // Test a call via top-level -> y1 -> x1 let (FinalizationResult { gas_left, .. }, refund, gas) = { @@ -2804,7 +2804,7 @@ mod tests { assert_eq!( state.storage_at(&operating_address, &k).unwrap(), - H256::from(U256::from(1)) + BigEndianHash::from_uint(&U256::from(1)) ); // Test a call via top-level -> y2 -> x2 let (FinalizationResult { gas_left, .. }, refund, gas) = { diff --git a/crates/ethcore/src/externalities.rs b/crates/ethcore/src/externalities.rs index d1910dd273..41c722e8fa 100644 --- a/crates/ethcore/src/externalities.rs +++ b/crates/ethcore/src/externalities.rs @@ -16,7 +16,7 @@ //! Transaction Execution environment. use bytes::Bytes; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; use executive::*; use machine::EthereumMachine as Machine; use state::{Backend as StateBackend, CleanupMode, State, Substate}; @@ -187,6 +187,8 @@ where Err(_) => return H256::zero(), }; + let data: H256 = BigEndianHash::from_uint(number); + let params = ActionParams { sender: self.origin_info.address.clone(), address: blockhash_contract_address.clone(), @@ -197,7 +199,7 @@ where gas_price: 0.into(), code: code, code_hash: code_hash, - data: Some(H256::from(number).to_vec()), + data: Some(data.as_bytes().to_vec()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, access_list: AccessList::default(), @@ -212,8 +214,8 @@ where self.vm_tracer, ); let output = match &r { - Ok(ref r) => H256::from(&r.return_data[..32]), - _ => H256::new(), + Ok(ref r) => H256::from_slice(&r.return_data[..32]), + _ => H256::default(), }; trace!( "ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", @@ -558,6 +560,7 @@ mod tests { use ethereum_types::{Address, U256}; use evm::{CallType, EnvInfo, Ext}; use state::{State, Substate}; + use std::str::FromStr; use test_helpers::get_temp_state; use trace::{NoopTracer, NoopVMTracer}; @@ -573,7 +576,7 @@ mod tests { fn get_test_env_info() -> EnvInfo { EnvInfo { number: 100, - author: 0.into(), + author: Address::zero(), timestamp: 0, difficulty: 0.into(), last_hashes: Arc::new(vec![]), @@ -672,7 +675,8 @@ mod tests { #[test] fn can_return_block_hash() { let test_hash = - H256::from("afafafafafafafafafafafbcbcbcbcbcbcbcbcbcbeeeeeeeeeeeeedddddddddd"); + H256::from_str("afafafafafafafafafafafbcbcbcbcbcbcbcbcbcbeeeeeeeeeeeeedddddddddd") + .unwrap(); let test_env_number = 0x120001; let mut setup = TestSetup::new(); @@ -741,15 +745,15 @@ mod tests { &"0000000000000000000000000000000000000000000000000000000000120000" .parse::() .unwrap(), - &Address::new(), - &Address::new(), + &Address::default(), + &Address::default(), Some( "0000000000000000000000000000000000000000000000000000000000150000" .parse::() .unwrap(), ), &[], - &Address::new(), + &Address::default(), CallType::Call, false, ) @@ -760,9 +764,10 @@ mod tests { #[test] fn can_log() { let log_data = vec![120u8, 110u8]; - let log_topics = vec![H256::from( + let log_topics = vec![H256::from_str( "af0fa234a6af46afa23faf23bcbc1c1cb4bcb7bcbe7e7e7ee3ee2edddddddddd", - )]; + ) + .unwrap()]; let mut setup = TestSetup::new(); let state = &mut setup.state; @@ -793,7 +798,7 @@ mod tests { #[test] fn can_suicide() { - let refund_account = &Address::new(); + let refund_account = &Address::default(); let mut setup = TestSetup::new(); let state = &mut setup.state; diff --git a/crates/ethcore/src/json_tests/executive.rs b/crates/ethcore/src/json_tests/executive.rs index 515b730456..ffd20e935b 100644 --- a/crates/ethcore/src/json_tests/executive.rs +++ b/crates/ethcore/src/json_tests/executive.rs @@ -16,6 +16,7 @@ use super::test_common::*; use bytes::Bytes; +use ethereum_types::BigEndianHash; use ethjson; use ethtrie; use evm::Finalize; @@ -398,10 +399,11 @@ pub fn json_executive_test( for (k, v) in storage { let key: U256 = k.into(); let value: U256 = v.into(); - let found_storage = - try_fail!(state.storage_at(&address, &From::from(&key))); + let found_storage = try_fail!( + state.storage_at(&address, &BigEndianHash::from_uint(&key)) + ); fail_unless( - found_storage == From::from(&value), + found_storage == BigEndianHash::from_uint(&value), "storage is incorrect", ); } diff --git a/crates/ethcore/src/lib.rs b/crates/ethcore/src/lib.rs index ba87d3ef48..1b8dcac708 100644 --- a/crates/ethcore/src/lib.rs +++ b/crates/ethcore/src/lib.rs @@ -31,9 +31,7 @@ extern crate ethcore_io as io; extern crate ethcore_miner; extern crate ethereum_types; extern crate ethjson; -extern crate ethkey; extern crate hash_db; -extern crate heapsize; extern crate itertools; extern crate journaldb; extern crate keccak_hash as hash; @@ -46,7 +44,9 @@ extern crate memory_cache; extern crate memory_db; extern crate num_cpus; extern crate parity_bytes as bytes; +extern crate parity_crypto as crypto; extern crate parity_snappy as snappy; +extern crate parity_util_mem; extern crate parking_lot; extern crate patricia_trie_ethereum as ethtrie; extern crate rand; @@ -84,8 +84,6 @@ extern crate tempfile; #[cfg(feature = "json-tests")] extern crate walkdir; -#[macro_use] -extern crate ethabi_derive; #[macro_use] extern crate ethabi_contract; #[macro_use] diff --git a/crates/ethcore/src/machine/impls.rs b/crates/ethcore/src/machine/impls.rs index b11a463b22..f5924e044e 100644 --- a/crates/ethcore/src/machine/impls.rs +++ b/crates/ethcore/src/machine/impls.rs @@ -72,7 +72,7 @@ impl From<::ethjson::spec::EthashParams> for EthashExtensions { .map_or(u64::max_value(), Into::into), dao_hardfork_beneficiary: p .dao_hardfork_beneficiary - .map_or_else(Address::new, Into::into), + .map_or_else(Address::default, Into::into), dao_hardfork_accounts: p .dao_hardfork_accounts .unwrap_or_else(Vec::new) @@ -232,7 +232,7 @@ impl EthereumMachine { block, params.eip210_contract_address, params.eip210_contract_gas, - Some(parent_hash.to_vec()), + Some(parent_hash.as_bytes().to_vec()), )?; } Ok(()) @@ -546,12 +546,15 @@ fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) #[cfg(test)] mod tests { use super::*; + use ethereum_types::H160; + use std::str::FromStr; fn get_default_ethash_extensions() -> EthashExtensions { EthashExtensions { homestead_transition: 1150000, dao_hardfork_transition: u64::max_value(), - dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(), + dao_hardfork_beneficiary: H160::from_str("0000000000000000000000000000000000000001") + .unwrap(), dao_hardfork_accounts: Vec::new(), } } @@ -576,7 +579,7 @@ mod tests { assert_eq!( res, Err(transaction::Error::InvalidSignature( - "Crypto error (Invalid EC signature)".into() + "invalid EC signature".into() )) ); } diff --git a/crates/ethcore/src/miner/miner.rs b/crates/ethcore/src/miner/miner.rs index 919059d20b..4335093c70 100644 --- a/crates/ethcore/src/miner/miner.rs +++ b/crates/ethcore/src/miner/miner.rs @@ -1502,7 +1502,7 @@ mod tests { use super::*; use accounts::AccountProvider; - use ethkey::{Generator, Random}; + use crypto::publickey::{Generator, Random}; use hash::keccak; use rustc_hex::FromHex; use types::BlockNumber; @@ -1583,7 +1583,7 @@ mod tests { } fn transaction_with_chain_id(chain_id: u64) -> SignedTransaction { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); TypedTransaction::Legacy(Transaction { action: Action::Create, value: U256::zero(), @@ -1636,7 +1636,7 @@ mod tests { // when new block is imported let client = generate_dummy_client(2); - let imported = [0.into()]; + let imported = [H256::zero()]; let empty = &[]; miner.chain_new_blocks(&*client, &imported, empty, &imported, empty, false); @@ -1716,7 +1716,7 @@ mod tests { #[test] fn should_treat_unfamiliar_locals_selectively() { // given - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let client = TestBlockChainClient::default(); let mut local_accounts = ::std::collections::HashSet::new(); local_accounts.insert(keypair.address()); @@ -1917,7 +1917,7 @@ mod tests { let addr = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); let client = generate_dummy_client_with_spec(spec); let engine_signer = Box::new((tap.clone(), addr, "".into())); - let msg = Default::default(); + let msg = [1u8; 32].into(); assert!(client.engine().sign(msg).is_err()); // should set engine signer and miner author diff --git a/crates/ethcore/src/miner/stratum.rs b/crates/ethcore/src/miner/stratum.rs index c08c02ca1b..180be26ccd 100644 --- a/crates/ethcore/src/miner/stratum.rs +++ b/crates/ethcore/src/miner/stratum.rs @@ -29,7 +29,7 @@ use ethcore_miner::work_notify::NotifyWork; #[cfg(feature = "work-notify")] use ethcore_stratum::PushWorkHandler; use ethcore_stratum::{Error as StratumServiceError, JobDispatcher, Stratum as StratumService}; -use ethereum_types::{clean_0x, H256, H64, U256}; +use ethereum_types::{H256, H64, U256}; use miner::{Miner, MinerService}; use parking_lot::Mutex; use rlp::encode; @@ -47,6 +47,14 @@ pub struct Options { pub secret: Option, } +fn clean_0x(s: &str) -> &str { + if s.starts_with("0x") { + &s[2..] + } else { + s + } +} + struct SubmitPayload { nonce: H64, pow_hash: H256, diff --git a/crates/ethcore/src/pod_account.rs b/crates/ethcore/src/pod_account.rs index ed7311e5a2..6187072db4 100644 --- a/crates/ethcore/src/pod_account.rs +++ b/crates/ethcore/src/pod_account.rs @@ -17,7 +17,7 @@ //! Account system expressed in Plain Old Data. use bytes::Bytes; -use ethereum_types::{H256, U256}; +use ethereum_types::{BigEndianHash, H256, U256}; use ethjson; use ethtrie::RlpCodec; use hash::keccak; @@ -85,7 +85,7 @@ impl PodAccount { stream.append(&sec_trie_root( self.storage .iter() - .map(|(k, v)| (k, rlp::encode(&U256::from(&**v)))), + .map(|(k, v)| (k, rlp::encode(&v.into_uint()))), )); stream.append(&keccak(&self.code.as_ref().unwrap_or(&vec![]))); stream.out() @@ -103,10 +103,10 @@ impl PodAccount { } _ => {} } - let mut r = H256::new(); + let mut r = H256::default(); let mut t = factory.create(db, &mut r); for (k, v) in &self.storage { - if let Err(e) = t.insert(k, &rlp::encode(&U256::from(&**v))) { + if let Err(e) = t.insert(k.as_bytes(), &rlp::encode(&v.into_uint())) { warn!("Encountered potential DB corruption: {}", e); } } @@ -125,7 +125,10 @@ impl From for PodAccount { .map(|(key, value)| { let key: U256 = key.into(); let value: U256 = value.into(); - (H256::from(key), H256::from(value)) + ( + BigEndianHash::from_uint(&key), + BigEndianHash::from_uint(&value), + ) }) .collect(), } @@ -143,7 +146,10 @@ impl From for PodAccount { .map(|(key, value)| { let key: U256 = key.into(); let value: U256 = value.into(); - (H256::from(key), H256::from(value)) + ( + BigEndianHash::from_uint(&key), + BigEndianHash::from_uint(&value), + ) }) .collect() }), @@ -159,7 +165,7 @@ impl fmt::Display for PodAccount { self.balance, self.nonce, self.code.as_ref().map_or(0, |c| c.len()), - self.code.as_ref().map_or_else(H256::new, |c| keccak(c)), + self.code.as_ref().map_or_else(H256::default, |c| keccak(c)), self.storage.len(), ) } @@ -183,7 +189,7 @@ pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option { let storage: Vec<_> = pre.storage.keys().merge(post.storage.keys()) - .filter(|k| pre.storage.get(k).unwrap_or(&H256::new()) != post.storage.get(k).unwrap_or(&H256::new())) + .filter(|k| pre.storage.get(k).unwrap_or(&H256::default()) != post.storage.get(k).unwrap_or(&H256::default())) .collect(); let r = AccountDiff { balance: Diff::new(pre.balance, post.balance), @@ -194,8 +200,8 @@ pub fn diff_pod(pre: Option<&PodAccount>, post: Option<&PodAccount>) -> Option, post: Option<&PodAccount>) -> Option 1, 2 => 2, 3 => 3, 4 => 4, 5 => 0, 6 => 0, 7 => 0], + storage: map_into![ + H256::from_low_u64_be(1) => H256::from_low_u64_be(1), + H256::from_low_u64_be(2) => H256::from_low_u64_be(2), + H256::from_low_u64_be(3) => H256::from_low_u64_be(3), + H256::from_low_u64_be(4) => H256::from_low_u64_be(4), + H256::from_low_u64_be(5) => H256::from_low_u64_be(0), + H256::from_low_u64_be(6) => H256::from_low_u64_be(0), + H256::from_low_u64_be(7) => H256::from_low_u64_be(0) + ], }; let b = PodAccount { balance: 0.into(), nonce: 0.into(), code: Some(vec![]), - storage: map_into![1 => 1, 2 => 3, 3 => 0, 5 => 0, 7 => 7, 8 => 0, 9 => 9], + storage: map_into![ + H256::from_low_u64_be(1) => H256::from_low_u64_be(1), + H256::from_low_u64_be(2) => H256::from_low_u64_be(3), + H256::from_low_u64_be(3) => H256::from_low_u64_be(0), + H256::from_low_u64_be(5) => H256::from_low_u64_be(0), + H256::from_low_u64_be(7) => H256::from_low_u64_be(7), + H256::from_low_u64_be(8) => H256::from_low_u64_be(0), + H256::from_low_u64_be(9) => H256::from_low_u64_be(9) + ], }; assert_eq!( diff_pod(Some(&a), Some(&b)), @@ -305,11 +328,11 @@ mod test { nonce: Diff::Same, code: Diff::Same, storage: map![ - 2.into() => Diff::new(2.into(), 3.into()), - 3.into() => Diff::new(3.into(), 0.into()), - 4.into() => Diff::new(4.into(), 0.into()), - 7.into() => Diff::new(0.into(), 7.into()), - 9.into() => Diff::new(0.into(), 9.into()) + H256::from_low_u64_be(2) => Diff::new(H256::from_low_u64_be(2), H256::from_low_u64_be(3)), + H256::from_low_u64_be(3) => Diff::new(H256::from_low_u64_be(3), H256::from_low_u64_be(0)), + H256::from_low_u64_be(4) => Diff::new(H256::from_low_u64_be(4), H256::from_low_u64_be(0)), + H256::from_low_u64_be(7) => Diff::new(H256::from_low_u64_be(0), H256::from_low_u64_be(7)), + H256::from_low_u64_be(9) => Diff::new(H256::from_low_u64_be(0), H256::from_low_u64_be(9)) ], }) ); diff --git a/crates/ethcore/src/pod_state.rs b/crates/ethcore/src/pod_state.rs index 5eafca5680..c28797836b 100644 --- a/crates/ethcore/src/pod_state.rs +++ b/crates/ethcore/src/pod_state.rs @@ -103,6 +103,7 @@ pub fn diff_pod(pre: &PodState, post: &PodState) -> StateDiff { #[cfg(test)] mod test { use super::PodState; + use ethereum_types::H160; use pod_account::PodAccount; use std::collections::BTreeMap; use types::{account_diff::*, state_diff::*}; @@ -110,7 +111,7 @@ mod test { #[test] fn create_delete() { let a = PodState::from(map![ - 1.into() => PodAccount { + H160::from_low_u64_be(1) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), @@ -121,7 +122,7 @@ mod test { super::diff_pod(&a, &PodState::new()), StateDiff { raw: map![ - 1.into() => AccountDiff{ + H160::from_low_u64_be(1) => AccountDiff{ balance: Diff::Died(69.into()), nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), @@ -134,7 +135,7 @@ mod test { super::diff_pod(&PodState::new(), &a), StateDiff { raw: map![ - 1.into() => AccountDiff{ + H160::from_low_u64_be(1) => AccountDiff{ balance: Diff::Born(69.into()), nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), @@ -148,7 +149,7 @@ mod test { #[test] fn create_delete_with_unchanged() { let a = PodState::from(map![ - 1.into() => PodAccount { + H160::from_low_u64_be(1) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), @@ -156,13 +157,13 @@ mod test { } ]); let b = PodState::from(map![ - 1.into() => PodAccount { + H160::from_low_u64_be(1) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), storage: map![], }, - 2.into() => PodAccount { + H160::from_low_u64_be(2) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), @@ -173,7 +174,7 @@ mod test { super::diff_pod(&a, &b), StateDiff { raw: map![ - 2.into() => AccountDiff{ + H160::from_low_u64_be(2) => AccountDiff{ balance: Diff::Born(69.into()), nonce: Diff::Born(0.into()), code: Diff::Born(vec![]), @@ -186,7 +187,7 @@ mod test { super::diff_pod(&b, &a), StateDiff { raw: map![ - 2.into() => AccountDiff{ + H160::from_low_u64_be(2) => AccountDiff{ balance: Diff::Died(69.into()), nonce: Diff::Died(0.into()), code: Diff::Died(vec![]), @@ -200,13 +201,13 @@ mod test { #[test] fn change_with_unchanged() { let a = PodState::from(map![ - 1.into() => PodAccount { + H160::from_low_u64_be(1) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), storage: map![], }, - 2.into() => PodAccount { + H160::from_low_u64_be(2) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), @@ -214,13 +215,13 @@ mod test { } ]); let b = PodState::from(map![ - 1.into() => PodAccount { + H160::from_low_u64_be(1) => PodAccount { balance: 69.into(), nonce: 1.into(), code: Some(Vec::new()), storage: map![], }, - 2.into() => PodAccount { + H160::from_low_u64_be(2) => PodAccount { balance: 69.into(), nonce: 0.into(), code: Some(Vec::new()), @@ -231,7 +232,7 @@ mod test { super::diff_pod(&a, &b), StateDiff { raw: map![ - 1.into() => AccountDiff{ + H160::from_low_u64_be(1) => AccountDiff{ balance: Diff::Same, nonce: Diff::Changed(0.into(), 1.into()), code: Diff::Same, diff --git a/crates/ethcore/src/snapshot/account.rs b/crates/ethcore/src/snapshot/account.rs index cb3f5e154e..7ce25e72c1 100644 --- a/crates/ethcore/src/snapshot/account.rs +++ b/crates/ethcore/src/snapshot/account.rs @@ -135,7 +135,7 @@ pub fn to_fat_rlps( stream.drain() }; if !account_stream.append_raw_checked(&pair, 1, target_chunk_size) { - account_stream.complete_unbounded_list(); + account_stream.finalize_unbounded_list(); let stream = ::std::mem::replace(&mut account_stream, RlpStream::new_list(2)); chunks.push(stream.out()); @@ -148,7 +148,7 @@ pub fn to_fat_rlps( return Err(e.into()); } None => { - account_stream.complete_unbounded_list(); + account_stream.finalize_unbounded_list(); let stream = ::std::mem::replace(&mut account_stream, RlpStream::new_list(2)); chunks.push(stream.out()); return Ok(chunks); diff --git a/crates/ethcore/src/snapshot/block.rs b/crates/ethcore/src/snapshot/block.rs index c602f6088c..9b276621c5 100644 --- a/crates/ethcore/src/snapshot/block.rs +++ b/crates/ethcore/src/snapshot/block.rs @@ -154,7 +154,12 @@ mod tests { let encoded = encode_block(&b); let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded)); - assert_eq!(abridged.to_block(H256::new(), 0, receipts_root).unwrap(), b); + assert_eq!( + abridged + .to_block(H256::default(), 0, receipts_root) + .unwrap(), + b + ); } #[test] @@ -165,7 +170,12 @@ mod tests { let encoded = encode_block(&b); let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded)); - assert_eq!(abridged.to_block(H256::new(), 2, receipts_root).unwrap(), b); + assert_eq!( + abridged + .to_block(H256::default(), 2, receipts_root) + .unwrap(), + b + ); } #[test] @@ -180,7 +190,7 @@ mod tests { value: U256::from(1), data: b"Hello!".to_vec(), }) - .fake_sign(Address::from(0x69)); + .fake_sign(Address::from_low_u64_be(0x69)); let t2 = TypedTransaction::Legacy(Transaction { action: Action::Create, @@ -190,7 +200,7 @@ mod tests { value: U256::from(1000000000), data: "Eep!".into(), }) - .fake_sign(Address::from(0x55)); + .fake_sign(Address::from_low_u64_be(0x55)); b.transactions.push(t1.into()); b.transactions.push(t2.into()); @@ -204,6 +214,11 @@ mod tests { let encoded = encode_block(&b); let abridged = AbridgedBlock::from_block_view(&view!(BlockView, &encoded[..])); - assert_eq!(abridged.to_block(H256::new(), 0, receipts_root).unwrap(), b); + assert_eq!( + abridged + .to_block(H256::default(), 0, receipts_root) + .unwrap(), + b + ); } } diff --git a/crates/ethcore/src/snapshot/consensus/work.rs b/crates/ethcore/src/snapshot/consensus/work.rs index ae9dc364b2..5c5d5305af 100644 --- a/crates/ethcore/src/snapshot/consensus/work.rs +++ b/crates/ethcore/src/snapshot/consensus/work.rs @@ -35,7 +35,7 @@ use bytes::Bytes; use db::KeyValueDB; use engines::EthEngine; use ethereum_types::H256; -use rand::OsRng; +use rand::rngs::OsRng; use rlp::{Rlp, RlpStream}; use snapshot::{block::AbridgedBlock, Error, ManifestData, Progress}; use types::encoded; @@ -242,7 +242,7 @@ impl PowRebuilder { Ok(PowRebuilder { chain: chain, db: db, - rng: OsRng::new()?, + rng: OsRng, disconnected: Vec::new(), best_number: manifest.block_number, best_hash: manifest.block_hash, diff --git a/crates/ethcore/src/snapshot/mod.rs b/crates/ethcore/src/snapshot/mod.rs index 444b49429c..32182de39a 100644 --- a/crates/ethcore/src/snapshot/mod.rs +++ b/crates/ethcore/src/snapshot/mod.rs @@ -50,7 +50,7 @@ use trie::{Trie, TrieMut}; use self::io::SnapshotWriter; use crossbeam_utils::thread; -use rand::{OsRng, Rng}; +use rand::{rngs::OsRng, Rng}; pub use self::error::Error; @@ -496,7 +496,7 @@ impl StateRebuilder { return Err(Error::RestorationAborted.into()); } - account_trie.insert(&hash, &thin_rlp)?; + account_trie.insert(hash.as_bytes(), &thin_rlp)?; } } trace!(target: "snapshot", "current state root: {:?}", self.state_root); diff --git a/crates/ethcore/src/snapshot/tests/helpers.rs b/crates/ethcore/src/snapshot/tests/helpers.rs index 7203a51ffa..fadc7067d0 100644 --- a/crates/ethcore/src/snapshot/tests/helpers.rs +++ b/crates/ethcore/src/snapshot/tests/helpers.rs @@ -129,7 +129,7 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) { SecTrieDBMut::from_existing(&mut db, root).unwrap() }; - for (k, v) in map.make_with(seed) { + for (k, v) in map.make_with(&mut seed.to_fixed_bytes()) { trie.insert(&k, &v).unwrap(); } } diff --git a/crates/ethcore/src/snapshot/tests/proof_of_authority.rs b/crates/ethcore/src/snapshot/tests/proof_of_authority.rs index a68e90cb90..dc111a025b 100644 --- a/crates/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/crates/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -20,7 +20,7 @@ use std::{cell::RefCell, str::FromStr, sync::Arc}; use accounts::AccountProvider; use client::{BlockChainClient, ChainInfo, Client}; -use ethkey::Secret; +use crypto::publickey::Secret; use snapshot::tests::helpers as snapshot_helpers; use spec::Spec; use tempdir::TempDir; @@ -132,7 +132,7 @@ fn make_chain( nonce: *nonce, gas_price: 1.into(), gas: 21_000.into(), - action: Action::Call(Address::new()), + action: Action::Call(Address::default()), value: 1.into(), data: Vec::new(), }) diff --git a/crates/ethcore/src/snapshot/tests/service.rs b/crates/ethcore/src/snapshot/tests/service.rs index 90bdc19235..801c11a206 100644 --- a/crates/ethcore/src/snapshot/tests/service.rs +++ b/crates/ethcore/src/snapshot/tests/service.rs @@ -364,6 +364,8 @@ fn recover_aborted_recovery() { e => panic!("Snapshot restoration must be ongoing ; {:?}", e), } + service.abort_restore(); + // Remove the snapshot directory, and restart the restoration // It shouldn't have restored any previous blocks fs::remove_dir_all(tempdir.path()).unwrap(); diff --git a/crates/ethcore/src/snapshot/tests/state.rs b/crates/ethcore/src/snapshot/tests/state.rs index 03653acf61..39eb380c8c 100644 --- a/crates/ethcore/src/snapshot/tests/state.rs +++ b/crates/ethcore/src/snapshot/tests/state.rs @@ -16,6 +16,8 @@ //! State snapshotting tests. +extern crate rand_xorshift; + use hash::{keccak, KECCAK_NULL_RLP}; use std::sync::{atomic::AtomicBool, Arc}; @@ -29,18 +31,21 @@ use types::basic_account::BasicAccount; use error::{Error, ErrorKind}; +use self::rand_xorshift::XorShiftRng; use ethereum_types::H256; use journaldb::{self, Algorithm}; use kvdb_rocksdb::{Database, DatabaseConfig}; use parking_lot::Mutex; -use rand::{SeedableRng, XorShiftRng}; +use rand::SeedableRng; use tempdir::TempDir; +const RNG_SEED: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + #[test] fn snap_and_restore() { use hash_db::HashDB; let mut producer = StateProducer::new(); - let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]); + let mut rng = XorShiftRng::from_seed(RNG_SEED); let mut old_db = journaldb::new_memory_db(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); @@ -190,7 +195,7 @@ fn get_code_from_prev_chunk() { #[test] fn checks_flag() { let mut producer = StateProducer::new(); - let mut rng = XorShiftRng::from_seed([5, 6, 7, 8]); + let mut rng = XorShiftRng::from_seed(RNG_SEED); let mut old_db = journaldb::new_memory_db(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); diff --git a/crates/ethcore/src/snapshot/watcher.rs b/crates/ethcore/src/snapshot/watcher.rs index d949c1c4ab..968d1e08cb 100644 --- a/crates/ethcore/src/snapshot/watcher.rs +++ b/crates/ethcore/src/snapshot/watcher.rs @@ -141,7 +141,7 @@ mod tests { use client::{ChainNotify, ChainRoute, NewBlocks}; - use ethereum_types::{H256, U256}; + use ethereum_types::{BigEndianHash, H256, U256}; use std::{collections::HashMap, time::Duration}; @@ -176,7 +176,7 @@ mod tests { let hashes: Vec<_> = numbers .clone() .into_iter() - .map(|x| H256::from(U256::from(x))) + .map(|x| BigEndianHash::from_uint(&U256::from(x))) .collect(); let map = hashes.clone().into_iter().zip(numbers).collect(); diff --git a/crates/ethcore/src/spec/spec.rs b/crates/ethcore/src/spec/spec.rs index 24688c21d6..2d0bb719d7 100644 --- a/crates/ethcore/src/spec/spec.rs +++ b/crates/ethcore/src/spec/spec.rs @@ -25,7 +25,7 @@ use std::{ }; use bytes::Bytes; -use ethereum_types::{Address, Bloom, H256, U256}; +use ethereum_types::{Address, Bloom, H160, H256, U256}; use ethjson; use hash::{keccak, KECCAK_NULL_RLP}; use parking_lot::RwLock; @@ -318,7 +318,9 @@ impl From for CommonParams { eip210_transition: p .eip210_transition .map_or_else(BlockNumber::max_value, Into::into), - eip210_contract_address: p.eip210_contract_address.map_or(0xf0.into(), Into::into), + eip210_contract_address: p + .eip210_contract_address + .map_or(H160::from_low_u64_be(0xf0), Into::into), eip210_contract_code: p.eip210_contract_code.map_or_else( || { DEFAULT_BLOCKHASH_CONTRACT @@ -382,7 +384,7 @@ impl From for CommonParams { nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), - registrar: p.registrar.map_or_else(Address::new, Into::into), + registrar: p.registrar.map_or_else(Address::default, Into::into), node_permission_contract: p.node_permission_contract.map(Into::into), max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), max_transaction_size: p @@ -742,7 +744,7 @@ impl Spec { let mut t = factories.trie.create(db.as_hash_db_mut(), &mut root); for (address, account) in self.genesis_state.get().iter() { - t.insert(&**address, &account.rlp())?; + t.insert(address.as_bytes(), &account.rlp())?; } } @@ -1119,7 +1121,9 @@ impl Spec { #[cfg(test)] mod tests { use super::*; + use ethereum_types::{H160, H256}; use state::State; + use std::str::FromStr; use tempdir::TempDir; use test_helpers::get_temp_state_db; use types::{view, views::BlockView}; @@ -1136,12 +1140,14 @@ mod tests { assert_eq!( test_spec.state_root(), - "f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9".into() + H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9") + .unwrap() ); let genesis = test_spec.genesis_block(); assert_eq!( view!(BlockView, &genesis).header_view().hash(), - "0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303".into() + H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303") + .unwrap() ); } @@ -1159,8 +1165,10 @@ mod tests { Default::default(), ) .unwrap(); - let expected = "0000000000000000000000000000000000000000000000000000000000000001".into(); - let address = "0000000000000000000000000000000000001337".into(); + let expected = + H256::from_str("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + let address = H160::from_str("0000000000000000000000000000000000001337").unwrap(); assert_eq!(state.storage_at(&address, &H256::zero()).unwrap(), expected); assert_eq!(state.balance(&address).unwrap(), 1.into()); diff --git a/crates/ethcore/src/state/account.rs b/crates/ethcore/src/state/account.rs index 799fc24d6e..e524285c5a 100644 --- a/crates/ethcore/src/state/account.rs +++ b/crates/ethcore/src/state/account.rs @@ -18,7 +18,7 @@ use bytes::{Bytes, ToPretty}; use error::Error; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; use ethtrie::{Result as TrieResult, SecTrieDB, TrieDB, TrieFactory}; use hash::{keccak, KECCAK_EMPTY, KECCAK_NULL_RLP}; use hash_db::HashDB; @@ -279,9 +279,9 @@ impl Account { let panicky_decoder = |bytes: &[u8]| ::rlp::decode(&bytes).expect("decoding db value failed"); let item: U256 = db - .get_with(key, panicky_decoder)? + .get_with(key.as_bytes(), panicky_decoder)? .unwrap_or_else(U256::zero); - let value: H256 = item.into(); + let value: H256 = BigEndianHash::from_uint(&item); storage_cache.insert(key.clone(), value.clone()); Ok(value) } @@ -311,7 +311,7 @@ impl Account { // If storage root is empty RLP, then early return zero value. Practically, this makes it so that if // `original_storage_cache` is used, then `storage_cache` will always remain empty. if self.storage_root == KECCAK_NULL_RLP { - return Some(H256::new()); + return Some(H256::default()); } self.storage_cache @@ -538,8 +538,8 @@ impl Account { // cast key and value to trait type, // so we can call overloaded `to_bytes` method match v.is_zero() { - true => t.remove(&k)?, - false => t.insert(&k, &encode(&U256::from(&*v)))?, + true => t.remove(k.as_bytes())?, + false => t.insert(k.as_bytes(), &encode(&v.into_uint()))?, }; self.storage_cache.borrow_mut().insert(k, v); @@ -661,13 +661,13 @@ impl Account { let panicky_decoder = |bytes: &[u8]| ::rlp::decode(bytes).expect("decoding db value failed"); let query = (&mut recorder, panicky_decoder); - trie.get_with(&storage_key, query)? + trie.get_with(storage_key.as_bytes(), query)? .unwrap_or_else(U256::zero) }; Ok(( recorder.drain().into_iter().map(|r| r.data).collect(), - item.into(), + BigEndianHash::from_uint(&item), )) } } @@ -694,6 +694,7 @@ mod tests { use ethereum_types::{Address, H256}; use journaldb::new_memory_db; use rlp_compress::{compress, decompress, snapshot_swapper}; + use std::str::FromStr; #[test] fn account_compress() { @@ -707,10 +708,13 @@ mod tests { #[test] fn storage_at() { let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); let rlp = { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); - a.set_storage(0x00u64.into(), 0x1234u64.into()); + a.set_storage( + H256::from_low_u64_be(0x00u64), + H256::from_low_u64_be(0x1234u64), + ); a.commit_storage(&Default::default(), &mut db).unwrap(); a.init_code(vec![]); a.commit_code(&mut db); @@ -720,14 +724,17 @@ mod tests { let a = Account::from_rlp(&rlp).expect("decoding db value failed"); assert_eq!( a.storage_root().unwrap(), - "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into() + H256::from_str("c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2") + .unwrap() ); assert_eq!( - a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), - 0x1234u64.into() + a.storage_at(&db.immutable(), &H256::from_low_u64_be(0x00u64)) + .unwrap(), + H256::from_low_u64_be(0x1234u64) ); assert_eq!( - a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), + a.storage_at(&db.immutable(), &H256::from_low_u64_be(0x01u64)) + .unwrap(), H256::default() ); } @@ -735,7 +742,7 @@ mod tests { #[test] fn note_code() { let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); let rlp = { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); @@ -755,13 +762,14 @@ mod tests { fn commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); - a.set_storage(0.into(), 0x1234.into()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); + a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234)); assert_eq!(a.storage_root(), None); a.commit_storage(&Default::default(), &mut db).unwrap(); assert_eq!( a.storage_root().unwrap(), - "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into() + H256::from_str("c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2") + .unwrap() ); } @@ -769,16 +777,17 @@ mod tests { fn commit_remove_commit_storage() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); - a.set_storage(0.into(), 0x1234.into()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); + a.set_storage(H256::from_low_u64_be(0), H256::from_low_u64_be(0x1234)); a.commit_storage(&Default::default(), &mut db).unwrap(); - a.set_storage(1.into(), 0x1234.into()); + a.set_storage(H256::from_low_u64_be(1), H256::from_low_u64_be(0x1234)); a.commit_storage(&Default::default(), &mut db).unwrap(); - a.set_storage(1.into(), 0.into()); + a.set_storage(H256::from_low_u64_be(1), H256::from_low_u64_be(0)); a.commit_storage(&Default::default(), &mut db).unwrap(); assert_eq!( a.storage_root().unwrap(), - "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into() + H256::from_str("c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2") + .unwrap() ); } @@ -786,14 +795,15 @@ mod tests { fn commit_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); assert_eq!(a.code_size(), Some(3)); a.commit_code(&mut db); assert_eq!( a.code_hash(), - "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb".into() + H256::from_str("af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb") + .unwrap() ); } @@ -801,21 +811,23 @@ mod tests { fn reset_code() { let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = new_memory_db(); - let mut db = AccountDBMut::new(&mut db, &Address::new()); + let mut db = AccountDBMut::new(&mut db, &Address::default()); a.init_code(vec![0x55, 0x44, 0xffu8]); assert_eq!(a.code_filth, Filth::Dirty); a.commit_code(&mut db); assert_eq!(a.code_filth, Filth::Clean); assert_eq!( a.code_hash(), - "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb".into() + H256::from_str("af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb") + .unwrap() ); a.reset_code(vec![0x55]); assert_eq!(a.code_filth, Filth::Dirty); a.commit_code(&mut db); assert_eq!( a.code_hash(), - "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be".into() + H256::from_str("37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be") + .unwrap() ); } diff --git a/crates/ethcore/src/state/mod.rs b/crates/ethcore/src/state/mod.rs index f15e2b77d0..2617412c2f 100644 --- a/crates/ethcore/src/state/mod.rs +++ b/crates/ethcore/src/state/mod.rs @@ -371,7 +371,7 @@ impl State { /// Creates new state with empty state root /// Used for tests. pub fn new(mut db: B, account_start_nonce: U256, factories: Factories) -> State { - let mut root = H256::new(); + let mut root = H256::default(); { // init trie and reset root to null let _ = factories.trie.create(db.as_hash_db_mut(), &mut root); @@ -528,7 +528,7 @@ impl State { let (nonce, overflow) = self.account_start_nonce.overflowing_add(nonce_offset); if overflow { return Err(Box::new(TrieError::DecoderError( - H256::from(contract), + H256::from(contract.clone()), rlp::DecoderError::Custom("Nonce overflow".into()), ))); } @@ -658,12 +658,14 @@ impl State { // would always be empty. Note that this branch is actually never called, because // `cached_storage_at` handled this case. warn!(target: "state", "Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty."); - return Ok(Some(H256::new())); + return Ok(Some(H256::default())); } } } // The account didn't exist at that point. Return empty value. - Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())), + Some(Some(AccountEntry { account: None, .. })) => { + return Ok(Some(H256::default())) + } // The value was not cached at that checkpoint, meaning it was not modified at all. Some(None) => { kind = Some(ReturnKind::OriginalAt); @@ -718,12 +720,12 @@ impl State { local_account = Some(maybe_acc); } } - _ => return Ok(H256::new()), + _ => return Ok(H256::default()), } } // check the global cache and and cache storage key there if found, let trie_res = self.db.get_cached(address, |acc| match acc { - None => Ok(H256::new()), + None => Ok(H256::default()), Some(a) => { let account_db = self .factories @@ -746,7 +748,7 @@ impl State { .readonly(self.db.as_hash_db(), account.address_hash(address)); return f_at(account, account_db.as_hash_db(), key); } else { - return Ok(H256::new()); + return Ok(H256::default()); } } } @@ -759,8 +761,8 @@ impl State { .readonly(db, &self.root) .expect(SEC_TRIE_DB_UNWRAP_STR); let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); - let maybe_acc = db.get_with(address, from_rlp)?; - let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { + let maybe_acc = db.get_with(address.as_bytes(), from_rlp)?; + let r = maybe_acc.as_ref().map_or(Ok(H256::zero()), |a| { let account_db = self .factories .accountdb @@ -1025,10 +1027,10 @@ impl State { a.state = AccountState::Committed; match a.account { Some(ref mut account) => { - trie.insert(address, &account.rlp())?; + trie.insert(address.as_bytes(), &account.rlp())?; } None => { - trie.remove(address)?; + trie.remove(address.as_bytes())?; } }; } @@ -1151,6 +1153,7 @@ impl State { account: &Account, address: &Address, ) -> Result { + use ethereum_types::BigEndianHash; let mut pod_storage = BTreeMap::new(); let addr_hash = account.address_hash(address); let accountdb = self @@ -1164,10 +1167,11 @@ impl State { for o_kv in trie.iter()? { if let Ok((key, val)) = o_kv { pod_storage.insert( - key[..].into(), - rlp::decode::(&val[..]) - .expect("Decoded from trie which was encoded from the same type; qed") - .into(), + H256::from_slice(&key[..]), + BigEndianHash::from_uint( + &rlp::decode::(&val[..]) + .expect("Decoded from trie which was encoded from the same type; qed"), + ), ); } } @@ -1327,7 +1331,7 @@ impl State { if Self::update_account_cache(require, account, &self.db, accountdb.as_hash_db()) { return Ok(f(Some(account))); } else { - return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(*a)))); } } return Ok(f(None)); @@ -1340,7 +1344,7 @@ impl State { .accountdb .readonly(self.db.as_hash_db(), account.address_hash(a)); if !Self::update_account_cache(require, account, &self.db, accountdb.as_hash_db()) { - return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(*a)))); } } Ok(f(acc.map(|a| &*a))) @@ -1352,7 +1356,7 @@ impl State { let db = &self.db.as_hash_db(); let db = self.factories.trie.readonly(db, &self.root)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); - let mut maybe_acc = db.get_with(a, from_rlp)?; + let mut maybe_acc = db.get_with(a.as_bytes(), from_rlp)?; if let Some(ref mut account) = maybe_acc.as_mut() { let accountdb = self .factories @@ -1364,7 +1368,7 @@ impl State { &self.db, accountdb.as_hash_db(), ) { - return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(*a)))); } } let r = f(maybe_acc.as_ref()); @@ -1406,7 +1410,7 @@ impl State { let db = self.factories.trie.readonly(db, &self.root)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); - let maybe_acc = AccountEntry::new_clean(db.get_with(a, from_rlp)?); + let maybe_acc = AccountEntry::new_clean(db.get_with(a.as_bytes(), from_rlp)?); self.insert_cache(a, maybe_acc); } } @@ -1445,7 +1449,7 @@ impl State { &self.db, accountdb.as_hash_db(), ) { - return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(*a)))); } } @@ -1486,7 +1490,7 @@ impl State { }) }; let query = (&mut recorder, panicky_decoder); - trie.get_with(&account_key, query)? + trie.get_with(account_key.as_bytes(), query)? }; let account = maybe_account.unwrap_or_else(|| BasicAccount { balance: 0.into(), @@ -1516,9 +1520,9 @@ impl State { let db = &self.db.as_hash_db(); let trie = TrieDB::new(db, &self.root)?; let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); - let acc = match trie.get_with(&account_key, from_rlp)? { + let acc = match trie.get_with(account_key.as_bytes(), from_rlp)? { Some(acc) => acc, - None => return Ok((Vec::new(), H256::new())), + None => return Ok((Vec::new(), H256::default())), }; let account_db = self @@ -1570,8 +1574,8 @@ impl Clone for State { #[cfg(test)] mod tests { use super::*; - use ethereum_types::{Address, H256, U256}; - use ethkey::Secret; + use crypto::publickey::Secret; + use ethereum_types::{Address, BigEndianHash, H256, U256}; use evm::CallType; use hash::{keccak, KECCAK_NULL_RLP}; use machine::EthereumMachine; @@ -1622,7 +1626,7 @@ mod tests { trace_address: Default::default(), subtraces: 0, action: trace::Action::Create(trace::Create { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), value: 100.into(), gas: 77412.into(), init: vec![ @@ -1685,7 +1689,7 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Create(trace::Create { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), value: 100.into(), gas: 78792.into(), init: vec![91, 96, 0, 86], @@ -1711,14 +1715,17 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) .sign(&secret(), None); state - .init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()) + .init_code( + &Address::from_low_u64_be(0xa), + FromHex::from_hex("6000").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -1727,8 +1734,8 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -1758,7 +1765,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -1771,8 +1778,8 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -1802,7 +1809,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0x1.into()), + action: Action::Call(Address::from_low_u64_be(0x1)), value: 0.into(), data: vec![], }) @@ -1813,8 +1820,8 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: "0000000000000000000000000000000000000001".into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_str("0000000000000000000000000000000000000001").unwrap(), value: 0.into(), gas: 79_000.into(), input: vec![], @@ -1844,7 +1851,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 0.into(), data: vec![], }) @@ -1852,7 +1859,7 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("600060006000600060006001610be0f1").unwrap(), ) .unwrap(); @@ -1861,8 +1868,8 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 0.into(), gas: 79000.into(), input: vec![], @@ -1892,7 +1899,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 0.into(), data: vec![], }) @@ -1900,12 +1907,15 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006000600b611000f2").unwrap(), ) .unwrap(); state - .init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()) + .init_code( + &Address::from_low_u64_be(0xb), + FromHex::from_hex("6000").unwrap(), + ) .unwrap(); let result = state.apply(&info, &machine, &t, true).unwrap(); @@ -1914,8 +1924,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 0.into(), gas: 79000.into(), input: vec![], @@ -1930,8 +1940,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 4096.into(), input: vec![], @@ -1962,7 +1972,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 0.into(), data: vec![], }) @@ -1970,13 +1980,13 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("6000600060006000600b618000f4").unwrap(), ) .unwrap(); state .init_code( - &0xb.into(), + &Address::from_low_u64_be(0xb), FromHex::from_hex("60056000526001601ff3").unwrap(), ) .unwrap(); @@ -1987,8 +1997,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 0.into(), gas: 79000.into(), input: vec![], @@ -2003,8 +2013,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 32768.into(), input: vec![], @@ -2034,14 +2044,17 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) .sign(&secret(), None); state - .init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()) + .init_code( + &Address::from_low_u64_be(0xa), + FromHex::from_hex("5b600056").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -2050,8 +2063,8 @@ mod tests { let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2078,7 +2091,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -2086,12 +2099,15 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap(), ) .unwrap(); state - .init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()) + .init_code( + &Address::from_low_u64_be(0xb), + FromHex::from_hex("6000").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -2103,8 +2119,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2119,8 +2135,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 78934.into(), input: vec![], @@ -2150,7 +2166,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -2158,7 +2174,7 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006045600b6000f1").unwrap(), ) .unwrap(); @@ -2171,8 +2187,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2187,8 +2203,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 69.into(), gas: 2300.into(), input: vec![], @@ -2215,7 +2231,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -2223,7 +2239,7 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap(), ) .unwrap(); // not enough funds. @@ -2235,8 +2251,8 @@ mod tests { trace_address: Default::default(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2265,7 +2281,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], //600480600b6000396000f35b600056 }) @@ -2273,12 +2289,15 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap(), ) .unwrap(); state - .init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()) + .init_code( + &Address::from_low_u64_be(0xb), + FromHex::from_hex("5b600056").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -2289,8 +2308,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2305,8 +2324,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 78934.into(), input: vec![], @@ -2333,7 +2352,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -2341,18 +2360,21 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap(), ) .unwrap(); state .init_code( - &0xb.into(), + &Address::from_low_u64_be(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap(), ) .unwrap(); state - .init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()) + .init_code( + &Address::from_low_u64_be(0xc), + FromHex::from_hex("6000").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -2363,8 +2385,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2379,8 +2401,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 78934.into(), input: vec![], @@ -2395,8 +2417,8 @@ mod tests { trace_address: vec![0, 0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xb.into(), - to: 0xc.into(), + from: Address::from_low_u64_be(0xb), + to: Address::from_low_u64_be(0xc), value: 0.into(), gas: 78868.into(), input: vec![], @@ -2426,7 +2448,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], //600480600b6000396000f35b600056 }) @@ -2434,18 +2456,21 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap(), ) .unwrap(); state .init_code( - &0xb.into(), + &Address::from_low_u64_be(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap(), ) .unwrap(); state - .init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()) + .init_code( + &Address::from_low_u64_be(0xc), + FromHex::from_hex("6000").unwrap(), + ) .unwrap(); state .add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty) @@ -2457,8 +2482,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2473,8 +2498,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: 0xa.into(), - to: 0xb.into(), + from: Address::from_low_u64_be(0xa), + to: Address::from_low_u64_be(0xb), value: 0.into(), gas: 78934.into(), input: vec![], @@ -2486,8 +2511,8 @@ mod tests { trace_address: vec![0, 0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: 0xb.into(), - to: 0xc.into(), + from: Address::from_low_u64_be(0xb), + to: Address::from_low_u64_be(0xc), value: 0.into(), gas: 78868.into(), call_type: CallType::Call, @@ -2517,7 +2542,7 @@ mod tests { nonce: 0.into(), gas_price: 0.into(), gas: 100_000.into(), - action: Action::Call(0xa.into()), + action: Action::Call(Address::from_low_u64_be(0xa)), value: 100.into(), data: vec![], }) @@ -2525,12 +2550,16 @@ mod tests { state .init_code( - &0xa.into(), + &Address::from_low_u64_be(0xa), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap(), ) .unwrap(); state - .add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty) + .add_balance( + &Address::from_low_u64_be(0xa), + &50.into(), + CleanupMode::NoEmpty, + ) .unwrap(); state .add_balance(&t.sender(), &100.into(), CleanupMode::NoEmpty) @@ -2541,8 +2570,8 @@ mod tests { trace_address: Default::default(), subtraces: 1, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: Address::from_str("9cce34f7ab185c7aba1b7c8140d620b4bda941d6").unwrap(), + to: Address::from_low_u64_be(0xa), value: 100.into(), gas: 79000.into(), input: vec![], @@ -2557,8 +2586,8 @@ mod tests { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Suicide(trace::Suicide { - address: 0xa.into(), - refund_address: 0xb.into(), + address: Address::from_low_u64_be(0xa), + refund_address: Address::from_low_u64_be(0xb), balance: 150.into(), }), result: trace::Res::None, @@ -2600,8 +2629,8 @@ mod tests { state .set_storage( &a, - H256::from(&U256::from(1u64)), - H256::from(&U256::from(69u64)), + BigEndianHash::from_uint(&U256::from(1u64)), + BigEndianHash::from_uint(&U256::from(69u64)), ) .unwrap(); state.commit().unwrap(); @@ -2610,8 +2639,9 @@ mod tests { let s = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); assert_eq!( - s.storage_at(&a, &H256::from(&U256::from(1u64))).unwrap(), - H256::from(&U256::from(69u64)) + s.storage_at(&a, &BigEndianHash::from_uint(&U256::from(1u64))) + .unwrap(), + BigEndianHash::from_uint(&U256::from(69u64)) ); } @@ -2717,7 +2747,7 @@ mod tests { fn alter_balance() { let mut state = get_temp_state(); let a = Address::zero(); - let b = 1u64.into(); + let b = Address::from_low_u64_be(1u64); state .add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty) .unwrap(); @@ -2775,7 +2805,8 @@ mod tests { state.commit().unwrap(); assert_eq!( *state.root(), - "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785".into() + H256::from_str("0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785") + .unwrap() ); } @@ -2819,147 +2850,164 @@ mod tests { fn checkpoint_revert_to_get_storage_at() { let mut state = get_temp_state(); let a = Address::zero(); - let k = H256::from(U256::from(0)); + let k = BigEndianHash::from_uint(&U256::from(0)); let c0 = state.checkpoint(); let c1 = state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(1))) + .unwrap(); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) + ); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(1)) ); - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); state.revert_to_checkpoint(); // Revert to c1. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) + ); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(0)) ); - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); } #[test] fn checkpoint_from_empty_get_storage_at() { let mut state = get_temp_state(); let a = Address::zero(); - let k = H256::from(U256::from(0)); - let k2 = H256::from(U256::from(1)); + let k = BigEndianHash::from_uint(&U256::from(0)); + let k2 = BigEndianHash::from_uint(&U256::from(1)); - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(0)) + ); state.clear(); let c0 = state.checkpoint(); state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); let c1 = state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(1))) + .unwrap(); let c2 = state.checkpoint(); let c3 = state.checkpoint(); state - .set_storage(&a, k2, H256::from(U256::from(3))) + .set_storage(&a, k2, BigEndianHash::from_uint(&U256::from(3))) + .unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(3))) .unwrap(); - state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); let c4 = state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(4))) + .unwrap(); let c5 = state.checkpoint(); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c4, &a, &k).unwrap(), - Some(H256::from(U256::from(3))) + Some(BigEndianHash::from_uint(&U256::from(3))) ); assert_eq!( state.checkpoint_storage_at(c5, &a, &k).unwrap(), - Some(H256::from(U256::from(4))) + Some(BigEndianHash::from_uint(&U256::from(4))) ); state.discard_checkpoint(); // Commit/discard c5. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c4, &a, &k).unwrap(), - Some(H256::from(U256::from(3))) + Some(BigEndianHash::from_uint(&U256::from(3))) ); state.revert_to_checkpoint(); // Revert to c4. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); state.discard_checkpoint(); // Commit/discard c3. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); state.revert_to_checkpoint(); // Revert to c2. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); state.discard_checkpoint(); // Commit/discard c1. assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); } @@ -2967,18 +3015,18 @@ mod tests { fn checkpoint_get_storage_at() { let mut state = get_temp_state(); let a = Address::zero(); - let k = H256::from(U256::from(0)); - let k2 = H256::from(U256::from(1)); + let k = BigEndianHash::from_uint(&U256::from(0)); + let k2 = BigEndianHash::from_uint(&U256::from(1)); state - .set_storage(&a, k, H256::from(U256::from(0xffff))) + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(0xffff))) .unwrap(); state.commit().unwrap(); state.clear(); assert_eq!( state.storage_at(&a, &k).unwrap(), - H256::from(U256::from(0xffff)) + BigEndianHash::from_uint(&U256::from(0xffff)) ); state.clear(); @@ -2986,134 +3034,140 @@ mod tests { let c0 = state.checkpoint(); state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); let c1 = state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(1))) + .unwrap(); let c2 = state.checkpoint(); let c3 = state.checkpoint(); state - .set_storage(&a, k2, H256::from(U256::from(3))) + .set_storage(&a, k2, BigEndianHash::from_uint(&U256::from(3))) + .unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(3))) .unwrap(); - state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); let c4 = state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(4))) + .unwrap(); let c5 = state.checkpoint(); assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c4, &a, &k).unwrap(), - Some(H256::from(U256::from(3))) + Some(BigEndianHash::from_uint(&U256::from(3))) ); assert_eq!( state.checkpoint_storage_at(c5, &a, &k).unwrap(), - Some(H256::from(U256::from(4))) + Some(BigEndianHash::from_uint(&U256::from(4))) ); state.discard_checkpoint(); // Commit/discard c5. assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c4, &a, &k).unwrap(), - Some(H256::from(U256::from(3))) + Some(BigEndianHash::from_uint(&U256::from(3))) ); state.revert_to_checkpoint(); // Revert to c4. assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); assert_eq!( state.checkpoint_storage_at(c3, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); state.discard_checkpoint(); // Commit/discard c3. assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); assert_eq!( state.checkpoint_storage_at(c2, &a, &k).unwrap(), - Some(H256::from(U256::from(1))) + Some(BigEndianHash::from_uint(&U256::from(1))) ); state.revert_to_checkpoint(); // Revert to c2. assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c1, &a, &k).unwrap(), - Some(H256::from(U256::from(0))) + Some(BigEndianHash::from_uint(&U256::from(0))) ); state.discard_checkpoint(); // Commit/discard c1. assert_eq!( state.checkpoint_storage_at(cm1, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); assert_eq!( state.checkpoint_storage_at(c0, &a, &k).unwrap(), - Some(H256::from(U256::from(0xffff))) + Some(BigEndianHash::from_uint(&U256::from(0xffff))) ); } @@ -3121,22 +3175,30 @@ mod tests { fn kill_account_with_checkpoints() { let mut state = get_temp_state(); let a = Address::zero(); - let k = H256::from(U256::from(0)); + let k = BigEndianHash::from_uint(&U256::from(0)); state.checkpoint(); - state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(1))) + .unwrap(); state.checkpoint(); state.kill_account(&a); - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(0)) + ); state.revert_to_checkpoint(); - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(1)) + ); } #[test] fn create_contract_fail() { let mut state = get_temp_state(); let orig_root = state.root().clone(); - let a: Address = 1000.into(); + let a = Address::from_low_u64_be(1000); state.checkpoint(); // c1 state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); @@ -3158,11 +3220,11 @@ mod tests { #[test] fn create_contract_fail_previous_storage() { let mut state = get_temp_state(); - let a: Address = 1000.into(); - let k = H256::from(U256::from(0)); + let a = Address::from_low_u64_be(1000); + let k = BigEndianHash::from_uint(&U256::from(0)); state - .set_storage(&a, k, H256::from(U256::from(0xffff))) + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(0xffff))) .unwrap(); state.commit().unwrap(); state.clear(); @@ -3170,20 +3232,25 @@ mod tests { let orig_root = state.root().clone(); assert_eq!( state.storage_at(&a, &k).unwrap(), - H256::from(U256::from(0xffff)) + BigEndianHash::from_uint(&U256::from(0xffff)) ); state.clear(); state.checkpoint(); // c1 state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); state.checkpoint(); // c2 - state.set_storage(&a, k, H256::from(U256::from(2))).unwrap(); + state + .set_storage(&a, k, BigEndianHash::from_uint(&U256::from(2))) + .unwrap(); state.revert_to_checkpoint(); // revert to c2 - assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + assert_eq!( + state.storage_at(&a, &k).unwrap(), + BigEndianHash::from_uint(&U256::from(0)) + ); state.revert_to_checkpoint(); // revert to c1 assert_eq!( state.storage_at(&a, &k).unwrap(), - H256::from(U256::from(0xffff)) + BigEndianHash::from_uint(&U256::from(0xffff)) ); state.commit().unwrap(); @@ -3196,7 +3263,8 @@ mod tests { state.commit().unwrap(); assert_eq!( *state.root(), - "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into() + H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + .unwrap() ); } @@ -3204,27 +3272,31 @@ mod tests { fn should_not_panic_on_state_diff_with_storage() { let mut state = get_temp_state(); - let a: Address = 0xa.into(); + let a: Address = Address::from_low_u64_be(0xa); state.init_code(&a, b"abcdefg".to_vec()).unwrap(); state .add_balance(&a, &256.into(), CleanupMode::NoEmpty) .unwrap(); - state.set_storage(&a, 0xb.into(), 0xc.into()).unwrap(); + state + .set_storage(&a, H256::from_low_u64_be(0xb), H256::from_low_u64_be(0xc)) + .unwrap(); let mut new_state = state.clone(); - new_state.set_storage(&a, 0xb.into(), 0xd.into()).unwrap(); + new_state + .set_storage(&a, H256::from_low_u64_be(0xb), H256::from_low_u64_be(0xd)) + .unwrap(); new_state.diff_from(state).unwrap(); } #[test] fn should_kill_garbage() { - let a = 10.into(); - let b = 20.into(); - let c = 30.into(); - let d = 40.into(); - let e = 50.into(); - let x = 0.into(); + let a = Address::from_low_u64_be(10); + let b = Address::from_low_u64_be(20); + let c = Address::from_low_u64_be(30); + let d = Address::from_low_u64_be(40); + let e = Address::from_low_u64_be(50); + let x = Address::from_low_u64_be(0); let db = get_temp_state_db(); let (root, db) = { let mut state = State::new(db, U256::from(0), Default::default()); @@ -3287,7 +3359,7 @@ mod tests { fn should_trace_diff_suicided_accounts() { use pod_account; - let a = 10.into(); + let a = Address::from_low_u64_be(10); let db = get_temp_state_db(); let (root, db) = { let mut state = State::new(db, U256::from(0), Default::default()); @@ -3326,7 +3398,7 @@ mod tests { fn should_trace_diff_unmodified_storage() { use pod_account; - let a = 10.into(); + let a = Address::from_low_u64_be(10); let db = get_temp_state_db(); let (root, db) = { @@ -3334,8 +3406,8 @@ mod tests { state .set_storage( &a, - H256::from(&U256::from(1u64)), - H256::from(&U256::from(20u64)), + BigEndianHash::from_uint(&U256::from(1u64)), + BigEndianHash::from_uint(&U256::from(20u64)), ) .unwrap(); state.commit().unwrap(); @@ -3348,8 +3420,8 @@ mod tests { state .set_storage( &a, - H256::from(&U256::from(1u64)), - H256::from(&U256::from(100u64)), + BigEndianHash::from_uint(&U256::from(1u64)), + BigEndianHash::from_uint(&U256::from(100u64)), ) .unwrap(); @@ -3365,8 +3437,8 @@ mod tests { nonce: U256::zero(), code: Some(Default::default()), storage: vec![( - H256::from(&U256::from(1u64)), - H256::from(&U256::from(20u64)) + BigEndianHash::from_uint(&U256::from(1u64)), + BigEndianHash::from_uint(&U256::from(20u64)) )] .into_iter() .collect(), @@ -3376,8 +3448,8 @@ mod tests { nonce: U256::zero(), code: Some(Default::default()), storage: vec![( - H256::from(&U256::from(1u64)), - H256::from(&U256::from(100u64)) + BigEndianHash::from_uint(&U256::from(1u64)), + BigEndianHash::from_uint(&U256::from(100u64)) )] .into_iter() .collect(), @@ -3392,7 +3464,7 @@ mod tests { fn should_get_full_pod_storage_values() { use trie::{TrieFactory, TrieSpec}; - let a = 10.into(); + let a = Address::from_low_u64_be(10); let db = get_temp_state_db(); let factories = Factories { @@ -3412,23 +3484,27 @@ mod tests { .clone() }; - let storage_address = H256::from(&U256::from(1u64)); + let storage_address: H256 = BigEndianHash::from_uint(&U256::from(1u64)); let (root, db) = { let mut state = State::new(db, U256::from(0), factories.clone()); state - .set_storage(&a, storage_address.clone(), H256::from(&U256::from(20u64))) + .set_storage( + &a, + storage_address.clone(), + BigEndianHash::from_uint(&U256::from(20u64)), + ) .unwrap(); let dump = state.to_pod_full().unwrap(); assert_eq!( get_pod_state_val(&dump, &a, storage_address.clone()), - H256::from(&U256::from(20u64)) + BigEndianHash::from_uint(&U256::from(20u64)) ); state.commit().unwrap(); let dump = state.to_pod_full().unwrap(); assert_eq!( get_pod_state_val(&dump, &a, storage_address.clone()), - H256::from(&U256::from(20u64)) + BigEndianHash::from_uint(&U256::from(20u64)) ); state.drop() }; @@ -3437,24 +3513,32 @@ mod tests { let dump = state.to_pod_full().unwrap(); assert_eq!( get_pod_state_val(&dump, &a, storage_address.clone()), - H256::from(&U256::from(20u64)) + BigEndianHash::from_uint(&U256::from(20u64)) ); state - .set_storage(&a, storage_address.clone(), H256::from(&U256::from(21u64))) + .set_storage( + &a, + storage_address.clone(), + BigEndianHash::from_uint(&U256::from(21u64)), + ) .unwrap(); let dump = state.to_pod_full().unwrap(); assert_eq!( get_pod_state_val(&dump, &a, storage_address.clone()), - H256::from(&U256::from(21u64)) + BigEndianHash::from_uint(&U256::from(21u64)) ); state.commit().unwrap(); state - .set_storage(&a, storage_address.clone(), H256::from(&U256::from(0u64))) + .set_storage( + &a, + storage_address.clone(), + BigEndianHash::from_uint(&U256::from(0u64)), + ) .unwrap(); let dump = state.to_pod_full().unwrap(); assert_eq!( get_pod_state_val(&dump, &a, storage_address.clone()), - H256::from(&U256::from(0u64)) + BigEndianHash::from_uint(&U256::from(0u64)) ); } } diff --git a/crates/ethcore/src/state/substate.rs b/crates/ethcore/src/state/substate.rs index e2fe024839..a91dabbbea 100644 --- a/crates/ethcore/src/state/substate.rs +++ b/crates/ethcore/src/state/substate.rs @@ -88,6 +88,7 @@ impl Substate { #[cfg(test)] mod tests { use super::Substate; + use ethereum_types::Address; use types::log_entry::LogEntry; #[test] @@ -99,19 +100,23 @@ mod tests { #[test] fn accrue() { let mut sub_state = Substate::new(); - sub_state.contracts_created.push(1u64.into()); + sub_state + .contracts_created + .push(Address::from_low_u64_be(1u64)); sub_state.logs.push(LogEntry { - address: 1u64.into(), + address: Address::from_low_u64_be(1u64), topics: vec![], data: vec![], }); sub_state.sstore_clears_refund = (15000 * 5).into(); - sub_state.suicides.insert(10u64.into()); + sub_state.suicides.insert(Address::from_low_u64_be(10u64)); let mut sub_state_2 = Substate::new(); - sub_state_2.contracts_created.push(2u64.into()); + sub_state_2 + .contracts_created + .push(Address::from_low_u64_be(2u64)); sub_state_2.logs.push(LogEntry { - address: 1u64.into(), + address: Address::from_low_u64_be(1u64), topics: vec![], data: vec![], }); diff --git a/crates/ethcore/src/test_helpers.rs b/crates/ethcore/src/test_helpers.rs index 57652dd3df..13a1455715 100644 --- a/crates/ethcore/src/test_helpers.rs +++ b/crates/ethcore/src/test_helpers.rs @@ -23,9 +23,9 @@ use blockchain::{ }; use blooms_db; use bytes::Bytes; +use crypto::publickey::KeyPair; use db::KeyValueDB; use ethereum_types::{Address, H256, U256}; -use ethkey::KeyPair; use evm::Factory as EvmFactory; use hash::keccak; use io::IoChannel; @@ -169,7 +169,7 @@ where let mut last_hashes = vec![]; let mut last_header = genesis_header.clone(); - let kp = KeyPair::from_secret_slice(&keccak("")).unwrap(); + let kp = KeyPair::from_secret_slice(keccak("").as_bytes()).unwrap(); let author = kp.address(); let mut n = 0; @@ -605,7 +605,7 @@ pub fn get_bad_state_dummy_block() -> Bytes { block_header.set_timestamp(40); block_header.set_number(1); block_header.set_parent_hash(test_spec.genesis_header().hash()); - block_header.set_state_root(0xbad.into()); + block_header.set_state_root(H256::from_low_u64_be(0xbad)); create_test_block(&block_header) } diff --git a/crates/ethcore/src/tests/client.rs b/crates/ethcore/src/tests/client.rs index a5f0b2d882..035bf0405d 100644 --- a/crates/ethcore/src/tests/client.rs +++ b/crates/ethcore/src/tests/client.rs @@ -25,9 +25,9 @@ use client::{ }, Client, ClientConfig, ImportSealedBlock, PrepareOpenBlock, }; +use crypto::publickey::KeyPair; use ethereum; use ethereum_types::{Address, U256}; -use ethkey::KeyPair; use executive::{Executive, TransactOptions}; use hash::keccak; use io::IoChannel; diff --git a/crates/ethcore/src/tests/evm.rs b/crates/ethcore/src/tests/evm.rs index c3ba39d784..b8e1f5c214 100644 --- a/crates/ethcore/src/tests/evm.rs +++ b/crates/ethcore/src/tests/evm.rs @@ -43,7 +43,7 @@ fn test_blockhash_eip210(factory: Factory) { // populate state with 256 last hashes let mut state = get_temp_state_with_factory(factory); - let contract_address: Address = 0xf0.into(); + let contract_address = Address::from_low_u64_be(0xf0); state .init_code(&contract_address, (*blockhash_contract_code).clone()) .unwrap(); @@ -59,7 +59,7 @@ fn test_blockhash_eip210(factory: Factory) { value: ActionValue::Transfer(0.into()), code: Some(blockhash_contract_code.clone()), code_hash: Some(blockhash_contract_code_hash), - data: Some(H256::from(i - 1).to_vec()), + data: Some(H256::from_low_u64_be(i - 1).as_bytes().to_vec()), call_type: CallType::Call, params_type: ParamsType::Separate, access_list: AccessList::default(), @@ -74,10 +74,10 @@ fn test_blockhash_eip210(factory: Factory) { env_info.number = 256; let params = ActionParams { - code_address: Address::new(), - address: Address::new(), - sender: Address::new(), - origin: Address::new(), + code_address: Address::default(), + address: Address::default(), + sender: Address::default(), + origin: Address::default(), gas: 100000.into(), gas_price: 0.into(), value: ActionValue::Transfer(0.into()), @@ -93,10 +93,10 @@ fn test_blockhash_eip210(factory: Factory) { let mut substate = Substate::new(); let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer); let output = match res { - Ok(res) => H256::from(&res.return_data[..32]), + Ok(res) => H256::from_slice(&res.return_data[..32]), Err(e) => { panic!("Encountered error on getting last hash: {}", e); } }; - assert_eq!(output, 255.into()); + assert_eq!(output, H256::from_low_u64_be(255)); } diff --git a/crates/ethcore/src/tests/trace.rs b/crates/ethcore/src/tests/trace.rs index 3835a6a034..4cb92a2e35 100644 --- a/crates/ethcore/src/tests/trace.rs +++ b/crates/ethcore/src/tests/trace.rs @@ -18,13 +18,13 @@ use block::*; use client::{BlockChainClient, Client, ClientConfig, *}; +use crypto::publickey::KeyPair; use ethereum_types::{Address, U256}; -use ethkey::KeyPair; use hash::keccak; use io::*; use miner::Miner; use spec::*; -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use test_helpers::{self, get_temp_state_db}; use trace::{trace::Action::Reward, LocalizedTrace, RewardType}; use types::{ @@ -73,7 +73,7 @@ fn can_trace_block_and_uncle_reward() { let mut last_header = genesis_header.clone(); last_hashes.push(last_header.hash()); - let kp = KeyPair::from_secret_slice(&keccak("")).unwrap(); + let kp = KeyPair::from_secret_slice(keccak("").as_bytes()).unwrap(); let author = kp.address(); // Add root block first @@ -187,7 +187,7 @@ fn can_trace_block_and_uncle_reward() { } let mut uncle = Header::new(); - let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + let uncle_author = Address::from_str("ef2d6d194084c2de36e0dabfce45d046b37d1106").unwrap(); uncle.set_author(uncle_author); uncle.set_parent_hash(root_header.hash()); uncle.set_gas_limit(genesis_gas); diff --git a/crates/ethcore/src/trace/db.rs b/crates/ethcore/src/trace/db.rs index f0943649ea..33ca541f2a 100644 --- a/crates/ethcore/src/trace/db.rs +++ b/crates/ethcore/src/trace/db.rs @@ -20,8 +20,8 @@ use std::{collections::HashMap, sync::Arc}; use blockchain::BlockChainDB; use db::{self, cache_manager::CacheManager, CacheUpdatePolicy, Key, Readable, Writable}; use ethereum_types::{H256, H264}; -use heapsize::HeapSizeOf; use kvdb::DBTransaction; +use parity_util_mem::MallocSizeOfExt; use parking_lot::RwLock; use types::BlockNumber; @@ -43,8 +43,11 @@ impl Key for H256 { fn key(&self) -> H264 { let mut result = H264::default(); - result[0] = TraceDBIndex::BlockTraces as u8; - result[1..33].copy_from_slice(self); + { + let bytes = result.as_bytes_mut(); + bytes[0] = TraceDBIndex::BlockTraces as u8; + bytes[1..33].copy_from_slice(self.as_bytes()); + } result } } @@ -101,7 +104,7 @@ where } fn cache_size(&self) -> usize { - self.traces.read().heap_size_of_children() + self.traces.read().malloc_size_of() } /// Let the cache system know that a cacheable item has been used. @@ -123,7 +126,7 @@ where } traces.shrink_to_fit(); - traces.heap_size_of_children() + traces.malloc_size_of() }); } @@ -497,8 +500,8 @@ mod tests { trace_address: Default::default(), subtraces: 0, action: Action::Call(Call { - from: 1.into(), - to: 2.into(), + from: Address::from_low_u64_be(1), + to: Address::from_low_u64_be(2), value: 3.into(), gas: 4.into(), input: vec![], @@ -522,8 +525,8 @@ mod tests { trace_address: Default::default(), subtraces: 0, action: Action::Call(Call { - from: 1.into(), - to: 2.into(), + from: Address::from_low_u64_be(1), + to: Address::from_low_u64_be(2), value: 3.into(), gas: 4.into(), input: vec![], @@ -545,8 +548,8 @@ mod tests { ) -> LocalizedTrace { LocalizedTrace { action: Action::Call(Call { - from: Address::from(1), - to: Address::from(2), + from: Address::from_low_u64_be(1), + to: Address::from_low_u64_be(2), value: U256::from(3), gas: U256::from(4), input: vec![], @@ -567,10 +570,10 @@ mod tests { let db = new_db(); let mut config = Config::default(); config.enabled = true; - let block_0 = H256::from(0xa1); - let block_1 = H256::from(0xa2); - let tx_0 = H256::from(0xff); - let tx_1 = H256::from(0xaf); + let block_0 = H256::from_low_u64_be(0xa1); + let block_1 = H256::from_low_u64_be(0xa2); + let tx_0 = H256::from_low_u64_be(0xff); + let tx_1 = H256::from_low_u64_be(0xaf); let mut extras = Extras::default(); extras.block_hashes.insert(0, block_0.clone()); @@ -597,10 +600,10 @@ mod tests { let db = new_db(); let mut config = Config::default(); config.enabled = true; - let block_1 = H256::from(0xa1); - let block_2 = H256::from(0xa2); - let tx_1 = H256::from(0xff); - let tx_2 = H256::from(0xaf); + let block_1 = H256::from_low_u64_be(0xa1); + let block_2 = H256::from_low_u64_be(0xa2); + let tx_1 = H256::from_low_u64_be(0xff); + let tx_2 = H256::from_low_u64_be(0xaf); let mut extras = Extras::default(); extras.block_hashes.insert(0, H256::default()); @@ -620,7 +623,7 @@ mod tests { let filter = Filter { range: (1..1), - from_address: AddressesFilter::from(vec![Address::from(1)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), to_address: AddressesFilter::from(vec![]), }; @@ -639,7 +642,7 @@ mod tests { let filter = Filter { range: (1..2), - from_address: AddressesFilter::from(vec![Address::from(1)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), to_address: AddressesFilter::from(vec![]), }; @@ -706,8 +709,8 @@ mod tests { let db = new_db(); let mut config = Config::default(); let mut extras = Extras::default(); - let block_0 = H256::from(0xa1); - let tx_0 = H256::from(0xff); + let block_0 = H256::from_low_u64_be(0xa1); + let tx_0 = H256::from_low_u64_be(0xff); extras.block_hashes.insert(0, H256::default()); extras.transaction_hashes.insert(0, vec![]); @@ -742,7 +745,7 @@ mod tests { let db = new_db(); let mut config = Config::default(); let mut extras = Extras::default(); - let block_0 = H256::from(0xa1); + let block_0 = H256::from_low_u64_be(0xa1); extras.block_hashes.insert(0, block_0.clone()); extras.transaction_hashes.insert(0, vec![]); diff --git a/crates/ethcore/src/trace/types/error.rs b/crates/ethcore/src/trace/types/error.rs index 691e6cc397..01e6365109 100644 --- a/crates/ethcore/src/trace/types/error.rs +++ b/crates/ethcore/src/trace/types/error.rs @@ -16,12 +16,13 @@ //! Trace errors. +use parity_util_mem::MallocSizeOf; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; use std::fmt; use vm::Error as VmError; /// Trace evm errors. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, MallocSizeOf)] pub enum Error { /// `OutOfGas` is returned when transaction execution runs out of gas. OutOfGas, diff --git a/crates/ethcore/src/trace/types/filter.rs b/crates/ethcore/src/trace/types/filter.rs index 604981e4ed..fe1bbf2914 100644 --- a/crates/ethcore/src/trace/types/filter.rs +++ b/crates/ethcore/src/trace/types/filter.rs @@ -53,7 +53,7 @@ impl AddressesFilter { false => self .list .iter() - .map(|address| Bloom::from(BloomInput::Raw(address))) + .map(|address| Bloom::from(BloomInput::Raw(address.as_bytes()))) .collect(), } } @@ -69,7 +69,7 @@ impl AddressesFilter { .iter() .map(|address| { let mut bloom = bloom.clone(); - bloom.accrue(BloomInput::Raw(address)); + bloom.accrue(BloomInput::Raw(address.as_bytes())); bloom }) .collect::>() @@ -156,31 +156,31 @@ mod tests { fn single_trace_filter_bloom_possibility() { let filter = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1)]), - to_address: AddressesFilter::from(vec![Address::from(2)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), + to_address: AddressesFilter::from(vec![Address::from_low_u64_be(2)]), }; let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); - assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(3)))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); + assert!(!blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(3).as_bytes()))); } #[test] fn only_from_trace_filter_bloom_possibility() { let filter = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), to_address: AddressesFilter::from(vec![]), }; let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(!blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); } #[test] @@ -188,59 +188,68 @@ mod tests { let filter = Filter { range: (0..0), from_address: AddressesFilter::from(vec![]), - to_address: AddressesFilter::from(vec![Address::from(1)]), + to_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), }; let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(!blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); } #[test] fn multiple_trace_filter_bloom_possibility() { let filter = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1), Address::from(3)]), - to_address: AddressesFilter::from(vec![Address::from(2), Address::from(4)]), + from_address: AddressesFilter::from(vec![ + Address::from_low_u64_be(1), + Address::from_low_u64_be(3), + ]), + to_address: AddressesFilter::from(vec![ + Address::from_low_u64_be(2), + Address::from_low_u64_be(4), + ]), }; let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 4); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); - assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(3)))); - assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(4)))); - - assert!(blooms[1].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(blooms[1].contains_input(BloomInput::Raw(&Address::from(4)))); - assert!(!blooms[1].contains_input(BloomInput::Raw(&Address::from(2)))); - assert!(!blooms[1].contains_input(BloomInput::Raw(&Address::from(3)))); - - assert!(blooms[2].contains_input(BloomInput::Raw(&Address::from(2)))); - assert!(blooms[2].contains_input(BloomInput::Raw(&Address::from(3)))); - assert!(!blooms[2].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(!blooms[2].contains_input(BloomInput::Raw(&Address::from(4)))); - - assert!(blooms[3].contains_input(BloomInput::Raw(&Address::from(3)))); - assert!(blooms[3].contains_input(BloomInput::Raw(&Address::from(4)))); - assert!(!blooms[3].contains_input(BloomInput::Raw(&Address::from(1)))); - assert!(!blooms[3].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); + assert!(!blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(3).as_bytes()))); + assert!(!blooms[0].contains_input(BloomInput::Raw(Address::from_low_u64_be(4).as_bytes()))); + + assert!(blooms[1].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(blooms[1].contains_input(BloomInput::Raw(Address::from_low_u64_be(4).as_bytes()))); + assert!(!blooms[1].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); + assert!(!blooms[1].contains_input(BloomInput::Raw(Address::from_low_u64_be(3).as_bytes()))); + + assert!(blooms[2].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); + assert!(blooms[2].contains_input(BloomInput::Raw(Address::from_low_u64_be(3).as_bytes()))); + assert!(!blooms[2].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(!blooms[2].contains_input(BloomInput::Raw(Address::from_low_u64_be(4).as_bytes()))); + + assert!(blooms[3].contains_input(BloomInput::Raw(Address::from_low_u64_be(3).as_bytes()))); + assert!(blooms[3].contains_input(BloomInput::Raw(Address::from_low_u64_be(4).as_bytes()))); + assert!(!blooms[3].contains_input(BloomInput::Raw(Address::from_low_u64_be(1).as_bytes()))); + assert!(!blooms[3].contains_input(BloomInput::Raw(Address::from_low_u64_be(2).as_bytes()))); } #[test] fn filter_matches() { let f0 = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), to_address: AddressesFilter::from(vec![]), }; let f1 = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(3), Address::from(1)]), + from_address: AddressesFilter::from(vec![ + Address::from_low_u64_be(3), + Address::from_low_u64_be(1), + ]), to_address: AddressesFilter::from(vec![]), }; @@ -253,31 +262,37 @@ mod tests { let f3 = Filter { range: (0..0), from_address: AddressesFilter::from(vec![]), - to_address: AddressesFilter::from(vec![Address::from(2)]), + to_address: AddressesFilter::from(vec![Address::from_low_u64_be(2)]), }; let f4 = Filter { range: (0..0), from_address: AddressesFilter::from(vec![]), - to_address: AddressesFilter::from(vec![Address::from(2), Address::from(3)]), + to_address: AddressesFilter::from(vec![ + Address::from_low_u64_be(2), + Address::from_low_u64_be(3), + ]), }; let f5 = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1)]), - to_address: AddressesFilter::from(vec![Address::from(2), Address::from(3)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), + to_address: AddressesFilter::from(vec![ + Address::from_low_u64_be(2), + Address::from_low_u64_be(3), + ]), }; let f6 = Filter { range: (0..0), - from_address: AddressesFilter::from(vec![Address::from(1)]), - to_address: AddressesFilter::from(vec![Address::from(4)]), + from_address: AddressesFilter::from(vec![Address::from_low_u64_be(1)]), + to_address: AddressesFilter::from(vec![Address::from_low_u64_be(4)]), }; let trace = FlatTrace { action: Action::Call(Call { - from: 1.into(), - to: 2.into(), + from: Address::from_low_u64_be(1), + to: Address::from_low_u64_be(2), value: 3.into(), gas: 4.into(), input: vec![0x5], @@ -298,7 +313,7 @@ mod tests { let trace = FlatTrace { action: Action::Create(Create { - from: 1.into(), + from: Address::from_low_u64_be(1), value: 3.into(), gas: 4.into(), init: vec![0x5], @@ -306,7 +321,7 @@ mod tests { result: Res::Create(CreateResult { gas_used: 10.into(), code: vec![], - address: 2.into(), + address: Address::from_low_u64_be(2), }), trace_address: vec![0].into_iter().collect(), subtraces: 0, @@ -322,8 +337,8 @@ mod tests { let trace = FlatTrace { action: Action::Suicide(Suicide { - address: 1.into(), - refund_address: 2.into(), + address: Address::from_low_u64_be(1), + refund_address: Address::from_low_u64_be(2), balance: 3.into(), }), result: Res::None, @@ -341,7 +356,7 @@ mod tests { let trace = FlatTrace { action: Action::Reward(Reward { - author: 2.into(), + author: Address::from_low_u64_be(2), value: 100.into(), reward_type: RewardType::Block, }), @@ -363,7 +378,7 @@ mod tests { fn filter_match_block_reward_fix_8070() { let f0 = Filter { range: (0..0), - from_address: vec![1.into()].into(), + from_address: vec![Address::from_low_u64_be(1)].into(), to_address: vec![].into(), }; @@ -376,12 +391,12 @@ mod tests { let f2 = Filter { range: (0..0), from_address: vec![].into(), - to_address: vec![2.into()].into(), + to_address: vec![Address::from_low_u64_be(2)].into(), }; let trace = FlatTrace { action: Action::Reward(Reward { - author: 2.into(), + author: Address::from_low_u64_be(2), value: 10.into(), reward_type: RewardType::Block, }), @@ -399,7 +414,7 @@ mod tests { fn filter_match_failed_contract_creation_fix_9822() { let f0 = Filter { range: (0..0), - from_address: vec![1.into()].into(), + from_address: vec![Address::from_low_u64_be(1)].into(), to_address: vec![].into(), }; @@ -412,12 +427,12 @@ mod tests { let f2 = Filter { range: (0..0), from_address: vec![].into(), - to_address: vec![2.into()].into(), + to_address: vec![Address::from_low_u64_be(2)].into(), }; let trace = FlatTrace { action: Action::Create(Create { - from: 1.into(), + from: Address::from_low_u64_be(1), gas: 4.into(), init: vec![0x5], value: 3.into(), diff --git a/crates/ethcore/src/trace/types/flat.rs b/crates/ethcore/src/trace/types/flat.rs index caf5b6be6b..a165e2e91b 100644 --- a/crates/ethcore/src/trace/types/flat.rs +++ b/crates/ethcore/src/trace/types/flat.rs @@ -18,16 +18,18 @@ use super::trace::{Action, Res}; use ethereum_types::Bloom; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; /// Trace localized in vector of traces produced by a single transaction. /// /// Parent and children indexes refer to positions in this vector. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, MallocSizeOf)] pub struct FlatTrace { + #[ignore_malloc_size_of = "ignored for performance reason"] /// Type of action performed by a transaction. pub action: Action, + #[ignore_malloc_size_of = "ignored for performance reason"] /// Result of this action. pub result: Res, /// Number of subtraces. @@ -45,12 +47,6 @@ impl FlatTrace { } } -impl HeapSizeOf for FlatTrace { - fn heap_size_of_children(&self) -> usize { - self.trace_address.heap_size_of_children() - } -} - impl Encodable for FlatTrace { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(4); @@ -76,7 +72,7 @@ impl Decodable for FlatTrace { } /// Represents all traces produced by a single transaction. -#[derive(Debug, PartialEq, Clone, RlpEncodableWrapper, RlpDecodableWrapper)] +#[derive(Debug, PartialEq, Clone, RlpEncodableWrapper, RlpDecodableWrapper, MallocSizeOf)] pub struct FlatTransactionTraces(Vec); impl From> for FlatTransactionTraces { @@ -85,12 +81,6 @@ impl From> for FlatTransactionTraces { } } -impl HeapSizeOf for FlatTransactionTraces { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - impl FlatTransactionTraces { /// Returns bloom of all traces in the collection. pub fn bloom(&self) -> Bloom { @@ -107,15 +97,11 @@ impl Into> for FlatTransactionTraces { } /// Represents all traces produced by transactions in a single block. -#[derive(Debug, PartialEq, Clone, Default, RlpEncodableWrapper, RlpDecodableWrapper)] +#[derive( + Debug, PartialEq, Clone, Default, RlpEncodableWrapper, RlpDecodableWrapper, MallocSizeOf, +)] pub struct FlatBlockTraces(Vec); -impl HeapSizeOf for FlatBlockTraces { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - impl From> for FlatBlockTraces { fn from(v: Vec) -> Self { FlatBlockTraces(v) diff --git a/crates/ethcore/src/trace/types/trace.rs b/crates/ethcore/src/trace/types/trace.rs index 28f7c3f726..62a1160dd2 100644 --- a/crates/ethcore/src/trace/types/trace.rs +++ b/crates/ethcore/src/trace/types/trace.rs @@ -47,7 +47,7 @@ pub struct CreateResult { impl CreateResult { /// Returns bloom. pub fn bloom(&self) -> Bloom { - BloomInput::Raw(&self.address).into() + BloomInput::Raw(self.address.as_bytes()).into() } } @@ -96,8 +96,8 @@ impl Call { /// The bloom contains from and to addresses. pub fn bloom(&self) -> Bloom { let mut bloom = Bloom::default(); - bloom.accrue(BloomInput::Raw(&self.from)); - bloom.accrue(BloomInput::Raw(&self.to)); + bloom.accrue(BloomInput::Raw(self.from.as_bytes())); + bloom.accrue(BloomInput::Raw(self.to.as_bytes())); bloom } } @@ -130,7 +130,7 @@ impl Create { /// Returns bloom create action bloom. /// The bloom contains only from address. pub fn bloom(&self) -> Bloom { - BloomInput::Raw(&self.from).into() + BloomInput::Raw(self.from.as_bytes()).into() } } @@ -187,7 +187,7 @@ pub struct Reward { impl Reward { /// Return reward action bloom. pub fn bloom(&self) -> Bloom { - BloomInput::Raw(&self.author).into() + BloomInput::Raw(self.author.as_bytes()).into() } } @@ -227,8 +227,8 @@ impl Suicide { /// Return suicide action bloom. pub fn bloom(&self) -> Bloom { let mut bloom = Bloom::default(); - bloom.accrue(BloomInput::Raw(&self.address)); - bloom.accrue(BloomInput::Raw(&self.refund_address)); + bloom.accrue(BloomInput::Raw(self.address.as_bytes())); + bloom.accrue(BloomInput::Raw(self.refund_address.as_bytes())); bloom } } diff --git a/crates/ethcore/src/tx_filter.rs b/crates/ethcore/src/tx_filter.rs index 573fbbfbf5..3bcc7df90c 100644 --- a/crates/ethcore/src/tx_filter.rs +++ b/crates/ethcore/src/tx_filter.rs @@ -84,7 +84,7 @@ impl TransactionFilter { let mut contract_version_cache = self.contract_version_cache.lock(); let (tx_type, to) = match transaction.tx().action { - Action::Create => (tx_permissions::CREATE, Address::new()), + Action::Create => (tx_permissions::CREATE, Address::default()), Action::Call(address) => { if client .code_hash(&address, BlockId::Hash(*parent_hash)) @@ -173,12 +173,12 @@ impl TransactionFilter { mod test { use super::TransactionFilter; use client::{BlockChainClient, BlockId, Client, ClientConfig}; + use crypto::publickey::{KeyPair, Secret}; use ethereum_types::{Address, U256}; - use ethkey::{KeyPair, Secret}; use io::IoChannel; use miner::Miner; use spec::Spec; - use std::sync::Arc; + use std::{str::FromStr, sync::Arc}; use tempdir::TempDir; use test_helpers; use types::transaction::{Action, Transaction, TypedTransaction}; @@ -200,59 +200,66 @@ mod test { IoChannel::disconnected(), ) .unwrap(); - let key1 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000001", - )) + let key1 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(), + ) .unwrap(); - let key2 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000002", - )) + let key2 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000002") + .unwrap(), + ) .unwrap(); - let key3 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000003", - )) + let key3 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000003") + .unwrap(), + ) .unwrap(); - let key4 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000004", - )) + let key4 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000004") + .unwrap(), + ) .unwrap(); - let key5 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000005", - )) + let key5 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000005") + .unwrap(), + ) .unwrap(); - let key6 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000006", - )) + let key6 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000006") + .unwrap(), + ) .unwrap(); - let key7 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000007", - )) + let key7 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000007") + .unwrap(), + ) .unwrap(); let filter = TransactionFilter::from_params(spec.params()).unwrap(); let mut basic_tx = TypedTransaction::Legacy(Transaction::default()); basic_tx.tx_mut().action = - Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb")); + Action::Call(Address::from_str("d41c057fd1c78805aac12b0a94a405c0461a6fbb").unwrap()); let create_tx = TypedTransaction::Legacy(Transaction::default()); let mut call_tx = TypedTransaction::Legacy(Transaction::default()); call_tx.tx_mut().action = - Action::Call(Address::from("0000000000000000000000000000000000000005")); + Action::Call(Address::from_str("0000000000000000000000000000000000000005").unwrap()); let mut basic_tx_with_ether_and_to_key7 = TypedTransaction::Legacy(Transaction::default()); basic_tx_with_ether_and_to_key7.tx_mut().action = - Action::Call(Address::from("d41c057fd1c78805aac12b0a94a405c0461a6fbb")); + Action::Call(Address::from_str("d41c057fd1c78805aac12b0a94a405c0461a6fbb").unwrap()); basic_tx_with_ether_and_to_key7.tx_mut().value = U256::from(123123); let mut call_tx_with_ether = TypedTransaction::Legacy(Transaction::default()); call_tx_with_ether.tx_mut().action = - Action::Call(Address::from("0000000000000000000000000000000000000005")); + Action::Call(Address::from_str("0000000000000000000000000000000000000005").unwrap()); call_tx_with_ether.tx_mut().value = U256::from(123123); let mut basic_tx_to_key6 = TypedTransaction::Legacy(Transaction::default()); basic_tx_to_key6.tx_mut().action = - Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141")); + Action::Call(Address::from_str("e57bfe9f44b819898f47bf37e5af72a0783e1141").unwrap()); let mut basic_tx_with_ether_and_to_key6 = TypedTransaction::Legacy(Transaction::default()); basic_tx_with_ether_and_to_key6.tx_mut().action = - Action::Call(Address::from("e57bfe9f44b819898f47bf37e5af72a0783e1141")); + Action::Call(Address::from_str("e57bfe9f44b819898f47bf37e5af72a0783e1141").unwrap()); basic_tx_with_ether_and_to_key6.tx_mut().value = U256::from(123123); let genesis = client.block_hash(BlockId::Latest).unwrap(); @@ -428,31 +435,35 @@ mod test { IoChannel::disconnected(), ) .unwrap(); - let key1 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000001", - )) + let key1 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(), + ) .unwrap(); - let key2 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000002", - )) + let key2 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000002") + .unwrap(), + ) .unwrap(); - let key3 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000003", - )) + let key3 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000003") + .unwrap(), + ) .unwrap(); - let key4 = KeyPair::from_secret(Secret::from( - "0000000000000000000000000000000000000000000000000000000000000004", - )) + let key4 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000004") + .unwrap(), + ) .unwrap(); let filter = TransactionFilter::from_params(spec.params()).unwrap(); let mut basic_tx = TypedTransaction::Legacy(Transaction::default()); basic_tx.tx_mut().action = - Action::Call(Address::from("000000000000000000000000000000000000032")); + Action::Call(Address::from_str("0000000000000000000000000000000000000032").unwrap()); let create_tx = TypedTransaction::Legacy(Transaction::default()); let mut call_tx = TypedTransaction::Legacy(Transaction::default()); call_tx.tx_mut().action = - Action::Call(Address::from("0000000000000000000000000000000000000005")); + Action::Call(Address::from_str("0000000000000000000000000000000000000005").unwrap()); let genesis = client.block_hash(BlockId::Latest).unwrap(); let block_number = 1; diff --git a/crates/ethcore/src/verification/queue/kind.rs b/crates/ethcore/src/verification/queue/kind.rs index 8bbcc46bdd..af8f0e1ce9 100644 --- a/crates/ethcore/src/verification/queue/kind.rs +++ b/crates/ethcore/src/verification/queue/kind.rs @@ -20,7 +20,7 @@ use engines::EthEngine; use error::Error; use ethereum_types::{H256, U256}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; pub use self::{blocks::Blocks, headers::Headers}; @@ -51,13 +51,13 @@ pub trait BlockLike { /// consistent. pub trait Kind: 'static + Sized + Send + Sync { /// The first stage: completely unverified. - type Input: Sized + Send + BlockLike + HeapSizeOf; + type Input: Sized + Send + BlockLike + MallocSizeOf; /// The second stage: partially verified. - type Unverified: Sized + Send + BlockLike + HeapSizeOf; + type Unverified: Sized + Send + BlockLike + MallocSizeOf; /// The third stage: completely verified. - type Verified: Sized + Send + BlockLike + HeapSizeOf; + type Verified: Sized + Send + BlockLike + MallocSizeOf; /// Attempt to create the `Unverified` item from the input. fn create( @@ -88,7 +88,7 @@ pub mod blocks { use bytes::Bytes; use ethereum_types::{H256, U256}; - use heapsize::HeapSizeOf; + use parity_util_mem::MallocSizeOf; /// A mode for verifying blocks. pub struct Blocks; @@ -135,7 +135,7 @@ pub mod blocks { } /// An unverified block. - #[derive(PartialEq, Debug)] + #[derive(PartialEq, Debug, MallocSizeOf)] pub struct Unverified { /// Unverified block header. pub header: Header, @@ -168,15 +168,6 @@ pub mod blocks { } } - impl HeapSizeOf for Unverified { - fn heap_size_of_children(&self) -> usize { - self.header.heap_size_of_children() - + self.transactions.heap_size_of_children() - + self.uncles.heap_size_of_children() - + self.bytes.heap_size_of_children() - } - } - impl BlockLike for Unverified { fn hash(&self) -> H256 { self.header.hash() diff --git a/crates/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs index 2928ccc2e7..e4202c564a 100644 --- a/crates/ethcore/src/verification/queue/mod.rs +++ b/crates/ethcore/src/verification/queue/mod.rs @@ -22,9 +22,9 @@ use client::ClientIoMessage; use engines::EthEngine; use error::{BlockError, Error, ErrorKind, ImportErrorKind}; use ethereum_types::{H256, U256}; -use heapsize::HeapSizeOf; use io::*; use len_caching_lock::LenCachingMutex; +use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; use parking_lot::{Condvar, Mutex, RwLock}; use std::{ cmp, @@ -108,17 +108,12 @@ enum State { } /// An item which is in the process of being verified. +#[derive(MallocSizeOf)] pub struct Verifying { hash: H256, output: Option, } -impl HeapSizeOf for Verifying { - fn heap_size_of_children(&self) -> usize { - self.output.heap_size_of_children() - } -} - /// Status of items in the queue. pub enum Status { /// Currently queued. @@ -378,7 +373,7 @@ impl VerificationQueue { verification .sizes .unverified - .fetch_sub(item.heap_size_of_children(), AtomicOrdering::SeqCst); + .fetch_sub(item.malloc_size_of(), AtomicOrdering::SeqCst); verifying.push_back(Verifying { hash: item.hash(), output: None, @@ -397,10 +392,10 @@ impl VerificationQueue { if e.hash == hash { idx = Some(i); - verification.sizes.verifying.fetch_add( - verified.heap_size_of_children(), - AtomicOrdering::SeqCst, - ); + verification + .sizes + .verifying + .fetch_add(verified.malloc_size_of(), AtomicOrdering::SeqCst); e.output = Some(verified); break; } @@ -460,7 +455,7 @@ impl VerificationQueue { while let Some(output) = verifying.front_mut().and_then(|x| x.output.take()) { assert!(verifying.pop_front().is_some()); - let size = output.heap_size_of_children(); + let size = output.malloc_size_of(); removed_size += size; if bad.contains(&output.parent_hash()) { @@ -564,7 +559,7 @@ impl VerificationQueue { self.verification .sizes .unverified - .fetch_add(item.heap_size_of_children(), AtomicOrdering::SeqCst); + .fetch_add(item.malloc_size_of(), AtomicOrdering::SeqCst); //self.processing.write().insert(hash, item.difficulty()); { @@ -621,7 +616,7 @@ impl VerificationQueue { let mut removed_size = 0; for output in verified.drain(..) { if bad.contains(&output.parent_hash()) { - removed_size += output.heap_size_of_children(); + removed_size += output.malloc_size_of(); bad.insert(output.hash()); if let Some((difficulty, _)) = processing.remove(&output.hash()) { let mut td = self.total_difficulty.write(); @@ -663,7 +658,7 @@ impl VerificationQueue { let drained_size = result .iter() - .map(HeapSizeOf::heap_size_of_children) + .map(MallocSizeOfExt::malloc_size_of) .fold(0, |a, c| a + c); self.verification .sizes diff --git a/crates/ethcore/src/verification/verification.rs b/crates/ethcore/src/verification/verification.rs index 0cafaf8415..f09cef8d37 100644 --- a/crates/ethcore/src/verification/verification.rs +++ b/crates/ethcore/src/verification/verification.rs @@ -28,7 +28,7 @@ use std::{ use bytes::Bytes; use hash::keccak; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::Rlp; use triehash::ordered_trie_root; use unexpected::{Mismatch, OutOfBounds}; @@ -44,6 +44,7 @@ use verification::queue::kind::blocks::Unverified; use time_utils::CheckedSystemTime; /// Preprocessed block data gathered in `verify_block_unordered` call +#[derive(MallocSizeOf)] pub struct PreverifiedBlock { /// Populated block header pub header: Header, @@ -55,14 +56,6 @@ pub struct PreverifiedBlock { pub bytes: Bytes, } -impl HeapSizeOf for PreverifiedBlock { - fn heap_size_of_children(&self) -> usize { - self.header.heap_size_of_children() - + self.transactions.heap_size_of_children() - + self.bytes.heap_size_of_children() - } -} - /// t_nb 4.0 Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block pub fn verify_block_basic( block: &Unverified, @@ -524,10 +517,10 @@ mod tests { use super::*; use blockchain::{BlockDetails, BlockReceipts, TransactionAddress}; + use crypto::publickey::{Generator, Random}; use engines::EthEngine; use error::{BlockError::*, ErrorKind}; - use ethereum_types::{BloomRef, H256, U256}; - use ethkey::{Generator, Random}; + use ethereum_types::{Address, BloomRef, H256, U256}; use hash::keccak; use rlp; use spec::{CommonParams, Spec}; @@ -771,7 +764,7 @@ mod tests { good.set_timestamp(40); good.set_number(10); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let tr1 = TypedTransaction::Legacy(Transaction { action: Action::Create, @@ -794,7 +787,7 @@ mod tests { .sign(keypair.secret(), None); let tr3 = TypedTransaction::Legacy(Transaction { - action: Action::Call(0x0.into()), + action: Action::Call(Address::from_low_u64_be(0x0)), value: U256::from(0), data: Bytes::new(), gas: U256::from(30_000), @@ -871,7 +864,7 @@ mod tests { bad_header.set_transactions_root(eip86_transactions_root.clone()); bad_header.set_uncles_hash(good_uncles_hash.clone()); match basic_test(&create_test_block_with_data(&bad_header, &eip86_transactions, &good_uncles), engine) { - Err(Error(ErrorKind::Transaction(ref e), _)) if e == &::ethkey::Error::InvalidSignature.into() => (), + Err(Error(ErrorKind::Transaction(ref e), _)) if e == &crypto::publickey::Error::InvalidSignature.into() => (), e => panic!("Block verification failed.\nExpected: Transaction Error (Invalid Signature)\nGot: {:?}", e), } @@ -1102,8 +1095,8 @@ mod tests { #[test] fn dust_protection() { + use crypto::publickey::{Generator, Random}; use engines::NullEngine; - use ethkey::{Generator, Random}; use machine::EthereumMachine; use types::transaction::{Action, Transaction}; @@ -1114,7 +1107,7 @@ mod tests { let mut header = Header::default(); header.set_number(1); - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); let bad_transactions: Vec<_> = (0..3) .map(|i| { TypedTransaction::Legacy(Transaction { diff --git a/crates/ethcore/sync/Cargo.toml b/crates/ethcore/sync/Cargo.toml index 5295370654..a449791a32 100644 --- a/crates/ethcore/sync/Cargo.toml +++ b/crates/ethcore/sync/Cargo.toml @@ -17,22 +17,23 @@ ethcore-network = { path = "../../net/network" } ethcore-network-devp2p = { path = "../../net/network-devp2p" } ethereum-forkid = "0.2" primitive_types07 = { package = "primitive-types", version = "0.7"} -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethkey = { path = "../../accounts/ethkey" } ethstore = { path = "../../accounts/ethstore" } fastmap = { path = "../../util/fastmap" } hash-db = "0.11.0" -heapsize = "0.4" -keccak-hash = "0.1" +keccak-hash = "0.5.0" keccak-hasher = { path = "../../util/keccak-hasher" } kvdb = "0.1" log = "0.4" macros = { path = "../../util/macros" } parity-bytes = "0.1" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +parity-util-mem = "0.7" parking_lot = "0.7" -rand = "0.4" -rlp = { version = "0.3.0", features = ["ethereum"] } -rlp04 = { package = "rlp", version = "0.4" } +rand = "0.7.3" +rand_xorshift = "0.2.0" +rlp = { version = "0.4.6" } trace-time = "0.1" triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" } stats = { path = "../../util/stats" } diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index e451969865..74c132a828 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -15,6 +15,7 @@ // along with OpenEthereum. If not, see . use bytes::Bytes; +use crypto::publickey::Secret; use devp2p::NetworkService; use network::{ client_version::ClientVersion, ConnectionFilter, Error, ErrorKind, @@ -38,7 +39,6 @@ use ethcore::{ snapshot::SnapshotService, }; use ethereum_types::{H256, H512, U256, U64}; -use ethkey::Secret; use io::TimerToken; use network::IpFilter; use parking_lot::{Mutex, RwLock}; diff --git a/crates/ethcore/sync/src/block_sync.rs b/crates/ethcore/sync/src/block_sync.rs index 44f33dd198..748e2199dd 100644 --- a/crates/ethcore/sync/src/block_sync.rs +++ b/crates/ethcore/sync/src/block_sync.rs @@ -99,12 +99,6 @@ pub enum BlockDownloaderImportError { Useless, } -impl From for BlockDownloaderImportError { - fn from(_: rlp04::DecoderError) -> BlockDownloaderImportError { - BlockDownloaderImportError::Invalid - } -} - impl From for BlockDownloaderImportError { fn from(_: rlp::DecoderError) -> BlockDownloaderImportError { BlockDownloaderImportError::Invalid @@ -770,8 +764,8 @@ where #[cfg(test)] mod tests { use super::*; + use crypto::publickey::{Generator, Random}; use ethcore::{client::TestBlockChainClient, spec::Spec}; - use ethkey::{Generator, Random}; use hash::keccak; use parking_lot::RwLock; use rlp::{encode_list, RlpStream}; @@ -794,7 +788,7 @@ mod tests { } fn dummy_signed_tx() -> SignedTransaction { - let keypair = Random.generate().unwrap(); + let keypair = Random.generate(); TypedTransaction::Legacy(Transaction::default()).sign(keypair.secret(), None) } diff --git a/crates/ethcore/sync/src/blocks.rs b/crates/ethcore/sync/src/blocks.rs index a4e5b61d81..f5c9ad6756 100644 --- a/crates/ethcore/sync/src/blocks.rs +++ b/crates/ethcore/sync/src/blocks.rs @@ -18,8 +18,8 @@ use bytes::Bytes; use ethcore::verification::queue::kind::blocks::Unverified; use ethereum_types::H256; use hash::{keccak, KECCAK_EMPTY_LIST_RLP, KECCAK_NULL_RLP}; -use heapsize::HeapSizeOf; use network; +use parity_util_mem::MallocSizeOf; use rlp::{DecoderError, Rlp, RlpStream}; use std::collections::{hash_map, BTreeMap, HashMap, HashSet}; use triehash_ethereum::ordered_trie_root; @@ -28,20 +28,14 @@ use types::{ transaction::{TypedTransaction, UnverifiedTransaction}, }; -known_heap_size!(0, HeaderId); +malloc_size_of_is_0!(HeaderId); -#[derive(PartialEq, Debug, Clone)] +#[derive(PartialEq, Debug, Clone, MallocSizeOf)] pub struct SyncHeader { pub bytes: Bytes, pub header: BlockHeader, } -impl HeapSizeOf for SyncHeader { - fn heap_size_of_children(&self) -> usize { - self.bytes.heap_size_of_children() + self.header.heap_size_of_children() - } -} - impl SyncHeader { pub fn from_rlp(bytes: Bytes) -> Result { let result = SyncHeader { @@ -53,6 +47,7 @@ impl SyncHeader { } } +#[derive(MallocSizeOf)] pub struct SyncBody { pub transactions_bytes: Bytes, pub transactions: Vec, @@ -86,16 +81,8 @@ impl SyncBody { } } -impl HeapSizeOf for SyncBody { - fn heap_size_of_children(&self) -> usize { - self.transactions_bytes.heap_size_of_children() - + self.transactions.heap_size_of_children() - + self.uncles_bytes.heap_size_of_children() - + self.uncles.heap_size_of_children() - } -} - /// Block data with optional body. +#[derive(MallocSizeOf)] struct SyncBlock { header: SyncHeader, body: Option, @@ -103,12 +90,6 @@ struct SyncBlock { receipts_root: H256, } -impl HeapSizeOf for SyncBlock { - fn heap_size_of_children(&self) -> usize { - self.header.heap_size_of_children() + self.body.heap_size_of_children() - } -} - fn unverified_from_sync(header: SyncHeader, body: Option) -> Unverified { let mut stream = RlpStream::new_list(3); stream.append_raw(&header.bytes, 1); @@ -588,7 +569,7 @@ impl BlockCollection { (None, receipt_root) } } else { - (None, H256::new()) + (None, H256::default()) }; self.parents.insert(*info.header.parent_hash(), hash); diff --git a/crates/ethcore/sync/src/chain/handler.rs b/crates/ethcore/sync/src/chain/handler.rs index a37eb862bf..6938209b88 100644 --- a/crates/ethcore/sync/src/chain/handler.rs +++ b/crates/ethcore/sync/src/chain/handler.rs @@ -692,8 +692,10 @@ impl SyncHandler { .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; let forkid_validation_error = { - let fork_id = rlp04::Rlp::new(r.as_raw()).val_at(5)?; - r_iter.next().ok_or(rlp::DecoderError::RlpIsTooShort)?; + let fork_id = r_iter + .next() + .ok_or(rlp::DecoderError::RlpIsTooShort)? + .as_val()?; sync.fork_filter .is_compatible(io.chain(), fork_id) .err() diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index bf6103a2bc..4d04fe3885 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -109,7 +109,7 @@ use fastmap::{H256FastMap, H256FastSet}; use hash::keccak; use network::{self, client_version::ClientVersion, PeerId}; use parking_lot::Mutex; -use rand::Rng; +use rand::{seq::SliceRandom, Rng}; use rlp::{DecoderError, RlpStream}; use snapshot::Snapshot; use std::{ @@ -136,7 +136,7 @@ use self::{ pub(crate) use self::supplier::SyncSupplier; use self::{propagator::SyncPropagator, requester::SyncRequester}; -known_heap_size!(0, PeerInfo); +malloc_size_of_is_0!(PeerInfo); /// Possible errors during packet's processing #[derive(Debug, Display)] @@ -380,15 +380,17 @@ impl PeerInfo { #[cfg(not(test))] pub mod random { use rand; - pub fn new() -> rand::ThreadRng { + pub fn new() -> rand::rngs::ThreadRng { rand::thread_rng() } } #[cfg(test)] pub mod random { - use rand::{self, SeedableRng}; - pub fn new() -> rand::XorShiftRng { - rand::XorShiftRng::from_seed([0, 1, 2, 3]) + use rand::SeedableRng; + use rand_xorshift::XorShiftRng; + const RNG_SEED: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + pub fn new() -> XorShiftRng { + XorShiftRng::from_seed(RNG_SEED) } } @@ -630,7 +632,7 @@ impl ChainSync { let mut count = (peers.len() as f64).powf(0.5).round() as usize; count = cmp::min(count, MAX_PEERS_PROPAGATION); count = cmp::max(count, MIN_PEERS_PROPAGATION); - random::new().shuffle(&mut peers); + peers.shuffle(&mut random::new()); peers.truncate(count); peers } @@ -1029,8 +1031,9 @@ impl ChainSync { self.active_peers.len(), peers.len(), self.peers.len() ); - random::new().shuffle(&mut peers); // TODO (#646): sort by rating + peers.shuffle(&mut random::new()); // TODO (#646): sort by rating // prefer peers with higher protocol version + peers.sort_by(|&(_, ref v1), &(_, ref v2)| v1.cmp(v2)); for (peer_id, _) in peers { @@ -1297,7 +1300,7 @@ impl ChainSync { }; trace!(target: "sync", "Sending status to {}, protocol version {}", peer, protocol); - let mut packet = rlp04::RlpStream::new(); + let mut packet = RlpStream::new(); packet.begin_unbounded_list(); let chain = io.chain().chain_info(); packet.append(&(protocol as u32)); @@ -1310,7 +1313,7 @@ impl ChainSync { if warp_protocol { let manifest = io.snapshot_service().manifest(); let block_number = manifest.as_ref().map_or(0, |m| m.block_number); - let manifest_hash = manifest.map_or(H256::new(), |m| keccak(m.into_rlp())); + let manifest_hash = manifest.map_or(H256::default(), |m| keccak(m.into_rlp())); packet.append(&primitive_types07::H256(manifest_hash.0)); packet.append(&block_number); } @@ -1521,7 +1524,6 @@ pub mod tests { miner::{MinerService, PendingOrdering}, }; use ethereum_types::{Address, H256, U256}; - use ethkey; use network::PeerId; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; @@ -1558,7 +1560,7 @@ pub mod tests { let mut rlp = RlpStream::new_list(5); for _ in 0..5 { let mut hash_d_rlp = RlpStream::new_list(2); - let hash: H256 = H256::from(0u64); + let hash: H256 = H256::from_low_u64_be(0u64); let diff: U256 = U256::from(1u64); hash_d_rlp.append(&hash); hash_d_rlp.append(&diff); @@ -1720,7 +1722,7 @@ pub mod tests { #[test] fn should_add_transactions_to_queue() { fn sender(tx: &UnverifiedTransaction) -> Address { - ethkey::public_to_address(&tx.recover_public().unwrap()) + crypto::publickey::public_to_address(&tx.recover_public().unwrap()) } // given diff --git a/crates/ethcore/sync/src/chain/propagator.rs b/crates/ethcore/sync/src/chain/propagator.rs index de79c12073..1d814bca94 100644 --- a/crates/ethcore/sync/src/chain/propagator.rs +++ b/crates/ethcore/sync/src/chain/propagator.rs @@ -20,7 +20,7 @@ use bytes::Bytes; use ethereum_types::H256; use fastmap::H256FastSet; use network::{client_version::ClientCapabilities, PeerId}; -use rand::Rng; +use rand::RngCore; use rlp::RlpStream; use sync_io::SyncIo; use types::{blockchain_info::BlockChainInfo, transaction::SignedTransaction, BlockNumber}; @@ -249,7 +249,7 @@ impl SyncPropagator { pushed += 1; } } - packet.complete_unbounded_list(); + packet.finalize_unbounded_list(); (packet, to_send) }; diff --git a/crates/ethcore/sync/src/chain/supplier.rs b/crates/ethcore/sync/src/chain/supplier.rs index 3746819d5f..9b667e921d 100644 --- a/crates/ethcore/sync/src/chain/supplier.rs +++ b/crates/ethcore/sync/src/chain/supplier.rs @@ -421,7 +421,7 @@ mod test { use ethereum_types::H256; use parking_lot::RwLock; use rlp::{Rlp, RlpStream}; - use std::{collections::VecDeque, sync::RwLock as StdRwLock}; + use std::{collections::VecDeque, str::FromStr, sync::RwLock as StdRwLock}; use tests::{helpers::TestIo, snapshot::TestSnapshotService}; #[test] @@ -470,7 +470,7 @@ mod test { let ss = TestSnapshotService::new(); let io = TestIo::new(&mut client, &ss, &queue, None); - let unknown: H256 = H256::new(); + let unknown: H256 = H256::default(); let result = SyncSupplier::return_block_headers( &io, &Rlp::new(&make_hash_req(&unknown, 1, 0, false)), @@ -614,23 +614,27 @@ mod test { fn return_receipts() { let mut client = TestBlockChainClient::new(); let queue = RwLock::new(VecDeque::new()); - let sync = dummy_sync_with_peer(H256::new(), &client); + let sync = dummy_sync_with_peer(H256::default(), &client); let ss = TestSnapshotService::new(); let mut io = TestIo::new(&mut client, &ss, &queue, None); let mut receipt_list = RlpStream::new_list(4); - receipt_list.append(&H256::from( - "0000000000000000000000000000000000000000000000005555555555555555", - )); - receipt_list.append(&H256::from( - "ff00000000000000000000000000000000000000000000000000000000000000", - )); - receipt_list.append(&H256::from( - "fff0000000000000000000000000000000000000000000000000000000000000", - )); - receipt_list.append(&H256::from( - "aff0000000000000000000000000000000000000000000000000000000000000", - )); + receipt_list.append( + &H256::from_str("0000000000000000000000000000000000000000000000005555555555555555") + .unwrap(), + ); + receipt_list.append( + &H256::from_str("ff00000000000000000000000000000000000000000000000000000000000000") + .unwrap(), + ); + receipt_list.append( + &H256::from_str("fff0000000000000000000000000000000000000000000000000000000000000") + .unwrap(), + ); + receipt_list.append( + &H256::from_str("aff0000000000000000000000000000000000000000000000000000000000000") + .unwrap(), + ); let receipts_request = receipt_list.out(); // it returns rlp ONLY for hashes started with "f" diff --git a/crates/ethcore/sync/src/lib.rs b/crates/ethcore/sync/src/lib.rs index ff2bf8bb3c..ea37d69822 100644 --- a/crates/ethcore/sync/src/lib.rs +++ b/crates/ethcore/sync/src/lib.rs @@ -34,11 +34,14 @@ extern crate ethstore; extern crate fastmap; extern crate keccak_hash as hash; extern crate parity_bytes as bytes; +extern crate parity_crypto as crypto; +#[macro_use] +extern crate parity_util_mem; extern crate parking_lot; extern crate primitive_types07; extern crate rand; +extern crate rand_xorshift; extern crate rlp; -extern crate rlp04; extern crate stats; extern crate triehash_ethereum; @@ -56,8 +59,6 @@ extern crate macros; #[macro_use] extern crate log; #[macro_use] -extern crate heapsize; -#[macro_use] extern crate trace_time; mod block_sync; diff --git a/crates/ethcore/sync/src/snapshot.rs b/crates/ethcore/sync/src/snapshot.rs index 72b90574da..b5f33081e7 100644 --- a/crates/ethcore/sync/src/snapshot.rs +++ b/crates/ethcore/sync/src/snapshot.rs @@ -191,15 +191,19 @@ mod test { } fn test_manifest() -> (ManifestData, H256, Vec, Vec) { - let state_chunks: Vec = (0..20).map(|_| H256::random().to_vec()).collect(); - let block_chunks: Vec = (0..20).map(|_| H256::random().to_vec()).collect(); + let state_chunks: Vec = (0..20) + .map(|_| H256::random().as_bytes().to_vec()) + .collect(); + let block_chunks: Vec = (0..20) + .map(|_| H256::random().as_bytes().to_vec()) + .collect(); let manifest = ManifestData { version: 2, state_hashes: state_chunks.iter().map(|data| keccak(data)).collect(), block_hashes: block_chunks.iter().map(|data| keccak(data)).collect(), - state_root: H256::new(), + state_root: H256::default(), block_number: 42, - block_hash: H256::new(), + block_hash: H256::default(), }; let mhash = keccak(manifest.clone().into_rlp()); (manifest, mhash, state_chunks, block_chunks) @@ -222,7 +226,9 @@ mod test { let (manifest, mhash, state_chunks, block_chunks) = test_manifest(); snapshot.reset_to(&manifest, &mhash); assert_eq!(snapshot.done_chunks(), 0); - assert!(snapshot.validate_chunk(&H256::random().to_vec()).is_err()); + assert!(snapshot + .validate_chunk(&H256::random().as_bytes().to_vec()) + .is_err()); let requested: Vec = (0..40).map(|_| snapshot.needed_chunk().unwrap()).collect(); assert!(snapshot.needed_chunk().is_none()); diff --git a/crates/ethcore/sync/src/tests/consensus.rs b/crates/ethcore/sync/src/tests/consensus.rs index 6af66ec295..d3e9495127 100644 --- a/crates/ethcore/sync/src/tests/consensus.rs +++ b/crates/ethcore/sync/src/tests/consensus.rs @@ -15,6 +15,7 @@ // along with OpenEthereum. If not, see . use super::helpers::*; +use crypto::publickey::{KeyPair, Secret}; use ethcore::{ client::{ChainInfo, ClientIoMessage}, engines, @@ -22,7 +23,6 @@ use ethcore::{ spec::Spec, }; use ethereum_types::{Address, U256}; -use ethkey::{KeyPair, Secret}; use hash::keccak; use io::{IoChannel, IoHandler}; use std::sync::Arc; @@ -44,8 +44,8 @@ fn new_tx(secret: &Secret, nonce: U256, chain_id: u64) -> PendingTransaction { #[test] fn authority_round() { - let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); - let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); + let s0 = KeyPair::from_secret_slice(keccak("1").as_bytes()).unwrap(); + let s1 = KeyPair::from_secret_slice(keccak("0").as_bytes()).unwrap(); let chain_id = Spec::new_test_round().chain_id(); let mut net = TestNet::with_spec(2, SyncConfig::default(), Spec::new_test_round); diff --git a/crates/ethcore/sync/src/tests/helpers.rs b/crates/ethcore/sync/src/tests/helpers.rs index 89eb22dd68..8d00714bec 100644 --- a/crates/ethcore/sync/src/tests/helpers.rs +++ b/crates/ethcore/sync/src/tests/helpers.rs @@ -37,10 +37,7 @@ use network::{self, client_version::ClientVersion, PacketId, PeerId, ProtocolId, use parking_lot::RwLock; use std::{ collections::{HashMap, HashSet, VecDeque}, - sync::{ - Arc, RwLock as StdRwLock, RwLockReadGuard as StdRwLockReadGuard, - RwLockWriteGuard as StdRwLockWriteGuard, - }, + sync::{Arc, RwLock as StdRwLock}, }; use sync_io::SyncIo; use tests::snapshot::*; diff --git a/crates/ethcore/sync/src/tests/snapshot.rs b/crates/ethcore/sync/src/tests/snapshot.rs index 89f635b5f6..9cc07c1b3b 100644 --- a/crates/ethcore/sync/src/tests/snapshot.rs +++ b/crates/ethcore/sync/src/tests/snapshot.rs @@ -56,16 +56,16 @@ impl TestSnapshotService { let num_state_chunks = num_chunks / 2; let num_block_chunks = num_chunks - num_state_chunks; let state_chunks: Vec = (0..num_state_chunks) - .map(|_| H256::random().to_vec()) + .map(|_| H256::random().as_bytes().to_vec()) .collect(); let block_chunks: Vec = (0..num_block_chunks) - .map(|_| H256::random().to_vec()) + .map(|_| H256::random().as_bytes().to_vec()) .collect(); let manifest = ManifestData { version: 2, state_hashes: state_chunks.iter().map(|data| keccak(data)).collect(), block_hashes: block_chunks.iter().map(|data| keccak(data)).collect(), - state_root: H256::new(), + state_root: H256::default(), block_number: block_number, block_hash: block_hash, }; @@ -188,7 +188,7 @@ fn snapshot_sync() { let mut net = TestNet::new_with_config(5, config); let snapshot_service = Arc::new(TestSnapshotService::new_with_snapshot( 16, - H256::new(), + H256::default(), 500000, )); for i in 0..4 { diff --git a/crates/ethcore/sync/src/transactions_stats.rs b/crates/ethcore/sync/src/transactions_stats.rs index 989900ecbd..44e47ec401 100644 --- a/crates/ethcore/sync/src/transactions_stats.rs +++ b/crates/ethcore/sync/src/transactions_stats.rs @@ -104,15 +104,16 @@ impl TransactionsStats { mod tests { use super::{Stats, TransactionsStats}; + use ethereum_types::{H256, H512}; use std::collections::{HashMap, HashSet}; #[test] fn should_keep_track_of_propagations() { // given let mut stats = TransactionsStats::default(); - let hash = 5.into(); - let enodeid1 = 2.into(); - let enodeid2 = 5.into(); + let hash = H256::from_low_u64_be(5); + let enodeid1 = H512::from_low_u64_be(2); + let enodeid2 = H512::from_low_u64_be(5); // when stats.propagated(&hash, Some(enodeid1), 5); @@ -137,8 +138,8 @@ mod tests { fn should_remove_hash_from_tracking() { // given let mut stats = TransactionsStats::default(); - let hash = 5.into(); - let enodeid1 = 5.into(); + let hash = H256::from_low_u64_be(5); + let enodeid1 = H512::from_low_u64_be(5); stats.propagated(&hash, Some(enodeid1), 10); // when diff --git a/crates/ethcore/types/Cargo.toml b/crates/ethcore/types/Cargo.toml index 9a16ddcb61..86c0d48ea8 100644 --- a/crates/ethcore/types/Cargo.toml +++ b/crates/ethcore/types/Cargo.toml @@ -5,12 +5,12 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -ethereum-types = "0.4" -ethkey = { path = "../../accounts/ethkey" } -heapsize = "0.4" -keccak-hash = "0.1" +ethereum-types = "0.9.2" +keccak-hash = "0.5.0" parity-bytes = "0.1" -rlp = { version = "0.3.0", features = ["ethereum"] } +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +parity-util-mem = "0.7" +rlp = { version = "0.4.6" } rlp_derive = { path = "../../util/rlp-derive" } unexpected = { path = "../../util/unexpected" } serde = "1.0" diff --git a/crates/ethcore/types/src/account_diff.rs b/crates/ethcore/types/src/account_diff.rs index 1144712c77..7ea690df1c 100644 --- a/crates/ethcore/types/src/account_diff.rs +++ b/crates/ethcore/types/src/account_diff.rs @@ -120,17 +120,17 @@ impl AccountDiff { // TODO: refactor into something nicer. fn interpreted_hash(u: &H256) -> String { - if u <= &H256::from(0xffffffff) { + if u <= &H256::from_low_u64_be(0xffffffff) { format!( "{} = 0x{:x}", - U256::from(&**u).low_u32(), - U256::from(&**u).low_u32() + U256::from(u.as_bytes()).low_u32(), + U256::from(u.as_bytes()).low_u32() ) - } else if u <= &H256::from(u64::max_value()) { + } else if u <= &H256::from_low_u64_be(u64::max_value()) { format!( "{} = 0x{:x}", - U256::from(&**u).low_u64(), - U256::from(&**u).low_u64() + U256::from(u.as_bytes()).low_u64(), + U256::from(u.as_bytes()).low_u64() ) // } else if u <= &H256::from("0xffffffffffffffffffffffffffffffffffffffff") { // format!("@{}", Address::from(u)) diff --git a/crates/ethcore/types/src/encoded.rs b/crates/ethcore/types/src/encoded.rs index daf15eba0e..f550740224 100644 --- a/crates/ethcore/types/src/encoded.rs +++ b/crates/ethcore/types/src/encoded.rs @@ -27,22 +27,16 @@ use block::Block as FullBlock; use ethereum_types::{Address, Bloom, H256, U256}; use hash::keccak; use header::Header as FullHeader; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::{self, Rlp, RlpStream}; use transaction::UnverifiedTransaction; use views::{self, BlockView, BodyView, HeaderView}; use BlockNumber; /// Owning header view. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub struct Header(Vec); -impl HeapSizeOf for Header { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - impl Header { /// Create a new owning header view. /// Expects the data to be an RLP-encoded header -- any other case will likely lead to @@ -153,15 +147,9 @@ impl Header { } /// Owning block body view. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub struct Body(Vec); -impl HeapSizeOf for Body { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - impl Body { /// Create a new owning block body view. The raw bytes passed in must be an rlp-encoded block /// body. @@ -246,15 +234,9 @@ impl Body { } /// Owning block view. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub struct Block(Vec); -impl HeapSizeOf for Block { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - impl Block { /// Create a new owning block view. The raw bytes passed in must be an rlp-encoded block. pub fn new(raw: Vec) -> Self { diff --git a/crates/ethcore/types/src/filter.rs b/crates/ethcore/types/src/filter.rs index 84b8a3b64a..822c2f7de4 100644 --- a/crates/ethcore/types/src/filter.rs +++ b/crates/ethcore/types/src/filter.rs @@ -71,7 +71,7 @@ impl Filter { let blooms = match self.address { Some(ref addresses) if !addresses.is_empty() => addresses .iter() - .map(|ref address| Bloom::from(BloomInput::Raw(address))) + .map(|ref address| Bloom::from(BloomInput::Raw(address.as_bytes()))) .collect(), _ => vec![Bloom::default()], }; @@ -85,7 +85,7 @@ impl Filter { .into_iter() .map(|topic| { let mut b = bloom.clone(); - b.accrue(BloomInput::Raw(topic)); + b.accrue(BloomInput::Raw(topic.as_bytes())); b }) .collect::>() @@ -119,10 +119,11 @@ impl Filter { #[cfg(test)] mod tests { - use ethereum_types::Bloom; + use ethereum_types::{Bloom, H160, H256}; use filter::Filter; use ids::BlockId; use log_entry::LogEntry; + use std::str::FromStr; #[test] fn test_bloom_possibilities_none() { @@ -145,11 +146,15 @@ mod tests { let filter = Filter { from_block: BlockId::Earliest, to_block: BlockId::Latest, - address: Some(vec!["b372018f3be9e171df0581136b59d2faf73a7d5d".into()]), + address: Some(vec![H160::from_str( + "b372018f3be9e171df0581136b59d2faf73a7d5d", + ) + .unwrap()]), topics: vec![ - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - ]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()]), None, None, None, @@ -158,7 +163,7 @@ mod tests { }; let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()] as Vec); + assert_eq!(possibilities, vec![Bloom::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()] as Vec); } #[test] @@ -166,14 +171,19 @@ mod tests { let filter = Filter { from_block: BlockId::Earliest, to_block: BlockId::Latest, - address: Some(vec!["b372018f3be9e171df0581136b59d2faf73a7d5d".into()]), + address: Some(vec![H160::from_str( + "b372018f3be9e171df0581136b59d2faf73a7d5d", + ) + .unwrap()]), topics: vec![ - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - ]), - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - ]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()]), None, None, ], @@ -181,7 +191,7 @@ mod tests { }; let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()] as Vec); + assert_eq!(possibilities, vec![Bloom::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()] as Vec); } #[test] @@ -190,21 +200,34 @@ mod tests { from_block: BlockId::Earliest, to_block: BlockId::Latest, address: Some(vec![ - "b372018f3be9e171df0581136b59d2faf73a7d5d".into(), - "b372018f3be9e171df0581136b59d2faf73a7d5d".into(), + H160::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), + H160::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), ]), topics: vec![ Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), + H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap(), + H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap(), ]), Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - ]), - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), + H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap(), + H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap(), ]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()]), None, ], limit: None, @@ -213,7 +236,7 @@ mod tests { // number of possibilites should be equal 2 * 2 * 2 * 1 = 8 let possibilities = filter.bloom_possibilities(); assert_eq!(possibilities.len(), 8); - assert_eq!(possibilities[0], Bloom::from("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000")); + assert_eq!(possibilities[0], Bloom::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()); } #[test] @@ -221,14 +244,19 @@ mod tests { let filter = Filter { from_block: BlockId::Earliest, to_block: BlockId::Latest, - address: Some(vec!["b372018f3be9e171df0581136b59d2faf73a7d5d".into()]), + address: Some(vec![H160::from_str( + "b372018f3be9e171df0581136b59d2faf73a7d5d", + ) + .unwrap()]), topics: vec![ - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - ]), - Some(vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa".into(), - ]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()]), + Some(vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa", + ) + .unwrap()]), None, None, ], @@ -236,28 +264,37 @@ mod tests { }; let entry0 = LogEntry { - address: "b372018f3be9e171df0581136b59d2faf73a7d5d".into(), + address: H160::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), topics: vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9") + .unwrap(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa") + .unwrap(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9") + .unwrap(), ], data: vec![], }; let entry1 = LogEntry { - address: "b372018f3be9e171df0581136b59d2faf73a7d5e".into(), + address: H160::from_str("b372018f3be9e171df0581136b59d2faf73a7d5e").unwrap(), topics: vec![ - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa".into(), - "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9") + .unwrap(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23fa") + .unwrap(), + H256::from_str("ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9") + .unwrap(), ], data: vec![], }; let entry2 = LogEntry { - address: "b372018f3be9e171df0581136b59d2faf73a7d5d".into(), - topics: vec!["ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9".into()], + address: H160::from_str("b372018f3be9e171df0581136b59d2faf73a7d5d").unwrap(), + topics: vec![H256::from_str( + "ff74e91598aed6ae5d2fdcf8b24cd2c7be49a0808112a305069355b7160f23f9", + ) + .unwrap()], data: vec![], }; diff --git a/crates/ethcore/types/src/header.rs b/crates/ethcore/types/src/header.rs index f53412becd..88c68e8358 100644 --- a/crates/ethcore/types/src/header.rs +++ b/crates/ethcore/types/src/header.rs @@ -19,7 +19,7 @@ use bytes::Bytes; use ethereum_types::{Address, Bloom, H256, U256}; use hash::{keccak, KECCAK_EMPTY_LIST_RLP, KECCAK_NULL_RLP}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; use BlockNumber; @@ -49,7 +49,7 @@ pub struct ExtendedHeader { /// which is non-specific. /// /// Doesn't do all that much on its own. -#[derive(Debug, Clone, Eq)] +#[derive(Debug, Clone, Eq, MallocSizeOf)] pub struct Header { /// Parent hash. parent_hash: H256, @@ -393,12 +393,6 @@ impl Encodable for Header { } } -impl HeapSizeOf for Header { - fn heap_size_of_children(&self) -> usize { - self.extra_data.heap_size_of_children() + self.seal.heap_size_of_children() - } -} - impl ExtendedHeader { /// Returns combined difficulty of all ancestors together with the difficulty of this header. pub fn total_score(&self) -> U256 { diff --git a/crates/ethcore/types/src/lib.rs b/crates/ethcore/types/src/lib.rs index 5c99c105bd..2eafc66ee8 100644 --- a/crates/ethcore/types/src/lib.rs +++ b/crates/ethcore/types/src/lib.rs @@ -35,10 +35,10 @@ #![warn(unused_extern_crates)] extern crate ethereum_types; -extern crate ethkey; -extern crate heapsize; extern crate keccak_hash as hash; extern crate parity_bytes as bytes; +extern crate parity_crypto as crypto; +extern crate parity_util_mem; extern crate rlp; extern crate serde_repr; extern crate unexpected; diff --git a/crates/ethcore/types/src/log_entry.rs b/crates/ethcore/types/src/log_entry.rs index 129e78a92b..8c72df15bb 100644 --- a/crates/ethcore/types/src/log_entry.rs +++ b/crates/ethcore/types/src/log_entry.rs @@ -18,13 +18,13 @@ use bytes::Bytes; use ethereum_types::{Address, Bloom, BloomInput, H256}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use std::ops::Deref; use BlockNumber; /// A record of execution for a `LOG` operation. -#[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] +#[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable, MallocSizeOf)] pub struct LogEntry { /// The address of the contract executing at the point of the `LOG` operation. pub address: Address, @@ -34,21 +34,16 @@ pub struct LogEntry { pub data: Bytes, } -impl HeapSizeOf for LogEntry { - fn heap_size_of_children(&self) -> usize { - self.topics.heap_size_of_children() + self.data.heap_size_of_children() - } -} - impl LogEntry { /// Calculates the bloom of this log entry. pub fn bloom(&self) -> Bloom { - self.topics - .iter() - .fold(Bloom::from(BloomInput::Raw(&self.address)), |mut b, t| { - b.accrue(BloomInput::Raw(t)); + self.topics.iter().fold( + Bloom::from(BloomInput::Raw(self.address.as_bytes())), + |mut b, t| { + b.accrue(BloomInput::Raw(t.as_bytes())); b - }) + }, + ) } } diff --git a/crates/ethcore/types/src/receipt.rs b/crates/ethcore/types/src/receipt.rs index 787c8f25f5..2026081a84 100644 --- a/crates/ethcore/types/src/receipt.rs +++ b/crates/ethcore/types/src/receipt.rs @@ -18,7 +18,7 @@ use super::transaction::TypedTxId; use ethereum_types::{Address, Bloom, H160, H256, U256}; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::{DecoderError, Rlp, RlpStream}; use std::ops::{Deref, DerefMut}; @@ -26,7 +26,7 @@ use log_entry::{LocalizedLogEntry, LogEntry}; use BlockNumber; /// Transaction outcome store in the receipt. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub enum TransactionOutcome { /// Status and state root are unknown under EIP-98 rules. Unknown, @@ -37,7 +37,7 @@ pub enum TransactionOutcome { } /// Information describing execution of a transaction. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub struct LegacyReceipt { /// The total gas used in the block following execution of the transaction. pub gas_used: U256, @@ -106,7 +106,7 @@ impl LegacyReceipt { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub enum TypedReceipt { Legacy(LegacyReceipt), AccessList(LegacyReceipt), @@ -231,12 +231,6 @@ impl DerefMut for TypedReceipt { } } -impl HeapSizeOf for TypedReceipt { - fn heap_size_of_children(&self) -> usize { - self.receipt().logs.heap_size_of_children() - } -} - /// Receipt with additional info. #[derive(Debug, Clone, PartialEq)] pub struct RichReceipt { @@ -302,7 +296,9 @@ pub struct LocalizedReceipt { #[cfg(test)] mod tests { use super::{LegacyReceipt, TransactionOutcome, TypedReceipt, TypedTxId}; + use ethereum_types::{H160, H256}; use log_entry::LogEntry; + use std::str::FromStr; #[test] fn test_no_state_root() { @@ -313,7 +309,7 @@ mod tests { TransactionOutcome::Unknown, 0x40cae.into(), vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + address: H160::from_str("dcf421d093428b096ca501a7cd1a740855a7976f").unwrap(), topics: vec![], data: vec![0u8; 32], }], @@ -329,11 +325,14 @@ mod tests { TypedTxId::Legacy, LegacyReceipt::new( TransactionOutcome::StateRoot( - "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + H256::from_str( + "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee", + ) + .unwrap(), ), 0x40cae.into(), vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + address: H160::from_str("dcf421d093428b096ca501a7cd1a740855a7976f").unwrap(), topics: vec![], data: vec![0u8; 32], }], @@ -352,11 +351,14 @@ mod tests { TypedTxId::AccessList, LegacyReceipt::new( TransactionOutcome::StateRoot( - "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into(), + H256::from_str( + "2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee", + ) + .unwrap(), ), 0x40cae.into(), vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + address: H160::from_str("dcf421d093428b096ca501a7cd1a740855a7976f").unwrap(), topics: vec![], data: vec![0u8; 32], }], @@ -377,7 +379,7 @@ mod tests { TransactionOutcome::StatusCode(0), 0x40cae.into(), vec![LogEntry { - address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + address: H160::from_str("dcf421d093428b096ca501a7cd1a740855a7976f").unwrap(), topics: vec![], data: vec![0u8; 32], }], diff --git a/crates/ethcore/types/src/transaction/error.rs b/crates/ethcore/types/src/transaction/error.rs index c4813eba30..aa927c55e4 100644 --- a/crates/ethcore/types/src/transaction/error.rs +++ b/crates/ethcore/types/src/transaction/error.rs @@ -17,7 +17,6 @@ use std::{error, fmt}; use ethereum_types::U256; -use ethkey; use rlp; use unexpected::OutOfBounds; @@ -88,8 +87,8 @@ pub enum Error { TransactionTypeNotEnabled, } -impl From for Error { - fn from(err: ethkey::Error) -> Self { +impl From for Error { + fn from(err: crypto::publickey::Error) -> Self { Error::InvalidSignature(format!("{}", err)) } } diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 892795a6ad..55a10506da 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -16,10 +16,10 @@ //! Transaction data structure. -use ethereum_types::{Address, H160, H256, U256}; -use ethkey::{self, public_to_address, recover, Public, Secret, Signature}; +use crypto::publickey::{self, public_to_address, recover, Public, Secret, Signature}; +use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; use hash::keccak; -use heapsize::HeapSizeOf; +use parity_util_mem::MallocSizeOf; use rlp::{self, DecoderError, Rlp, RlpStream}; use std::ops::Deref; @@ -43,7 +43,7 @@ pub const SYSTEM_ADDRESS: Address = H160([ ]); /// Transaction action type. -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub enum Action { /// Create creates new contract. Create, @@ -124,7 +124,7 @@ pub mod signature { /// A set of information describing an externally-originating message call /// or contract creation operation. -#[derive(Default, Debug, Clone, PartialEq, Eq)] +#[derive(Default, Debug, Clone, PartialEq, Eq, MallocSizeOf)] pub struct Transaction { /// Nonce. pub nonce: U256, @@ -229,13 +229,7 @@ impl Transaction { } } -impl HeapSizeOf for Transaction { - fn heap_size_of_children(&self) -> usize { - self.data.heap_size_of_children() - } -} - -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub struct AccessListTx { pub transaction: Transaction, //optional access list @@ -308,7 +302,7 @@ impl AccessListTx { }), chain_id, signature, - 0.into(), + H256::zero(), ) .compute_hash()) } @@ -368,7 +362,7 @@ impl AccessListTx { } } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub enum TypedTransaction { Legacy(Transaction), // old legacy RLP encoded transaction AccessList(AccessListTx), // EIP-2930 Transaction with a list of addresses and storage keys that the transaction plans to access. @@ -393,7 +387,7 @@ impl TypedTransaction { /// Signs the transaction as coming from `sender`. pub fn sign(self, secret: &Secret, chain_id: Option) -> SignedTransaction { - let sig = ::ethkey::sign(secret, &self.signature_hash(chain_id)) + let sig = publickey::sign(secret, &self.signature_hash(chain_id)) .expect("data is valid and context has signing capabilities; qed"); SignedTransaction::new(self.with_signature(sig, chain_id)) .expect("secret is valid so it's recoverable") @@ -409,7 +403,7 @@ impl TypedTransaction { s: sig.s().into(), standard_v: sig.v().into(), }, - hash: 0.into(), + hash: H256::zero(), } .compute_hash() } @@ -425,7 +419,7 @@ impl TypedTransaction { s: U256::one(), standard_v: 4, }, - hash: 0.into(), + hash: H256::zero(), } .compute_hash(), sender: from, @@ -447,7 +441,7 @@ impl TypedTransaction { s: U256::zero(), standard_v: 0, }, - hash: 0.into(), + hash: H256::zero(), } .compute_hash(), sender: UNSIGNED_SENDER, @@ -466,7 +460,7 @@ impl TypedTransaction { s: U256::one(), standard_v: 0, }, - hash: 0.into(), + hash: H256::zero(), } .compute_hash() } @@ -567,17 +561,8 @@ impl TypedTransaction { } } -impl HeapSizeOf for TypedTransaction { - fn heap_size_of_children(&self) -> usize { - match self { - TypedTransaction::Legacy(legacy) => legacy.heap_size_of_children(), - TypedTransaction::AccessList(oal) => oal.tx().heap_size_of_children(), - } - } -} - /// Components that constitute transaction signature -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub struct SignatureComponents { /// The V field of the signature; the LS bit described which half of the curve our point falls /// in. It can be 0 or 1. @@ -606,7 +591,7 @@ impl SignatureComponents { } /// Signed transaction information without verified signature. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub struct UnverifiedTransaction { /// Plain Transaction. unsigned: TypedTransaction, @@ -618,12 +603,6 @@ pub struct UnverifiedTransaction { hash: H256, } -impl HeapSizeOf for UnverifiedTransaction { - fn heap_size_of_children(&self) -> usize { - self.unsigned.heap_size_of_children() - } -} - impl Deref for UnverifiedTransaction { type Target = TypedTransaction; @@ -704,17 +683,15 @@ impl UnverifiedTransaction { /// Construct a signature object from the sig. pub fn signature(&self) -> Signature { - Signature::from_rsv( - &self.signature.r.into(), - &self.signature.s.into(), - self.standard_v(), - ) + let r: H256 = BigEndianHash::from_uint(&self.signature.r); + let s: H256 = BigEndianHash::from_uint(&self.signature.s); + Signature::from_rsv(&r, &s, self.standard_v()) } /// Checks whether the signature has a low 's' value. - pub fn check_low_s(&self) -> Result<(), ethkey::Error> { + pub fn check_low_s(&self) -> Result<(), publickey::Error> { if !self.signature().is_low_s() { - Err(ethkey::Error::InvalidSignature.into()) + Err(publickey::Error::InvalidSignature.into()) } else { Ok(()) } @@ -726,7 +703,7 @@ impl UnverifiedTransaction { } /// Recovers the public key of the sender. - pub fn recover_public(&self) -> Result { + pub fn recover_public(&self) -> Result { Ok(recover( &self.signature(), &self.unsigned.signature_hash(self.chain_id()), @@ -740,7 +717,7 @@ impl UnverifiedTransaction { chain_id: Option, ) -> Result<(), error::Error> { if self.is_unsigned() { - return Err(ethkey::Error::InvalidSignature.into()); + return Err(publickey::Error::InvalidSignature.into()); } if check_low_s { self.check_low_s()?; @@ -755,19 +732,13 @@ impl UnverifiedTransaction { } /// A `UnverifiedTransaction` with successfully recovered `sender`. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub struct SignedTransaction { transaction: UnverifiedTransaction, sender: Address, public: Option, } -impl HeapSizeOf for SignedTransaction { - fn heap_size_of_children(&self) -> usize { - self.transaction.heap_size_of_children() - } -} - impl Deref for SignedTransaction { type Target = UnverifiedTransaction; fn deref(&self) -> &Self::Target { @@ -783,9 +754,9 @@ impl From for UnverifiedTransaction { impl SignedTransaction { // t_nb 5.3.1 Try to verify transaction and recover sender. - pub fn new(transaction: UnverifiedTransaction) -> Result { + pub fn new(transaction: UnverifiedTransaction) -> Result { if transaction.is_unsigned() { - return Err(ethkey::Error::InvalidSignature); + return Err(publickey::Error::InvalidSignature); } let public = transaction.recover_public()?; let sender = public_to_address(&public); @@ -903,8 +874,9 @@ impl From for PendingTransaction { #[cfg(test)] mod tests { use super::*; - use ethereum_types::U256; + use ethereum_types::{H160, U256}; use hash::keccak; + use std::str::FromStr; #[test] fn sender_test() { @@ -915,14 +887,17 @@ mod tests { assert_eq!(t.tx().gas_price, U256::from(0x01u64)); assert_eq!(t.tx().nonce, U256::from(0x00u64)); if let Action::Call(ref to) = t.tx().action { - assert_eq!(*to, "095e7baea6a6c7c4c2dfeb977efac326af552d87".into()); + assert_eq!( + *to, + H160::from_str("095e7baea6a6c7c4c2dfeb977efac326af552d87").unwrap() + ); } else { panic!(); } assert_eq!(t.tx().value, U256::from(0x0au64)); assert_eq!( public_to_address(&t.recover_public().unwrap()), - "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into() + H160::from_str("0f65fe9276bc9a24ae7083ae28e2660ef72df99e").unwrap() ); assert_eq!(t.chain_id(), None); } @@ -943,9 +918,9 @@ mod tests { #[test] fn signing_eip155_zero_chainid() { - use ethkey::{Generator, Random}; + use self::publickey::{Generator, Random}; - let key = Random.generate().unwrap(); + let key = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), @@ -956,7 +931,7 @@ mod tests { }); let hash = t.signature_hash(Some(0)); - let sig = ::ethkey::sign(&key.secret(), &hash).unwrap(); + let sig = publickey::sign(&key.secret(), &hash).unwrap(); let u = t.with_signature(sig, Some(0)); assert!(SignedTransaction::new(u).is_ok()); @@ -964,9 +939,9 @@ mod tests { #[test] fn signing() { - use ethkey::{Generator, Random}; + use self::publickey::{Generator, Random}; - let key = Random.generate().unwrap(); + let key = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), @@ -990,12 +965,12 @@ mod tests { value: U256::from(1), data: b"Hello!".to_vec(), }) - .fake_sign(Address::from(0x69)); - assert_eq!(Address::from(0x69), t.sender()); + .fake_sign(Address::from_low_u64_be(0x69)); + assert_eq!(Address::from_low_u64_be(0x69), t.sender()); assert_eq!(t.chain_id(), None); let t = t.clone(); - assert_eq!(Address::from(0x69), t.sender()); + assert_eq!(Address::from_low_u64_be(0x69), t.sender()); assert_eq!(t.chain_id(), None); } @@ -1018,15 +993,15 @@ mod tests { let res = SignedTransaction::new(t.transaction); match res { - Err(ethkey::Error::InvalidSignature) => {} + Err(publickey::Error::InvalidSignature) => {} _ => panic!("null signature should be rejected"), } } #[test] fn should_recover_from_chain_specific_signing() { - use ethkey::{Generator, Random}; - let key = Random.generate().unwrap(); + use self::publickey::{Generator, Random}; + let key = Random.generate(); let t = TypedTransaction::Legacy(Transaction { action: Action::Create, nonce: U256::from(42), @@ -1042,8 +1017,8 @@ mod tests { #[test] fn should_encode_decode_access_list_tx() { - use ethkey::{Generator, Random}; - let key = Random.generate().unwrap(); + use self::publickey::{Generator, Random}; + let key = Random.generate(); let t = TypedTransaction::AccessList(AccessListTx::new( Transaction { action: Action::Create, @@ -1054,8 +1029,11 @@ mod tests { data: b"Hello!".to_vec(), }, vec![ - (H160::from(10), vec![H256::from(102), H256::from(103)]), - (H160::from(400), vec![]), + ( + H160::from_low_u64_be(10), + vec![H256::from_low_u64_be(102), H256::from_low_u64_be(103)], + ), + (H160::from_low_u64_be(400), vec![]), ], )) .sign(&key.secret(), Some(69)); @@ -1116,19 +1094,19 @@ mod tests { let signed = TypedTransaction::decode(&FromHex::from_hex(tx_data).unwrap()) .expect("decoding tx data failed"); let signed = SignedTransaction::new(signed).unwrap(); - assert_eq!(signed.sender(), address.into()); + assert_eq!(signed.sender(), H160::from_str(address).unwrap()); println!("chainid: {:?}", signed.chain_id()); }; - test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"); - test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112"); - test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be"); - test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0"); - test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554"); - test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4"); - test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35"); - test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332"); - test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029"); - test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f"); + test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "f0f6f18bca1b28cd68e4357452947e021241e9ce"); + test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "23ef145a395ea3fa3deb533b8a9e1b4c6c25d112"); + test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "2e485e0c23b4c3c542628a5f672eeab0ad4888be"); + test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "82a88539669a3fd524d669e858935de5e5410cf0"); + test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "f9358f2538fd5ccfeb848b64a96b743fcc930554"); + test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "a8f7aba377317440bc5b26198a363ad22af1f3a4"); + test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "f1f571dc362a0e5b2696b8e775f8491d3e50de35"); + test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "d37922162ab7cea97c97a87551ed02c9a38b7332"); + test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "9bddad43f934d313c2b79ca28a432dd2b7281029"); + test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "3c24d7329e92f84f08556ceb6df1cdb0104ca49f"); } } diff --git a/crates/ethcore/types/src/views/block.rs b/crates/ethcore/types/src/views/block.rs index 7b3b3e44d6..1d7fbf3457 100644 --- a/crates/ethcore/types/src/views/block.rs +++ b/crates/ethcore/types/src/views/block.rs @@ -201,7 +201,9 @@ impl<'a> BlockView<'a> { #[cfg(test)] mod tests { use super::BlockView; + use ethereum_types::H256; use rustc_hex::FromHex; + use std::str::FromStr; #[test] fn test_block_view() { @@ -211,7 +213,8 @@ mod tests { let view = view!(BlockView, &rlp); assert_eq!( view.hash(), - "2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259".into() + H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259") + .unwrap() ); assert_eq!(view.transactions_count(), 1); assert_eq!(view.uncles_count(), 0); diff --git a/crates/ethcore/types/src/views/header.rs b/crates/ethcore/types/src/views/header.rs index e29713e37d..a5ecd8e2ef 100644 --- a/crates/ethcore/types/src/views/header.rs +++ b/crates/ethcore/types/src/views/header.rs @@ -145,8 +145,9 @@ impl<'a> HeaderView<'a> { #[cfg(test)] mod tests { use super::HeaderView; - use ethereum_types::Bloom; + use ethereum_types::{Bloom, H160, H256}; use rustc_hex::FromHex; + use std::str::FromStr; #[test] fn test_header_view() { @@ -160,31 +161,37 @@ mod tests { let view = view!(HeaderView, &rlp); assert_eq!( view.hash(), - "2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259".into() + H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259") + .unwrap() ); assert_eq!( view.parent_hash(), - "d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7".into() + H256::from_str("d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7") + .unwrap() ); assert_eq!( view.uncles_hash(), - "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".into() + H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") + .unwrap() ); assert_eq!( view.author(), - "8888f1f195afa192cfee860698584c030f4c9db1".into() + H160::from_str("8888f1f195afa192cfee860698584c030f4c9db1").unwrap() ); assert_eq!( view.state_root(), - "5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25".into() + H256::from_str("5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25") + .unwrap() ); assert_eq!( view.transactions_root(), - "88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158".into() + H256::from_str("88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158") + .unwrap() ); assert_eq!( view.receipts_root(), - "07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1".into() + H256::from_str("07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1") + .unwrap() ); assert_eq!(view.log_bloom(), Bloom::default()); assert_eq!(view.difficulty(), 0x020080.into()); diff --git a/crates/ethjson/Cargo.toml b/crates/ethjson/Cargo.toml index b86f34f1d6..819db5dbf0 100644 --- a/crates/ethjson/Cargo.toml +++ b/crates/ethjson/Cargo.toml @@ -6,8 +6,8 @@ authors = ["Parity Technologies "] [dependencies] common-types = { path = "../ethcore/types", features = ["test-helpers"] } -ethkey = { path = "../accounts/ethkey" } -ethereum-types = "0.4" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } +ethereum-types = "0.9.2" rustc-hex = "1.0" serde = "1.0" serde_json = "1.0" diff --git a/crates/ethjson/src/hash.rs b/crates/ethjson/src/hash.rs index fc98dc3c62..c0b7d834bb 100644 --- a/crates/ethjson/src/hash.rs +++ b/crates/ethjson/src/hash.rs @@ -19,7 +19,6 @@ use ethereum_types::{ Bloom as Hash2048, H160 as Hash160, H256 as Hash256, H520 as Hash520, H64 as Hash64, }; -use rustc_hex::ToHex; use serde::{ de::{Error, Visitor}, Deserialize, Deserializer, Serialize, Serializer, @@ -63,8 +62,8 @@ macro_rules! impl_hash { E: Error, { let value = match value.len() { - 0 => $inner::from(0), - 2 if value == "0x" => $inner::from(0), + 0 => $inner::from_low_u64_be(0), + 2 if value == "0x" => $inner::from_low_u64_be(0), _ if value.starts_with("0x") => { $inner::from_str(&value[2..]).map_err(|e| { Error::custom( @@ -99,9 +98,7 @@ macro_rules! impl_hash { where S: Serializer, { - let mut hex = "0x".to_owned(); - hex.push_str(&self.0.to_hex()); - serializer.serialize_str(&hex) + serializer.serialize_str(&format!("{:#x}", self.0)) } } }; @@ -127,7 +124,7 @@ mod test { assert_eq!( deserialized, vec![ - H256(ethereum_types::H256::from(0)), + H256(ethereum_types::H256::zero()), H256( ethereum_types::H256::from_str( "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae" @@ -141,8 +138,8 @@ mod test { #[test] fn hash_into() { assert_eq!( - ethereum_types::H256::from(0), - H256(ethereum_types::H256::from(0)).into() + ethereum_types::H256::zero(), + H256(ethereum_types::H256::zero()).into() ); } } diff --git a/crates/ethjson/src/lib.rs b/crates/ethjson/src/lib.rs index f5a6d5f837..910175dfbd 100644 --- a/crates/ethjson/src/lib.rs +++ b/crates/ethjson/src/lib.rs @@ -16,7 +16,7 @@ extern crate common_types as types; extern crate ethereum_types; -extern crate ethkey; +extern crate parity_crypto as crypto; extern crate rustc_hex; extern crate serde; extern crate serde_json; diff --git a/crates/ethjson/src/spec/authority_round.rs b/crates/ethjson/src/spec/authority_round.rs index 6a76855d16..45132d7b73 100644 --- a/crates/ethjson/src/spec/authority_round.rs +++ b/crates/ethjson/src/spec/authority_round.rs @@ -77,6 +77,7 @@ mod tests { use hash::Address; use serde_json; use spec::{authority_round::AuthorityRound, validator_set::ValidatorSet}; + use std::str::FromStr; use uint::Uint; #[test] @@ -99,9 +100,9 @@ mod tests { assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); assert_eq!( deserialized.params.validators, - ValidatorSet::List(vec![Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b" - ))]) + ValidatorSet::List(vec![Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() + )]) ); assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24)))); assert_eq!(deserialized.params.immediate_transitions, None); @@ -138,9 +139,9 @@ mod tests { assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); assert_eq!( deserialized.params.validators, - ValidatorSet::Contract(Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b" - ))) + ValidatorSet::Contract(Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() + )) ); let mut rewards: BTreeMap = BTreeMap::new(); rewards.insert(Uint(U256::from(0)), Uint(U256::from(5000000))); diff --git a/crates/ethjson/src/spec/basic_authority.rs b/crates/ethjson/src/spec/basic_authority.rs index 0f0ebc1794..d744407a5b 100644 --- a/crates/ethjson/src/spec/basic_authority.rs +++ b/crates/ethjson/src/spec/basic_authority.rs @@ -44,6 +44,7 @@ mod tests { use hash::Address; use serde_json; use spec::{basic_authority::BasicAuthority, validator_set::ValidatorSet}; + use std::str::FromStr; use uint::Uint; #[test] @@ -60,9 +61,9 @@ mod tests { let deserialized: BasicAuthority = serde_json::from_str(s).unwrap(); assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d))); - let vs = ValidatorSet::List(vec![Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - ))]); + let vs = ValidatorSet::List(vec![Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap(), + )]); assert_eq!(deserialized.params.validators, vs); } } diff --git a/crates/ethjson/src/spec/ethash.rs b/crates/ethjson/src/spec/ethash.rs index 6d2ec0d40c..b7e8c0907c 100644 --- a/crates/ethjson/src/spec/ethash.rs +++ b/crates/ethjson/src/spec/ethash.rs @@ -109,6 +109,7 @@ mod tests { use hash::Address; use serde_json; use spec::ethash::{BlockReward, Ethash, EthashParams}; + use std::str::FromStr; use uint::Uint; #[test] @@ -168,30 +169,70 @@ mod tests { block_reward_contract_code: None, block_reward_contract_transition: None, dao_hardfork_transition: Some(Uint(U256::from(0x08))), - dao_hardfork_beneficiary: Some(Address(H160::from( - "0xabcabcabcabcabcabcabcabcabcabcabcabcabca" - ))), + dao_hardfork_beneficiary: Some(Address( + H160::from_str("abcabcabcabcabcabcabcabcabcabcabcabcabca").unwrap() + )), dao_hardfork_accounts: Some(vec![ - Address(H160::from("0x304a554a310c7e546dfe434669c62820b7d83490")), - Address(H160::from("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79")), - Address(H160::from("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f")), - Address(H160::from("0x17802f43a0137c506ba92291391a8a8f207f487d")), - Address(H160::from("0xb136707642a4ea12fb4bae820f03d2562ebff487")), - Address(H160::from("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940")), - Address(H160::from("0xf14c14075d6c4ed84b86798af0956deef67365b5")), - Address(H160::from("0xca544e5c4687d109611d0f8f928b53a25af72448")), - Address(H160::from("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c")), - Address(H160::from("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7")), - Address(H160::from("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6")), - Address(H160::from("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2")), - Address(H160::from("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a")), - Address(H160::from("0xd343b217de44030afaa275f54d31a9317c7f441e")), - Address(H160::from("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106")), - Address(H160::from("0xda2fef9e4a3230988ff17df2165440f37e8b1708")), - Address(H160::from("0xf4c64518ea10f995918a454158c6b61407ea345c")), - Address(H160::from("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97")), - Address(H160::from("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")), - Address(H160::from("0x807640a13483f8ac783c557fcdf27be11ea4ac7a")), + Address( + H160::from_str("304a554a310c7e546dfe434669c62820b7d83490").unwrap() + ), + Address( + H160::from_str("914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79").unwrap() + ), + Address( + H160::from_str("fe24cdd8648121a43a7c86d289be4dd2951ed49f").unwrap() + ), + Address( + H160::from_str("17802f43a0137c506ba92291391a8a8f207f487d").unwrap() + ), + Address( + H160::from_str("b136707642a4ea12fb4bae820f03d2562ebff487").unwrap() + ), + Address( + H160::from_str("dbe9b615a3ae8709af8b93336ce9b477e4ac0940").unwrap() + ), + Address( + H160::from_str("f14c14075d6c4ed84b86798af0956deef67365b5").unwrap() + ), + Address( + H160::from_str("ca544e5c4687d109611d0f8f928b53a25af72448").unwrap() + ), + Address( + H160::from_str("aeeb8ff27288bdabc0fa5ebb731b6f409507516c").unwrap() + ), + Address( + H160::from_str("cbb9d3703e651b0d496cdefb8b92c25aeb2171f7").unwrap() + ), + Address( + H160::from_str("accc230e8a6e5be9160b8cdf2864dd2a001c28b6").unwrap() + ), + Address( + H160::from_str("2b3455ec7fedf16e646268bf88846bd7a2319bb2").unwrap() + ), + Address( + H160::from_str("4613f3bca5c44ea06337a9e439fbc6d42e501d0a").unwrap() + ), + Address( + H160::from_str("d343b217de44030afaa275f54d31a9317c7f441e").unwrap() + ), + Address( + H160::from_str("84ef4b2357079cd7a7c69fd7a37cd0609a679106").unwrap() + ), + Address( + H160::from_str("da2fef9e4a3230988ff17df2165440f37e8b1708").unwrap() + ), + Address( + H160::from_str("f4c64518ea10f995918a454158c6b61407ea345c").unwrap() + ), + Address( + H160::from_str("7602b46df5390e432ef1c307d4f2c9ff6d65cc97").unwrap() + ), + Address( + H160::from_str("bb9bc244d798123fde783fcc1c72d3bb8c189413").unwrap() + ), + Address( + H160::from_str("807640a13483f8ac783c557fcdf27be11ea4ac7a").unwrap() + ), ]), difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))), difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))), diff --git a/crates/ethjson/src/spec/genesis.rs b/crates/ethjson/src/spec/genesis.rs index 0cbcd68795..38445f1234 100644 --- a/crates/ethjson/src/spec/genesis.rs +++ b/crates/ethjson/src/spec/genesis.rs @@ -83,29 +83,38 @@ mod tests { deserialized, Genesis { seal: Seal::Ethereum(Ethereum { - nonce: H64(Eth64::from("0x00006d6f7264656e")), - mix_hash: H256(Eth256::from( - "0x0000000000000000000000000000000000000000000000000000000000000000" - )) + nonce: H64(Eth64::from_str("00006d6f7264656e").unwrap()), + mix_hash: H256( + Eth256::from_str( + "0000000000000000000000000000000000000000000000000000000000000000" + ) + .unwrap() + ) }), difficulty: Uint(U256::from(0x400000000u64)), - author: Some(Address(H160::from( - "0x1000000000000000000000000000000000000001" - ))), + author: Some(Address( + H160::from_str("1000000000000000000000000000000000000001").unwrap() + )), timestamp: Some(Uint(U256::from(0x07))), - parent_hash: Some(H256(Eth256::from( - "0x9000000000000000000000000000000000000000000000000000000000000000" - ))), + parent_hash: Some(H256( + Eth256::from_str( + "9000000000000000000000000000000000000000000000000000000000000000" + ) + .unwrap() + )), gas_limit: Uint(U256::from(0x1388)), transactions_root: None, receipts_root: None, - state_root: Some(H256(Eth256::from( - "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" - ))), + state_root: Some(H256( + Eth256::from_str( + "d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" + ) + .unwrap() + )), gas_used: None, extra_data: Some( Bytes::from_str( - "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" + "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" ) .unwrap() ), diff --git a/crates/ethjson/src/spec/seal.rs b/crates/ethjson/src/spec/seal.rs index 5bf894fdfc..a53a1f07d5 100644 --- a/crates/ethjson/src/spec/seal.rs +++ b/crates/ethjson/src/spec/seal.rs @@ -75,6 +75,7 @@ mod tests { use hash::*; use serde_json; use spec::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal}; + use std::str::FromStr; use uint::Uint; #[test] @@ -108,10 +109,13 @@ mod tests { assert_eq!( deserialized[0], Seal::Ethereum(Ethereum { - nonce: H64(Eth64::from("0x0000000000000042")), - mix_hash: H256(Eth256::from( - "0x1000000000000000000000000000000000000000000000000000000000000001" - )) + nonce: H64(Eth64::from_str("0000000000000042").unwrap()), + mix_hash: H256( + Eth256::from_str( + "1000000000000000000000000000000000000000000000000000000000000001" + ) + .unwrap() + ) }) ); @@ -128,14 +132,14 @@ mod tests { // [2] assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal { step: Uint(U256::from(0x0)), - signature: H520(Eth520::from("0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002")) + signature: H520(Eth520::from_str("2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002").unwrap()) })); // [3] assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal { round: Uint(U256::from(0x3)), - proposal: H520(Eth520::from("0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")), - precommits: vec![H520(Eth520::from("0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"))] + proposal: H520(Eth520::from_str("3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003").unwrap()), + precommits: vec![H520(Eth520::from_str("4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004").unwrap())] })); } } diff --git a/crates/ethjson/src/spec/validator_set.rs b/crates/ethjson/src/spec/validator_set.rs index 17c75162c1..e419050820 100644 --- a/crates/ethjson/src/spec/validator_set.rs +++ b/crates/ethjson/src/spec/validator_set.rs @@ -41,6 +41,7 @@ mod tests { use hash::Address; use serde_json; use spec::validator_set::ValidatorSet; + use std::str::FromStr; use uint::Uint; #[test] @@ -64,21 +65,21 @@ mod tests { assert_eq!( deserialized[0], - ValidatorSet::List(vec![Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b" - ))]) + ValidatorSet::List(vec![Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() + )]) ); assert_eq!( deserialized[1], - ValidatorSet::SafeContract(Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b" - ))) + ValidatorSet::SafeContract(Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() + )) ); assert_eq!( deserialized[2], - ValidatorSet::Contract(Address(H160::from( - "0xc6d9d2cd449a754c494264e1809c50e34d64562b" - ))) + ValidatorSet::Contract(Address( + H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() + )) ); match deserialized[3] { ValidatorSet::Multi(ref map) => { diff --git a/crates/ethjson/src/state/test.rs b/crates/ethjson/src/state/test.rs index 4411ff5866..cc76fa1011 100644 --- a/crates/ethjson/src/state/test.rs +++ b/crates/ethjson/src/state/test.rs @@ -17,7 +17,7 @@ //! General test deserialization. use bytes::Bytes; -use ethkey::Secret; +use crypto::publickey::Secret; use hash::{Address, H256}; use maybe::MaybeEmpty; use serde_json::{self, Error}; @@ -100,7 +100,10 @@ fn sign_with_secret(tx: TypedTransaction, secret: Option) -> SignedTrans impl MultiTransaction { /// Build transaction with given indexes. pub fn select(&self, indexes: &PostStateIndexes) -> SignedTransaction { - let secret = self.secret.clone().map(|s| Secret::from(s.0)); + let secret = self + .secret + .clone() + .map(|s| Secret::import_key(s.0.as_bytes()).expect("Expect signature to be valid")); let to: Option
= self.to.clone().into(); let transaction = Transaction { nonce: self.nonce.clone().into(), diff --git a/crates/ethjson/src/uint.rs b/crates/ethjson/src/uint.rs index 0df6131d63..fdcf4931a2 100644 --- a/crates/ethjson/src/uint.rs +++ b/crates/ethjson/src/uint.rs @@ -35,19 +35,18 @@ impl Into for Uint { impl Into for Uint { fn into(self) -> u64 { - u64::from(self.0) + self.0.low_u64() } } impl Into for Uint { fn into(self) -> usize { - // TODO: clean it after util conversions refactored. - u64::from(self.0) as usize + self.0.low_u64() as usize } } impl Into for Uint { fn into(self) -> u8 { - u64::from(self.0) as u8 + self.0.low_u64() as u8 } } diff --git a/crates/net/network-devp2p/Cargo.toml b/crates/net/network-devp2p/Cargo.toml index 2b3873945a..3db0434e32 100644 --- a/crates/net/network-devp2p/Cargo.toml +++ b/crates/net/network-devp2p/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Parity Technologies "] log = "0.4" mio = "0.6.8" bytes = "0.4" -rand = "0.4" +rand = "0.7.3" tiny-keccak = "1.4" rust-crypto = "0.2.34" slab = "0.2" @@ -21,14 +21,14 @@ ansi_term = "0.10" rustc-hex = "1.0" ethcore-io = { path = "../../runtime/io", features = ["mio"] } parity-bytes = "0.1" -parity-crypto = "0.3.0" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } ethcore-network = { path = "../network" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethkey = { path = "../../../crates/accounts/ethkey" } -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } parity-path = "0.1" ipnetwork = "0.12.6" -keccak-hash = "0.1" +keccak-hash = "0.5.0" parity-snappy = "0.1" serde = "1.0" serde_json = "1.0" diff --git a/crates/net/network-devp2p/src/connection.rs b/crates/net/network-devp2p/src/connection.rs index 40dbd04876..16f22b77e2 100644 --- a/crates/net/network-devp2p/src/connection.rs +++ b/crates/net/network-devp2p/src/connection.rs @@ -15,8 +15,11 @@ // along with OpenEthereum. If not, see . use bytes::{Buf, BufMut}; +use crypto::{ + aes::{AesCtr256, AesEcb256}, + publickey::Secret, +}; use ethereum_types::{H128, H256, H512}; -use ethkey::crypto; use handshake::Handshake; use hash::{keccak, write_keccak}; use io::{IoContext, StreamToken}; @@ -27,7 +30,6 @@ use mio::{ }; use network::{Error, ErrorKind}; use parity_bytes::*; -use rcrypto::{aessafe::*, blockmodes::*, buffer::*, symmetriccipher::*}; use rlp::{Rlp, RlpStream}; use std::{ collections::VecDeque, @@ -320,11 +322,11 @@ pub struct EncryptedConnection { /// Underlying tcp connection pub connection: Connection, /// Egress data encryptor - encoder: CtrMode, + encoder: AesCtr256, /// Ingress data decryptor - decoder: CtrMode, + decoder: AesCtr256, /// Ingress data decryptor - mac_encoder: EcbEncryptor>, + mac_encoder_key: Secret, /// MAC for egress data egress_mac: Keccak, /// MAC for ingress data @@ -337,36 +339,46 @@ pub struct EncryptedConnection { payload_len: usize, } +const NULL_IV: [u8; 16] = [0; 16]; impl EncryptedConnection { /// Create an encrypted connection out of the handshake. pub fn new(handshake: &mut Handshake) -> Result { - let shared = crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)?; - let mut nonce_material = H512::new(); + let shared = parity_crypto::publickey::ecdh::agree( + handshake.ecdhe.secret(), + &handshake.remote_ephemeral, + )?; + let mut nonce_material = H512::default(); if handshake.originated { - handshake.remote_nonce.copy_to(&mut nonce_material[0..32]); - handshake.nonce.copy_to(&mut nonce_material[32..64]); + (&mut nonce_material[0..32]).copy_from_slice(handshake.remote_nonce.as_bytes()); + (&mut nonce_material[32..64]).copy_from_slice(handshake.nonce.as_bytes()); } else { - handshake.nonce.copy_to(&mut nonce_material[0..32]); - handshake.remote_nonce.copy_to(&mut nonce_material[32..64]); + (&mut nonce_material[0..32]).copy_from_slice(handshake.nonce.as_bytes()); + (&mut nonce_material[32..64]).copy_from_slice(handshake.remote_nonce.as_bytes()); } - let mut key_material = H512::new(); - shared.copy_to(&mut key_material[0..32]); + let mut key_material = H512::default(); + (&mut key_material[0..32]).copy_from_slice(shared.as_bytes()); write_keccak(&nonce_material, &mut key_material[32..64]); - keccak(&key_material).copy_to(&mut key_material[32..64]); - keccak(&key_material).copy_to(&mut key_material[32..64]); + let key_material_keccak = keccak(&key_material); + (&mut key_material[32..64]).copy_from_slice(key_material_keccak.as_bytes()); + let key_material_keccak = keccak(&key_material); + (&mut key_material[32..64]).copy_from_slice(key_material_keccak.as_bytes()); + + // Using a 0 IV with CTR is fine as long as the same IV is never reused with the same key. + // This is the case here: ecdh creates a new secret which will be the symmetric key used + // only for this session the 0 IV is only use once with this secret, so we are in the case + // of same IV use for different key. + let encoder = AesCtr256::new(&key_material[32..64], &NULL_IV)?; + let decoder = AesCtr256::new(&key_material[32..64], &NULL_IV)?; - let iv = vec![0u8; 16]; - let encoder = CtrMode::new(AesSafe256Encryptor::new(&key_material[32..64]), iv); - let iv = vec![0u8; 16]; - let decoder = CtrMode::new(AesSafe256Encryptor::new(&key_material[32..64]), iv); + let key_material_keccak = keccak(&key_material); + (&mut key_material[32..64]).copy_from_slice(key_material_keccak.as_bytes()); - keccak(&key_material).copy_to(&mut key_material[32..64]); - let mac_encoder = - EcbEncryptor::new(AesSafe256Encryptor::new(&key_material[32..64]), NoPadding); + let mac_encoder_key: Secret = Secret::copy_from_slice(&key_material[32..64]) + .expect("can create Secret from 32 bytes; qed"); let mut egress_mac = Keccak::new_keccak256(); let mut mac_material = H256::from_slice(&key_material[32..64]) ^ handshake.remote_nonce; - egress_mac.update(&mac_material); + egress_mac.update(mac_material.as_bytes()); egress_mac.update(if handshake.originated { &handshake.auth_cipher } else { @@ -375,7 +387,7 @@ impl EncryptedConnection { let mut ingress_mac = Keccak::new_keccak256(); mac_material = H256::from_slice(&key_material[32..64]) ^ handshake.nonce; - ingress_mac.update(&mac_material); + ingress_mac.update(mac_material.as_bytes()); ingress_mac.update(if handshake.originated { &handshake.ack_cipher } else { @@ -388,7 +400,7 @@ impl EncryptedConnection { connection, encoder, decoder, - mac_encoder, + mac_encoder_key, egress_mac, ingress_mac, read_state: EncryptedConnectionState::Header, @@ -408,86 +420,68 @@ impl EncryptedConnection { where Message: Send + Clone + Sync + 'static, { + const HEADER_LEN: usize = 16; let mut header = RlpStream::new(); let len = payload.len(); if len > MAX_PAYLOAD_SIZE { bail!(ErrorKind::OversizedPacket); } + header.append_raw(&[(len >> 16) as u8, (len >> 8) as u8, len as u8], 1); header.append_raw(&[0xc2u8, 0x80u8, 0x80u8], 1); - //TODO: get rid of vectors here + let padding = (16 - (len % 16)) % 16; + + let mut packet = vec![0u8; 16 + 16 + len + padding + 16]; let mut header = header.out(); - let padding = (16 - (payload.len() % 16)) % 16; - header.resize(16, 0u8); - - let mut packet = vec![0u8; 32 + payload.len() + padding + 16]; - self.encoder - .encrypt( - &mut RefReadBuffer::new(&header), - &mut RefWriteBuffer::new(&mut packet), - false, - ) - .expect("Invalid length or padding"); + header.resize(HEADER_LEN, 0u8); + &mut packet[..HEADER_LEN].copy_from_slice(&mut header); + self.encoder.encrypt(&mut packet[..HEADER_LEN])?; EncryptedConnection::update_mac( &mut self.egress_mac, - &mut self.mac_encoder, - &packet[0..16], - ); - self.egress_mac.clone().finalize(&mut packet[16..32]); - self.encoder - .encrypt( - &mut RefReadBuffer::new(payload), - &mut RefWriteBuffer::new(&mut packet[32..(32 + len)]), - padding == 0, - ) - .expect("Invalid length or padding"); + &self.mac_encoder_key, + &packet[..HEADER_LEN], + )?; + self.egress_mac + .clone() + .finalize(&mut packet[HEADER_LEN..32]); + &mut packet[32..32 + len].copy_from_slice(payload); + self.encoder.encrypt(&mut packet[32..32 + len])?; if padding != 0 { - let pad = [0u8; 16]; self.encoder - .encrypt( - &mut RefReadBuffer::new(&pad[0..padding]), - &mut RefWriteBuffer::new(&mut packet[(32 + len)..(32 + len + padding)]), - true, - ) - .expect("Invalid length or padding"); + .encrypt(&mut packet[(32 + len)..(32 + len + padding)])?; } self.egress_mac.update(&packet[32..(32 + len + padding)]); - EncryptedConnection::update_mac(&mut self.egress_mac, &mut self.mac_encoder, &[0u8; 0]); + EncryptedConnection::update_mac(&mut self.egress_mac, &self.mac_encoder_key, &[0u8; 0])?; self.egress_mac .clone() .finalize(&mut packet[(32 + len + padding)..]); self.connection.send(io, packet); + Ok(()) } /// Decrypt and authenticate an incoming packet header. Prepare for receiving payload. - fn read_header(&mut self, header: &[u8]) -> Result<(), Error> { + fn read_header(&mut self, mut header: Bytes) -> Result<(), Error> { if header.len() != ENCRYPTED_HEADER_LEN { return Err(ErrorKind::Auth.into()); } EncryptedConnection::update_mac( &mut self.ingress_mac, - &mut self.mac_encoder, + &self.mac_encoder_key, &header[0..16], - ); - let mac = &header[16..]; - let mut expected = H256::new(); - self.ingress_mac.clone().finalize(&mut expected); - if mac != &expected[0..16] { - return Err(ErrorKind::Auth.into()); + )?; + { + let mac = &header[16..]; + let mut expected = H256::zero(); + self.ingress_mac.clone().finalize(expected.as_bytes_mut()); + if mac != &expected[0..16] { + return Err(ErrorKind::Auth.into()); + } } + self.decoder.decrypt(&mut header[..16])?; - let mut hdec = H128::new(); - self.decoder - .decrypt( - &mut RefReadBuffer::new(&header[0..16]), - &mut RefWriteBuffer::new(&mut hdec), - false, - ) - .expect("Invalid length or padding"); - - let length = ((((hdec[0] as u32) << 8) + (hdec[1] as u32)) << 8) + (hdec[2] as u32); - let header_rlp = Rlp::new(&hdec[3..6]); + let length = ((((header[0] as u32) << 8) + (header[1] as u32)) << 8) + (header[2] as u32); + let header_rlp = Rlp::new(&header[3..6]); let protocol_id = header_rlp.val_at::(0)?; self.payload_len = length as usize; @@ -501,60 +495,40 @@ impl EncryptedConnection { } /// Decrypt and authenticate packet payload. - fn read_payload(&mut self, payload: &[u8]) -> Result { + fn read_payload(&mut self, mut payload: Bytes) -> Result { let padding = (16 - (self.payload_len % 16)) % 16; let full_length = self.payload_len + padding + 16; if payload.len() != full_length { return Err(ErrorKind::Auth.into()); } self.ingress_mac.update(&payload[0..payload.len() - 16]); - EncryptedConnection::update_mac(&mut self.ingress_mac, &mut self.mac_encoder, &[0u8; 0]); - let mac = &payload[(payload.len() - 16)..]; - let mut expected = H128::new(); - self.ingress_mac.clone().finalize(&mut expected); - if mac != &expected[..] { - return Err(ErrorKind::Auth.into()); - } + EncryptedConnection::update_mac(&mut self.ingress_mac, &self.mac_encoder_key, &[0u8; 0])?; - let mut packet = vec![0u8; self.payload_len]; - self.decoder - .decrypt( - &mut RefReadBuffer::new(&payload[0..self.payload_len]), - &mut RefWriteBuffer::new(&mut packet), - false, - ) - .expect("Invalid length or padding"); - let mut pad_buf = [0u8; 16]; + { + let mac = &payload[(payload.len() - 16)..]; + let mut expected = H128::default(); + self.ingress_mac.clone().finalize(expected.as_bytes_mut()); + if mac != &expected[..] { + return Err(ErrorKind::Auth.into()); + } + } self.decoder - .decrypt( - &mut RefReadBuffer::new(&payload[self.payload_len..(payload.len() - 16)]), - &mut RefWriteBuffer::new(&mut pad_buf), - false, - ) - .expect("Invalid length or padding"); + .decrypt(&mut payload[..self.payload_len + padding])?; + payload.truncate(self.payload_len); Ok(Packet { protocol: self.protocol_id, - data: packet, + data: payload, }) } /// Update MAC after reading or writing any data. - fn update_mac( - mac: &mut Keccak, - mac_encoder: &mut EcbEncryptor>, - seed: &[u8], - ) { - let mut prev = H128::new(); - mac.clone().finalize(&mut prev); - let mut enc = H128::new(); - mac_encoder - .encrypt( - &mut RefReadBuffer::new(&prev), - &mut RefWriteBuffer::new(&mut enc), - true, - ) - .expect("Error updating MAC"); - mac_encoder.reset(); + fn update_mac(mac: &mut Keccak, mac_encoder_key: &Secret, seed: &[u8]) -> Result<(), Error> { + let mut prev = H128::default(); + mac.clone().finalize(prev.as_bytes_mut()); + let mut enc = H128::default(); + &mut enc[..].copy_from_slice(prev.as_bytes()); + let mac_encoder = AesEcb256::new(mac_encoder_key.as_bytes())?; + mac_encoder.encrypt(enc.as_bytes_mut())?; enc = enc ^ if seed.is_empty() { @@ -562,7 +536,8 @@ impl EncryptedConnection { } else { H128::from_slice(seed) }; - mac.update(&enc); + mac.update(enc.as_bytes()); + Ok(()) } /// Readable IO handler. Tracker receive status and returns decoded packet if available. @@ -573,7 +548,7 @@ impl EncryptedConnection { io.clear_timer(self.connection.token)?; if let EncryptedConnectionState::Header = self.read_state { if let Some(data) = self.connection.readable()? { - self.read_header(&data)?; + self.read_header(data)?; io.register_timer(self.connection.token, RECEIVE_PAYLOAD)?; } }; @@ -582,7 +557,7 @@ impl EncryptedConnection { Some(data) => { self.read_state = EncryptedConnectionState::Header; self.connection.expect(ENCRYPTED_HEADER_LEN); - Ok(Some(self.read_payload(&data)?)) + Ok(Some(self.read_payload(data)?)) } None => Ok(None), } @@ -601,41 +576,6 @@ impl EncryptedConnection { } } -#[test] -pub fn test_encryption() { - use ethereum_types::{H128, H256}; - use std::str::FromStr; - let key = - H256::from_str("2212767d793a7a3d66f869ae324dd11bd17044b82c9f463b8a541a4d089efec5").unwrap(); - let before = H128::from_str("12532abaec065082a3cf1da7d0136f15").unwrap(); - let before2 = H128::from_str("7e99f682356fdfbc6b67a9562787b18a").unwrap(); - let after = H128::from_str("89464c6b04e7c99e555c81d3f7266a05").unwrap(); - let after2 = H128::from_str("85c070030589ef9c7a2879b3a8489316").unwrap(); - - let mut got = H128::new(); - - let mut encoder = EcbEncryptor::new(AesSafe256Encryptor::new(&key), NoPadding); - encoder - .encrypt( - &mut RefReadBuffer::new(&before), - &mut RefWriteBuffer::new(&mut got), - true, - ) - .unwrap(); - encoder.reset(); - assert_eq!(got, after); - got = H128::new(); - encoder - .encrypt( - &mut RefReadBuffer::new(&before2), - &mut RefWriteBuffer::new(&mut got), - true, - ) - .unwrap(); - encoder.reset(); - assert_eq!(got, after2); -} - #[cfg(test)] mod tests { use std::{ @@ -794,6 +734,32 @@ mod tests { IoContext::new(IoChannel::disconnected(), 0) } + #[test] + pub fn test_encryption() { + use ethereum_types::{H128, H256}; + use std::str::FromStr; + let key = + H256::from_str("2212767d793a7a3d66f869ae324dd11bd17044b82c9f463b8a541a4d089efec5") + .unwrap(); + let before = H128::from_str("12532abaec065082a3cf1da7d0136f15").unwrap(); + let before2 = H128::from_str("7e99f682356fdfbc6b67a9562787b18a").unwrap(); + let after = H128::from_str("89464c6b04e7c99e555c81d3f7266a05").unwrap(); + let after2 = H128::from_str("85c070030589ef9c7a2879b3a8489316").unwrap(); + + let mut got = H128::default(); + + let encoder = AesEcb256::new(key.as_bytes()).unwrap(); + got.as_bytes_mut().copy_from_slice(before.as_bytes()); + encoder.encrypt(got.as_bytes_mut()).unwrap(); + assert_eq!(got, after); + + let encoder = AesEcb256::new(key.as_bytes()).unwrap(); + got = H128::default(); + got.as_bytes_mut().copy_from_slice(&before2.as_bytes()); + encoder.encrypt(got.as_bytes_mut()).unwrap(); + assert_eq!(got, after2); + } + #[test] fn connection_expect() { let mut connection = TestConnection::new(); diff --git a/crates/net/network-devp2p/src/discovery.rs b/crates/net/network-devp2p/src/discovery.rs index 72f785a427..794e51f329 100644 --- a/crates/net/network-devp2p/src/discovery.rs +++ b/crates/net/network-devp2p/src/discovery.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{recover, sign, KeyPair, Secret}; use ethereum_types::{H256, H520}; -use ethkey::{recover, sign, KeyPair, Secret}; use hash::keccak; use lru_cache::LruCache; use network::{Error, ErrorKind, IpFilter}; @@ -199,7 +199,7 @@ impl<'a> Discovery<'a> { public_endpoint: public, discovery_initiated: false, discovery_round: None, - discovery_id: NodeId::new(), + discovery_id: NodeId::default(), discovery_nodes: HashSet::new(), node_buckets: (0..ADDRESS_BITS).map(|_| NodeBucket::new()).collect(), other_observed_nodes: LruCache::new(OBSERVED_NODES_MAX_SIZE), @@ -450,7 +450,7 @@ impl<'a> Discovery<'a> { payload: &[u8], ) -> Result { let packet = assemble_packet(packet_id, payload, &self.secret)?; - let hash = H256::from(&packet[0..32]); + let hash = H256::from_slice(&packet[0..32]); self.send_to(packet, address.clone()); Ok(hash) } @@ -531,7 +531,7 @@ impl<'a> Discovery<'a> { let packet_id = signed[0]; let rlp = Rlp::new(&signed[1..]); match packet_id { - PACKET_PING => self.on_ping(&rlp, &node_id, &from, &hash_signed), + PACKET_PING => self.on_ping(&rlp, &node_id, &from, hash_signed.as_bytes()), PACKET_PONG => self.on_pong(&rlp, &node_id, &from), PACKET_FIND_NODE => self.on_find_node(&rlp, &node_id, &from), PACKET_NEIGHBOURS => self.on_neighbours(&rlp, &node_id, &from), @@ -960,7 +960,7 @@ fn assemble_packet(packet_id: u8, bytes: &[u8], secret: &Secret) -> Result. use connection::Connection; +use crypto::publickey::{ecdh, ecies, recover, sign, Generator, KeyPair, Public, Random, Secret}; use ethereum_types::{H256, H520}; -use ethkey::{ - crypto::{ecdh, ecies}, - recover, sign, Generator, KeyPair, Public, Random, Secret, -}; use host::HostInfo; use io::{IoContext, StreamToken}; use mio::tcp::*; @@ -91,15 +88,15 @@ impl Handshake { id: if let Some(id) = id { *id } else { - NodeId::new() + NodeId::default() }, connection: Connection::new(token, socket), originated: false, state: HandshakeState::New, - ecdhe: Random.generate()?, + ecdhe: Random.generate(), nonce: *nonce, - remote_ephemeral: Public::new(), - remote_nonce: H256::new(), + remote_ephemeral: Public::default(), + remote_nonce: H256::default(), remote_version: PROTOCOL_VERSION, auth_cipher: Bytes::new(), ack_cipher: Bytes::new(), @@ -184,8 +181,8 @@ impl Handshake { remote_nonce: &[u8], remote_version: u64, ) -> Result<(), Error> { - self.id.clone_from_slice(remote_public); - self.remote_nonce.clone_from_slice(remote_nonce); + self.id = NodeId::from_slice(remote_public); + self.remote_nonce = H256::from_slice(remote_nonce); self.remote_version = remote_version; let shared = *ecdh::agree(host_secret, &self.id)?; let signature = H520::from_slice(sig); @@ -252,9 +249,9 @@ impl Handshake { let remote_version: u64 = rlp.val_at(3)?; self.set_auth( secret, - &signature, - &remote_public, - &remote_nonce, + signature.as_bytes(), + remote_public.as_bytes(), + remote_nonce.as_bytes(), remote_version, )?; self.write_ack_eip8(io)?; @@ -271,8 +268,8 @@ impl Handshake { self.ack_cipher = data.to_vec(); match ecies::decrypt(secret, &[], data) { Ok(ack) => { - self.remote_ephemeral.clone_from_slice(&ack[0..64]); - self.remote_nonce.clone_from_slice(&ack[64..(64 + 32)]); + self.remote_ephemeral = Public::from_slice(&ack[0..64]); + self.remote_nonce = H256::from_slice(&ack[64..(64 + 32)]); self.state = HandshakeState::StartSession; } Err(_) => { @@ -320,10 +317,7 @@ impl Handshake { rlp.append(&self.nonce); rlp.append(&PROTOCOL_VERSION); let mut encoded = rlp.out(); - encoded.resize( - encoded.len() + rand::thread_rng().gen_range::(100, 301), - 0, - ); + encoded.resize(encoded.len() + rand::thread_rng().gen_range(100, 301), 0); let len = (encoded.len() + ECIES_OVERHEAD) as u16; let prefix = len.to_be_bytes(); let message = ecies::encrypt(&self.id, &prefix, &encoded)?; @@ -347,8 +341,8 @@ impl Handshake { data[len - 1] = 0x0; let (epubk, rest) = data.split_at_mut(64); let (nonce, _) = rest.split_at_mut(32); - self.ecdhe.public().copy_to(epubk); - self.nonce.copy_to(nonce); + epubk.copy_from_slice(self.ecdhe.public().as_bytes()); + nonce.copy_from_slice(self.nonce.as_bytes()); } let message = ecies::encrypt(&self.id, &[], &data)?; self.ack_cipher = message.clone(); @@ -387,35 +381,38 @@ impl Handshake { #[cfg(test)] mod test { use super::*; - use ethereum_types::H256; - use ethkey::Public; + use crypto::publickey::Public; + use ethereum_types::{H256, H512}; use io::*; use mio::tcp::TcpStream; use rustc_hex::FromHex; + use std::str::FromStr; fn check_auth(h: &Handshake, version: u64) { - assert_eq!(h.id, "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into()); + assert_eq!(h.id, H512::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap()); assert_eq!( h.remote_nonce, - "7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6".into() + H256::from_str("7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6") + .unwrap() ); - assert_eq!(h.remote_ephemeral, "654d1044b69c577a44e5f01a1209523adb4026e70c62d1c13a067acabc09d2667a49821a0ad4b634554d330a15a58fe61f8a8e0544b310c6de7b0c8da7528a8d".into()); + assert_eq!(h.remote_ephemeral, H512::from_str("654d1044b69c577a44e5f01a1209523adb4026e70c62d1c13a067acabc09d2667a49821a0ad4b634554d330a15a58fe61f8a8e0544b310c6de7b0c8da7528a8d").unwrap()); assert_eq!(h.remote_version, version); } fn check_ack(h: &Handshake, version: u64) { assert_eq!( h.remote_nonce, - "559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd".into() + H256::from_str("559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd") + .unwrap() ); - assert_eq!(h.remote_ephemeral, "b6d82fa3409da933dbf9cb0140c5dde89f4e64aec88d476af648880f4a10e1e49fe35ef3e69e93dd300b4797765a747c6384a6ecf5db9c2690398607a86181e4".into()); + assert_eq!(h.remote_ephemeral, H512::from_str("b6d82fa3409da933dbf9cb0140c5dde89f4e64aec88d476af648880f4a10e1e49fe35ef3e69e93dd300b4797765a747c6384a6ecf5db9c2690398607a86181e4").unwrap()); assert_eq!(h.remote_version, version); } fn create_handshake(to: Option<&Public>) -> Handshake { let addr = "127.0.0.1:50556".parse().unwrap(); let socket = TcpStream::connect(&addr).unwrap(); - let nonce = H256::new(); + let nonce = H256::default(); Handshake::new(0, to, socket, &nonce).unwrap() } @@ -515,7 +512,7 @@ mod test { #[test] fn test_handshake_ack_plain() { - let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into(); + let remote = H512::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); let mut h = create_handshake(Some(&remote)); let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee" .parse() @@ -538,7 +535,7 @@ mod test { #[test] fn test_handshake_ack_eip8() { - let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into(); + let remote = H512::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); let mut h = create_handshake(Some(&remote)); let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee" .parse() @@ -572,7 +569,7 @@ mod test { #[test] fn test_handshake_ack_eip8_2() { - let remote = "fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877".into(); + let remote = H512::from_str("fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877").unwrap(); let mut h = create_handshake(Some(&remote)); let secret = "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee" .parse() diff --git a/crates/net/network-devp2p/src/host.rs b/crates/net/network-devp2p/src/host.rs index 9ac7221d32..92191c1154 100644 --- a/crates/net/network-devp2p/src/host.rs +++ b/crates/net/network-devp2p/src/host.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{Generator, KeyPair, Random, Secret}; use ethereum_types::H256; -use ethkey::{Generator, KeyPair, Random, Secret}; use hash::keccak; use mio::{deprecated::EventLoop, tcp::*, udp::*, *}; use rlp::{Encodable, RlpStream}; @@ -310,7 +310,7 @@ impl Host { .and_then(|ref p| load_key(Path::new(&p))) .map_or_else( || { - let key = Random.generate().expect("Error generating random key pair"); + let key = Random.generate(); if let Some(path) = config.config_path.clone() { save_key(Path::new(&path), key.secret()); } @@ -1457,7 +1457,7 @@ fn save_key(path: &Path, key: &Secret) { if let Err(e) = restrict_permissions_owner(path, true, false) { warn!(target: "network", "Failed to modify permissions of the file ({})", e); } - if let Err(e) = file.write(&key.hex().into_bytes()[2..]) { + if let Err(e) = file.write(&key.to_hex().into_bytes()) { warn!("Error writing key file: {:?}", e); } } diff --git a/crates/net/network-devp2p/src/node_table.rs b/crates/net/network-devp2p/src/node_table.rs index 03232e2ff8..ef46e526ff 100644 --- a/crates/net/network-devp2p/src/node_table.rs +++ b/crates/net/network-devp2p/src/node_table.rs @@ -18,7 +18,7 @@ use discovery::{NodeEntry, TableUpdates}; use ethereum_types::H512; use ip_utils::*; use network::{AllowIP, Error, ErrorKind, IpFilter}; -use rand::{self, Rng}; +use rand::seq::SliceRandom; use rlp::{DecoderError, Rlp, RlpStream}; use serde_json; use std::{ @@ -242,7 +242,7 @@ impl FromStr for Node { NodeEndpoint::from_str(&s[137..])?, ) } else { - (NodeId::new(), NodeEndpoint::from_str(s)?) + (NodeId::default(), NodeEndpoint::from_str(s)?) }; Ok(Node { @@ -351,7 +351,8 @@ impl NodeTable { a.time().cmp(&b.time()) }); - rand::thread_rng().shuffle(&mut unknown); + let mut rng = rand::thread_rng(); + unknown.shuffle(&mut rng); success.append(&mut unknown); success.append(&mut failures); diff --git a/crates/net/network-devp2p/tests/tests.rs b/crates/net/network-devp2p/tests/tests.rs index eec2aad786..ea501ad310 100644 --- a/crates/net/network-devp2p/tests/tests.rs +++ b/crates/net/network-devp2p/tests/tests.rs @@ -19,14 +19,14 @@ extern crate ethcore_io as io; extern crate ethcore_network; extern crate ethcore_network_devp2p; extern crate ethereum_types; -extern crate ethkey; extern crate parity_bytes; +extern crate parity_crypto as crypto; extern crate parking_lot; +use crypto::publickey::{Generator, Random}; use ethcore_network::*; use ethcore_network_devp2p::NetworkService; use ethereum_types::U64; -use ethkey::{Generator, Random}; use io::TimerToken; use parity_bytes::Bytes; use parking_lot::Mutex; @@ -136,7 +136,7 @@ fn net_start_stop() { #[test] fn net_disconnect() { - let key1 = Random.generate().unwrap(); + let key1 = Random.generate(); let mut config1 = NetworkConfiguration::new_local(); config1.use_secret = Some(key1.secret().clone()); config1.boot_nodes = vec![]; diff --git a/crates/net/network/Cargo.toml b/crates/net/network/Cargo.toml index 30827dee8d..5cc8a560a5 100644 --- a/crates/net/network/Cargo.toml +++ b/crates/net/network/Cargo.toml @@ -8,13 +8,13 @@ authors = ["Parity Technologies "] [dependencies] error-chain = { version = "0.12", default-features = false } -parity-crypto = "0.3.0" +parity-crypto = { version = "0.6.2", features = [ "publickey"] } ethcore-io = { path = "../../runtime/io" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethkey = { path = "../../../crates/accounts/ethkey" } ipnetwork = "0.12.6" lazy_static = "1.0" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } libc = "0.2" parity-snappy = "0.1" semver = {version="0.9.0", features=["serde"]} diff --git a/crates/net/network/src/error.rs b/crates/net/network/src/error.rs index 041dee4085..f37ebd6a82 100644 --- a/crates/net/network/src/error.rs +++ b/crates/net/network/src/error.rs @@ -19,7 +19,6 @@ #![allow(deprecated)] use crypto; -use ethkey; use io::IoError; use libc::{EMFILE, ENFILE}; use rlp; @@ -179,14 +178,14 @@ impl From for Error { } } -impl From for Error { - fn from(_err: ethkey::Error) -> Self { +impl From for Error { + fn from(_err: crypto::Error) -> Self { ErrorKind::Auth.into() } } -impl From for Error { - fn from(_err: ethkey::crypto::Error) -> Self { +impl From for Error { + fn from(_err: crypto::publickey::Error) -> Self { ErrorKind::Auth.into() } } @@ -217,7 +216,7 @@ fn test_errors() { _ => panic!("Unexpected error"), } - match *>::from(ethkey::crypto::Error::InvalidMessage) + match *>::from(crypto::publickey::Error::InvalidMessage) .kind() { ErrorKind::Auth => {} diff --git a/crates/net/network/src/lib.rs b/crates/net/network/src/lib.rs index 5c0f40a6a6..dbf70ca01c 100644 --- a/crates/net/network/src/lib.rs +++ b/crates/net/network/src/lib.rs @@ -50,8 +50,8 @@ pub use error::{DisconnectReason, Error, ErrorKind}; pub use io::TimerToken; use client_version::ClientVersion; +use crypto::publickey::Secret; use ethereum_types::{H512, U64}; -use ethkey::Secret; use ipnetwork::{IpNetwork, IpNetworkError}; use rlp::{Decodable, DecoderError, Rlp}; use std::{ diff --git a/crates/net/node-filter/Cargo.toml b/crates/net/node-filter/Cargo.toml index ca812ca19a..4b23d2ef5e 100644 --- a/crates/net/node-filter/Cargo.toml +++ b/crates/net/node-filter/Cargo.toml @@ -10,16 +10,16 @@ authors = ["Parity Technologies "] ethcore = { path = "../../ethcore"} ethcore-network = { path = "../network" } ethcore-network-devp2p = { path = "../network-devp2p" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" log = "0.4" parking_lot = "0.7" -ethabi = "6.0" -ethabi-derive = "6.0" -ethabi-contract = "6.0" +ethabi = "12.0.0" +ethabi-derive = "12.0.0" +ethabi-contract = "11.0.0" lru-cache = "0.1" [dev-dependencies] ethcore = { path = "../../ethcore", features = ["test-helpers"] } kvdb-memorydb = "0.1" ethcore-io = { path = "../../runtime/io" } -tempdir = "0.3" \ No newline at end of file +tempdir = "0.3" diff --git a/crates/net/node-filter/src/lib.rs b/crates/net/node-filter/src/lib.rs index c32463b3e5..6d72290a11 100644 --- a/crates/net/node-filter/src/lib.rs +++ b/crates/net/node-filter/src/lib.rs @@ -24,7 +24,6 @@ extern crate ethereum_types; extern crate lru_cache; extern crate parking_lot; -#[macro_use] extern crate ethabi_derive; #[macro_use] extern crate ethabi_contract; @@ -104,15 +103,19 @@ mod test { spec::Spec, test_helpers, }; + use ethereum_types::Address; use io::IoChannel; use network::{ConnectionDirection, ConnectionFilter, NodeId}; - use std::sync::{Arc, Weak}; + use std::{ + str::FromStr, + sync::{Arc, Weak}, + }; use tempdir::TempDir; /// Contract code: https://gist.github.com/arkpar/467dbcc73cbb85b0997a7a10ffa0695f #[test] fn node_filter() { - let contract_addr = "0000000000000000000000000000000000000005".into(); + let contract_addr = Address::from_str("0000000000000000000000000000000000000005").unwrap(); let data = include_bytes!("../res/node_filter.json"); let tempdir = TempDir::new("").unwrap(); let spec = Spec::load(&tempdir.path(), &data[..]).unwrap(); @@ -130,11 +133,11 @@ mod test { Arc::downgrade(&client) as Weak, contract_addr, ); - let self1: NodeId = "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002".into(); - let self2: NodeId = "00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003".into(); - let node1: NodeId = "00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012".into(); - let node2: NodeId = "00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022".into(); - let nodex: NodeId = "77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let self1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002").unwrap(); + let self2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003").unwrap(); + let node1 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012").unwrap(); + let node2 = NodeId::from_str("00000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022").unwrap(); + let nodex = NodeId::from_str("77000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(); assert!(filter.connection_allowed(&self1, &node1, ConnectionDirection::Inbound)); assert!(filter.connection_allowed(&self1, &nodex, ConnectionDirection::Inbound)); diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 4b2d9bdef3..13fc5debab 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -13,7 +13,8 @@ futures = "0.1.6" log = "0.4" order-stat = "0.1" parking_lot = "0.7" -rand = "0.4" +rand = "0.7.3" +rand_xorshift = "0.2.0" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" @@ -39,19 +40,19 @@ ethcore-logger = { path = "../../bin/oe/logger" } ethcore-miner = { path = "../concensus/miner" } ethcore-network = { path = "../net/network" } ethcore-sync = { path = "../ethcore/sync" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" parity-bytes = "0.1" -parity-crypto = "0.3.0" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } eip-712 = { path = "../util/EIP-712" } ethjson = { path = "../ethjson" } ethkey = { path = "../accounts/ethkey" } ethstore = { path = "../accounts/ethstore" } fetch = { path = "../net/fetch" } -keccak-hash = "0.1.2" +keccak-hash = "0.5.0" parity-runtime = { path = "../runtime/runtime" } parity-version = { path = "../util/version" } -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } stats = { path = "../util/stats" } vm = { path = "../vm/vm" } diff --git a/crates/rpc/src/authcodes.rs b/crates/rpc/src/authcodes.rs index 12ec3dbb12..97240cae66 100644 --- a/crates/rpc/src/authcodes.rs +++ b/crates/rpc/src/authcodes.rs @@ -25,7 +25,7 @@ use std::{ use ethereum_types::H256; use hash::keccak; use itertools::Itertools; -use rand::{os::OsRng, Rng}; +use rand::{distributions::Alphanumeric, rngs::OsRng, Rng}; /// Providing current time in seconds pub trait TimeProvider { @@ -184,8 +184,11 @@ impl AuthCodes { /// Generates and returns a new code that can be used by `SignerUIs` pub fn generate_new(&mut self) -> io::Result { - let mut rng = OsRng::new()?; - let code = rng.gen_ascii_chars().take(TOKEN_LENGTH).collect::(); + let rng = OsRng; + let code = rng + .sample_iter(&Alphanumeric) + .take(TOKEN_LENGTH) + .collect::(); let readable_code = code .as_bytes() .chunks(4) diff --git a/crates/rpc/src/v1/extractors.rs b/crates/rpc/src/v1/extractors.rs index ef053fd6bb..df32a4fc90 100644 --- a/crates/rpc/src/v1/extractors.rs +++ b/crates/rpc/src/v1/extractors.rs @@ -53,7 +53,7 @@ impl HttpMetaExtractor for RpcExtractor { impl ipc::MetaExtractor for RpcExtractor { fn extract(&self, req: &ipc::RequestContext) -> Metadata { Metadata { - origin: Origin::Ipc(req.session_id.into()), + origin: Origin::Ipc(H256::from_low_u64_be(req.session_id)), session: Some(Arc::new(Session::new(req.sender.clone()))), } } @@ -85,10 +85,14 @@ impl ws::MetaExtractor for WsExtractor { .and_then(|p| auth_token_hash(&path, p, true)); match authorization { Some(id) => Origin::Signer { session: id }, - None => Origin::Ws { session: id.into() }, + None => Origin::Ws { + session: H256::from_low_u64_be(id), + }, } } - None => Origin::Ws { session: id.into() }, + None => Origin::Ws { + session: H256::from_low_u64_be(id), + }, }; let session = Some(Arc::new(Session::new(req.sender()))); Metadata { origin, session } diff --git a/crates/rpc/src/v1/helpers/dispatch/mod.rs b/crates/rpc/src/v1/helpers/dispatch/mod.rs index d211e35d40..3d64e4906f 100644 --- a/crates/rpc/src/v1/helpers/dispatch/mod.rs +++ b/crates/rpc/src/v1/helpers/dispatch/mod.rs @@ -86,9 +86,10 @@ pub use v1::helpers::nonce::Reservations; use std::{fmt::Debug, ops::Deref, sync::Arc}; use bytes::Bytes; +use crypto::publickey::Signature; use ethcore::{client::BlockChainClient, miner::MinerService}; use ethereum_types::{Address, H256, H520, U256}; -use ethkey::{Password, Signature}; +use ethkey::Password; use hash::keccak; use types::transaction::{PendingTransaction, SignedTransaction}; diff --git a/crates/rpc/src/v1/helpers/dispatch/signing.rs b/crates/rpc/src/v1/helpers/dispatch/signing.rs index 3ff004d34b..43704a6b00 100644 --- a/crates/rpc/src/v1/helpers/dispatch/signing.rs +++ b/crates/rpc/src/v1/helpers/dispatch/signing.rs @@ -18,9 +18,8 @@ use std::sync::Arc; use accounts::AccountProvider; use bytes::Bytes; -use crypto::DEFAULT_MAC; +use crypto::{publickey::Signature, DEFAULT_MAC}; use ethereum_types::{Address, H256, U256}; -use ethkey::Signature; use jsonrpc_core::{Error, ErrorCode}; use types::transaction::{ AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction, TypedTxId, diff --git a/crates/rpc/src/v1/helpers/engine_signer.rs b/crates/rpc/src/v1/helpers/engine_signer.rs index bcd9ca9bad..365ddae6ac 100644 --- a/crates/rpc/src/v1/helpers/engine_signer.rs +++ b/crates/rpc/src/v1/helpers/engine_signer.rs @@ -17,7 +17,8 @@ use std::sync::Arc; use accounts::AccountProvider; -use ethkey::{self, Address, Password}; +use crypto::publickey::{self, Address}; +use ethkey::Password; /// An implementation of EngineSigner using internal account management. pub struct EngineSigner { @@ -38,13 +39,13 @@ impl EngineSigner { } impl ethcore::engines::EngineSigner for EngineSigner { - fn sign(&self, message: ethkey::Message) -> Result { + fn sign(&self, message: publickey::Message) -> Result { match self .accounts .sign(self.address, Some(self.password.clone()), message) { Ok(ok) => Ok(ok), - Err(_e) => Err(ethkey::Error::InvalidSecret), + Err(e) => Err(publickey::Error::Custom(e.to_string())), } } diff --git a/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs b/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs index e7c0319382..6954c27724 100644 --- a/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs +++ b/crates/rpc/src/v1/helpers/external_signer/signing_queue.rs @@ -242,7 +242,7 @@ impl SigningQueue for ConfirmationsQueue { #[cfg(test)] mod test { - use ethereum_types::{Address, U256}; + use ethereum_types::{Address, H256, U256}; use jsonrpc_core::futures::Future; use parking_lot::Mutex; use std::sync::Arc; @@ -257,9 +257,9 @@ mod test { fn request() -> ConfirmationPayload { ConfirmationPayload::SendTransaction(FilledTransactionRequest { transaction_type: Default::default(), - from: Address::from(1), + from: Address::from_low_u64_be(1), used_default_from: false, - to: Some(Address::from(2)), + to: Some(Address::from_low_u64_be(2)), gas_price: 0.into(), gas: 10_000.into(), value: 10_000_000.into(), @@ -279,13 +279,20 @@ mod test { // when let (id, future) = queue.add_request(request, Default::default()).unwrap(); let sender = queue.take(&id).unwrap(); - queue.request_confirmed(sender, Ok(ConfirmationResponse::SendTransaction(1.into()))); + queue.request_confirmed( + sender, + Ok(ConfirmationResponse::SendTransaction( + H256::from_low_u64_be(1), + )), + ); // then let confirmation = future.wait().unwrap(); assert_eq!( confirmation, - Ok(ConfirmationResponse::SendTransaction(1.into())) + Ok(ConfirmationResponse::SendTransaction( + H256::from_low_u64_be(1) + )) ); } diff --git a/crates/rpc/src/v1/helpers/secretstore.rs b/crates/rpc/src/v1/helpers/secretstore.rs index ed24d83cad..35df732473 100644 --- a/crates/rpc/src/v1/helpers/secretstore.rs +++ b/crates/rpc/src/v1/helpers/secretstore.rs @@ -15,11 +15,10 @@ // along with OpenEthereum. If not, see . use bytes::Bytes; -use crypto; +use crypto::publickey::{self, ec_math_utils, Generator, Public, Random, Secret}; use ethereum_types::{H256, H512}; -use ethkey::{self, math, Generator, Public, Random, Secret}; use jsonrpc_core::Error; -use rand::{OsRng, Rng}; +use rand::{rngs::OsRng, RngCore}; use std::collections::BTreeSet; use tiny_keccak::Keccak; use v1::{helpers::errors, types::EncryptedDocumentKey}; @@ -33,17 +32,17 @@ pub fn generate_document_key( server_key_public: Public, ) -> Result { // generate random plain document key - let document_key = Random.generate().map_err(errors::encryption)?; + let document_key = Random.generate(); // encrypt document key using server key let (common_point, encrypted_point) = encrypt_secret(document_key.public(), &server_key_public)?; // ..and now encrypt document key with account public - let encrypted_key = ethkey::crypto::ecies::encrypt( + let encrypted_key = publickey::ecies::encrypt( &account_public, &crypto::DEFAULT_MAC, - document_key.public(), + document_key.public().as_bytes(), ) .map_err(errors::encryption)?; @@ -104,7 +103,7 @@ pub fn decrypt_document_with_shadow( encrypted_document: Bytes, ) -> Result { let key = decrypt_with_shadow_coefficients(decrypted_secret, common_point, shadows)?; - decrypt_document(key.to_vec(), encrypted_document) + decrypt_document(key.as_bytes().to_vec(), encrypted_document) } /// Calculate Keccak(ordered servers set) @@ -132,7 +131,7 @@ fn into_document_key(key: Bytes) -> Result { fn initialization_vector() -> [u8; INIT_VEC_LEN] { let mut result = [0u8; INIT_VEC_LEN]; - let mut rng = OsRng::new().unwrap(); + let mut rng = OsRng; rng.fill_bytes(&mut result); result } @@ -149,9 +148,10 @@ fn decrypt_with_shadow_coefficients( .map_err(errors::encryption)?; } - math::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum) + ec_math_utils::public_mul_secret(&mut common_shadow_point, &shadow_coefficients_sum) + .map_err(errors::encryption)?; + ec_math_utils::public_add(&mut decrypted_shadow, &common_shadow_point) .map_err(errors::encryption)?; - math::public_add(&mut decrypted_shadow, &common_shadow_point).map_err(errors::encryption)?; Ok(decrypted_shadow) } @@ -159,16 +159,18 @@ fn encrypt_secret(secret: &Public, joint_public: &Public) -> Result<(Public, Pub // TODO: it is copypaste of `encrypt_secret` from secret_store/src/key_server_cluster/math.rs // use shared version from SS math library, when it'll be available - let key_pair = Random.generate().map_err(errors::encryption)?; + let key_pair = Random.generate(); // k * T - let mut common_point = math::generation_point(); - math::public_mul_secret(&mut common_point, key_pair.secret()).map_err(errors::encryption)?; + let mut common_point = ec_math_utils::generation_point(); + ec_math_utils::public_mul_secret(&mut common_point, key_pair.secret()) + .map_err(errors::encryption)?; // M + k * y let mut encrypted_point = joint_public.clone(); - math::public_mul_secret(&mut encrypted_point, key_pair.secret()).map_err(errors::encryption)?; - math::public_add(&mut encrypted_point, secret).map_err(errors::encryption)?; + ec_math_utils::public_mul_secret(&mut encrypted_point, key_pair.secret()) + .map_err(errors::encryption)?; + ec_math_utils::public_add(&mut encrypted_point, secret).map_err(errors::encryption)?; Ok((common_point, encrypted_point)) } diff --git a/crates/rpc/src/v1/helpers/signature.rs b/crates/rpc/src/v1/helpers/signature.rs index ce71b9f2dc..c7844aac30 100644 --- a/crates/rpc/src/v1/helpers/signature.rs +++ b/crates/rpc/src/v1/helpers/signature.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{public_to_address, recover, Signature}; use ethereum_types::{H256, U64}; -use ethkey::{public_to_address, recover, Signature}; use hash::keccak; use jsonrpc_core::Result; use v1::{ @@ -59,8 +59,8 @@ pub fn verify_signature( #[cfg(test)] mod tests { use super::*; + use crypto::publickey::{self, Generator}; use ethereum_types::{H160, U64}; - use ethkey::Generator; pub fn add_chain_replay_protection(v: u64, chain_id: Option) -> u64 { v + if let Some(n) = chain_id { @@ -88,9 +88,9 @@ mod tests { } else { keccak(data) }; - let account = ethkey::Random.generate().unwrap(); + let account = publickey::Random.generate(); let address = account.address(); - let sig = ethkey::sign(account.secret(), &hash).unwrap(); + let sig = publickey::sign(account.secret(), &hash).unwrap(); let (r, s, v) = (sig.r(), sig.s(), sig.v()); let v = add_chain_replay_protection(v as u64, signing_chain_id); let (r_buf, s_buf) = { diff --git a/crates/rpc/src/v1/helpers/subscribers.rs b/crates/rpc/src/v1/helpers/subscribers.rs index b428d7fbc0..2dac203a44 100644 --- a/crates/rpc/src/v1/helpers/subscribers.rs +++ b/crates/rpc/src/v1/helpers/subscribers.rs @@ -21,7 +21,6 @@ use jsonrpc_pubsub::{ typed::{Sink, Subscriber}, SubscriptionId, }; -use rand::{Rng, StdRng}; use std::{collections::HashMap, ops, str}; #[derive(Debug, Clone, Hash, Eq, PartialEq)] @@ -44,34 +43,44 @@ impl Id { } } -#[derive(Clone)] +#[cfg(not(test))] +mod random { + use rand::rngs::OsRng; + pub type Rng = rand::rngs::OsRng; + pub fn new() -> Rng { + OsRng + } +} + +#[cfg(test)] +mod random { + extern crate rand_xorshift; + use self::rand_xorshift::XorShiftRng; + use rand::SeedableRng; + const RNG_SEED: [u8; 16] = [0u8; 16]; + pub type Rng = XorShiftRng; + pub fn new() -> Rng { + Rng::from_seed(RNG_SEED) + } +} + pub struct Subscribers { - rand: StdRng, + rand: random::Rng, subscriptions: HashMap, } impl Default for Subscribers { fn default() -> Self { Subscribers { - rand: StdRng::new().expect("Valid random source is required."), + rand: random::new(), subscriptions: HashMap::new(), } } } impl Subscribers { - /// Create a new Subscribers with given random source. - #[cfg(test)] - pub fn new_test() -> Self { - Subscribers { - rand: ::rand::SeedableRng::from_seed([0usize].as_ref()), - subscriptions: HashMap::new(), - } - } - fn next_id(&mut self) -> Id { - let mut data = H64::default(); - self.rand.fill_bytes(&mut data.0); + let data = H64::random_using(&mut self.rand); Id(data) } diff --git a/crates/rpc/src/v1/helpers/subscription_manager.rs b/crates/rpc/src/v1/helpers/subscription_manager.rs index 2bf525b9b8..5fa45ee7d6 100644 --- a/crates/rpc/src/v1/helpers/subscription_manager.rs +++ b/crates/rpc/src/v1/helpers/subscription_manager.rs @@ -66,7 +66,7 @@ impl> GenericPollManager { #[cfg(test)] pub fn new_test(rpc: MetaIoHandler) -> Self { let mut manager = Self::new(rpc); - manager.subscribers = Subscribers::new_test(); + manager.subscribers = Subscribers::default(); manager } @@ -187,7 +187,7 @@ mod tests { let mut el = Runtime::new().unwrap(); let mut poll_manager = poll_manager(); let (id, rx) = poll_manager.subscribe(Default::default(), "hello".into(), Params::None); - assert_eq!(id, SubscriptionId::String("0x416d77337e24399d".into())); + assert_eq!(id, SubscriptionId::String("0x43ca64edf03768e1".into())); // then poll_manager.tick().wait().unwrap(); diff --git a/crates/rpc/src/v1/impls/eth.rs b/crates/rpc/src/v1/impls/eth.rs index aa6529380f..3c59a151a0 100644 --- a/crates/rpc/src/v1/impls/eth.rs +++ b/crates/rpc/src/v1/impls/eth.rs @@ -22,7 +22,7 @@ use std::{ time::{Duration, Instant, SystemTime, UNIX_EPOCH}, }; -use ethereum_types::{Address, H160, H256, H64, U256, U64}; +use ethereum_types::{Address, BigEndianHash, H160, H256, H64, U256, U64}; use parking_lot::Mutex; use ethash::{self, SeedHashCompute}; @@ -637,7 +637,7 @@ where fn author(&self) -> Result { let miner = self.miner.authoring_params().author; - if miner == 0.into() { + if miner.is_zero() { (self.accounts)() .first() .cloned() @@ -732,8 +732,8 @@ where let key2: H256 = storage_index; self.client.prove_storage(key1, keccak(key2), id).map( |(storage_proof, storage_value)| StorageProof { - key: key2.into(), - value: storage_value.into(), + key: key2.into_uint(), + value: storage_value.into_uint(), proof: storage_proof.into_iter().map(Bytes::new).collect(), }, ) @@ -755,10 +755,11 @@ where let num = num.unwrap_or_default(); try_bf!(check_known(&*self.client, num.clone())); - let res = match self - .client - .storage_at(&address, &H256::from(position), self.get_state(num)) - { + let res = match self.client.storage_at( + &address, + &BigEndianHash::from_uint(&position), + self.get_state(num), + ) { Some(s) => Ok(s), None => Err(errors::state_pruned()), }; diff --git a/crates/rpc/src/v1/impls/eth_pubsub.rs b/crates/rpc/src/v1/impls/eth_pubsub.rs index c8199d4633..7bf41bee7f 100644 --- a/crates/rpc/src/v1/impls/eth_pubsub.rs +++ b/crates/rpc/src/v1/impls/eth_pubsub.rs @@ -79,9 +79,9 @@ impl EthPubSubClient { #[cfg(test)] pub fn new_test(client: Arc, executor: Executor) -> Self { let client = Self::new(client, executor); - *client.heads_subscribers.write() = Subscribers::new_test(); - *client.logs_subscribers.write() = Subscribers::new_test(); - *client.transactions_subscribers.write() = Subscribers::new_test(); + *client.heads_subscribers.write() = Subscribers::default(); + *client.logs_subscribers.write() = Subscribers::default(); + *client.transactions_subscribers.write() = Subscribers::default(); client } diff --git a/crates/rpc/src/v1/impls/parity.rs b/crates/rpc/src/v1/impls/parity.rs index 3c1c9c7629..2a4bc3e329 100644 --- a/crates/rpc/src/v1/impls/parity.rs +++ b/crates/rpc/src/v1/impls/parity.rs @@ -17,7 +17,7 @@ //! Parity-specific rpc implementation. use std::{collections::BTreeMap, str::FromStr, sync::Arc}; -use crypto::DEFAULT_MAC; +use crypto::{publickey::ecies, DEFAULT_MAC}; use ethcore::{ client::{BlockChainClient, Call, StateClient}, miner::{self, MinerService}, @@ -26,7 +26,7 @@ use ethcore::{ }; use ethcore_logger::RotatingLogger; use ethereum_types::{Address, H160, H256, H512, H64, U256, U64}; -use ethkey::{crypto::ecies, Brain, Generator}; +use ethkey::Brain; use ethstore::random_phrase; use jsonrpc_core::{futures::future, BoxFuture, Result}; use stats::PrometheusMetrics; @@ -213,10 +213,7 @@ where } fn phrase_to_address(&self, phrase: String) -> Result { - Ok(Brain::new(phrase) - .generate() - .expect("Brain::generate always returns Ok; qed") - .address()) + Ok(Brain::new(phrase).generate().address()) } fn list_accounts( diff --git a/crates/rpc/src/v1/impls/parity_accounts.rs b/crates/rpc/src/v1/impls/parity_accounts.rs index 053a8dd710..151c3f12a0 100644 --- a/crates/rpc/src/v1/impls/parity_accounts.rs +++ b/crates/rpc/src/v1/impls/parity_accounts.rs @@ -24,8 +24,9 @@ use std::{ }; use accounts::AccountProvider; +use crypto::publickey::Secret; use ethereum_types::{Address, H160, H256, H520}; -use ethkey::{Brain, Generator, Password, Secret}; +use ethkey::{Brain, Password}; use ethstore::KeyFile; use jsonrpc_core::Result; use v1::{ @@ -139,7 +140,7 @@ impl ParityAccounts for ParityAccountsClient { fn new_account_from_phrase(&self, phrase: String, pass: Password) -> Result { self.deprecation_notice("parity_newAccountFromPhrase"); - let brain = Brain::new(phrase).generate().unwrap(); + let brain = Brain::new(phrase).generate(); self.accounts .insert_account(brain.secret().clone(), &pass) .map(Into::into) @@ -157,7 +158,7 @@ impl ParityAccounts for ParityAccountsClient { fn new_account_from_secret(&self, secret: H256, pass: Password) -> Result { self.deprecation_notice("parity_newAccountFromSecret"); - let secret = Secret::from_unsafe_slice(&secret.0) + let secret = Secret::import_key(&secret.0) .map_err(|e| errors::account("Could not create account.", e))?; self.accounts .insert_account(secret, &pass) diff --git a/crates/rpc/src/v1/impls/parity_set.rs b/crates/rpc/src/v1/impls/parity_set.rs index 21489d0349..62c1d801c1 100644 --- a/crates/rpc/src/v1/impls/parity_set.rs +++ b/crates/rpc/src/v1/impls/parity_set.rs @@ -23,7 +23,6 @@ use ethcore::{ miner::{self, MinerService}, }; use ethereum_types::{H160, H256, U256}; -use ethkey; use fetch::{self, Fetch}; use hash::keccak_buffer; use sync::ManageNetwork; @@ -150,7 +149,7 @@ where } fn set_engine_signer_secret(&self, secret: H256) -> Result { - let keypair = ethkey::KeyPair::from_secret(secret.into()) + let keypair = crypto::publickey::KeyPair::from_secret(secret.into()) .map_err(|e| errors::account("Invalid secret", e))?; self.miner.set_author(miner::Author::Sealer( ethcore::engines::signer::from_keypair(keypair), diff --git a/crates/rpc/src/v1/impls/personal.rs b/crates/rpc/src/v1/impls/personal.rs index ce03eebdf3..813790333b 100644 --- a/crates/rpc/src/v1/impls/personal.rs +++ b/crates/rpc/src/v1/impls/personal.rs @@ -19,9 +19,9 @@ use std::sync::Arc; use accounts::AccountProvider; use bytes::Bytes; +use crypto::publickey::{public_to_address, recover, Signature}; use eip_712::{hash_structured_data, EIP712}; use ethereum_types::{Address, H160, H256, H520, U128}; -use ethkey::{public_to_address, recover, Signature}; use types::transaction::{PendingTransaction, SignedTransaction}; use jsonrpc_core::{ @@ -282,7 +282,7 @@ impl Personal for PersonalClient { fn ec_recover(&self, data: RpcBytes, signature: H520) -> BoxFuture { let signature: H520 = signature.into(); - let signature = Signature::from_electrum(&signature); + let signature = Signature::from_electrum(signature.as_bytes()); let data: Bytes = data.into(); let hash = eth_data_hash(data); diff --git a/crates/rpc/src/v1/impls/secretstore.rs b/crates/rpc/src/v1/impls/secretstore.rs index 8844fd62be..9c219e875a 100644 --- a/crates/rpc/src/v1/impls/secretstore.rs +++ b/crates/rpc/src/v1/impls/secretstore.rs @@ -19,9 +19,8 @@ use std::{collections::BTreeSet, sync::Arc}; use accounts::AccountProvider; -use crypto::DEFAULT_MAC; +use crypto::{publickey::Secret, DEFAULT_MAC}; use ethereum_types::{H160, H256, H512}; -use ethkey::Secret; use ethkey::Password; use jsonrpc_core::Result; @@ -59,9 +58,8 @@ impl SecretStoreClient { /// Decrypt secret key using account' private key fn decrypt_secret(&self, address: H160, password: Password, key: Bytes) -> Result { - self.decrypt_key(address, password, key).and_then(|s| { - Secret::from_unsafe_slice(&s).map_err(|e| errors::account("invalid secret", e)) - }) + self.decrypt_key(address, password, key) + .and_then(|s| Secret::import_key(&s).map_err(|e| errors::account("invalid secret", e))) } } diff --git a/crates/rpc/src/v1/impls/signer.rs b/crates/rpc/src/v1/impls/signer.rs index 049ed2ab6b..33a1f653ec 100644 --- a/crates/rpc/src/v1/impls/signer.rs +++ b/crates/rpc/src/v1/impls/signer.rs @@ -18,8 +18,8 @@ use std::sync::Arc; -use ethereum_types::U256; -use ethkey; +use crypto::publickey; +use ethereum_types::{H520, U256}; use parity_runtime::Executor; use parking_lot::Mutex; use types::transaction::{PendingTransaction, SignedTransaction, TypedTransaction}; @@ -289,11 +289,11 @@ impl Signer for SignerClient { } ConfirmationPayload::EthSignMessage(address, data) => { let expected_hash = eth_data_hash(data); - let signature = ethkey::Signature::from_electrum(&bytes.0); - match ethkey::verify_address(&address, &signature, &expected_hash) { - Ok(true) => { - Ok(ConfirmationResponse::Signature(bytes.0.as_slice().into())) - } + let signature = publickey::Signature::from_electrum(&bytes.0); + match publickey::verify_address(&address, &signature, &expected_hash) { + Ok(true) => Ok(ConfirmationResponse::Signature(H520::from_slice( + bytes.0.as_slice(), + ))), Ok(false) => Err(errors::invalid_params( "Sender address does not match the signature.", (), @@ -304,11 +304,11 @@ impl Signer for SignerClient { } } ConfirmationPayload::SignMessage(address, hash) => { - let signature = ethkey::Signature::from_electrum(&bytes.0); - match ethkey::verify_address(&address, &signature, &hash) { - Ok(true) => { - Ok(ConfirmationResponse::Signature(bytes.0.as_slice().into())) - } + let signature = publickey::Signature::from_electrum(&bytes.0); + match publickey::verify_address(&address, &signature, &hash) { + Ok(true) => Ok(ConfirmationResponse::Signature(H520::from_slice( + bytes.0.as_slice(), + ))), Ok(false) => Err(errors::invalid_params( "Sender address does not match the signature.", (), diff --git a/crates/rpc/src/v1/tests/eth.rs b/crates/rpc/src/v1/tests/eth.rs index a3999f431b..620c22c0a3 100644 --- a/crates/rpc/src/v1/tests/eth.rs +++ b/crates/rpc/src/v1/tests/eth.rs @@ -571,7 +571,7 @@ fn starting_nonce_test() { let tester = EthTester::from_spec( Spec::load(&env::temp_dir(), POSITIVE_NONCE_SPEC).expect("invalid chain spec"), ); - let address = Address::from(10); + let address = Address::from_low_u64_be(10); let sample = tester .handler diff --git a/crates/rpc/src/v1/tests/helpers/sync_provider.rs b/crates/rpc/src/v1/tests/helpers/sync_provider.rs index c0e87b8935..2d56808b27 100644 --- a/crates/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/crates/rpc/src/v1/tests/helpers/sync_provider.rs @@ -16,7 +16,7 @@ //! Test implementation of SyncProvider. -use ethereum_types::H256; +use ethereum_types::{H256, H512}; use network::client_version::ClientVersion; use parking_lot::RwLock; use stats::{PrometheusMetrics, PrometheusRegistry}; @@ -88,7 +88,7 @@ impl SyncProvider for TestSyncProvider { eth_info: Some(EthProtocolInfo { version: 63, difficulty: Some(40.into()), - head: 50.into(), + head: H256::from_low_u64_be(50), }), }, PeerInfo { @@ -100,7 +100,7 @@ impl SyncProvider for TestSyncProvider { eth_info: Some(EthProtocolInfo { version: 65, difficulty: None, - head: 60.into(), + head: H256::from_low_u64_be(60), }), }, ] @@ -112,16 +112,16 @@ impl SyncProvider for TestSyncProvider { fn transactions_stats(&self) -> BTreeMap { map![ - 1.into() => TransactionStats { + H256::from_low_u64_be(1) => TransactionStats { first_seen: 10, propagated_to: map![ - 128.into() => 16 + H512::from_low_u64_be(128) => 16 ], }, - 5.into() => TransactionStats { + H256::from_low_u64_be(5) => TransactionStats { first_seen: 16, propagated_to: map![ - 16.into() => 1 + H512::from_low_u64_be(16) => 1 ], } ] diff --git a/crates/rpc/src/v1/tests/mocked/eth.rs b/crates/rpc/src/v1/tests/mocked/eth.rs index 00ea5c6c2d..5b712054ec 100644 --- a/crates/rpc/src/v1/tests/mocked/eth.rs +++ b/crates/rpc/src/v1/tests/mocked/eth.rs @@ -223,15 +223,15 @@ fn rpc_eth_chain_id() { fn rpc_eth_hashrate() { let tester = EthTester::default(); tester.hashrates.lock().insert( - H256::from(0), + H256::from_low_u64_be(0), (Instant::now() + Duration::from_secs(2), U256::from(0xfffa)), ); tester.hashrates.lock().insert( - H256::from(0), + H256::from_low_u64_be(0), (Instant::now() + Duration::from_secs(2), U256::from(0xfffb)), ); tester.hashrates.lock().insert( - H256::from(1), + H256::from_low_u64_be(1), (Instant::now() + Duration::from_secs(2), U256::from(0x1)), ); @@ -302,10 +302,16 @@ fn rpc_eth_logs() { #[test] fn rpc_eth_logs_error() { + fn h256_from_digit_be(d: u8) -> H256 { + let mut bytes = [0u8; 32]; + bytes[0] = d; + H256(bytes) + } + let tester = EthTester::default(); tester .client - .set_error_on_logs(Some(BlockId::Hash(H256::from([5u8].as_ref())))); + .set_error_on_logs(Some(BlockId::Hash(h256_from_digit_be(5)))); let request = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":1,"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"One of the blocks specified in filter (fromBlock, toBlock or blockHash) cannot be found","data":"0x0500000000000000000000000000000000000000000000000000000000000000"},"id":1}"#; assert_eq!( @@ -457,9 +463,10 @@ fn rpc_eth_submit_hashrate() { tester .hashrates .lock() - .get(&H256::from( - "0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c" - )) + .get( + &H256::from_str("59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c") + .unwrap() + ) .cloned() .unwrap() .1, @@ -536,10 +543,10 @@ fn rpc_eth_accounts() { let address = tester.accounts_provider.new_account(&"".into()).unwrap(); tester .accounts_provider - .set_address_name(1.into(), "1".into()); + .set_address_name(Address::from_low_u64_be(1), "1".into()); tester .accounts_provider - .set_address_name(10.into(), "10".into()); + .set_address_name(Address::from_low_u64_be(10), "10".into()); // with current policy it should return the account let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; @@ -569,7 +576,9 @@ fn rpc_eth_block_number() { #[test] fn rpc_eth_balance() { let tester = EthTester::default(); - tester.client.set_balance(Address::from(1), U256::from(5)); + tester + .client + .set_balance(Address::from_low_u64_be(1), U256::from(5)); let request = r#"{ "jsonrpc": "2.0", @@ -588,7 +597,9 @@ fn rpc_eth_balance() { #[test] fn rpc_eth_balance_pending() { let tester = EthTester::default(); - tester.client.set_balance(Address::from(1), U256::from(5)); + tester + .client + .set_balance(Address::from_low_u64_be(1), U256::from(5)); let request = r#"{ "jsonrpc": "2.0", @@ -608,9 +619,11 @@ fn rpc_eth_balance_pending() { #[test] fn rpc_eth_storage_at() { let tester = EthTester::default(); - tester - .client - .set_storage(Address::from(1), H256::from(4), H256::from(7)); + tester.client.set_storage( + Address::from_low_u64_be(1), + H256::from_low_u64_be(4), + H256::from_low_u64_be(7), + ); let request = r#"{ "jsonrpc": "2.0", @@ -755,7 +768,9 @@ fn rpc_eth_uncle_count_by_block_number() { #[test] fn rpc_eth_code() { let tester = EthTester::default(); - tester.client.set_code(Address::from(1), vec![0xff, 0x21]); + tester + .client + .set_code(Address::from_low_u64_be(1), vec![0xff, 0x21]); let request = r#"{ "jsonrpc": "2.0", @@ -1162,13 +1177,13 @@ fn rpc_eth_transaction_receipt() { ) .unwrap(), block_number: 0x4510c, - transaction_hash: H256::new(), + transaction_hash: H256::default(), transaction_index: 0, transaction_log_index: 0, log_index: 1, }], - log_bloom: 0.into(), - outcome: TransactionOutcome::StateRoot(0.into()), + log_bloom: Bloom::zero(), + outcome: TransactionOutcome::StateRoot(H256::zero()), }; let hash = diff --git a/crates/rpc/src/v1/tests/mocked/eth_pubsub.rs b/crates/rpc/src/v1/tests/mocked/eth_pubsub.rs index 0e5c6bbba6..e19768c27d 100644 --- a/crates/rpc/src/v1/tests/mocked/eth_pubsub.rs +++ b/crates/rpc/src/v1/tests/mocked/eth_pubsub.rs @@ -29,6 +29,7 @@ use v1::{EthPubSub, EthPubSubClient, Metadata}; use ethcore::client::{ ChainNotify, ChainRoute, ChainRouteType, EachBlockWith, NewBlocks, TestBlockChainClient, }; +use ethereum_types::{Address, H256}; use parity_runtime::Runtime; const DURATION_ZERO: Duration = Duration::from_millis(0); @@ -58,7 +59,7 @@ fn should_subscribe_to_new_heads() { // Subscribe let request = r#"{"jsonrpc": "2.0", "method": "eth_subscribe", "params": ["newHeads"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":"0x416d77337e24399d","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x43ca64edf03768e1","id":1}"#; assert_eq!( io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()) @@ -75,7 +76,7 @@ fn should_subscribe_to_new_heads() { true, )); let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x1","parentHash":"0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x1","parentHash":"0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // Notify about two blocks @@ -94,14 +95,14 @@ fn should_subscribe_to_new_heads() { // Receive both let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x2","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x44e5ecf454ea99af9d8a8f2ca0daba96964c90de05db7a78f59b84ae9e749706","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x2","parentHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x2","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x44e5ecf454ea99af9d8a8f2ca0daba96964c90de05db7a78f59b84ae9e749706","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x2","parentHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x3","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0xdf04a98bb0c6fa8441bd429822f65a46d0cb553f6bcef602b973e65c81497f8e","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x3","parentHash":"0x44e5ecf454ea99af9d8a8f2ca0daba96964c90de05db7a78f59b84ae9e749706","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x3","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0xdf04a98bb0c6fa8441bd429822f65a46d0cb553f6bcef602b973e65c81497f8e","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x3","parentHash":"0x44e5ecf454ea99af9d8a8f2ca0daba96964c90de05db7a78f59b84ae9e749706","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // And unsubscribe - let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x416d77337e24399d"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x43ca64edf03768e1"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!( io.handle_request_sync(request, metadata), @@ -130,8 +131,13 @@ fn should_subscribe_to_logs() { let tx_hash = block.transactions()[0].hash(); client.set_logs(vec![LocalizedLogEntry { entry: LogEntry { - address: 5.into(), - topics: vec![1.into(), 2.into(), 0.into(), 0.into()], + address: Address::from_low_u64_be(5), + topics: vec![ + H256::from_low_u64_be(1), + H256::from_low_u64_be(2), + H256::from_low_u64_be(0), + H256::from_low_u64_be(0), + ], data: vec![], }, block_hash: h1, @@ -156,7 +162,7 @@ fn should_subscribe_to_logs() { // Subscribe let request = r#"{"jsonrpc": "2.0", "method": "eth_subscribe", "params": ["logs", {}], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":"0x416d77337e24399d","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x43ca64edf03768e1","id":1}"#; assert_eq!( io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()) @@ -175,7 +181,7 @@ fn should_subscribe_to_logs() { let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","removed":false,"topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) - + r#"","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},"subscription":"0x416d77337e24399d"}}"#; + + r#"","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},"subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // Check notifications (retracted) @@ -191,11 +197,11 @@ fn should_subscribe_to_logs() { let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","removed":true,"topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) - + r#"","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"removed"},"subscription":"0x416d77337e24399d"}}"#; + + r#"","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"removed"},"subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // And unsubscribe - let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x416d77337e24399d"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x43ca64edf03768e1"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!( io.handle_request_sync(request, metadata), @@ -233,25 +239,25 @@ fn should_subscribe_to_pending_transactions() { // Subscribe let request = r#"{"jsonrpc": "2.0", "method": "eth_subscribe", "params": ["newPendingTransactions"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":"0x416d77337e24399d","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x43ca64edf03768e1","id":1}"#; assert_eq!( io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()) ); // Send new transactions - handler.notify_new_transactions(&[5.into(), 7.into()]); + handler.notify_new_transactions(&[H256::from_low_u64_be(5), H256::from_low_u64_be(7)]); let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000005","subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000005","subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000007","subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000007","subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // And unsubscribe - let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x416d77337e24399d"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0x43ca64edf03768e1"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!( io.handle_request_sync(request, metadata), diff --git a/crates/rpc/src/v1/tests/mocked/parity.rs b/crates/rpc/src/v1/tests/mocked/parity.rs index ea1b7c31a5..49cd95a1d3 100644 --- a/crates/rpc/src/v1/tests/mocked/parity.rs +++ b/crates/rpc/src/v1/tests/mocked/parity.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crypto::publickey::{Generator, Random}; use ethcore::client::{Executed, TestBlockChainClient, TransactionId}; use ethcore_logger::RotatingLogger; -use ethereum_types::{Address, H256, U256}; -use ethstore::ethkey::{Generator, Random}; +use ethereum_types::{Address, BigEndianHash, Bloom, H256, U256}; use miner::pool::local_transactions::Status as LocalTransactionStatus; use std::sync::Arc; use sync::ManageNetwork; @@ -294,7 +294,7 @@ fn rpc_parity_pending_transactions() { fn rpc_parity_encrypt() { let deps = Dependencies::new(); let io = deps.default_client(); - let key = format!("{:x}", Random.generate().unwrap().public()); + let key = format!("{:x}", Random.generate().public()); let request = r#"{"jsonrpc": "2.0", "method": "parity_encryptMessage", "params":["0x"# .to_owned() @@ -382,16 +382,16 @@ fn rpc_parity_local_transactions() { data: vec![1, 2, 3], nonce: 0.into(), }) - .fake_sign(3.into()); + .fake_sign(Address::from_low_u64_be(3)); let tx = Arc::new(::miner::pool::VerifiedTransaction::from_pending_block_transaction(tx)); - deps.miner - .local_transactions - .lock() - .insert(10.into(), LocalTransactionStatus::Pending(tx.clone())); - deps.miner - .local_transactions - .lock() - .insert(15.into(), LocalTransactionStatus::Pending(tx.clone())); + deps.miner.local_transactions.lock().insert( + H256::from_low_u64_be(10), + LocalTransactionStatus::Pending(tx.clone()), + ); + deps.miner.local_transactions.lock().insert( + H256::from_low_u64_be(15), + LocalTransactionStatus::Pending(tx.clone()), + ); let request = r#"{"jsonrpc": "2.0", "method": "parity_localTransactions", "params":[], "id": 1}"#; @@ -406,7 +406,7 @@ fn rpc_parity_chain_status() { let io = deps.default_client(); *deps.client.ancient_block.write() = Some((H256::default(), 5)); - *deps.client.first_block.write() = Some((H256::from(U256::from(1234)), 3333)); + *deps.client.first_block.write() = Some((BigEndianHash::from_uint(&U256::from(1234)), 3333)); let request = r#"{"jsonrpc": "2.0", "method": "parity_chainStatus", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"blockGap":["0x6","0xd05"]},"id":1}"#; @@ -467,21 +467,21 @@ fn rpc_parity_call() { fn rpc_parity_block_receipts() { let deps = Dependencies::new(); deps.client.receipts.write().insert( - TransactionId::Hash(1.into()), + TransactionId::Hash(H256::from_low_u64_be(1)), LocalizedReceipt { - transaction_hash: 1.into(), + transaction_hash: H256::from_low_u64_be(1), transaction_type: TypedTxId::Legacy, transaction_index: 0, - block_hash: 3.into(), + block_hash: H256::from_low_u64_be(3), block_number: 0, cumulative_gas_used: 21_000.into(), gas_used: 21_000.into(), contract_address: None, logs: vec![], - log_bloom: 1.into(), + log_bloom: Bloom::from_low_u64_be(1), outcome: TransactionOutcome::Unknown, to: None, - from: 9.into(), + from: Address::from_low_u64_be(9), }, ); let io = deps.default_client(); diff --git a/crates/rpc/src/v1/tests/mocked/parity_accounts.rs b/crates/rpc/src/v1/tests/mocked/parity_accounts.rs index 78cd70d390..c154a577b1 100644 --- a/crates/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/crates/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use accounts::{AccountProvider, AccountProviderSettings}; use ethereum_types::Address; @@ -76,7 +76,9 @@ fn rpc_parity_accounts_info() { assert_eq!(accounts.len(), 1); let address = accounts[0]; - tester.accounts.set_address_name(1.into(), "XX".into()); + tester + .accounts + .set_address_name(Address::from_low_u64_be(1), "XX".into()); tester .accounts .set_account_name(address.clone(), "Test".into()) @@ -645,7 +647,7 @@ fn should_import_wallet() { let account_meta = tester .accounts - .account_meta("0x00bac56a8a27232baa044c03f43bf3648c961735".into()) + .account_meta(Address::from_str("00bac56a8a27232baa044c03f43bf3648c961735").unwrap()) .unwrap(); let account_uuid: String = account_meta.uuid.unwrap().into(); diff --git a/crates/rpc/src/v1/tests/mocked/parity_set.rs b/crates/rpc/src/v1/tests/mocked/parity_set.rs index bea2000a3a..2384f92489 100644 --- a/crates/rpc/src/v1/tests/mocked/parity_set.rs +++ b/crates/rpc/src/v1/tests/mocked/parity_set.rs @@ -191,11 +191,11 @@ fn rpc_parity_remove_transaction() { nonce: 1.into(), gas_price: 0x9184e72a000u64.into(), gas: 0x76c0.into(), - action: Action::Call(5.into()), + action: Action::Call(Address::from_low_u64_be(5)), value: 0x9184e72au64.into(), data: vec![], }); - let signed = tx.fake_sign(2.into()); + let signed = tx.fake_sign(Address::from_low_u64_be(2)); let hash = signed.hash(); let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""# diff --git a/crates/rpc/src/v1/tests/mocked/personal.rs b/crates/rpc/src/v1/tests/mocked/personal.rs index 3a7743220a..eeaefed8f3 100644 --- a/crates/rpc/src/v1/tests/mocked/personal.rs +++ b/crates/rpc/src/v1/tests/mocked/personal.rs @@ -18,6 +18,7 @@ use std::{str::FromStr, sync::Arc}; use accounts::AccountProvider; use bytes::ToPretty; +use crypto::publickey::Secret; use ethcore::client::TestBlockChainClient; use ethereum_types::{Address, H520, U256}; use hash::keccak; @@ -26,7 +27,6 @@ use parity_runtime::Runtime; use parking_lot::Mutex; use types::transaction::{Action, Transaction, TypedTransaction}; -use ethkey::Secret; use serde_json::to_value; use v1::{ helpers::{ @@ -392,6 +392,7 @@ fn ec_recover_invalid_signature() { fn should_unlock_account_permanently() { let tester = setup(); let address = tester.accounts.new_account(&"password123".into()).unwrap(); + let message = [1u8; 32].into(); let request = r#"{ "jsonrpc": "2.0", @@ -412,10 +413,7 @@ fn should_unlock_account_permanently() { Some(response.into()) ); assert!( - tester - .accounts - .sign(address, None, Default::default()) - .is_ok(), + tester.accounts.sign(address, None, message).is_ok(), "Should unlock account." ); } @@ -446,7 +444,7 @@ fn sign_eip191_with_validator() { }"#; let with_validator = to_value(PresignedTransaction { validator: address.into(), - data: keccak("hello world").to_vec().into(), + data: keccak("hello world").as_bytes().to_vec().into(), }) .unwrap(); let result = eip191::hash_message(EIP191Version::PresignedTransaction, with_validator).unwrap(); diff --git a/crates/rpc/src/v1/tests/mocked/pubsub.rs b/crates/rpc/src/v1/tests/mocked/pubsub.rs index cf144a21b8..5e05c254f3 100644 --- a/crates/rpc/src/v1/tests/mocked/pubsub.rs +++ b/crates/rpc/src/v1/tests/mocked/pubsub.rs @@ -57,7 +57,7 @@ fn should_subscribe_to_a_method() { // Subscribe let request = r#"{"jsonrpc": "2.0", "method": "parity_subscribe", "params": ["hello", []], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":"0x416d77337e24399d","id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x43ca64edf03768e1","id":1}"#; assert_eq!( io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()) @@ -65,15 +65,15 @@ fn should_subscribe_to_a_method() { // Check notifications let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"hello","subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"hello","subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); let (res, receiver) = receiver.into_future().wait().unwrap(); - let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"world","subscription":"0x416d77337e24399d"}}"#; + let response = r#"{"jsonrpc":"2.0","method":"parity_subscription","params":{"result":"world","subscription":"0x43ca64edf03768e1"}}"#; assert_eq!(res, Some(response.into())); // And unsubscribe - let request = r#"{"jsonrpc": "2.0", "method": "parity_unsubscribe", "params": ["0x416d77337e24399d"], "id": 1}"#; + let request = r#"{"jsonrpc": "2.0", "method": "parity_unsubscribe", "params": ["0x43ca64edf03768e1"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; assert_eq!( io.handle_request_sync(request, metadata), diff --git a/crates/rpc/src/v1/tests/mocked/secretstore.rs b/crates/rpc/src/v1/tests/mocked/secretstore.rs index 2b702823c6..76dbbce500 100644 --- a/crates/rpc/src/v1/tests/mocked/secretstore.rs +++ b/crates/rpc/src/v1/tests/mocked/secretstore.rs @@ -17,9 +17,11 @@ use std::sync::Arc; use accounts::AccountProvider; -use crypto::DEFAULT_MAC; +use crypto::{ + publickey::{verify_public, KeyPair, Signature}, + DEFAULT_MAC, +}; use ethereum_types::H256; -use ethkey::{verify_public, KeyPair, Signature}; use jsonrpc_core::{IoHandler, Success}; use serde_json; diff --git a/crates/rpc/src/v1/tests/mocked/signer.rs b/crates/rpc/src/v1/tests/mocked/signer.rs index 58dc1232f4..759659fffd 100644 --- a/crates/rpc/src/v1/tests/mocked/signer.rs +++ b/crates/rpc/src/v1/tests/mocked/signer.rs @@ -92,7 +92,7 @@ fn should_return_list_of_items_to_confirm() { .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { transaction_type: Default::default(), - from: Address::from(1), + from: Address::from_low_u64_be(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: U256::from(10_000), @@ -109,7 +109,7 @@ fn should_return_list_of_items_to_confirm() { let _sign_future = tester .signer .add_request( - ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), + ConfirmationPayload::EthSignMessage(Address::from_low_u64_be(1), vec![5].into()), Origin::Unknown, ) .unwrap(); @@ -139,7 +139,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { transaction_type: Default::default(), - from: Address::from(1), + from: Address::from_low_u64_be(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: U256::from(10_000), @@ -177,7 +177,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { transaction_type: Default::default(), - from: Address::from(1), + from: Address::from_low_u64_be(1), used_default_from: false, to: Some(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), gas_price: U256::from(10_000), @@ -213,7 +213,7 @@ fn should_not_remove_sign_if_password_is_invalid() { let _confirmation_future = tester .signer .add_request( - ConfirmationPayload::EthSignMessage(0.into(), vec![5].into()), + ConfirmationPayload::EthSignMessage(Address::from_low_u64_be(0), vec![5].into()), Origin::Unknown, ) .unwrap(); @@ -308,7 +308,7 @@ fn should_alter_the_sender_and_nonce() { .add_request( ConfirmationPayload::SendTransaction(FilledTransactionRequest { transaction_type: Default::default(), - from: 0.into(), + from: Address::from_low_u64_be(0), used_default_from: false, to: Some(recipient), gas_price: U256::from(10_000), diff --git a/crates/rpc/src/v1/tests/mocked/signing.rs b/crates/rpc/src/v1/tests/mocked/signing.rs index dd7ae5a9b2..f8a675beeb 100644 --- a/crates/rpc/src/v1/tests/mocked/signing.rs +++ b/crates/rpc/src/v1/tests/mocked/signing.rs @@ -32,10 +32,9 @@ use v1::{ use accounts::AccountProvider; use bytes::ToPretty; +use crypto::publickey::{Generator, Random, Secret}; use ethcore::client::TestBlockChainClient; -use ethereum_types::{Address, U256}; -use ethkey::Secret; -use ethstore::ethkey::{Generator, Random}; +use ethereum_types::{Address, H256, H520, U256}; use parity_runtime::{Executor, Runtime}; use parking_lot::Mutex; use serde_json; @@ -156,7 +155,10 @@ fn should_add_sign_to_queue() { if signer.requests().len() == 1 { // respond let sender = signer.take(&1.into()).unwrap(); - signer.request_confirmed(sender, Ok(ConfirmationResponse::Signature(0.into()))); + signer.request_confirmed( + sender, + Ok(ConfirmationResponse::Signature(H520::from_low_u64_be(0))), + ); break; } ::std::thread::sleep(Duration::from_millis(100)) @@ -250,9 +252,10 @@ fn should_check_status_of_request_when_its_resolved() { }"#; tester.io.handle_request_sync(&request).expect("Sent"); let sender = tester.signer.take(&1.into()).unwrap(); - tester - .signer - .request_confirmed(sender, Ok(ConfirmationResponse::Signature(1.into()))); + tester.signer.request_confirmed( + sender, + Ok(ConfirmationResponse::Signature(H520::from_low_u64_be(1))), + ); // This is not ideal, but we need to give futures some time to be executed, and they need to run in a separate thread thread::sleep(Duration::from_millis(20)); @@ -343,7 +346,12 @@ fn should_add_transaction_to_queue() { if signer.requests().len() == 1 { // respond let sender = signer.take(&1.into()).unwrap(); - signer.request_confirmed(sender, Ok(ConfirmationResponse::SendTransaction(0.into()))); + signer.request_confirmed( + sender, + Ok(ConfirmationResponse::SendTransaction( + H256::from_low_u64_be(0), + )), + ); break; } ::std::thread::sleep(Duration::from_millis(100)) @@ -549,7 +557,7 @@ fn should_decrypt_message_if_account_is_unlocked() { fn should_add_decryption_to_the_queue() { // given let tester = eth_signing(); - let acc = Random.generate().unwrap(); + let acc = Random.generate(); assert_eq!(tester.signer.requests().len(), 0); // when @@ -592,7 +600,7 @@ fn should_add_decryption_to_the_queue() { fn should_compose_transaction() { // given let tester = eth_signing(); - let acc = Random.generate().unwrap(); + let acc = Random.generate(); assert_eq!(tester.signer.requests().len(), 0); let from = format!("{:x}", acc.address()); diff --git a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs index 088c95b83f..fd9b517002 100644 --- a/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs +++ b/crates/rpc/src/v1/tests/mocked/signing_unsafe.rs @@ -256,7 +256,7 @@ fn rpc_eth_send_transaction_with_bad_to() { "id": 1 }"#; - let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: prefix is missing."},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: 0x prefix is missing."},"id":1}"#; assert_eq!( tester.io.handle_request_sync(&request), diff --git a/crates/rpc/src/v1/tests/mocked/traces.rs b/crates/rpc/src/v1/tests/mocked/traces.rs index 34b0a28967..f9363da5be 100644 --- a/crates/rpc/src/v1/tests/mocked/traces.rs +++ b/crates/rpc/src/v1/tests/mocked/traces.rs @@ -24,6 +24,7 @@ use ethcore::{ LocalizedTrace, }, }; +use ethereum_types::{Address, H256}; use vm::CallType; @@ -40,8 +41,8 @@ fn io() -> Tester { let client = Arc::new(TestBlockChainClient::new()); *client.traces.write() = Some(vec![LocalizedTrace { action: Action::Call(Call { - from: 0xf.into(), - to: 0x10.into(), + from: Address::from_low_u64_be(0xf), + to: Address::from_low_u64_be(0x10), value: 0x1.into(), gas: 0x100.into(), input: vec![1, 2, 3], @@ -51,9 +52,9 @@ fn io() -> Tester { subtraces: 0, trace_address: vec![0], transaction_number: Some(0), - transaction_hash: Some(5.into()), + transaction_hash: Some(H256::from_low_u64_be(5)), block_number: 10, - block_hash: 10.into(), + block_hash: H256::from_low_u64_be(10), }]); *client.execution_result.write() = Some(Ok(Executed { exception: None, diff --git a/crates/rpc/src/v1/types/call_request.rs b/crates/rpc/src/v1/types/call_request.rs index 609686040d..37a79c9b25 100644 --- a/crates/rpc/src/v1/types/call_request.rs +++ b/crates/rpc/src/v1/types/call_request.rs @@ -88,8 +88,8 @@ mod tests { deserialized, CallRequest { transaction_type: Default::default(), - from: Some(H160::from(1)), - to: Some(H160::from(2)), + from: Some(H160::from_low_u64_be(1)), + to: Some(H160::from_low_u64_be(2)), gas_price: Some(U256::from(1)), gas: Some(U256::from(2)), value: Some(U256::from(3)), @@ -134,7 +134,7 @@ mod tests { deserialized, CallRequest { transaction_type: Default::default(), - from: Some(H160::from(1)), + from: Some(H160::from_low_u64_be(1)), to: None, gas_price: None, gas: None, diff --git a/crates/rpc/src/v1/types/confirmations.rs b/crates/rpc/src/v1/types/confirmations.rs index b489f354c4..152821335e 100644 --- a/crates/rpc/src/v1/types/confirmations.rs +++ b/crates/rpc/src/v1/types/confirmations.rs @@ -302,7 +302,7 @@ where #[cfg(test)] mod tests { use super::*; - use ethereum_types::{H256, U256}; + use ethereum_types::{Address, H256, U256}; use serde_json; use std::str::FromStr; use v1::{helpers, types::TransactionCondition}; @@ -312,7 +312,10 @@ mod tests { // given let request = helpers::ConfirmationRequest { id: 15.into(), - payload: helpers::ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), + payload: helpers::ConfirmationPayload::EthSignMessage( + Address::from_low_u64_be(1), + vec![5].into(), + ), origin: Origin::Rpc("test service".into()), }; @@ -332,7 +335,7 @@ mod tests { payload: helpers::ConfirmationPayload::SendTransaction( helpers::FilledTransactionRequest { transaction_type: Default::default(), - from: 0.into(), + from: Address::from_low_u64_be(0), used_default_from: false, to: None, gas: 15_000.into(), @@ -344,7 +347,9 @@ mod tests { access_list: None, }, ), - origin: Origin::Signer { session: 5.into() }, + origin: Origin::Signer { + session: H256::from_low_u64_be(5), + }, }; // when @@ -363,7 +368,7 @@ mod tests { payload: helpers::ConfirmationPayload::SignTransaction( helpers::FilledTransactionRequest { transaction_type: Default::default(), - from: 0.into(), + from: Address::from_low_u64_be(0), used_default_from: false, to: None, gas: 15_000.into(), @@ -391,7 +396,10 @@ mod tests { // given let request = helpers::ConfirmationRequest { id: 15.into(), - payload: helpers::ConfirmationPayload::Decrypt(10.into(), vec![1, 2, 3].into()), + payload: helpers::ConfirmationPayload::Decrypt( + Address::from_low_u64_be(10), + vec![1, 2, 3].into(), + ), origin: Default::default(), }; @@ -423,7 +431,7 @@ mod tests { assert_eq!( res1, TransactionModification { - sender: Some(10.into()), + sender: Some(Address::from_low_u64_be(10)), gas_price: Some(U256::from_str("0ba43b7400").unwrap()), gas: None, condition: Some(Some(TransactionCondition::Number(0x42))), diff --git a/crates/rpc/src/v1/types/eth_types.rs b/crates/rpc/src/v1/types/eth_types.rs index f048cf814a..32cee83875 100644 --- a/crates/rpc/src/v1/types/eth_types.rs +++ b/crates/rpc/src/v1/types/eth_types.rs @@ -18,10 +18,10 @@ fn should_serialize_u256() { #[test] fn should_serialize_h256() { - let serialized1 = serde_json::to_string(&H256::from(0)).unwrap(); - let serialized2 = serde_json::to_string(&H256::from(1)).unwrap(); - let serialized3 = serde_json::to_string(&H256::from(16)).unwrap(); - let serialized4 = serde_json::to_string(&H256::from(256)).unwrap(); + let serialized1 = serde_json::to_string(&H256::from_low_u64_be(0)).unwrap(); + let serialized2 = serde_json::to_string(&H256::from_low_u64_be(1)).unwrap(); + let serialized3 = serde_json::to_string(&H256::from_low_u64_be(16)).unwrap(); + let serialized4 = serde_json::to_string(&H256::from_low_u64_be(256)).unwrap(); assert_eq!( serialized1, @@ -109,7 +109,7 @@ fn should_deserialize_h256() { ) .unwrap(); - assert_eq!(deserialized1, 0.into()); - assert_eq!(deserialized2, 1.into()); - assert_eq!(deserialized3, 256.into()); + assert_eq!(deserialized1, H256::from_low_u64_be(0)); + assert_eq!(deserialized2, H256::from_low_u64_be(1)); + assert_eq!(deserialized3, H256::from_low_u64_be(256)); } diff --git a/crates/rpc/src/v1/types/filter.rs b/crates/rpc/src/v1/types/filter.rs index 07c841c32e..7e610e1849 100644 --- a/crates/rpc/src/v1/types/filter.rs +++ b/crates/rpc/src/v1/types/filter.rs @@ -238,7 +238,10 @@ mod tests { topics: Some(vec![ VariadicValue::Null, VariadicValue::Single( - "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b".into(), + H256::from_str( + "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + ) + .unwrap(), ), VariadicValue::Null, ]), @@ -254,9 +257,10 @@ mod tests { address: Some(vec![]), topics: vec![ None, - Some(vec![ - "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b".into() - ]), + Some(vec![H256::from_str( + "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b" + ) + .unwrap()]), None, None, ], diff --git a/crates/rpc/src/v1/types/provenance.rs b/crates/rpc/src/v1/types/provenance.rs index 5311cc4006..5352cdc44e 100644 --- a/crates/rpc/src/v1/types/provenance.rs +++ b/crates/rpc/src/v1/types/provenance.rs @@ -66,16 +66,21 @@ impl fmt::Display for Origin { #[cfg(test)] mod tests { use super::Origin; + use ethereum_types::H256; use serde_json; #[test] fn should_serialize_origin() { // given let o1 = Origin::Rpc("test service".into()); - let o3 = Origin::Ipc(5.into()); - let o4 = Origin::Signer { session: 10.into() }; + let o3 = Origin::Ipc(H256::from_low_u64_be(5)); + let o4 = Origin::Signer { + session: H256::from_low_u64_be(10), + }; let o5 = Origin::Unknown; - let o6 = Origin::Ws { session: 5.into() }; + let o6 = Origin::Ws { + session: H256::from_low_u64_be(5), + }; // when let res1 = serde_json::to_string(&o1).unwrap(); diff --git a/crates/rpc/src/v1/types/receipt.rs b/crates/rpc/src/v1/types/receipt.rs index dd083aabeb..7a21d08006 100644 --- a/crates/rpc/src/v1/types/receipt.rs +++ b/crates/rpc/src/v1/types/receipt.rs @@ -140,6 +140,7 @@ impl From for Receipt { #[cfg(test)] mod tests { + use ethereum_types::{Bloom, H256}; use serde_json; use types::transaction::TypedTxId; use v1::types::{Log, Receipt}; @@ -152,7 +153,7 @@ mod tests { from: None, to: None, transaction_type: TypedTxId::AccessList.to_U64_option_id(), - transaction_hash: Some(0.into()), + transaction_hash: Some(H256::zero()), transaction_index: Some(0.into()), block_hash: Some( "ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5" @@ -180,15 +181,15 @@ mod tests { .unwrap(), ), block_number: Some(0x4510c.into()), - transaction_hash: Some(0.into()), + transaction_hash: Some(H256::zero()), transaction_index: Some(0.into()), transaction_log_index: None, log_index: Some(1.into()), log_type: "mined".into(), removed: false, }], - logs_bloom: 15.into(), - state_root: Some(10.into()), + logs_bloom: Bloom::from_low_u64_be(15), + state_root: Some(H256::from_low_u64_be(10)), status_code: Some(1u64.into()), }; diff --git a/crates/rpc/src/v1/types/secretstore.rs b/crates/rpc/src/v1/types/secretstore.rs index b73d4c1d3a..bf77ca0a00 100644 --- a/crates/rpc/src/v1/types/secretstore.rs +++ b/crates/rpc/src/v1/types/secretstore.rs @@ -32,13 +32,14 @@ pub struct EncryptedDocumentKey { #[cfg(test)] mod tests { use super::EncryptedDocumentKey; + use ethereum_types::H512; use serde_json; #[test] fn test_serialize_encrypted_document_key() { let initial = EncryptedDocumentKey { - common_point: 1.into(), - encrypted_point: 2.into(), + common_point: H512::from_low_u64_be(1), + encrypted_point: H512::from_low_u64_be(2), encrypted_key: vec![3].into(), }; @@ -49,8 +50,8 @@ mod tests { ); let deserialized: EncryptedDocumentKey = serde_json::from_str(&serialized).unwrap(); - assert_eq!(deserialized.common_point, 1.into()); - assert_eq!(deserialized.encrypted_point, 2.into()); + assert_eq!(deserialized.common_point, H512::from_low_u64_be(1)); + assert_eq!(deserialized.encrypted_point, H512::from_low_u64_be(2)); assert_eq!(deserialized.encrypted_key, vec![3].into()); } } diff --git a/crates/rpc/src/v1/types/sync.rs b/crates/rpc/src/v1/types/sync.rs index 0563b557a9..7254ef960f 100644 --- a/crates/rpc/src/v1/types/sync.rs +++ b/crates/rpc/src/v1/types/sync.rs @@ -175,6 +175,7 @@ pub struct ChainStatus { #[cfg(test)] mod tests { use super::{ChainStatus, Peers, SyncInfo, SyncStatus, TransactionStats}; + use ethereum_types::H512; use serde_json; use std::collections::BTreeMap; @@ -229,7 +230,7 @@ mod tests { let stats = TransactionStats { first_seen: 100, propagated_to: map![ - 10.into() => 50 + H512::from_low_u64_be(10) => 50 ], }; diff --git a/crates/rpc/src/v1/types/trace.rs b/crates/rpc/src/v1/types/trace.rs index e4595879b5..7e055c5423 100644 --- a/crates/rpc/src/v1/types/trace.rs +++ b/crates/rpc/src/v1/types/trace.rs @@ -679,6 +679,7 @@ impl From<(H256, Executed)> for TraceResultsWithTransactionHash { mod tests { use super::*; use ethcore::trace::TraceError; + use ethereum_types::{Address, H256}; use serde_json; use std::collections::BTreeMap; use v1::types::Bytes; @@ -702,8 +703,8 @@ mod tests { fn test_trace_call_serialize() { let t = LocalizedTrace { action: Action::Call(Call { - from: 4.into(), - to: 5.into(), + from: Address::from_low_u64_be(4), + to: Address::from_low_u64_be(5), value: 6.into(), gas: 7.into(), input: Bytes::new(vec![0x12, 0x34]), @@ -716,9 +717,9 @@ mod tests { trace_address: vec![10], subtraces: 1, transaction_position: Some(11), - transaction_hash: Some(12.into()), + transaction_hash: Some(H256::from_low_u64_be(12)), block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -731,8 +732,8 @@ mod tests { fn test_trace_failed_call_serialize() { let t = LocalizedTrace { action: Action::Call(Call { - from: 4.into(), - to: 5.into(), + from: Address::from_low_u64_be(4), + to: Address::from_low_u64_be(5), value: 6.into(), gas: 7.into(), input: Bytes::new(vec![0x12, 0x34]), @@ -742,9 +743,9 @@ mod tests { trace_address: vec![10], subtraces: 1, transaction_position: Some(11), - transaction_hash: Some(12.into()), + transaction_hash: Some(H256::from_low_u64_be(12)), block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -757,7 +758,7 @@ mod tests { fn test_trace_create_serialize() { let t = LocalizedTrace { action: Action::Create(Create { - from: 4.into(), + from: Address::from_low_u64_be(4), value: 6.into(), gas: 7.into(), init: Bytes::new(vec![0x12, 0x34]), @@ -765,14 +766,14 @@ mod tests { result: Res::Create(CreateResult { gas_used: 8.into(), code: vec![0x56, 0x78].into(), - address: 0xff.into(), + address: Address::from_low_u64_be(0xff), }), trace_address: vec![10], subtraces: 1, transaction_position: Some(11), - transaction_hash: Some(12.into()), + transaction_hash: Some(H256::from_low_u64_be(12)), block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -785,7 +786,7 @@ mod tests { fn test_trace_failed_create_serialize() { let t = LocalizedTrace { action: Action::Create(Create { - from: 4.into(), + from: Address::from_low_u64_be(4), value: 6.into(), gas: 7.into(), init: Bytes::new(vec![0x12, 0x34]), @@ -794,9 +795,9 @@ mod tests { trace_address: vec![10], subtraces: 1, transaction_position: Some(11), - transaction_hash: Some(12.into()), + transaction_hash: Some(H256::from_low_u64_be(12)), block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -809,17 +810,17 @@ mod tests { fn test_trace_suicide_serialize() { let t = LocalizedTrace { action: Action::Suicide(Suicide { - address: 4.into(), - refund_address: 6.into(), + address: Address::from_low_u64_be(4), + refund_address: Address::from_low_u64_be(6), balance: 7.into(), }), result: Res::None, trace_address: vec![10], subtraces: 1, transaction_position: Some(11), - transaction_hash: Some(12.into()), + transaction_hash: Some(H256::from_low_u64_be(12)), block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -832,7 +833,7 @@ mod tests { fn test_trace_reward_serialize() { let t = LocalizedTrace { action: Action::Reward(Reward { - author: 4.into(), + author: Address::from_low_u64_be(4), value: 6.into(), reward_type: RewardType::Block, }), @@ -842,7 +843,7 @@ mod tests { transaction_position: None, transaction_hash: None, block_number: 13, - block_hash: 14.into(), + block_hash: H256::from_low_u64_be(14), }; let serialized = serde_json::to_string(&t).unwrap(); assert_eq!( @@ -904,15 +905,15 @@ mod tests { #[test] fn test_statediff_serialize() { let t = StateDiff(map![ - 42.into() => AccountDiff { + Address::from_low_u64_be(42) => AccountDiff { balance: Diff::Same, nonce: Diff::Born(1.into()), code: Diff::Same, storage: map![ - 42.into() => Diff::Same + H256::from_low_u64_be(42) => Diff::Same ] }, - 69.into() => AccountDiff { + Address::from_low_u64_be(69) => AccountDiff { balance: Diff::Same, nonce: Diff::Changed(ChangedType { from: 1.into(), to: 0.into() }), code: Diff::Died(vec![96].into()), diff --git a/crates/rpc/src/v1/types/trace_filter.rs b/crates/rpc/src/v1/types/trace_filter.rs index 50b3ea47f1..7c61c78a3d 100644 --- a/crates/rpc/src/v1/types/trace_filter.rs +++ b/crates/rpc/src/v1/types/trace_filter.rs @@ -106,8 +106,8 @@ mod tests { TraceFilter { from_block: Some(BlockNumber::Latest), to_block: Some(BlockNumber::Latest), - from_address: Some(vec![Address::from(3).into()]), - to_address: Some(vec![Address::from(5).into()]), + from_address: Some(vec![Address::from_low_u64_be(3).into()]), + to_address: Some(vec![Address::from_low_u64_be(5).into()]), after: 50.into(), count: 100.into(), } diff --git a/crates/rpc/src/v1/types/transaction.rs b/crates/rpc/src/v1/types/transaction.rs index 14f7608e7a..f84a8951e8 100644 --- a/crates/rpc/src/v1/types/transaction.rs +++ b/crates/rpc/src/v1/types/transaction.rs @@ -317,6 +317,7 @@ impl LocalTransactionStatus { #[cfg(test)] mod tests { use super::{LocalTransactionStatus, Transaction}; + use ethereum_types::H256; use serde_json; use types::transaction::TypedTxId; use v1::types::AccessListItem; @@ -343,7 +344,11 @@ mod tests { let status5 = LocalTransactionStatus::Invalid(Transaction::default()); let status6 = LocalTransactionStatus::Rejected(Transaction::default(), "Just because".into()); - let status7 = LocalTransactionStatus::Replaced(Transaction::default(), 5.into(), 10.into()); + let status7 = LocalTransactionStatus::Replaced( + Transaction::default(), + 5.into(), + H256::from_low_u64_be(10), + ); assert_eq!( serde_json::to_string(&status1).unwrap(), diff --git a/crates/rpc/src/v1/types/transaction_request.rs b/crates/rpc/src/v1/types/transaction_request.rs index 8aab53876c..77d0282b25 100644 --- a/crates/rpc/src/v1/types/transaction_request.rs +++ b/crates/rpc/src/v1/types/transaction_request.rs @@ -178,8 +178,8 @@ mod tests { deserialized, TransactionRequest { transaction_type: Default::default(), - from: Some(H160::from(1)), - to: Some(H160::from(2)), + from: Some(H160::from_low_u64_be(1)), + to: Some(H160::from_low_u64_be(2)), gas_price: Some(U256::from(1)), gas: Some(U256::from(2)), value: Some(U256::from(3)), @@ -226,7 +226,7 @@ mod tests { deserialized, TransactionRequest { transaction_type: Default::default(), - from: Some(H160::from(1).into()), + from: Some(H160::from_low_u64_be(1).into()), to: None, gas_price: None, gas: None, diff --git a/crates/util/EIP-712/Cargo.toml b/crates/util/EIP-712/Cargo.toml index 3d6320b038..48428a0b7c 100644 --- a/crates/util/EIP-712/Cargo.toml +++ b/crates/util/EIP-712/Cargo.toml @@ -14,9 +14,9 @@ edition = "2018" serde_derive = "1.0" serde = "1.0" serde_json = "1.0" -ethabi = "6.0" -keccak-hash = "0.1" -ethereum-types = "0.4" +ethabi = "12.0.0" +keccak-hash = "0.5.0" +ethereum-types = "0.9.2" failure = "0.1.7" itertools = "0.7" lazy_static = "1.1" diff --git a/crates/util/EIP-712/src/encode.rs b/crates/util/EIP-712/src/encode.rs index 09d6caef9b..a63f8300cf 100644 --- a/crates/util/EIP-712/src/encode.rs +++ b/crates/util/EIP-712/src/encode.rs @@ -134,8 +134,7 @@ fn encode_data( items.append(&mut encoded); } - // keccak(items).as_ref().to_vec() - keccak(items).to_vec() + keccak(items).as_ref().to_vec() } Type::Custom(ref ident) if message_types.get(&*ident).is_some() => { @@ -152,8 +151,7 @@ fn encode_data( tokens.append(&mut encoded); } - // keccak(tokens).as_ref().to_vec() - keccak(tokens).to_vec() + keccak(tokens).as_ref().to_vec() } Type::Bytes => { @@ -164,8 +162,7 @@ fn encode_data( let bytes = (&string[2..]) .from_hex::>() .map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; - // let bytes = keccak(&bytes).as_ref().to_vec(); - let bytes = keccak(&bytes).to_vec(); + let bytes = keccak(&bytes).as_ref().to_vec(); encode(&[EthAbiToken::FixedBytes(bytes)]) } @@ -184,8 +181,7 @@ fn encode_data( Type::String => { let value = value.as_str().ok_or(serde_error("string", field_name))?; - // let hash = keccak(value).as_ref().to_vec(); - let hash = keccak(value).to_vec(); + let hash = keccak(value).as_ref().to_vec(); encode(&[EthAbiToken::FixedBytes(hash)]) } diff --git a/crates/util/cli-signer/Cargo.toml b/crates/util/cli-signer/Cargo.toml index afc3352cac..83fe9c0c2f 100644 --- a/crates/util/cli-signer/Cargo.toml +++ b/crates/util/cli-signer/Cargo.toml @@ -7,7 +7,7 @@ version = "1.4.0" authors = ["Parity "] [dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" futures = "0.1" rpassword = "1.0" parity-rpc = { path = "../../rpc" } diff --git a/crates/util/cli-signer/rpc-client/Cargo.toml b/crates/util/cli-signer/rpc-client/Cargo.toml index 19d2c61a8a..fe54b5fccf 100644 --- a/crates/util/cli-signer/rpc-client/Cargo.toml +++ b/crates/util/cli-signer/rpc-client/Cargo.toml @@ -7,7 +7,7 @@ version = "1.4.0" authors = ["Parity "] [dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" futures = "0.1" log = "0.4" serde = "1.0" @@ -18,4 +18,4 @@ parking_lot = "0.9" jsonrpc-core = "15.0.0" jsonrpc-ws-server = "15.0.0" parity-rpc = { path = "../../../rpc" } -keccak-hash = "0.1" +keccak-hash = "0.5.0" diff --git a/crates/util/dir/Cargo.toml b/crates/util/dir/Cargo.toml index 449805c38d..bfa27f23e6 100644 --- a/crates/util/dir/Cargo.toml +++ b/crates/util/dir/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] license = "GPL3" [dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" journaldb = { path = "../../db/journaldb" } app_dirs = { git = "https://github.com/openethereum/app-dirs-rs" } home = "0.3" diff --git a/crates/util/dir/src/lib.rs b/crates/util/dir/src/lib.rs index 05d8b7b22d..f105014b4f 100644 --- a/crates/util/dir/src/lib.rs +++ b/crates/util/dir/src/lib.rs @@ -188,9 +188,10 @@ impl DatabaseDirectories { /// Base DB directory for the given fork. // TODO: remove in 1.7 pub fn legacy_fork_path(&self) -> PathBuf { + let gh = H64::from_slice(&self.genesis_hash.as_bytes()[20..28]); Path::new(&self.legacy_path).join(format!( "{:x}{}", - H64::from(self.genesis_hash), + gh, self.fork_name .as_ref() .map(|f| format!("-{}", f)) @@ -212,9 +213,8 @@ impl DatabaseDirectories { /// DB root path, named after genesis hash pub fn db_root_path(&self) -> PathBuf { - self.spec_root_path() - .join("db") - .join(format!("{:x}", H64::from(self.genesis_hash))) + let gh = H64::from_slice(&self.genesis_hash.as_bytes()[20..28]); + self.spec_root_path().join("db").join(format!("{:x}", gh)) } /// DB path diff --git a/crates/util/fastmap/Cargo.toml b/crates/util/fastmap/Cargo.toml index 371eebe976..6ca397d773 100644 --- a/crates/util/fastmap/Cargo.toml +++ b/crates/util/fastmap/Cargo.toml @@ -6,5 +6,5 @@ description = "Specialized version of `HashMap` with H256 keys and fast hashing license = "GPL-3.0" [dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" plain_hasher = "0.2" diff --git a/crates/util/fastmap/src/lib.rs b/crates/util/fastmap/src/lib.rs index cc7929b01e..cc39591e17 100644 --- a/crates/util/fastmap/src/lib.rs +++ b/crates/util/fastmap/src/lib.rs @@ -38,6 +38,6 @@ mod tests { #[test] fn test_works() { let mut h = H256FastMap::default(); - h.insert(H256::from(123), "abc"); + h.insert(H256::from_low_u64_be(123), "abc"); } } diff --git a/crates/util/keccak-hasher/Cargo.toml b/crates/util/keccak-hasher/Cargo.toml index edeecda833..ba3af0d3d2 100644 --- a/crates/util/keccak-hasher/Cargo.toml +++ b/crates/util/keccak-hasher/Cargo.toml @@ -6,7 +6,7 @@ description = "Keccak-256 implementation of the Hasher trait" license = "GPL-3.0" [dependencies] -ethereum-types = "0.4" +ethereum-types = "0.9.2" tiny-keccak = "1.4.2" hash-db = "0.11.0" plain_hasher = "0.2" diff --git a/crates/util/memory-cache/Cargo.toml b/crates/util/memory-cache/Cargo.toml index f2b612463a..213772857f 100644 --- a/crates/util/memory-cache/Cargo.toml +++ b/crates/util/memory-cache/Cargo.toml @@ -6,5 +6,5 @@ description = "An LRU-cache which operates on memory used" license = "GPL3" [dependencies] -heapsize = "0.4" +parity-util-mem = "0.7" lru-cache = "0.1" diff --git a/crates/util/memory-cache/src/lib.rs b/crates/util/memory-cache/src/lib.rs index bfa260c742..1f401671db 100644 --- a/crates/util/memory-cache/src/lib.rs +++ b/crates/util/memory-cache/src/lib.rs @@ -18,29 +18,29 @@ //! crate. // TODO: push changes upstream in a clean way. -extern crate heapsize; extern crate lru_cache; +extern crate parity_util_mem; -use heapsize::HeapSizeOf; use lru_cache::LruCache; +use parity_util_mem::{MallocSizeOf, MallocSizeOfExt}; use std::hash::Hash; const INITIAL_CAPACITY: usize = 4; /// An LRU-cache which operates on memory used. -pub struct MemoryLruCache { +pub struct MemoryLruCache { inner: LruCache, cur_size: usize, max_size: usize, } // amount of memory used when the item will be put on the heap. -fn heap_size_of(val: &T) -> usize { - ::std::mem::size_of::() + val.heap_size_of_children() +fn heap_size_of(val: &T) -> usize { + ::std::mem::size_of::() + val.malloc_size_of() } -impl MemoryLruCache { +impl MemoryLruCache { /// Create a new cache with a maximum size in bytes. pub fn new(max_size: usize) -> Self { MemoryLruCache { diff --git a/crates/util/rlp-compress/Cargo.toml b/crates/util/rlp-compress/Cargo.toml index 4bd34bce13..e16c5b3de2 100644 --- a/crates/util/rlp-compress/Cargo.toml +++ b/crates/util/rlp-compress/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } elastic-array = "0.10" lazy_static = "1.0" diff --git a/crates/util/rlp-derive/Cargo.toml b/crates/util/rlp-derive/Cargo.toml index 2087f75243..d843d75a52 100644 --- a/crates/util/rlp-derive/Cargo.toml +++ b/crates/util/rlp-derive/Cargo.toml @@ -13,4 +13,4 @@ quote = "0.6" proc-macro2 = "0.4" [dev-dependencies] -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } diff --git a/crates/util/triehash-ethereum/Cargo.toml b/crates/util/triehash-ethereum/Cargo.toml index 5b63642975..929baf1d2b 100644 --- a/crates/util/triehash-ethereum/Cargo.toml +++ b/crates/util/triehash-ethereum/Cargo.toml @@ -6,6 +6,6 @@ description = "Trie-root helpers, ethereum style" license = "GPL-3.0" [dependencies] -triehash = { version = "0.4.0", features = ["ethereum"] } -ethereum-types = "0.4" +triehash = { version = "0.5.0" } +ethereum-types = "0.9.2" keccak-hasher = { path = "../keccak-hasher" } diff --git a/crates/util/triehash-ethereum/src/lib.rs b/crates/util/triehash-ethereum/src/lib.rs index 0409d04329..029f59f796 100644 --- a/crates/util/triehash-ethereum/src/lib.rs +++ b/crates/util/triehash-ethereum/src/lib.rs @@ -55,7 +55,9 @@ where #[cfg(test)] mod tests { use super::{ordered_trie_root, sec_trie_root, trie_root}; + use ethereum_types::H256; use keccak_hasher::KeccakHasher; + use std::str::FromStr; use triehash; #[test] @@ -65,7 +67,8 @@ mod tests { b"A", b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8] )]), - "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab".into() + H256::from_str("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab") + .unwrap() ); } diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index 7fdef2e3b7..2c0db378e7 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -9,7 +9,7 @@ build = "build.rs" [dependencies] parity-bytes = "0.1" -rlp = { version = "0.3.0", features = ["ethereum"] } +rlp = { version = "0.4.6" } target_info = "0.1" [build-dependencies] diff --git a/crates/vm/builtin/Cargo.toml b/crates/vm/builtin/Cargo.toml index 540d179b09..45167eb969 100644 --- a/crates/vm/builtin/Cargo.toml +++ b/crates/vm/builtin/Cargo.toml @@ -9,15 +9,15 @@ edition = "2018" bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.3.2" eip-152 = { path = "../../util/EIP-152" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" ethjson = { path = "../../ethjson" } ethkey = { path = "../../accounts/ethkey" } -keccak-hash = "0.1.0" +keccak-hash = "0.5.0" log = "0.4" macros = { path = "../../util/macros" } num = { version = "0.1", default-features = false, features = ["bigint"] } parity-bytes = "0.1" -parity-crypto = "0.4.0" +parity-crypto = { version = "0.6.2", features = [ "publickey" ] } eth_pairings = { git = "https://github.com/matter-labs/eip1962.git", default-features = false, features = ["eip_2537"], rev = "ece6cbabc41948db4200e41f0bfdab7ab94c7af8" } [dev-dependencies] diff --git a/crates/vm/builtin/src/lib.rs b/crates/vm/builtin/src/lib.rs index 5ba9247724..3583c2d692 100644 --- a/crates/vm/builtin/src/lib.rs +++ b/crates/vm/builtin/src/lib.rs @@ -35,12 +35,14 @@ use eth_pairings::public_interface::eip2537::{ }; use ethereum_types::{H256, U256}; use ethjson; -use ethkey::{recover as ec_recover, Signature}; use keccak_hash::keccak; use log::{trace, warn}; use num::{BigUint, One, Zero}; use parity_bytes::BytesRef; -use parity_crypto::digest; +use parity_crypto::{ + digest, + publickey::{recover_allowing_all_zero_message, Signature, ZeroesAllowedMessage}, +}; /// Native implementation of a built-in contract. pub trait Implementation: Send + Sync { @@ -192,7 +194,7 @@ impl ModexpPricer { reader .read_exact(&mut buf[..]) .expect("reading from zero-extended memory cannot fail; qed"); - U256::from(H256::from_slice(&buf[..])) + U256::from_big_endian(&buf[..]) }; let base_len_u256 = read_len(); let exp_len_u256 = read_len(); @@ -210,7 +212,7 @@ impl ModexpPricer { reader .read_exact(&mut buf[(32 - len)..]) .expect("reading from zero-extended memory cannot fail; qed"); - U256::from(H256::from_slice(&buf[..])) + U256::from_big_endian(&buf[..]) }; (base_len_u256, exp_len_u256, exp_low, mod_len_u256) @@ -829,10 +831,16 @@ impl Implementation for EcRecover { let s = Signature::from_rsv(&r, &s, bit); if s.is_valid() { - if let Ok(p) = ec_recover(&s, &hash) { + // The builtin allows/requires all-zero messages to be valid to + // recover the public key. Use of such messages is disallowed in + // `rust-secp256k1` and this is a workaround for that. It is not an + // openethereum-level error to fail here; instead we return all + // zeroes and let the caller interpret that outcome. + let recovery_message = ZeroesAllowedMessage(hash); + if let Ok(p) = recover_allowing_all_zero_message(&s, recovery_message) { let r = keccak(p); output.write(0, &[0; 12]); - output.write(12, &r[12..r.len()]); + output.write(12, &r.as_bytes()[12..]); } } diff --git a/crates/vm/call-contract/Cargo.toml b/crates/vm/call-contract/Cargo.toml index 08066e9888..da5606487b 100644 --- a/crates/vm/call-contract/Cargo.toml +++ b/crates/vm/call-contract/Cargo.toml @@ -8,5 +8,5 @@ edition = "2018" [dependencies] types = { path = "../../ethcore/types", package = "common-types" } -ethereum-types = "0.4" +ethereum-types = "0.9.2" bytes = { version = "0.1", package = "parity-bytes" } diff --git a/crates/vm/evm/Cargo.toml b/crates/vm/evm/Cargo.toml index e59bf7e6d9..d79bf5f87b 100644 --- a/crates/vm/evm/Cargo.toml +++ b/crates/vm/evm/Cargo.toml @@ -7,12 +7,12 @@ authors = ["Parity Technologies "] [dependencies] bit-set = "0.4" parity-bytes = "0.1" -ethereum-types = "0.4" -heapsize = "0.4" +ethereum-types = "0.9.2" lazy_static = "1.0" log = "0.4" vm = { path = "../vm" } -keccak-hash = "0.1" +keccak-hash = "0.5.0" +parity-util-mem = "0.7" parking_lot = "0.7" memory-cache = { path = "../../util/memory-cache" } ethcore-builtin = { path = "../builtin" } diff --git a/crates/vm/evm/benches/basic.rs b/crates/vm/evm/benches/basic.rs index f6b7fa4727..4d2d8e4a60 100644 --- a/crates/vm/evm/benches/basic.rs +++ b/crates/vm/evm/benches/basic.rs @@ -21,7 +21,6 @@ extern crate criterion; extern crate bit_set; extern crate ethereum_types; extern crate evm; -extern crate heapsize; extern crate keccak_hash as hash; extern crate memory_cache; extern crate parity_bytes as bytes; diff --git a/crates/vm/evm/src/interpreter/gasometer.rs b/crates/vm/evm/src/interpreter/gasometer.rs index 8a710069e5..aec51b4ecf 100644 --- a/crates/vm/evm/src/interpreter/gasometer.rs +++ b/crates/vm/evm/src/interpreter/gasometer.rs @@ -15,7 +15,7 @@ // along with OpenEthereum. If not, see . use super::u256_to_address; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::{Address, BigEndianHash, U256}; use std::cmp; use super::stack::VecStack; @@ -139,14 +139,14 @@ impl Gasometer { if schedule.eip1706 && self.current_gas <= Gas::from(schedule.call_stipend) { return Err(vm::Error::OutOfGas); } - let key = H256::from(stack.peek(0)); + let key = BigEndianHash::from_uint(stack.peek(0)); let newval = stack.peek(1); - let val = U256::from(&*ext.storage_at(&key)?); + let val = ext.storage_at(&key)?.into_uint(); let is_cold = !ext.al_contains_storage_key(current_address, &key); let gas = if schedule.eip1283 { - let orig = U256::from(&*ext.initial_storage_at(&key)?); + let orig = ext.initial_storage_at(&key)?.into_uint(); calculate_eip1283_eip2929_sstore_gas(schedule, is_cold, &orig, &val, &newval) } else { if val.is_zero() && !newval.is_zero() { @@ -161,7 +161,7 @@ impl Gasometer { Request::Gas(gas.into()) } instructions::SLOAD => { - let key = H256::from(stack.peek(0)); + let key = BigEndianHash::from_uint(stack.peek(0)); let gas = if ext.al_is_enabled() { if ext.al_contains_storage_key(current_address, &key) { schedule.warm_storage_read_cost diff --git a/crates/vm/evm/src/interpreter/mod.rs b/crates/vm/evm/src/interpreter/mod.rs index 418c3572a5..302013f5e5 100644 --- a/crates/vm/evm/src/interpreter/mod.rs +++ b/crates/vm/evm/src/interpreter/mod.rs @@ -24,7 +24,7 @@ mod shared_cache; mod stack; use bytes::Bytes; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; use hash::keccak; use num_bigint::BigUint; use std::{cmp, marker::PhantomData, mem, sync::Arc}; @@ -694,7 +694,7 @@ impl Interpreter { let address_scheme = match instruction { instructions::CREATE => CreateContractAddress::FromSenderAndNonce, instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash( - self.stack.pop_back().into(), + BigEndianHash::from_uint(&self.stack.pop_back()), ), _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), }; @@ -940,7 +940,7 @@ impl Interpreter { .stack .pop_n(no_of_topics) .iter() - .map(H256::from) + .map(BigEndianHash::from_uint) .collect(); ext.log(topics, self.mem.read_slice(offset, size))?; } @@ -1003,23 +1003,23 @@ impl Interpreter { let offset = self.stack.pop_back(); let size = self.stack.pop_back(); let k = keccak(self.mem.read_slice(offset, size)); - self.stack.push(U256::from(&*k)); + self.stack.push(k.into_uint()); } instructions::SLOAD => { - let key = H256::from(&self.stack.pop_back()); - let word = U256::from(&*ext.storage_at(&key)?); + let key = BigEndianHash::from_uint(&self.stack.pop_back()); + let word = ext.storage_at(&key)?.into_uint(); self.stack.push(word); ext.al_insert_storage_key(self.params.address, key); } instructions::SSTORE => { - let key = H256::from(&self.stack.pop_back()); + let key = BigEndianHash::from_uint(&self.stack.pop_back()); let val = self.stack.pop_back(); - let current_val = U256::from(&*ext.storage_at(&key)?); + let current_val = ext.storage_at(&key)?.into_uint(); // Increase refund for clear if ext.schedule().eip1283 { - let original_val = U256::from(&*ext.initial_storage_at(&key)?); + let original_val = ext.initial_storage_at(&key)?.into_uint(); gasometer::handle_eip1283_sstore_clears_refund( ext, &original_val, @@ -1032,7 +1032,7 @@ impl Interpreter { ext.add_sstore_refund(sstore_clears_schedule); } } - ext.set_storage(key, H256::from(&val))?; + ext.set_storage(key, BigEndianHash::from_uint(&val))?; ext.al_insert_storage_key(self.params.address, key); } instructions::PC => { @@ -1099,7 +1099,7 @@ impl Interpreter { let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero); ext.al_insert_address(address); - self.stack.push(U256::from(hash)); + self.stack.push(hash.into_uint()); } instructions::CALLDATACOPY => { Self::copy_data_to_memory( @@ -1142,7 +1142,7 @@ impl Interpreter { instructions::BLOCKHASH => { let block_number = self.stack.pop_back(); let block_hash = ext.blockhash(&block_number); - self.stack.push(U256::from(&*block_hash)); + self.stack.push(block_hash.into_uint()); } instructions::COINBASE => { self.stack @@ -1528,16 +1528,18 @@ fn set_sign(value: U256, sign: bool) -> U256 { #[inline] fn u256_to_address(value: &U256) -> Address { - Address::from(H256::from(value)) + let addr: H256 = BigEndianHash::from_uint(value); + Address::from(addr) } #[inline] fn address_to_u256(value: Address) -> U256 { - U256::from(&*H256::from(value)) + H256::from(value).into_uint() } #[cfg(test)] mod tests { + use ethereum_types::Address; use factory::Factory; use rustc_hex::FromHex; use std::sync::Arc; @@ -1557,13 +1559,14 @@ mod tests { let code = "7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055".from_hex().unwrap(); let mut params = ActionParams::default(); - params.address = 5.into(); + params.address = Address::from_low_u64_be(5); params.gas = 300_000.into(); params.gas_price = 1.into(); params.value = ActionValue::Transfer(100_000.into()); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new(); - ext.balances.insert(5.into(), 1_000_000_000.into()); + ext.balances + .insert(Address::from_low_u64_be(5), 1_000_000_000.into()); ext.tracing = true; let gas_left = { @@ -1580,12 +1583,13 @@ mod tests { let code = "6001600160000360003e00".from_hex().unwrap(); let mut params = ActionParams::default(); - params.address = 5.into(); + params.address = Address::from_low_u64_be(5); params.gas = 300_000.into(); params.gas_price = 1.into(); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new_byzantium(); - ext.balances.insert(5.into(), 1_000_000_000.into()); + ext.balances + .insert(Address::from_low_u64_be(5), 1_000_000_000.into()); ext.tracing = true; let err = { diff --git a/crates/vm/evm/src/interpreter/shared_cache.rs b/crates/vm/evm/src/interpreter/shared_cache.rs index 459bb1a90d..cc25ff464f 100644 --- a/crates/vm/evm/src/interpreter/shared_cache.rs +++ b/crates/vm/evm/src/interpreter/shared_cache.rs @@ -18,36 +18,29 @@ use super::super::instructions::{self, Instruction}; use bit_set::BitSet; use ethereum_types::H256; use hash::KECCAK_EMPTY; -use heapsize::HeapSizeOf; use memory_cache::MemoryLruCache; +use parity_util_mem::{MallocSizeOf, MallocSizeOfOps}; use parking_lot::Mutex; use std::sync::Arc; const DEFAULT_CACHE_SIZE: usize = 4 * 1024 * 1024; -// stub for a HeapSizeOf implementation. #[derive(Clone)] struct Bits(Arc); -impl HeapSizeOf for Bits { - fn heap_size_of_children(&self) -> usize { +impl MallocSizeOf for Bits { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { // dealing in bits here self.0.capacity() * 8 } } -#[derive(Clone)] +#[derive(MallocSizeOf, Clone)] struct CacheItem { jump_destination: Bits, sub_entrypoint: Bits, } -impl HeapSizeOf for CacheItem { - fn heap_size_of_children(&self) -> usize { - self.jump_destination.heap_size_of_children() + self.sub_entrypoint.heap_size_of_children() - } -} - /// Global cache for EVM interpreter pub struct SharedCache { jump_destinations: Mutex>, diff --git a/crates/vm/evm/src/lib.rs b/crates/vm/evm/src/lib.rs index 144cbf8950..66431fa3dc 100644 --- a/crates/vm/evm/src/lib.rs +++ b/crates/vm/evm/src/lib.rs @@ -19,11 +19,11 @@ extern crate bit_set; extern crate ethcore_builtin as builtin; extern crate ethereum_types; -extern crate heapsize; extern crate keccak_hash as hash; extern crate memory_cache; extern crate num_bigint; extern crate parity_bytes as bytes; +extern crate parity_util_mem; extern crate parking_lot; extern crate vm; diff --git a/crates/vm/evm/src/tests.rs b/crates/vm/evm/src/tests.rs index 14fa069411..32daa37e16 100644 --- a/crates/vm/evm/src/tests.rs +++ b/crates/vm/evm/src/tests.rs @@ -334,7 +334,7 @@ fn test_blockhash(factory: super::Factory) { }; assert_eq!(gas_left, U256::from(79_974)); - assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash); + assert_eq!(ext.store.get(&H256::default()).unwrap(), &blockhash); } evm_test! {test_calldataload: test_calldataload_int} @@ -1207,8 +1207,8 @@ evm_test! {test_calls: test_calls_int} fn test_calls(factory: super::Factory) { let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap(); - let address = Address::from(0x155); - let code_address = Address::from(0x998); + let address = Address::from_low_u64_be(0x155); + let code_address = Address::from_low_u64_be(0x998); let mut params = ActionParams::default(); params.gas = U256::from(150_000); params.code = Some(Arc::new(code)); @@ -1259,7 +1259,7 @@ evm_test! {test_create_in_staticcall: test_create_in_staticcall_int} fn test_create_in_staticcall(factory: super::Factory) { let code = "600060006064f000".from_hex().unwrap(); - let address = Address::from(0x155); + let address = Address::from_low_u64_be(0x155); let mut params = ActionParams::default(); params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); @@ -1579,12 +1579,12 @@ fn test_access_list_ext_at_precompiles(factory: super::Factory) { params.gas = U256::from(8653); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new_berlin( - Address::from("0x0000000000000000000000000000000000000000"), - Address::from("0x000000000000000000000000636F6E7472616374"), + Address::from_str("0000000000000000000000000000000000000000").unwrap(), + Address::from_str("000000000000000000000000636F6E7472616374").unwrap(), &[ - Address::from("0x0000000000000000000000000000000000000001"), - Address::from("0x0000000000000000000000000000000000000002"), - Address::from("0x0000000000000000000000000000000000000003"), + Address::from_str("0000000000000000000000000000000000000001").unwrap(), + Address::from_str("0000000000000000000000000000000000000002").unwrap(), + Address::from_str("0000000000000000000000000000000000000003").unwrap(), ], ); let gas_left = { @@ -1603,8 +1603,8 @@ fn test_access_list_extcodecopy_twice(factory: super::Factory) { params.gas = U256::from(2835); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new_berlin( - Address::from("0x0000000000000000000000000000000000000000"), - Address::from("0x000000000000000000000000636F6E7472616374"), + Address::from_str("0000000000000000000000000000000000000000").unwrap(), + Address::from_str("000000000000000000000000636F6E7472616374").unwrap(), &[], ); let gas_left = { @@ -1629,8 +1629,8 @@ fn test_access_list_sload_sstore(factory: super::Factory) { params.gas = U256::from(44529); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new_berlin( - Address::from("0x0000000000000000000000000000000000000000"), - Address::from("0x000000000000000000000000636F6E7472616374"), + Address::from_str("0000000000000000000000000000000000000000").unwrap(), + Address::from_str("000000000000000000000000636F6E7472616374").unwrap(), &[], ); let gas_left = { @@ -1649,9 +1649,9 @@ fn test_access_list_cheap_expensive_cheap(factory: super::Factory) { params.gas = U256::from(2869); params.code = Some(Arc::new(code)); let mut ext = FakeExt::new_berlin( - Address::from("0x0000000000000000000000000000000000000000"), - Address::from("0x000000000000000000000000636F6E7472616374"), - &[Address::from("0x0000000000000000000000000000000000000004")], + Address::from_str("0000000000000000000000000000000000000000").unwrap(), + Address::from_str("000000000000000000000000636F6E7472616374").unwrap(), + &[Address::from_str("0000000000000000000000000000000000000004").unwrap()], ); let gas_left = { let vm = factory.create(params, ext.schedule(), ext.depth()); @@ -1705,7 +1705,7 @@ fn assert_set_contains(set: &HashSet, val: fn assert_store(ext: &FakeExt, pos: u64, val: &str) { assert_eq!( - ext.store.get(&H256::from(pos)).unwrap(), + ext.store.get(&H256::from_low_u64_be(pos)).unwrap(), &H256::from_str(val).unwrap() ); } diff --git a/crates/vm/vm/Cargo.toml b/crates/vm/vm/Cargo.toml index 70a7056b35..ece0197c49 100644 --- a/crates/vm/vm/Cargo.toml +++ b/crates/vm/vm/Cargo.toml @@ -6,8 +6,8 @@ authors = ["Parity Technologies "] [dependencies] parity-bytes = "0.1" -ethereum-types = "0.4" +ethereum-types = "0.9.2" patricia-trie-ethereum = { path = "../../db/patricia-trie-ethereum" } ethjson = { path = "../../ethjson" } -rlp = { version = "0.3.0", features = ["ethereum"] } -keccak-hash = "0.1" +rlp = { version = "0.4.6" } +keccak-hash = "0.5.0" diff --git a/crates/vm/vm/src/access_list.rs b/crates/vm/vm/src/access_list.rs index 3d3545604a..aa6c71f9af 100644 --- a/crates/vm/vm/src/access_list.rs +++ b/crates/vm/vm/src/access_list.rs @@ -182,12 +182,16 @@ mod tests { #[test] fn default_disabled_accesslist_does_nothing() { let mut access_list = AccessList::default(); - access_list.insert_address(Address::from(1)); - access_list.insert_storage_key(Address::from(2), H256::from(3)); - assert_eq!(false, access_list.contains_address(&Address::from(1))); + access_list.insert_address(Address::from_low_u64_be(1)); + access_list.insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); assert_eq!( false, - access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + access_list.contains_address(&Address::from_low_u64_be(1)) + ); + assert_eq!( + false, + access_list + .contains_storage_key(&Address::from_low_u64_be(2), &H256::from_low_u64_be(3)) ); } @@ -196,12 +200,16 @@ mod tests { let mut access_list = AccessList::default(); access_list.enable(); assert_eq!(true, access_list.is_enabled()); - access_list.insert_address(Address::from(1)); - access_list.insert_storage_key(Address::from(2), H256::from(3)); - assert_eq!(true, access_list.contains_address(&Address::from(1))); + access_list.insert_address(Address::from_low_u64_be(1)); + access_list.insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); + assert_eq!( + true, + access_list.contains_address(&Address::from_low_u64_be(1)) + ); assert_eq!( true, - access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + access_list + .contains_storage_key(&Address::from_low_u64_be(2), &H256::from_low_u64_be(3)) ); } @@ -210,51 +218,74 @@ mod tests { let mut access_list = AccessList::default(); access_list.enable(); assert_eq!(true, access_list.is_enabled()); - access_list.insert_address(Address::from(1)); - access_list.insert_storage_key(Address::from(2), H256::from(3)); + access_list.insert_address(Address::from_low_u64_be(1)); + access_list.insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); let access_list_call = access_list.clone(); - assert_eq!(true, access_list_call.contains_address(&Address::from(1))); assert_eq!( true, - access_list_call.contains_storage_key(&Address::from(2), &H256::from(3)) + access_list_call.contains_address(&Address::from_low_u64_be(1)) + ); + assert_eq!( + true, + access_list_call + .contains_storage_key(&Address::from_low_u64_be(2), &H256::from_low_u64_be(3)) + ); + access_list.insert_address(Address::from_low_u64_be(4)); + assert_eq!( + true, + access_list_call.contains_address(&Address::from_low_u64_be(4)) ); - access_list.insert_address(Address::from(4)); - assert_eq!(true, access_list_call.contains_address(&Address::from(4))); - assert_eq!(true, access_list.contains_address(&Address::from(4))); + assert_eq!( + true, + access_list.contains_address(&Address::from_low_u64_be(4)) + ); } #[test] fn cloned_accesslist_rollbacks_in_parent() { let mut access_list = AccessList::default(); access_list.enable(); assert_eq!(true, access_list.is_enabled()); - access_list.insert_address(Address::from(1)); - access_list.insert_storage_key(Address::from(2), H256::from(3)); + access_list.insert_address(Address::from_low_u64_be(1)); + access_list.insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); let mut access_list_call = access_list.clone(); - access_list_call.insert_address(Address::from(1)); - access_list_call.insert_storage_key(Address::from(2), H256::from(3)); - access_list_call.insert_address(Address::from(4)); + access_list_call.insert_address(Address::from_low_u64_be(1)); + access_list_call.insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); + access_list_call.insert_address(Address::from_low_u64_be(4)); let mut access_list_call_call = access_list.clone(); - access_list_call_call.insert_address(Address::from(1)); - access_list_call_call.insert_storage_key(Address::from(2), H256::from(3)); - access_list_call_call.insert_address(Address::from(5)); - access_list_call_call.insert_storage_key(Address::from(6), H256::from(7)); + access_list_call_call.insert_address(Address::from_low_u64_be(1)); + access_list_call_call + .insert_storage_key(Address::from_low_u64_be(2), H256::from_low_u64_be(3)); + access_list_call_call.insert_address(Address::from_low_u64_be(5)); + access_list_call_call + .insert_storage_key(Address::from_low_u64_be(6), H256::from_low_u64_be(7)); access_list_call.rollback(); - assert_eq!(true, access_list.contains_address(&Address::from(1))); - assert_eq!(false, access_list.contains_address(&Address::from(4))); - assert_eq!(false, access_list.contains_address(&Address::from(5))); assert_eq!( true, - access_list.contains_storage_key(&Address::from(2), &H256::from(3)) + access_list.contains_address(&Address::from_low_u64_be(1)) + ); + assert_eq!( + false, + access_list.contains_address(&Address::from_low_u64_be(4)) + ); + assert_eq!( + false, + access_list.contains_address(&Address::from_low_u64_be(5)) + ); + assert_eq!( + true, + access_list + .contains_storage_key(&Address::from_low_u64_be(2), &H256::from_low_u64_be(3)) ); assert_eq!( false, - access_list.contains_storage_key(&Address::from(6), &H256::from(7)) + access_list + .contains_storage_key(&Address::from_low_u64_be(6), &H256::from_low_u64_be(7)) ); } } diff --git a/crates/vm/vm/src/action_params.rs b/crates/vm/vm/src/action_params.rs index b9aaf38bc4..f2076e6e04 100644 --- a/crates/vm/vm/src/action_params.rs +++ b/crates/vm/vm/src/action_params.rs @@ -98,11 +98,11 @@ impl Default for ActionParams { /// Returns default ActionParams initialized with zeros fn default() -> ActionParams { ActionParams { - code_address: Address::new(), + code_address: Address::default(), code_hash: Some(KECCAK_EMPTY), - address: Address::new(), - sender: Address::new(), - origin: Address::new(), + address: Address::default(), + sender: Address::default(), + origin: Address::default(), gas: U256::zero(), gas_price: U256::zero(), value: ActionValue::Transfer(U256::zero()), @@ -119,7 +119,7 @@ impl From for ActionParams { fn from(t: ethjson::vm::Transaction) -> Self { let address: Address = t.address.into(); ActionParams { - code_address: Address::new(), + code_address: Address::default(), code_hash: Some(keccak(&*t.code)), address: address, sender: t.sender.into(), diff --git a/crates/vm/vm/src/tests.rs b/crates/vm/vm/src/tests.rs index 6bcb46fd25..11daf4be9d 100644 --- a/crates/vm/vm/src/tests.rs +++ b/crates/vm/vm/src/tests.rs @@ -145,11 +145,11 @@ impl FakeExt { impl Ext for FakeExt { fn initial_storage_at(&self, _key: &H256) -> Result { - Ok(H256::new()) + Ok(H256::default()) } fn storage_at(&self, key: &H256) -> Result { - Ok(self.store.get(key).unwrap_or(&H256::new()).clone()) + Ok(self.store.get(key).unwrap_or(&H256::default()).clone()) } fn set_storage(&mut self, key: H256, value: H256) -> Result<()> { @@ -174,7 +174,10 @@ impl Ext for FakeExt { } fn blockhash(&mut self, number: &U256) -> H256 { - self.blockhashes.get(number).unwrap_or(&H256::new()).clone() + self.blockhashes + .get(number) + .unwrap_or(&H256::default()) + .clone() } fn create( diff --git a/crates/vm/wasm/Cargo.toml b/crates/vm/wasm/Cargo.toml index e724a6a4cf..2b1bafca22 100644 --- a/crates/vm/wasm/Cargo.toml +++ b/crates/vm/wasm/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" -ethereum-types = "0.4" +ethereum-types = "0.9.2" log = "0.4" parity-wasm = "0.31" libc = "0.2" diff --git a/crates/vm/wasm/src/runtime.rs b/crates/vm/wasm/src/runtime.rs index 386ae577bc..b4de3f77c6 100644 --- a/crates/vm/wasm/src/runtime.rs +++ b/crates/vm/wasm/src/runtime.rs @@ -15,7 +15,7 @@ // along with OpenEthereum. If not, see . use super::panic_payload; -use ethereum_types::{Address, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; use std::cmp; use vm::{self, CallType}; use wasmi::{ @@ -171,7 +171,7 @@ impl<'a> Runtime<'a> { let mut buf = [0u8; 32]; self.memory.get_into(ptr, &mut buf[..])?; - Ok(H256::from(&buf[..])) + Ok(H256::from_slice(&buf[..])) } /// Loads 160-bit hash (Ethereum address) from the specified sandboxed memory pointer @@ -179,7 +179,7 @@ impl<'a> Runtime<'a> { let mut buf = [0u8; 20]; self.memory.get_into(ptr, &mut buf[..])?; - Ok(Address::from(&buf[..])) + Ok(Address::from_slice(&buf[..])) } /// Loads 256-bit integer represented with bigendian from the specified sandboxed memory pointer @@ -275,7 +275,7 @@ impl<'a> Runtime<'a> { self.adjusted_charge(|schedule| schedule.sload_gas as u64)?; - self.memory.set(val_ptr as u32, &*val)?; + self.memory.set(val_ptr as u32, val.as_bytes())?; Ok(()) } @@ -532,14 +532,14 @@ impl<'a> Runtime<'a> { fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<()> { self.charge(|schedule| schedule.wasm().static_address as u64)?; - self.memory.set(ptr, &*val)?; + self.memory.set(ptr, val.as_bytes())?; Ok(()) } fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<()> { - let value: H256 = val.into(); + let value: H256 = BigEndianHash::from_uint(&val); self.charge(|schedule| schedule.wasm().static_u256 as u64)?; - self.memory.set(ptr, &*value)?; + self.memory.set(ptr, value.as_bytes())?; Ok(()) } @@ -573,7 +573,7 @@ impl<'a> Runtime<'a> { .expect("Trap is false; trap error will not happen; qed") { vm::ContractCreateResult::Created(address, gas_left) => { - self.memory.set(result_ptr, &*address)?; + self.memory.set(result_ptr, address.as_bytes())?; self.gas_counter = self.gas_limit - // this cannot overflow, since initial gas is in [0..u64::max) range, // and gas_left cannot be bigger @@ -646,7 +646,7 @@ impl<'a> Runtime<'a> { trace!(target: "wasm", "runtime: CREATE2"); let endowment = self.u256_at(args.nth_checked(0)?)?; trace!(target: "wasm", " val: {:?}", endowment); - let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into(); + let salt: H256 = BigEndianHash::from_uint(&self.u256_at(args.nth_checked(1)?)?); trace!(target: "wasm", " salt: {:?}", salt); let code_ptr: u32 = args.nth_checked(2)?; trace!(target: "wasm", " code_ptr: {:?}", code_ptr); @@ -704,7 +704,7 @@ impl<'a> Runtime<'a> { pub fn blockhash(&mut self, args: RuntimeArgs) -> Result<()> { self.adjusted_charge(|schedule| schedule.blockhash_gas as u64)?; let hash = self.ext.blockhash(&U256::from(args.nth_checked::(0)?)); - self.memory.set(args.nth_checked(1)?, &*hash)?; + self.memory.set(args.nth_checked(1)?, hash.as_bytes())?; Ok(()) } @@ -794,7 +794,7 @@ impl<'a> Runtime<'a> { *topics.get_mut(i as usize) .expect("topics is resized to `topic_count`, i is in 0..topic count iterator, get_mut uses i as an indexer, get_mut cannot fail; qed") - = H256::from(&self.memory.get(offset, 32)?[..]); + = H256::from_slice(&self.memory.get(offset, 32)?[..]); } self.ext .log(topics, &self.memory.get(data_ptr, data_len as usize)?) From 48e7d6cee413fcf6e5f01b11fda6dfd38aecabc7 Mon Sep 17 00:00:00 2001 From: Simon KP Date: Fri, 12 Mar 2021 23:00:09 +1100 Subject: [PATCH 089/107] Send SIGTERM instead of SIGHUP to OE daemon (#317) * Send SIGTERM instead of SIGHUP to OE daemon * Address comments --- scripts/openethereum.service | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/openethereum.service b/scripts/openethereum.service index 0987b90409..73a8d68265 100644 --- a/scripts/openethereum.service +++ b/scripts/openethereum.service @@ -13,8 +13,9 @@ ExecStart=/usr/bin/openethereum --config /etc/openethereum/config.toml Restart=on-failure # Specifies which signal to use when killing a service. Defaults to SIGTERM. -# SIGHUP gives openethereum time to exit cleanly before SIGKILL (default 90s) -KillSignal=SIGHUP +# SIGTERM gives openethereum time to exit cleanly before sending SIGKILL +KillSignal=SIGTERM +TimeoutStopSec=300 [Install] WantedBy=default.target From 29dc10c446573173c40afd4d48fd64562e211a33 Mon Sep 17 00:00:00 2001 From: Karim Agha Date: Fri, 12 Mar 2021 14:55:49 +0100 Subject: [PATCH 090/107] Updating ethcore and ethjson crates to Rust Edition 2018 (#316) * Migrating use crate::Type imports to Rust 2018 edition * import name fixes * fmt * removing diff leftover * catching up with latest developments on dev * fmt * removing another diff leftover --- Cargo.lock | 24 ++++++ bin/oe/account.rs | 8 +- bin/oe/account_utils.rs | 8 +- bin/oe/blockchain.rs | 20 +++-- bin/oe/configuration.rs | 85 ++++++++++--------- bin/oe/helpers.rs | 16 ++-- bin/oe/informant.rs | 8 +- bin/oe/lib.rs | 8 +- bin/oe/modules.rs | 8 +- bin/oe/params.rs | 14 +-- bin/oe/presale.rs | 8 +- bin/oe/rpc.rs | 8 +- bin/oe/rpc_apis.rs | 8 +- bin/oe/run.rs | 45 +++++----- bin/oe/secretstore.rs | 3 +- bin/oe/signer.rs | 4 +- bin/oe/snapshot.rs | 17 ++-- crates/ethcore/types/Cargo.toml | 9 +- crates/ethcore/types/src/account_diff.rs | 4 +- crates/ethcore/types/src/block.rs | 8 +- crates/ethcore/types/src/blockchain_info.rs | 3 +- crates/ethcore/types/src/encoded.rs | 15 ++-- crates/ethcore/types/src/filter.rs | 7 +- crates/ethcore/types/src/header.rs | 12 +-- crates/ethcore/types/src/ids.rs | 2 +- crates/ethcore/types/src/lib.rs | 13 +-- crates/ethcore/types/src/log_entry.rs | 4 +- crates/ethcore/types/src/receipt.rs | 8 +- crates/ethcore/types/src/security_level.rs | 2 +- crates/ethcore/types/src/snapshot_manifest.rs | 2 +- crates/ethcore/types/src/state_diff.rs | 2 +- crates/ethcore/types/src/trace_filter.rs | 2 +- crates/ethcore/types/src/transaction/error.rs | 1 + .../types/src/transaction/transaction.rs | 31 +++---- crates/ethcore/types/src/views/block.rs | 13 +-- crates/ethcore/types/src/views/body.rs | 17 ++-- crates/ethcore/types/src/views/header.rs | 4 +- .../types/src/views/typed_transaction.rs | 10 ++- crates/ethjson/Cargo.toml | 6 +- crates/ethjson/src/blockchain/account.rs | 5 +- crates/ethjson/src/blockchain/block.rs | 8 +- crates/ethjson/src/blockchain/blockchain.rs | 12 +-- crates/ethjson/src/blockchain/header.rs | 10 ++- crates/ethjson/src/blockchain/test.rs | 2 +- crates/ethjson/src/blockchain/transaction.rs | 7 +- crates/ethjson/src/bytes.rs | 2 +- crates/ethjson/src/hash.rs | 2 +- crates/ethjson/src/lib.rs | 6 +- crates/ethjson/src/local_tests/mod.rs | 2 +- crates/ethjson/src/maybe.rs | 3 +- crates/ethjson/src/spec/account.rs | 8 +- crates/ethjson/src/spec/authority_round.rs | 12 +-- crates/ethjson/src/spec/basic_authority.rs | 10 ++- crates/ethjson/src/spec/builtin.rs | 2 +- crates/ethjson/src/spec/engine.rs | 2 +- crates/ethjson/src/spec/ethash.rs | 16 ++-- crates/ethjson/src/spec/genesis.rs | 20 +++-- crates/ethjson/src/spec/null_engine.rs | 4 +- crates/ethjson/src/spec/params.rs | 11 +-- crates/ethjson/src/spec/seal.rs | 14 +-- crates/ethjson/src/spec/spec.rs | 4 +- crates/ethjson/src/spec/state.rs | 8 +- crates/ethjson/src/spec/validator_set.rs | 7 +- crates/ethjson/src/state/log.rs | 19 ++++- crates/ethjson/src/state/mod.rs | 3 +- crates/ethjson/src/state/state.rs | 10 ++- crates/ethjson/src/state/test.rs | 22 +++-- crates/ethjson/src/state/transaction.rs | 12 +-- crates/ethjson/src/test/mod.rs | 3 +- crates/ethjson/src/transaction/test.rs | 2 +- crates/ethjson/src/transaction/transaction.rs | 39 +++++++-- crates/ethjson/src/transaction/txtest.rs | 10 ++- crates/ethjson/src/trie/input.rs | 4 +- crates/ethjson/src/trie/test.rs | 2 +- crates/ethjson/src/trie/trie.rs | 3 +- crates/ethjson/src/uint.rs | 2 +- crates/ethjson/src/vm/call.rs | 11 +-- crates/ethjson/src/vm/env.rs | 5 +- crates/ethjson/src/vm/test.rs | 2 +- crates/ethjson/src/vm/transaction.rs | 6 +- crates/ethjson/src/vm/vm.rs | 14 +-- 81 files changed, 467 insertions(+), 346 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97cb5d1937..4baf2a7869 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aes" version = "0.3.2" @@ -438,6 +444,9 @@ name = "common-types" version = "0.1.0" dependencies = [ "ethereum-types", + "ethkey", + "hex", + "inflate", "keccak-hash", "parity-bytes", "parity-crypto", @@ -1804,6 +1813,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hex-literal" version = "0.2.1" @@ -2056,6 +2071,15 @@ dependencies = [ "autocfg 0.1.7", ] +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + [[package]] name = "interleaved-ordered" version = "0.1.1" diff --git a/bin/oe/account.rs b/bin/oe/account.rs index 430dd2a19f..0bd87cdbd8 100644 --- a/bin/oe/account.rs +++ b/bin/oe/account.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use params::SpecType; +use crate::params::SpecType; use std::num::NonZeroU32; #[derive(Debug, PartialEq)] @@ -53,9 +53,11 @@ pub fn execute(_cmd: AccountCmd) -> Result { #[cfg(feature = "accounts")] mod command { use super::*; - use accounts::{AccountProvider, AccountProviderSettings}; + use crate::{ + accounts::{AccountProvider, AccountProviderSettings}, + helpers::{password_from_file, password_prompt}, + }; use ethstore::{accounts_dir::RootDiskDirectory, import_account, import_accounts, EthStore}; - use helpers::{password_from_file, password_prompt}; use std::path::PathBuf; pub fn execute(cmd: AccountCmd) -> Result { diff --git a/bin/oe/account_utils.rs b/bin/oe/account_utils.rs index 902e557ccd..405aa917cd 100644 --- a/bin/oe/account_utils.rs +++ b/bin/oe/account_utils.rs @@ -21,7 +21,7 @@ use dir::Directories; use ethereum_types::{Address, H160}; use ethkey::Password; -use params::{AccountsConfig, SpecType}; +use crate::params::{AccountsConfig, SpecType}; #[cfg(not(feature = "accounts"))] mod accounts { @@ -71,10 +71,10 @@ mod accounts { #[cfg(feature = "accounts")] mod accounts { use super::*; + use crate::upgrade::upgrade_key_location; use std::str::FromStr; - use upgrade::upgrade_key_location; - pub use accounts::AccountProvider; + pub use crate::accounts::AccountProvider; /// Pops along with error messages when a password is missing or invalid. const VERIFY_PASSWORD_HINT: &str = "Make sure valid password is present in files passed using `--password` or in the configuration file."; @@ -87,7 +87,7 @@ mod accounts { cfg: AccountsConfig, passwords: &[Password], ) -> Result { - use accounts::AccountProviderSettings; + use crate::accounts::AccountProviderSettings; use ethstore::{accounts_dir::RootDiskDirectory, EthStore}; let path = dirs.keys_path(data_dir); diff --git a/bin/oe/blockchain.rs b/bin/oe/blockchain.rs index f101aa8690..d7f585758b 100644 --- a/bin/oe/blockchain.rs +++ b/bin/oe/blockchain.rs @@ -16,10 +16,18 @@ use std::{fs, io, sync::Arc, time::Instant}; +use crate::{ + bytes::ToPretty, + cache::CacheConfig, + db, + hash::{keccak, KECCAK_NULL_RLP}, + helpers::{execute_upgrades, to_client_config}, + informant::{FullNodeInformantData, Informant, MillisecondDuration}, + params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch}, + types::data_format::DataFormat, + user_defaults::UserDefaults, +}; use ansi_term::Colour; -use bytes::ToPretty; -use cache::CacheConfig; -use db; use dir::Directories; use ethcore::{ client::{ @@ -31,12 +39,6 @@ use ethcore::{ }; use ethcore_service::ClientService; use ethereum_types::{Address, H256, U256}; -use hash::{keccak, KECCAK_NULL_RLP}; -use helpers::{execute_upgrades, to_client_config}; -use informant::{FullNodeInformantData, Informant, MillisecondDuration}; -use params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch}; -use types::data_format::DataFormat; -use user_defaults::UserDefaults; #[derive(Debug, PartialEq)] pub enum BlockchainCmd { diff --git a/bin/oe/configuration.rs b/bin/oe/configuration.rs index 84c83bca81..1e3743c5cf 100644 --- a/bin/oe/configuration.rs +++ b/bin/oe/configuration.rs @@ -14,9 +14,16 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crate::{ + bytes::Bytes, + cli::{Args, ArgsError}, + hash::keccak, + metrics::MetricsConfiguration, + miner::pool, + sync::{self, validate_node_url, NetworkConfiguration}, +}; use ansi_term::Colour; -use bytes::Bytes; -use cli::{Args, ArgsError}; + use crypto::publickey::{Public, Secret}; use ethcore::{ client::VMType, @@ -25,9 +32,7 @@ use ethcore::{ verification::queue::VerifierSettings, }; use ethereum_types::{Address, H256, U256}; -use hash::keccak; -use metrics::MetricsConfiguration; -use miner::pool; + use num_cpus; use parity_version::{version, version_data}; use std::{ @@ -40,35 +45,37 @@ use std::{ path::PathBuf, time::Duration, }; -use sync::{self, validate_node_url, NetworkConfiguration}; -use account::{AccountCmd, ImportAccounts, ListAccounts, NewAccount}; -use blockchain::{ - BlockchainCmd, ExportBlockchain, ExportState, ImportBlockchain, KillBlockchain, ResetBlockchain, +use crate::{ + account::{AccountCmd, ImportAccounts, ListAccounts, NewAccount}, + blockchain::{ + BlockchainCmd, ExportBlockchain, ExportState, ImportBlockchain, KillBlockchain, + ResetBlockchain, + }, + cache::CacheConfig, + helpers::{ + parity_ipc_path, to_address, to_addresses, to_block_id, to_bootnodes, to_duration, to_mode, + to_pending_set, to_price, to_queue_penalization, to_queue_strategy, to_u256, + }, + network::IpFilter, + params::{AccountsConfig, GasPricerConfig, MinerExtras, ResealPolicy, SpecType}, + presale::ImportWallet, + rpc::{HttpConfiguration, IpcConfiguration, WsConfiguration}, + run::RunCmd, + secretstore::{ + Configuration as SecretStoreConfiguration, ContractAddress as SecretStoreContractAddress, + NodeSecretKey, + }, + snapshot::{self, SnapshotCommand}, + types::data_format::DataFormat, }; -use cache::CacheConfig; use dir::{ self, default_data_path, default_local_path, helpers::{replace_home, replace_home_and_local}, Directories, }; use ethcore_logger::Config as LogConfig; -use helpers::{ - parity_ipc_path, to_address, to_addresses, to_block_id, to_bootnodes, to_duration, to_mode, - to_pending_set, to_price, to_queue_penalization, to_queue_strategy, to_u256, -}; -use network::IpFilter; -use params::{AccountsConfig, GasPricerConfig, MinerExtras, ResealPolicy, SpecType}; use parity_rpc::NetworkSettings; -use presale::ImportWallet; -use rpc::{HttpConfiguration, IpcConfiguration, WsConfiguration}; -use run::RunCmd; -use secretstore::{ - Configuration as SecretStoreConfiguration, ContractAddress as SecretStoreContractAddress, - NodeSecretKey, -}; -use snapshot::{self, SnapshotCommand}; -use types::data_format::DataFormat; const DEFAULT_MAX_PEERS: u16 = 50; const DEFAULT_MIN_PEERS: u16 = 25; @@ -166,7 +173,7 @@ impl Configuration { let cmd = if self.args.flag_version { Cmd::Version } else if self.args.cmd_signer { - let authfile = ::signer::codes_path(&ws_conf.signer_path); + let authfile = crate::signer::codes_path(&ws_conf.signer_path); if self.args.cmd_signer_new_token { Cmd::SignerToken(ws_conf, logger_config.clone()) @@ -1243,23 +1250,25 @@ fn into_secretstore_service_contract_address( mod tests { use std::{fs::File, io::Write, str::FromStr}; - use account::{AccountCmd, ImportAccounts, ListAccounts, NewAccount}; - use blockchain::{BlockchainCmd, ExportBlockchain, ExportState, ImportBlockchain}; - use cli::Args; + use crate::{ + account::{AccountCmd, ImportAccounts, ListAccounts, NewAccount}, + blockchain::{BlockchainCmd, ExportBlockchain, ExportState, ImportBlockchain}, + cli::Args, + helpers::default_network_config, + miner::pool::PrioritizationStrategy, + params::SpecType, + presale::ImportWallet, + rpc::WsConfiguration, + rpc_apis::ApiSet, + run::RunCmd, + types::{data_format::DataFormat, ids::BlockId}, + }; use dir::Directories; use ethcore::{client::VMType, miner::MinerOptions}; - use helpers::default_network_config; - use miner::pool::PrioritizationStrategy; - use params::SpecType; use parity_rpc::NetworkSettings; - use presale::ImportWallet; - use rpc::WsConfiguration; - use rpc_apis::ApiSet; - use run::RunCmd; use tempdir::TempDir; - use types::{data_format::DataFormat, ids::BlockId}; - use network::{AllowIP, IpFilter}; + use crate::network::{AllowIP, IpFilter}; extern crate ipnetwork; use self::ipnetwork::IpNetwork; diff --git a/bin/oe/helpers.rs b/bin/oe/helpers.rs index e9cdf93df4..688ba25e4f 100644 --- a/bin/oe/helpers.rs +++ b/bin/oe/helpers.rs @@ -14,8 +14,13 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -use cache::CacheConfig; -use db::migrate; +use crate::{ + cache::CacheConfig, + db::migrate, + miner::pool::PrioritizationStrategy, + sync::{self, validate_node_url}, + upgrade::{upgrade, upgrade_data_paths}, +}; use dir::{helpers::replace_home, DatabaseDirectories}; use ethcore::{ client::{BlockId, ClientConfig, DatabaseCompactionProfile, Mode, VMType, VerifierType}, @@ -24,7 +29,6 @@ use ethcore::{ use ethereum_types::{Address, U256}; use ethkey::Password; use journaldb::Algorithm; -use miner::pool::PrioritizationStrategy; use std::{ collections::HashSet, fs::File, @@ -32,8 +36,6 @@ use std::{ io::{BufRead, BufReader, Write}, time::Duration, }; -use sync::{self, validate_node_url}; -use upgrade::{upgrade, upgrade_data_paths}; pub fn to_duration(s: &str) -> Result { to_seconds(s).map(Duration::from_secs) @@ -223,9 +225,9 @@ pub fn to_bootnodes(bootnodes: &Option) -> Result, String> { } #[cfg(test)] -pub fn default_network_config() -> ::sync::NetworkConfiguration { +pub fn default_network_config() -> crate::sync::NetworkConfiguration { use super::network::IpFilter; - use sync::NetworkConfiguration; + use crate::sync::NetworkConfiguration; NetworkConfiguration { config_path: Some(replace_home(&::dir::default_data_path(), "$BASE/network")), net_config_path: None, diff --git a/bin/oe/informant.rs b/bin/oe/informant.rs index 45d8eb3541..ae205f6fc5 100644 --- a/bin/oe/informant.rs +++ b/bin/oe/informant.rs @@ -29,6 +29,11 @@ use std::{ time::{Duration, Instant}, }; +use crate::{ + io::{IoContext, IoHandler, TimerToken}, + sync::{ManageNetwork, SyncProvider}, + types::BlockNumber, +}; use atty; use ethcore::{ client::{ @@ -37,12 +42,9 @@ use ethcore::{ }, snapshot::{service::Service as SnapshotService, RestorationStatus, SnapshotService as SS}, }; -use io::{IoContext, IoHandler, TimerToken}; use number_prefix::{binary_prefix, Prefixed, Standalone}; use parity_rpc::{informant::RpcStats, is_major_importing_or_waiting}; use parking_lot::{Mutex, RwLock}; -use sync::{ManageNetwork, SyncProvider}; -use types::BlockNumber; /// Format byte counts to standard denominations. pub fn format_bytes(b: usize) -> String { diff --git a/bin/oe/lib.rs b/bin/oe/lib.rs index ed9a7166ec..4c7a596b1a 100644 --- a/bin/oe/lib.rs +++ b/bin/oe/lib.rs @@ -114,9 +114,11 @@ mod user_defaults; use std::{fs::File, io::BufReader, sync::Arc}; -use cli::Args; -use configuration::{Cmd, Execute}; -use hash::keccak_buffer; +use crate::{ + cli::Args, + configuration::{Cmd, Execute}, + hash::keccak_buffer, +}; #[cfg(feature = "memory_profiling")] use std::alloc::System; diff --git a/bin/oe/modules.rs b/bin/oe/modules.rs index 5cf6971d67..8e80635219 100644 --- a/bin/oe/modules.rs +++ b/bin/oe/modules.rs @@ -16,14 +16,16 @@ use std::sync::{mpsc, Arc}; +use crate::{ + sync::{self, ConnectionFilter, NetworkConfiguration, Params, SyncConfig}, + types::BlockNumber, +}; use ethcore::{client::BlockChainClient, snapshot::SnapshotService}; use std::collections::BTreeSet; -use sync::{self, ConnectionFilter, NetworkConfiguration, Params, SyncConfig}; -use types::BlockNumber; +pub use crate::sync::{EthSync, ManageNetwork, SyncProvider}; pub use ethcore::client::ChainNotify; use ethcore_logger::Config as LogConfig; -pub use sync::{EthSync, ManageNetwork, SyncProvider}; pub type SyncModules = ( Arc, diff --git a/bin/oe/params.rs b/bin/oe/params.rs index b1be1cafb3..af2747ab17 100644 --- a/bin/oe/params.rs +++ b/bin/oe/params.rs @@ -16,6 +16,13 @@ use std::{collections::HashSet, fmt, fs, num::NonZeroU32, str, time::Duration}; +use crate::{ + miner::{ + gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions}, + gas_pricer::GasPricer, + }, + user_defaults::UserDefaults, +}; use ethcore::{ client::Mode, ethereum, @@ -24,13 +31,8 @@ use ethcore::{ use ethereum_types::{Address, U256}; use fetch::Client as FetchClient; use journaldb::Algorithm; -use miner::{ - gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions}, - gas_pricer::GasPricer, -}; use parity_runtime::Executor; use parity_version::version_data; -use user_defaults::UserDefaults; use crate::configuration; @@ -374,8 +376,8 @@ pub fn mode_switch_to_bool( #[cfg(test)] mod tests { use super::{tracing_switch_to_bool, Pruning, ResealPolicy, SpecType, Switch}; + use crate::user_defaults::UserDefaults; use journaldb::Algorithm; - use user_defaults::UserDefaults; #[test] fn test_spec_type_parsing() { diff --git a/bin/oe/presale.rs b/bin/oe/presale.rs index 5a5fecf0c1..c44c9fd1cf 100644 --- a/bin/oe/presale.rs +++ b/bin/oe/presale.rs @@ -14,11 +14,14 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . +use crate::{ + helpers::{password_from_file, password_prompt}, + params::SpecType, +}; use crypto::publickey; + use ethkey::Password; use ethstore::PresaleWallet; -use helpers::{password_from_file, password_prompt}; -use params::SpecType; use std::num::NonZeroU32; #[derive(Debug, PartialEq)] @@ -45,6 +48,7 @@ pub fn execute(cmd: ImportWallet) -> Result { } #[cfg(feature = "accounts")] + pub fn import_account(cmd: &ImportWallet, kp: publickey::KeyPair, password: Password) { use accounts::{AccountProvider, AccountProviderSettings}; use ethstore::{accounts_dir::RootDiskDirectory, EthStore}; diff --git a/bin/oe/rpc.rs b/bin/oe/rpc.rs index 4cd639ba6b..3d90b812ea 100644 --- a/bin/oe/rpc.rs +++ b/bin/oe/rpc.rs @@ -16,8 +16,11 @@ use std::{collections::HashSet, io, path::PathBuf, sync::Arc}; +use crate::{ + helpers::parity_ipc_path, + rpc_apis::{self, ApiSet}, +}; use dir::{default_data_path, helpers::replace_home}; -use helpers::parity_ipc_path; use jsonrpc_core::MetaIoHandler; use parity_rpc::{ self as rpc, @@ -25,7 +28,6 @@ use parity_rpc::{ DomainsValidation, Metadata, }; use parity_runtime::Executor; -use rpc_apis::{self, ApiSet}; pub use parity_rpc::{HttpServer, IpcServer, RequestMiddleware}; //pub use parity_rpc::ws::Server as WsServer; @@ -182,7 +184,7 @@ pub fn new_ws( let signer_path; let path = match conf.support_token_api { true => { - signer_path = ::signer::codes_path(&conf.signer_path); + signer_path = crate::signer::codes_path(&conf.signer_path); Some(signer_path.as_path()) } false => None, diff --git a/bin/oe/rpc_apis.rs b/bin/oe/rpc_apis.rs index 0acb886460..50db479cb6 100644 --- a/bin/oe/rpc_apis.rs +++ b/bin/oe/rpc_apis.rs @@ -23,12 +23,15 @@ use std::{ pub use parity_rpc::signer::SignerService; -use account_utils::{self, AccountProvider}; +use crate::{ + account_utils::{self, AccountProvider}, + miner::external::ExternalMiner, + sync::{ManageNetwork, SyncProvider}, +}; use ethcore::{client::Client, miner::Miner, snapshot::SnapshotService}; use ethcore_logger::RotatingLogger; use fetch::Client as FetchClient; use jsonrpc_core::{self as core, MetaIoHandler}; -use miner::external::ExternalMiner; use parity_rpc::{ dispatch::FullDispatcher, informant::{ActivityNotifier, ClientNotifier}, @@ -36,7 +39,6 @@ use parity_rpc::{ }; use parity_runtime::Executor; use parking_lot::Mutex; -use sync::{ManageNetwork, SyncProvider}; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Api { diff --git a/bin/oe/run.rs b/bin/oe/run.rs index 91d274a67e..503524c8b2 100644 --- a/bin/oe/run.rs +++ b/bin/oe/run.rs @@ -22,10 +22,24 @@ use std::{ time::{Duration, Instant}, }; -use account_utils; +use crate::{ + account_utils, + cache::CacheConfig, + db, + helpers::{execute_upgrades, passwords_from_files, to_client_config}, + informant::{FullNodeInformantData, Informant}, + metrics::{start_prometheus_metrics, MetricsConfiguration}, + miner::{external::ExternalMiner, work_notify::WorkPoster}, + modules, + params::{ + fatdb_switch_to_bool, mode_switch_to_bool, tracing_switch_to_bool, AccountsConfig, + GasPricerConfig, MinerExtras, Pruning, SpecType, Switch, + }, + rpc, rpc_apis, secretstore, signer, + sync::{self, SyncConfig}, + user_defaults::UserDefaults, +}; use ansi_term::Colour; -use cache::CacheConfig; -use db; use dir::{DatabaseDirectories, Directories}; use ethcore::{ client::{BlockChainClient, BlockInfo, Client, DatabaseCompactionProfile, Mode, VMType}, @@ -36,30 +50,15 @@ use ethcore::{ use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore_service::ClientService; use ethereum_types::{H256, U64}; -use helpers::{execute_upgrades, passwords_from_files, to_client_config}; -use informant::{FullNodeInformantData, Informant}; use journaldb::Algorithm; use jsonrpc_core; -use metrics::{start_prometheus_metrics, MetricsConfiguration}; -use miner::{external::ExternalMiner, work_notify::WorkPoster}; -use modules; use node_filter::NodeFilter; -use params::{ - fatdb_switch_to_bool, mode_switch_to_bool, tracing_switch_to_bool, AccountsConfig, - GasPricerConfig, MinerExtras, Pruning, SpecType, Switch, -}; use parity_rpc::{ informant, is_major_importing, FutureOutput, FutureResponse, FutureResult, Metadata, NetworkSettings, Origin, PubSubSession, }; use parity_runtime::Runtime; use parity_version::version; -use rpc; -use rpc_apis; -use secretstore; -use signer; -use sync::{self, SyncConfig}; -use user_defaults::UserDefaults; // How often we attempt to take a snapshot: only snapshot on blocknumbers that are multiples of this. const SNAPSHOT_PERIOD: u64 = 20000; @@ -120,8 +119,8 @@ struct FullNodeInfo { miner: Option>, // TODO: only TXQ needed, just use that after decoupling. } -impl ::local_store::NodeInfo for FullNodeInfo { - fn pending_transactions(&self) -> Vec<::types::transaction::PendingTransaction> { +impl crate::local_store::NodeInfo for FullNodeInfo { + fn pending_transactions(&self) -> Vec { let miner = match self.miner.as_ref() { Some(m) => m, None => return Vec::new(), @@ -131,7 +130,7 @@ impl ::local_store::NodeInfo for FullNodeInfo { .local_transactions() .values() .filter_map(|status| match *status { - ::miner::pool::local_transactions::Status::Pending(ref tx) => { + crate::miner::pool::local_transactions::Status::Pending(ref tx) => { Some(tx.pending().clone()) } _ => None, @@ -387,7 +386,7 @@ pub fn execute(cmd: RunCmd, logger: Arc) -> Result) -> Result. -use account_utils::AccountProvider; +use crate::{account_utils::AccountProvider, sync::SyncProvider}; use crypto::publickey::{Public, Secret}; use dir::{default_data_path, helpers::replace_home}; use ethcore::{client::Client, miner::Miner}; @@ -22,7 +22,6 @@ use ethereum_types::Address; use ethkey::Password; use parity_runtime::Executor; use std::{collections::BTreeMap, sync::Arc}; -use sync::SyncProvider; /// This node secret key. #[derive(Debug, PartialEq, Clone)] diff --git a/bin/oe/signer.rs b/bin/oe/signer.rs index 7dd00f728f..ff30c11f2b 100644 --- a/bin/oe/signer.rs +++ b/bin/oe/signer.rs @@ -19,12 +19,10 @@ use std::{ path::{Path, PathBuf}, }; +use crate::{path::restrict_permissions_owner, rpc, rpc_apis}; use ansi_term::Colour::White; use ethcore_logger::Config as LogConfig; use parity_rpc; -use path::restrict_permissions_owner; -use rpc; -use rpc_apis; pub const CODES_FILENAME: &'static str = "authcodes"; diff --git a/bin/oe/snapshot.rs b/bin/oe/snapshot.rs index 1cd4bbf991..3ed7f0f24c 100644 --- a/bin/oe/snapshot.rs +++ b/bin/oe/snapshot.rs @@ -22,6 +22,7 @@ use std::{ time::Duration, }; +use crate::{hash::keccak, types::ids::BlockId}; use ethcore::{ client::{DatabaseCompactionProfile, Mode, VMType}, miner::Miner, @@ -32,15 +33,15 @@ use ethcore::{ }, }; use ethcore_service::ClientService; -use hash::keccak; -use types::ids::BlockId; -use cache::CacheConfig; -use db; +use crate::{ + cache::CacheConfig, + db, + helpers::{execute_upgrades, to_client_config}, + params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch}, + user_defaults::UserDefaults, +}; use dir::Directories; -use helpers::{execute_upgrades, to_client_config}; -use params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch}; -use user_defaults::UserDefaults; /// Kinds of snapshot commands. #[derive(Debug, PartialEq, Clone, Copy)] @@ -303,7 +304,7 @@ impl SnapshotCommand { let cur_size = p.size(); if cur_size != last_size { last_size = cur_size; - let bytes = ::informant::format_bytes(cur_size as usize); + let bytes = crate::informant::format_bytes(cur_size as usize); info!( "Snapshot: {} accounts {} blocks {}", p.accounts(), diff --git a/crates/ethcore/types/Cargo.toml b/crates/ethcore/types/Cargo.toml index 86c0d48ea8..e0c059a3ed 100644 --- a/crates/ethcore/types/Cargo.toml +++ b/crates/ethcore/types/Cargo.toml @@ -2,9 +2,14 @@ description = "Parity Ethereum Common Types" name = "common-types" version = "0.1.0" -authors = ["Parity Technologies "] +edition = "2018" +authors = [ + "Gnosis Ltd ", + "Parity Technologies ", +] [dependencies] +ethkey = { path = "../../accounts/ethkey" } ethereum-types = "0.9.2" keccak-hash = "0.5.0" parity-bytes = "0.1" @@ -16,6 +21,8 @@ unexpected = { path = "../../util/unexpected" } serde = "1.0" serde_json = "1.0" serde_repr = "0.1" +hex = "0.4.3" +inflate = "0.4.5" [dev-dependencies] rustc-hex = "1.0" diff --git a/crates/ethcore/types/src/account_diff.rs b/crates/ethcore/types/src/account_diff.rs index 7ea690df1c..92a12902eb 100644 --- a/crates/ethcore/types/src/account_diff.rs +++ b/crates/ethcore/types/src/account_diff.rs @@ -16,7 +16,7 @@ //! Diff between two accounts. -use bytes::Bytes; +use crate::bytes::Bytes; use ethereum_types::{H256, U256}; use std::{cmp::*, collections::BTreeMap, fmt}; @@ -141,7 +141,7 @@ fn interpreted_hash(u: &H256) -> String { impl fmt::Display for AccountDiff { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use bytes::ToPretty; + use crate::bytes::ToPretty; match self.nonce { Diff::Born(ref x) => write!(f, " non {}", x)?, diff --git a/crates/ethcore/types/src/block.rs b/crates/ethcore/types/src/block.rs index 221d4d64e9..d0c1cc3e8f 100644 --- a/crates/ethcore/types/src/block.rs +++ b/crates/ethcore/types/src/block.rs @@ -31,11 +31,13 @@ //! `ExecutedBlock` is an underlaying data structure used by all structs above to store block //! related info. -use bytes::Bytes; +use crate::bytes::Bytes; -use header::Header; +use crate::{ + header::Header, + transaction::{TypedTransaction, UnverifiedTransaction}, +}; use rlp::{Decodable, DecoderError, Rlp, RlpStream}; -use transaction::{TypedTransaction, UnverifiedTransaction}; /// A block, encoded as it is on the block chain. #[derive(Default, Debug, Clone, PartialEq)] diff --git a/crates/ethcore/types/src/blockchain_info.rs b/crates/ethcore/types/src/blockchain_info.rs index b04a8640d4..008fb5a55a 100644 --- a/crates/ethcore/types/src/blockchain_info.rs +++ b/crates/ethcore/types/src/blockchain_info.rs @@ -18,9 +18,8 @@ use std::fmt; +use crate::{security_level::SecurityLevel, BlockNumber}; use ethereum_types::{H256, U256}; -use security_level::SecurityLevel; -use BlockNumber; /// Information about the blockchain gathered together. #[derive(Clone, Debug)] diff --git a/crates/ethcore/types/src/encoded.rs b/crates/ethcore/types/src/encoded.rs index f550740224..7bad7945ea 100644 --- a/crates/ethcore/types/src/encoded.rs +++ b/crates/ethcore/types/src/encoded.rs @@ -23,15 +23,18 @@ //! When the entirety of the object is needed, it's better to upgrade it to a fully //! decoded object where parts like the hash can be saved. -use block::Block as FullBlock; +use crate::{ + block::Block as FullBlock, + hash::keccak, + header::Header as FullHeader, + transaction::UnverifiedTransaction, + views::{self, BlockView, BodyView, HeaderView}, + BlockNumber, +}; + use ethereum_types::{Address, Bloom, H256, U256}; -use hash::keccak; -use header::Header as FullHeader; use parity_util_mem::MallocSizeOf; use rlp::{self, Rlp, RlpStream}; -use transaction::UnverifiedTransaction; -use views::{self, BlockView, BodyView, HeaderView}; -use BlockNumber; /// Owning header view. #[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] diff --git a/crates/ethcore/types/src/filter.rs b/crates/ethcore/types/src/filter.rs index 822c2f7de4..5415b447fc 100644 --- a/crates/ethcore/types/src/filter.rs +++ b/crates/ethcore/types/src/filter.rs @@ -16,9 +16,8 @@ //! Blockchain filter +use crate::{ids::BlockId, log_entry::LogEntry}; use ethereum_types::{Address, Bloom, BloomInput, H256}; -use ids::BlockId; -use log_entry::LogEntry; /// Blockchain Filter. #[derive(Debug, PartialEq)] @@ -119,10 +118,8 @@ impl Filter { #[cfg(test)] mod tests { + use crate::{filter::Filter, ids::BlockId, log_entry::LogEntry}; use ethereum_types::{Bloom, H160, H256}; - use filter::Filter; - use ids::BlockId; - use log_entry::LogEntry; use std::str::FromStr; #[test] diff --git a/crates/ethcore/types/src/header.rs b/crates/ethcore/types/src/header.rs index 88c68e8358..a5f9b988ef 100644 --- a/crates/ethcore/types/src/header.rs +++ b/crates/ethcore/types/src/header.rs @@ -16,12 +16,14 @@ //! Block header. -use bytes::Bytes; +use crate::{ + bytes::Bytes, + hash::{keccak, KECCAK_EMPTY_LIST_RLP, KECCAK_NULL_RLP}, + BlockNumber, +}; use ethereum_types::{Address, Bloom, H256, U256}; -use hash::{keccak, KECCAK_EMPTY_LIST_RLP, KECCAK_NULL_RLP}; use parity_util_mem::MallocSizeOf; use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}; -use BlockNumber; /// Semantic boolean for when a seal/signature is included. #[derive(Debug, Clone, Copy)] @@ -307,8 +309,8 @@ impl Header { } /// Encode the header, getting a type-safe wrapper around the RLP. - pub fn encoded(&self) -> ::encoded::Header { - ::encoded::Header::new(self.rlp(Seal::With)) + pub fn encoded(&self) -> crate::encoded::Header { + crate::encoded::Header::new(self.rlp(Seal::With)) } /// Get the RLP representation of this Header. diff --git a/crates/ethcore/types/src/ids.rs b/crates/ethcore/types/src/ids.rs index c117ed3c14..7be363d1d9 100644 --- a/crates/ethcore/types/src/ids.rs +++ b/crates/ethcore/types/src/ids.rs @@ -16,8 +16,8 @@ //! Unique identifiers. +use crate::BlockNumber; use ethereum_types::H256; -use BlockNumber; /// Uniquely identifies block. #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] diff --git a/crates/ethcore/types/src/lib.rs b/crates/ethcore/types/src/lib.rs index 2eafc66ee8..73e934284a 100644 --- a/crates/ethcore/types/src/lib.rs +++ b/crates/ethcore/types/src/lib.rs @@ -34,20 +34,15 @@ #![allow(missing_docs)] #![warn(unused_extern_crates)] -extern crate ethereum_types; -extern crate keccak_hash as hash; -extern crate parity_bytes as bytes; -extern crate parity_crypto as crypto; -extern crate parity_util_mem; -extern crate rlp; -extern crate serde_repr; -extern crate unexpected; +pub use keccak_hash as hash; +pub use parity_bytes as bytes; +pub use parity_crypto as crypto; #[macro_use] extern crate rlp_derive; #[cfg(test)] -extern crate rustc_hex; +pub use rustc_hex; #[macro_use] pub mod views; diff --git a/crates/ethcore/types/src/log_entry.rs b/crates/ethcore/types/src/log_entry.rs index 8c72df15bb..f607ce8b38 100644 --- a/crates/ethcore/types/src/log_entry.rs +++ b/crates/ethcore/types/src/log_entry.rs @@ -16,13 +16,11 @@ //! Log entry type definition. -use bytes::Bytes; +use crate::{bytes::Bytes, BlockNumber}; use ethereum_types::{Address, Bloom, BloomInput, H256}; use parity_util_mem::MallocSizeOf; use std::ops::Deref; -use BlockNumber; - /// A record of execution for a `LOG` operation. #[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable, MallocSizeOf)] pub struct LogEntry { diff --git a/crates/ethcore/types/src/receipt.rs b/crates/ethcore/types/src/receipt.rs index 2026081a84..1ae47bc16e 100644 --- a/crates/ethcore/types/src/receipt.rs +++ b/crates/ethcore/types/src/receipt.rs @@ -22,8 +22,10 @@ use parity_util_mem::MallocSizeOf; use rlp::{DecoderError, Rlp, RlpStream}; use std::ops::{Deref, DerefMut}; -use log_entry::{LocalizedLogEntry, LogEntry}; -use BlockNumber; +use crate::{ + log_entry::{LocalizedLogEntry, LogEntry}, + BlockNumber, +}; /// Transaction outcome store in the receipt. #[derive(Debug, Clone, PartialEq, Eq, MallocSizeOf)] @@ -296,8 +298,8 @@ pub struct LocalizedReceipt { #[cfg(test)] mod tests { use super::{LegacyReceipt, TransactionOutcome, TypedReceipt, TypedTxId}; + use crate::log_entry::LogEntry; use ethereum_types::{H160, H256}; - use log_entry::LogEntry; use std::str::FromStr; #[test] diff --git a/crates/ethcore/types/src/security_level.rs b/crates/ethcore/types/src/security_level.rs index 10439ff02d..c49bbe40cf 100644 --- a/crates/ethcore/types/src/security_level.rs +++ b/crates/ethcore/types/src/security_level.rs @@ -16,7 +16,7 @@ //! Indication of how secure the chain is. -use BlockNumber; +use crate::BlockNumber; /// Indication of how secure the chain is. #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] diff --git a/crates/ethcore/types/src/snapshot_manifest.rs b/crates/ethcore/types/src/snapshot_manifest.rs index 461e2a5bb4..e5220e0ebe 100644 --- a/crates/ethcore/types/src/snapshot_manifest.rs +++ b/crates/ethcore/types/src/snapshot_manifest.rs @@ -16,7 +16,7 @@ //! Snapshot manifest type definition -use bytes::Bytes; +use crate::bytes::Bytes; use ethereum_types::H256; use rlp::{DecoderError, Rlp, RlpStream}; diff --git a/crates/ethcore/types/src/state_diff.rs b/crates/ethcore/types/src/state_diff.rs index 439133c834..0045796c64 100644 --- a/crates/ethcore/types/src/state_diff.rs +++ b/crates/ethcore/types/src/state_diff.rs @@ -16,7 +16,7 @@ //! State diff module. -use account_diff::*; +use crate::account_diff::*; use ethereum_types::Address; use std::{collections::BTreeMap, fmt, ops::*}; diff --git a/crates/ethcore/types/src/trace_filter.rs b/crates/ethcore/types/src/trace_filter.rs index 5404bad950..66104acb42 100644 --- a/crates/ethcore/types/src/trace_filter.rs +++ b/crates/ethcore/types/src/trace_filter.rs @@ -16,8 +16,8 @@ //! Trace filter related types +use crate::ids::BlockId; use ethereum_types::Address; -use ids::BlockId; use std::ops::Range; /// Easy to use trace filter. diff --git a/crates/ethcore/types/src/transaction/error.rs b/crates/ethcore/types/src/transaction/error.rs index aa927c55e4..d3351cad85 100644 --- a/crates/ethcore/types/src/transaction/error.rs +++ b/crates/ethcore/types/src/transaction/error.rs @@ -16,6 +16,7 @@ use std::{error, fmt}; +use crate::crypto; use ethereum_types::U256; use rlp; use unexpected::OutOfBounds; diff --git a/crates/ethcore/types/src/transaction/transaction.rs b/crates/ethcore/types/src/transaction/transaction.rs index 55a10506da..892b00ea0c 100644 --- a/crates/ethcore/types/src/transaction/transaction.rs +++ b/crates/ethcore/types/src/transaction/transaction.rs @@ -16,10 +16,14 @@ //! Transaction data structure. -use crypto::publickey::{self, public_to_address, recover, Public, Secret, Signature}; +use crate::{ + crypto::publickey::{self, public_to_address, recover, Public, Secret, Signature}, + hash::keccak, + transaction::error, +}; use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; -use hash::keccak; use parity_util_mem::MallocSizeOf; + use rlp::{self, DecoderError, Rlp, RlpStream}; use std::ops::Deref; @@ -28,8 +32,6 @@ pub type AccessList = Vec; use super::TypedTxId; -use transaction::error; - type Bytes = Vec; type BlockNumber = u64; @@ -134,7 +136,7 @@ pub struct Transaction { pub gas: U256, /// Action, can be either call or contract create. pub action: Action, - /// Transfered value. + /// Transfered value.s pub value: U256, /// Transaction data. pub data: Bytes, @@ -430,7 +432,6 @@ impl TypedTransaction { /// Legacy EIP-86 compatible empty signature. /// This method is used in json tests as well as /// signature verification tests. - #[cfg(any(test, feature = "test-helpers"))] pub fn null_sign(self, chain_id: u64) -> SignedTransaction { SignedTransaction { transaction: UnverifiedTransaction { @@ -566,11 +567,11 @@ impl TypedTransaction { pub struct SignatureComponents { /// The V field of the signature; the LS bit described which half of the curve our point falls /// in. It can be 0 or 1. - standard_v: u8, + pub standard_v: u8, /// The R field of the signature; helps describe the point on the curve. - r: U256, + pub r: U256, /// The S field of the signature; helps describe the point on the curve. - s: U256, + pub s: U256, } impl SignatureComponents { @@ -594,13 +595,13 @@ impl SignatureComponents { #[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf)] pub struct UnverifiedTransaction { /// Plain Transaction. - unsigned: TypedTransaction, + pub unsigned: TypedTransaction, /// Transaction signature - signature: SignatureComponents, + pub signature: SignatureComponents, /// chain_id recover from signature in legacy transaction. For TypedTransaction it is probably separate field. - chain_id: Option, + pub chain_id: Option, /// Hash of the transaction - hash: H256, + pub hash: H256, } impl Deref for UnverifiedTransaction { @@ -628,7 +629,7 @@ impl UnverifiedTransaction { } /// Used to compute hash of created transactions. - fn compute_hash(mut self) -> UnverifiedTransaction { + pub fn compute_hash(mut self) -> UnverifiedTransaction { let hash = keccak(&*self.encode()); self.hash = hash; self @@ -874,8 +875,8 @@ impl From for PendingTransaction { #[cfg(test)] mod tests { use super::*; + use crate::hash::keccak; use ethereum_types::{H160, U256}; - use hash::keccak; use std::str::FromStr; #[test] diff --git a/crates/ethcore/types/src/views/block.rs b/crates/ethcore/types/src/views/block.rs index 1d7fbf3457..06edfe9eaa 100644 --- a/crates/ethcore/types/src/views/block.rs +++ b/crates/ethcore/types/src/views/block.rs @@ -17,12 +17,15 @@ //! View onto block rlp. use super::ViewRlp; -use bytes::Bytes; +use crate::{ + bytes::Bytes, + hash::keccak, + header::Header, + transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}, + views::{HeaderView, TypedTransactionView}, +}; + use ethereum_types::H256; -use hash::keccak; -use header::Header; -use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; -use views::{HeaderView, TypedTransactionView}; /// View onto block rlp. pub struct BlockView<'a> { diff --git a/crates/ethcore/types/src/views/body.rs b/crates/ethcore/types/src/views/body.rs index 3bdf7f2743..218e79185f 100644 --- a/crates/ethcore/types/src/views/body.rs +++ b/crates/ethcore/types/src/views/body.rs @@ -17,13 +17,15 @@ //! View onto block body rlp. use super::ViewRlp; -use bytes::Bytes; +use crate::{ + bytes::Bytes, + hash::keccak, + header::Header, + transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}, + views::{HeaderView, TypedTransactionView}, + BlockNumber, +}; use ethereum_types::H256; -use hash::keccak; -use header::Header; -use transaction::{LocalizedTransaction, TypedTransaction, UnverifiedTransaction}; -use views::{HeaderView, TypedTransactionView}; -use BlockNumber; /// View onto block rlp. pub struct BodyView<'a> { @@ -184,10 +186,9 @@ impl<'a> BodyView<'a> { #[cfg(test)] mod tests { use super::BodyView; - use bytes::Bytes; + use crate::{bytes::Bytes, views::BlockView}; use rlp::RlpStream; use rustc_hex::FromHex; - use views::BlockView; fn block_to_body(block: &[u8]) -> Bytes { let mut body = RlpStream::new_list(2); diff --git a/crates/ethcore/types/src/views/header.rs b/crates/ethcore/types/src/views/header.rs index a5ecd8e2ef..db33b2eb66 100644 --- a/crates/ethcore/types/src/views/header.rs +++ b/crates/ethcore/types/src/views/header.rs @@ -17,11 +17,9 @@ //! View onto block header rlp use super::ViewRlp; -use bytes::Bytes; +use crate::{bytes::Bytes, hash::keccak, BlockNumber}; use ethereum_types::{Address, Bloom, H256, U256}; -use hash::keccak; use rlp::{self}; -use BlockNumber; /// View onto block header rlp. pub struct HeaderView<'a> { diff --git a/crates/ethcore/types/src/views/typed_transaction.rs b/crates/ethcore/types/src/views/typed_transaction.rs index e9a9da1152..39b670c65e 100644 --- a/crates/ethcore/types/src/views/typed_transaction.rs +++ b/crates/ethcore/types/src/views/typed_transaction.rs @@ -16,12 +16,14 @@ //! View onto transaction rlp -use crate::transaction::{signature, TypedTxId}; +use crate::{ + bytes::Bytes, + hash::keccak, + transaction::{signature, TypedTxId}, + views::ViewRlp, +}; -use super::ViewRlp; -use bytes::Bytes; use ethereum_types::{H256, U256}; -use hash::keccak; use rlp::Rlp; /// View onto transaction rlp. Assumption is this is part of block. diff --git a/crates/ethjson/Cargo.toml b/crates/ethjson/Cargo.toml index 819db5dbf0..436bfef02b 100644 --- a/crates/ethjson/Cargo.toml +++ b/crates/ethjson/Cargo.toml @@ -2,7 +2,11 @@ description = "Parity Ethereum JSON Deserialization" name = "ethjson" version = "0.1.0" -authors = ["Parity Technologies "] +edition = "2018" +authors = [ + "Gnosis Ltd ", + "Parity Technologies " + ] [dependencies] common-types = { path = "../ethcore/types", features = ["test-helpers"] } diff --git a/crates/ethjson/src/blockchain/account.rs b/crates/ethjson/src/blockchain/account.rs index fc39b074e8..678db5d100 100644 --- a/crates/ethjson/src/blockchain/account.rs +++ b/crates/ethjson/src/blockchain/account.rs @@ -16,9 +16,8 @@ //! Blockchain test account deserializer. -use bytes::Bytes; +use crate::{bytes::Bytes, uint::Uint}; use std::collections::BTreeMap; -use uint::Uint; /// Blockchain test account deserializer. #[derive(Debug, PartialEq, Deserialize, Clone)] @@ -35,7 +34,7 @@ pub struct Account { #[cfg(test)] mod tests { - use blockchain::account::Account; + use crate::blockchain::account::Account; use serde_json; #[test] diff --git a/crates/ethjson/src/blockchain/block.rs b/crates/ethjson/src/blockchain/block.rs index 045a42f335..2c6fa38396 100644 --- a/crates/ethjson/src/blockchain/block.rs +++ b/crates/ethjson/src/blockchain/block.rs @@ -16,8 +16,10 @@ //! Blockchain test block deserializer. -use blockchain::{header::Header, transaction::Transaction}; -use bytes::Bytes; +use crate::{ + blockchain::{header::Header, transaction::Transaction}, + bytes::Bytes, +}; /// Blockchain test block deserializer. #[derive(Debug, PartialEq, Deserialize)] @@ -39,7 +41,7 @@ impl Block { #[cfg(test)] mod tests { - use blockchain::block::Block; + use crate::blockchain::block::Block; use serde_json; #[test] diff --git a/crates/ethjson/src/blockchain/blockchain.rs b/crates/ethjson/src/blockchain/blockchain.rs index 7e1406f0a3..3f7e5b0617 100644 --- a/crates/ethjson/src/blockchain/blockchain.rs +++ b/crates/ethjson/src/blockchain/blockchain.rs @@ -16,10 +16,12 @@ //! Blockchain deserialization. -use blockchain::{block::Block, header::Header, state::State}; -use bytes::Bytes; -use hash::H256; -use spec::{Ethereum, ForkSpec, Genesis, Seal}; +use crate::{ + blockchain::{block::Block, header::Header, state::State}, + bytes::Bytes, + hash::H256, + spec::{Ethereum, ForkSpec, Genesis, Seal}, +}; /// Json Block test possible engine kind. #[derive(Debug, PartialEq, Deserialize)] @@ -93,7 +95,7 @@ impl BlockChain { #[cfg(test)] mod tests { - use blockchain::blockchain::BlockChain; + use crate::blockchain::blockchain::BlockChain; use serde_json; #[test] diff --git a/crates/ethjson/src/blockchain/header.rs b/crates/ethjson/src/blockchain/header.rs index 8fcb25caaa..f03cb7dcff 100644 --- a/crates/ethjson/src/blockchain/header.rs +++ b/crates/ethjson/src/blockchain/header.rs @@ -16,9 +16,11 @@ //! Blockchain test header deserializer. -use bytes::Bytes; -use hash::{Address, Bloom, H256, H64}; -use uint::Uint; +use crate::{ + bytes::Bytes, + hash::{Address, Bloom, H256, H64}, + uint::Uint, +}; /// Blockchain test header deserializer. #[derive(Debug, PartialEq, Deserialize)] @@ -64,7 +66,7 @@ pub struct Header { #[cfg(test)] mod tests { - use blockchain::header::Header; + use crate::blockchain::header::Header; use serde_json; #[test] diff --git a/crates/ethjson/src/blockchain/test.rs b/crates/ethjson/src/blockchain/test.rs index 01ace8eb6f..3eb8bed76f 100644 --- a/crates/ethjson/src/blockchain/test.rs +++ b/crates/ethjson/src/blockchain/test.rs @@ -16,7 +16,7 @@ //! Blockchain test deserializer. -use blockchain::blockchain::BlockChain; +use crate::blockchain::blockchain::BlockChain; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read}; diff --git a/crates/ethjson/src/blockchain/transaction.rs b/crates/ethjson/src/blockchain/transaction.rs index 277e520018..dc470a29d6 100644 --- a/crates/ethjson/src/blockchain/transaction.rs +++ b/crates/ethjson/src/blockchain/transaction.rs @@ -16,9 +16,8 @@ //! Blockchain test transaction deserialization. -use bytes::Bytes; +use crate::{bytes::Bytes, uint::Uint}; use ethereum_types::{H160, H256}; -use uint::Uint; /// Blockchain test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -39,11 +38,11 @@ pub struct Transaction { pub hash: Option, } -pub type AccessList = Vec; - #[derive(Debug, PartialEq, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct AccessListItem { pub address: H160, pub storage_keys: Vec, } + +pub type AccessList = Vec; diff --git a/crates/ethjson/src/bytes.rs b/crates/ethjson/src/bytes.rs index bc9804f5d9..8fd7852acb 100644 --- a/crates/ethjson/src/bytes.rs +++ b/crates/ethjson/src/bytes.rs @@ -102,7 +102,7 @@ impl<'a> Visitor<'a> for BytesVisitor { #[cfg(test)] mod test { - use bytes::Bytes; + use crate::bytes::Bytes; use serde_json; #[test] diff --git a/crates/ethjson/src/hash.rs b/crates/ethjson/src/hash.rs index c0b7d834bb..bc59c966be 100644 --- a/crates/ethjson/src/hash.rs +++ b/crates/ethjson/src/hash.rs @@ -112,8 +112,8 @@ impl_hash!(Bloom, Hash2048); #[cfg(test)] mod test { + use crate::hash::H256; use ethereum_types; - use hash::H256; use serde_json; use std::str::FromStr; diff --git a/crates/ethjson/src/lib.rs b/crates/ethjson/src/lib.rs index 910175dfbd..851b1dbabd 100644 --- a/crates/ethjson/src/lib.rs +++ b/crates/ethjson/src/lib.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -extern crate common_types as types; -extern crate ethereum_types; -extern crate parity_crypto as crypto; +pub use common_types as types; +pub use parity_crypto as crypto; + extern crate rustc_hex; extern crate serde; extern crate serde_json; diff --git a/crates/ethjson/src/local_tests/mod.rs b/crates/ethjson/src/local_tests/mod.rs index f051528fb4..d7b490d756 100644 --- a/crates/ethjson/src/local_tests/mod.rs +++ b/crates/ethjson/src/local_tests/mod.rs @@ -1,4 +1,4 @@ -use blockchain::block::Block; +use crate::blockchain::block::Block; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read}; diff --git a/crates/ethjson/src/maybe.rs b/crates/ethjson/src/maybe.rs index 4d72a67355..da11169420 100644 --- a/crates/ethjson/src/maybe.rs +++ b/crates/ethjson/src/maybe.rs @@ -94,9 +94,8 @@ impl Into> for MaybeEmpty { #[cfg(test)] mod tests { + use crate::{hash::H256, maybe::MaybeEmpty}; use ethereum_types; - use hash::H256; - use maybe::MaybeEmpty; use serde_json; use std::str::FromStr; diff --git a/crates/ethjson/src/spec/account.rs b/crates/ethjson/src/spec/account.rs index 0f920db4c7..f2aef63d7c 100644 --- a/crates/ethjson/src/spec/account.rs +++ b/crates/ethjson/src/spec/account.rs @@ -18,9 +18,7 @@ use std::collections::BTreeMap; -use bytes::Bytes; -use spec::builtin::BuiltinCompat; -use uint::Uint; +use crate::{bytes::Bytes, spec::builtin::BuiltinCompat, uint::Uint}; /// Spec account. #[derive(Clone, Debug, PartialEq, Deserialize)] @@ -53,12 +51,10 @@ impl Account { #[cfg(test)] mod tests { - use bytes::Bytes; + use crate::{bytes::Bytes, spec::account::Account, uint::Uint}; use ethereum_types::U256; use serde_json; - use spec::account::Account; use std::collections::BTreeMap; - use uint::Uint; #[test] fn account_balance_missing_not_empty() { diff --git a/crates/ethjson/src/spec/authority_round.rs b/crates/ethjson/src/spec/authority_round.rs index 45132d7b73..f84e933a9b 100644 --- a/crates/ethjson/src/spec/authority_round.rs +++ b/crates/ethjson/src/spec/authority_round.rs @@ -17,9 +17,7 @@ //! Authority params deserialization. use super::{BlockReward, ValidatorSet}; -use bytes::Bytes; -use hash::Address; -use uint::Uint; +use crate::{bytes::Bytes, hash::Address, uint::Uint}; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -73,12 +71,14 @@ mod tests { use std::collections::BTreeMap; use super::BlockReward; + use crate::{ + hash::Address, + spec::{authority_round::AuthorityRound, validator_set::ValidatorSet}, + uint::Uint, + }; use ethereum_types::{H160, U256}; - use hash::Address; use serde_json; - use spec::{authority_round::AuthorityRound, validator_set::ValidatorSet}; use std::str::FromStr; - use uint::Uint; #[test] fn authority_round_deserialization() { diff --git a/crates/ethjson/src/spec/basic_authority.rs b/crates/ethjson/src/spec/basic_authority.rs index d744407a5b..e42e5164f9 100644 --- a/crates/ethjson/src/spec/basic_authority.rs +++ b/crates/ethjson/src/spec/basic_authority.rs @@ -17,7 +17,7 @@ //! Authority params deserialization. use super::ValidatorSet; -use uint::Uint; +use crate::uint::Uint; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -40,12 +40,14 @@ pub struct BasicAuthority { #[cfg(test)] mod tests { + use crate::{ + hash::Address, + spec::{basic_authority::BasicAuthority, validator_set::ValidatorSet}, + uint::Uint, + }; use ethereum_types::{H160, U256}; - use hash::Address; use serde_json; - use spec::{basic_authority::BasicAuthority, validator_set::ValidatorSet}; use std::str::FromStr; - use uint::Uint; #[test] fn basic_authority_deserialization() { diff --git a/crates/ethjson/src/spec/builtin.rs b/crates/ethjson/src/spec/builtin.rs index 5c0adb45e1..a4c7455b21 100644 --- a/crates/ethjson/src/spec/builtin.rs +++ b/crates/ethjson/src/spec/builtin.rs @@ -16,8 +16,8 @@ //! Spec builtin deserialization. +use crate::uint::Uint; use std::collections::BTreeMap; -use uint::Uint; /// Linear pricing. #[derive(Debug, PartialEq, Deserialize, Clone)] diff --git a/crates/ethjson/src/spec/engine.rs b/crates/ethjson/src/spec/engine.rs index 2a6e9faf6f..f85f1dc871 100644 --- a/crates/ethjson/src/spec/engine.rs +++ b/crates/ethjson/src/spec/engine.rs @@ -40,8 +40,8 @@ pub enum Engine { #[cfg(test)] mod tests { + use crate::spec::Engine; use serde_json; - use spec::Engine; #[test] fn engine_deserialization() { diff --git a/crates/ethjson/src/spec/ethash.rs b/crates/ethjson/src/spec/ethash.rs index b7e8c0907c..df20119a5f 100644 --- a/crates/ethjson/src/spec/ethash.rs +++ b/crates/ethjson/src/spec/ethash.rs @@ -16,10 +16,12 @@ //! Ethash params deserialization. -use bytes::Bytes; -use hash::Address; +use crate::{ + bytes::Bytes, + hash::Address, + uint::{self, Uint}, +}; use std::collections::BTreeMap; -use uint::{self, Uint}; /// Deserializable doppelganger of block rewards for EthashParams #[derive(Clone, Debug, PartialEq, Deserialize)] @@ -105,12 +107,14 @@ pub struct Ethash { #[cfg(test)] mod tests { + use crate::{ + hash::Address, + spec::ethash::{BlockReward, Ethash, EthashParams}, + uint::Uint, + }; use ethereum_types::{H160, U256}; - use hash::Address; use serde_json; - use spec::ethash::{BlockReward, Ethash, EthashParams}; use std::str::FromStr; - use uint::Uint; #[test] fn ethash_deserialization() { diff --git a/crates/ethjson/src/spec/genesis.rs b/crates/ethjson/src/spec/genesis.rs index 38445f1234..0bbc954316 100644 --- a/crates/ethjson/src/spec/genesis.rs +++ b/crates/ethjson/src/spec/genesis.rs @@ -16,10 +16,12 @@ //! Spec genesis deserialization. -use bytes::Bytes; -use hash::{Address, H256}; -use spec::Seal; -use uint::{self, Uint}; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + spec::Seal, + uint::{self, Uint}, +}; /// Spec genesis. #[derive(Debug, PartialEq, Deserialize)] @@ -53,13 +55,15 @@ pub struct Genesis { #[cfg(test)] mod tests { - use bytes::Bytes; + use crate::{ + bytes::Bytes, + hash::{Address, H256, H64}, + spec::{genesis::Genesis, Ethereum, Seal}, + uint::Uint, + }; use ethereum_types::{H160, H256 as Eth256, H64 as Eth64, U256}; - use hash::{Address, H256, H64}; use serde_json; - use spec::{genesis::Genesis, Ethereum, Seal}; use std::str::FromStr; - use uint::Uint; #[test] fn genesis_deserialization() { diff --git a/crates/ethjson/src/spec/null_engine.rs b/crates/ethjson/src/spec/null_engine.rs index 6c978b4796..caa0bc47fc 100644 --- a/crates/ethjson/src/spec/null_engine.rs +++ b/crates/ethjson/src/spec/null_engine.rs @@ -16,7 +16,7 @@ //! Null engine params deserialization. -use uint::Uint; +use crate::uint::Uint; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -40,9 +40,9 @@ pub struct NullEngine { #[cfg(test)] mod tests { use super::*; + use crate::uint::Uint; use ethereum_types::U256; use serde_json; - use uint::Uint; #[test] fn null_engine_deserialization() { diff --git a/crates/ethjson/src/spec/params.rs b/crates/ethjson/src/spec/params.rs index 15c1747d48..7933208fef 100644 --- a/crates/ethjson/src/spec/params.rs +++ b/crates/ethjson/src/spec/params.rs @@ -16,9 +16,11 @@ //! Spec params deserialization. -use bytes::Bytes; -use hash::{Address, H256}; -use uint::{self, Uint}; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + uint::{self, Uint}, +}; /// Spec params. #[derive(Debug, PartialEq, Deserialize)] @@ -146,10 +148,9 @@ pub struct Params { #[cfg(test)] mod tests { + use crate::{spec::params::Params, uint::Uint}; use ethereum_types::U256; use serde_json; - use spec::params::Params; - use uint::Uint; #[test] fn params_deserialization() { diff --git a/crates/ethjson/src/spec/seal.rs b/crates/ethjson/src/spec/seal.rs index a53a1f07d5..aebdca41ae 100644 --- a/crates/ethjson/src/spec/seal.rs +++ b/crates/ethjson/src/spec/seal.rs @@ -16,9 +16,7 @@ //! Spec seal deserialization. -use bytes::Bytes; -use hash::*; -use uint::Uint; +use crate::{bytes::Bytes, hash::*, uint::Uint}; /// Ethereum seal. #[derive(Debug, PartialEq, Deserialize)] @@ -70,13 +68,15 @@ pub enum Seal { #[cfg(test)] mod tests { - use bytes::Bytes; + use crate::{ + bytes::Bytes, + hash::*, + spec::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal}, + uint::Uint, + }; use ethereum_types::{H256 as Eth256, H520 as Eth520, H64 as Eth64, U256}; - use hash::*; use serde_json; - use spec::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal}; use std::str::FromStr; - use uint::Uint; #[test] fn seal_deserialization() { diff --git a/crates/ethjson/src/spec/spec.rs b/crates/ethjson/src/spec/spec.rs index e5e23be778..9db235ac62 100644 --- a/crates/ethjson/src/spec/spec.rs +++ b/crates/ethjson/src/spec/spec.rs @@ -16,8 +16,8 @@ //! Spec deserialization. +use crate::spec::{Engine, Genesis, Params, State}; use serde_json::{self, Error}; -use spec::{Engine, Genesis, Params, State}; use std::io::Read; /// Fork spec definition @@ -73,8 +73,8 @@ impl Spec { #[cfg(test)] mod tests { + use crate::spec::spec::Spec; use serde_json; - use spec::spec::Spec; #[test] fn should_error_on_unknown_fields() { diff --git a/crates/ethjson/src/spec/state.rs b/crates/ethjson/src/spec/state.rs index 0bf295589a..c38c32cbf5 100644 --- a/crates/ethjson/src/spec/state.rs +++ b/crates/ethjson/src/spec/state.rs @@ -16,9 +16,11 @@ //! Blockchain test state deserializer. -use bytes::Bytes; -use hash::Address; -use spec::{Account, Builtin}; +use crate::{ + bytes::Bytes, + hash::Address, + spec::{Account, Builtin}, +}; use std::collections::BTreeMap; /// Blockchain test state deserializer. diff --git a/crates/ethjson/src/spec/validator_set.rs b/crates/ethjson/src/spec/validator_set.rs index e419050820..a544665513 100644 --- a/crates/ethjson/src/spec/validator_set.rs +++ b/crates/ethjson/src/spec/validator_set.rs @@ -16,9 +16,8 @@ //! Validator set deserialization. -use hash::Address; +use crate::{hash::Address, uint::Uint}; use std::collections::BTreeMap; -use uint::Uint; /// Different ways of specifying validators. #[derive(Debug, PartialEq, Deserialize)] @@ -37,12 +36,10 @@ pub enum ValidatorSet { #[cfg(test)] mod tests { + use crate::{hash::Address, spec::validator_set::ValidatorSet, uint::Uint}; use ethereum_types::{H160, U256}; - use hash::Address; use serde_json; - use spec::validator_set::ValidatorSet; use std::str::FromStr; - use uint::Uint; #[test] fn validator_set_deserialization() { diff --git a/crates/ethjson/src/state/log.rs b/crates/ethjson/src/state/log.rs index bd753d4c9e..89e0f18e15 100644 --- a/crates/ethjson/src/state/log.rs +++ b/crates/ethjson/src/state/log.rs @@ -15,8 +15,11 @@ // along with OpenEthereum. If not, see . //! State test log deserialization. -use bytes::Bytes; -use hash::{Address, Bloom, H256}; +use crate::{ + bytes::Bytes, + hash::{Address, Bloom, H256}, +}; +use common_types::log_entry::LogEntry; /// State test log deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -33,8 +36,8 @@ pub struct Log { #[cfg(test)] mod tests { + use super::Log; use serde_json; - use state::Log; #[test] fn log_deserialization() { @@ -50,3 +53,13 @@ mod tests { // TODO: validate all fields } } + +impl From for LogEntry { + fn from(l: Log) -> Self { + LogEntry { + address: l.address.into(), + topics: l.topics.into_iter().map(Into::into).collect(), + data: l.data.into(), + } + } +} diff --git a/crates/ethjson/src/state/mod.rs b/crates/ethjson/src/state/mod.rs index 865e3373ea..5060a58e66 100644 --- a/crates/ethjson/src/state/mod.rs +++ b/crates/ethjson/src/state/mod.rs @@ -22,5 +22,4 @@ pub mod test; pub mod transaction; pub use self::{log::Log, state::State, test::Test, transaction::Transaction}; -pub use blockchain::State as AccountState; -pub use vm::Env; +pub use crate::{blockchain::State as AccountState, vm::Env}; diff --git a/crates/ethjson/src/state/state.rs b/crates/ethjson/src/state/state.rs index fc18e54400..f53a7ea661 100644 --- a/crates/ethjson/src/state/state.rs +++ b/crates/ethjson/src/state/state.rs @@ -16,9 +16,11 @@ //! State test deserialization. -use bytes::Bytes; -use hash::H256; -use state::{AccountState, Env, Log, Transaction}; +use crate::{ + bytes::Bytes, + hash::H256, + state::{AccountState, Env, Log, Transaction}, +}; /// State test deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -45,8 +47,8 @@ pub struct State { #[cfg(test)] mod tests { + use super::State; use serde_json; - use state::State; #[test] fn state_deserialization() { diff --git a/crates/ethjson/src/state/test.rs b/crates/ethjson/src/state/test.rs index cc76fa1011..5ee43e40bb 100644 --- a/crates/ethjson/src/state/test.rs +++ b/crates/ethjson/src/state/test.rs @@ -16,16 +16,22 @@ //! General test deserialization. -use bytes::Bytes; -use crypto::publickey::Secret; -use hash::{Address, H256}; -use maybe::MaybeEmpty; +use crate::{ + bytes::Bytes, + crypto::publickey::Secret, + hash::{Address, H256}, + maybe::MaybeEmpty, + spec::ForkSpec, + state::{AccountState, Env}, + uint::Uint, +}; + +use common_types::transaction::{ + AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction, +}; + use serde_json::{self, Error}; -use spec::ForkSpec; -use state::{AccountState, Env}; use std::{collections::BTreeMap, io::Read}; -use types::transaction::{AccessListTx, Action, SignedTransaction, Transaction, TypedTransaction}; -use uint::Uint; use crate::blockchain::transaction::AccessList; diff --git a/crates/ethjson/src/state/transaction.rs b/crates/ethjson/src/state/transaction.rs index b770a30a42..ffb2914716 100644 --- a/crates/ethjson/src/state/transaction.rs +++ b/crates/ethjson/src/state/transaction.rs @@ -16,10 +16,12 @@ //! State test transaction deserialization. -use bytes::Bytes; -use hash::{Address, H256}; -use maybe::MaybeEmpty; -use uint::Uint; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + maybe::MaybeEmpty, + uint::Uint, +}; /// State test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -44,8 +46,8 @@ pub struct Transaction { #[cfg(test)] mod tests { + use super::Transaction; use serde_json; - use state::Transaction; #[test] fn transaction_deserialization() { diff --git a/crates/ethjson/src/test/mod.rs b/crates/ethjson/src/test/mod.rs index e4d69a27e2..b64cd47631 100644 --- a/crates/ethjson/src/test/mod.rs +++ b/crates/ethjson/src/test/mod.rs @@ -16,10 +16,9 @@ //! Additional test structures deserialization. -use hash::H256; +use crate::{hash::H256, uint::Uint}; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read, path::PathBuf}; -use uint::Uint; /// Blockchain test header deserializer. #[derive(Debug, PartialEq, Deserialize)] diff --git a/crates/ethjson/src/transaction/test.rs b/crates/ethjson/src/transaction/test.rs index 2fd4a1c7d8..4712a75e81 100644 --- a/crates/ethjson/src/transaction/test.rs +++ b/crates/ethjson/src/transaction/test.rs @@ -16,9 +16,9 @@ //! TransactionTest test deserializer. +use crate::transaction::TransactionTest; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read}; -use transaction::TransactionTest; /// TransactionTest test deserializer. #[derive(Debug, Deserialize)] diff --git a/crates/ethjson/src/transaction/transaction.rs b/crates/ethjson/src/transaction/transaction.rs index 5186918aae..9d33b07162 100644 --- a/crates/ethjson/src/transaction/transaction.rs +++ b/crates/ethjson/src/transaction/transaction.rs @@ -16,10 +16,12 @@ //! Transaction test transaction deserialization. -use bytes::Bytes; -use hash::Address; -use maybe::MaybeEmpty; -use uint::Uint; +use crate::{bytes::Bytes, hash::Address, maybe::MaybeEmpty, uint::Uint}; +use common_types::transaction::{ + signature, Action, SignatureComponents, Transaction as CoreTransaction, TypedTransaction, + UnverifiedTransaction, +}; +use ethereum_types::H256; /// Transaction test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -45,10 +47,37 @@ pub struct Transaction { pub v: Uint, } +impl From for UnverifiedTransaction { + fn from(t: Transaction) -> Self { + let to: Option
= t.to.into(); + UnverifiedTransaction { + unsigned: TypedTransaction::Legacy(CoreTransaction { + nonce: t.nonce.into(), + gas_price: t.gas_price.into(), + gas: t.gas_limit.into(), + action: match to { + Some(to) => Action::Call(to.into()), + None => Action::Create, + }, + value: t.value.into(), + data: t.data.into(), + }), + chain_id: signature::extract_chain_id_from_legacy_v(t.v.into()), + signature: SignatureComponents { + r: t.r.into(), + s: t.s.into(), + standard_v: signature::extract_standard_v(t.v.into()), + }, + hash: H256::zero(), + } + .compute_hash() + } +} + #[cfg(test)] mod tests { + use super::Transaction; use serde_json; - use transaction::Transaction; #[test] fn transaction_deserialization() { diff --git a/crates/ethjson/src/transaction/txtest.rs b/crates/ethjson/src/transaction/txtest.rs index e466374f6c..be73a06493 100644 --- a/crates/ethjson/src/transaction/txtest.rs +++ b/crates/ethjson/src/transaction/txtest.rs @@ -16,9 +16,11 @@ //! Transaction test deserialization. -use bytes::Bytes; -use hash::{Address, H256}; -use spec::ForkSpec; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + spec::ForkSpec, +}; use std::collections::BTreeMap; /// Transaction test deserialization. @@ -42,8 +44,8 @@ pub struct PostState { #[cfg(test)] mod tests { + use super::TransactionTest; use serde_json; - use transaction::TransactionTest; #[test] fn transaction_deserialization() { diff --git a/crates/ethjson/src/trie/input.rs b/crates/ethjson/src/trie/input.rs index 0bdbc82db8..80f9060ab1 100644 --- a/crates/ethjson/src/trie/input.rs +++ b/crates/ethjson/src/trie/input.rs @@ -16,7 +16,7 @@ //! Trie test input deserialization. -use bytes::Bytes; +use crate::bytes::Bytes; use serde::{ de::{Error as ErrorTrait, MapAccess, SeqAccess, Visitor}, Deserialize, Deserializer, @@ -135,7 +135,7 @@ impl<'a> Visitor<'a> for InputVisitor { #[cfg(test)] mod tests { use super::Input; - use bytes::Bytes; + use crate::bytes::Bytes; use serde_json; use std::collections::BTreeMap; diff --git a/crates/ethjson/src/trie/test.rs b/crates/ethjson/src/trie/test.rs index eb2bcea959..1a51485715 100644 --- a/crates/ethjson/src/trie/test.rs +++ b/crates/ethjson/src/trie/test.rs @@ -16,9 +16,9 @@ //! TransactionTest test deserializer. +use crate::trie::Trie; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read}; -use trie::Trie; /// TransactionTest test deserializer. #[derive(Debug, PartialEq, Deserialize)] diff --git a/crates/ethjson/src/trie/trie.rs b/crates/ethjson/src/trie/trie.rs index ec8f9466da..94e1c38093 100644 --- a/crates/ethjson/src/trie/trie.rs +++ b/crates/ethjson/src/trie/trie.rs @@ -16,8 +16,7 @@ //! Trie test deserialization. -use hash::H256; -use trie::Input; +use crate::{hash::H256, trie::Input}; /// Trie test deserialization. #[derive(Debug, Deserialize, PartialEq)] diff --git a/crates/ethjson/src/uint.rs b/crates/ethjson/src/uint.rs index fdcf4931a2..8fd6b3723b 100644 --- a/crates/ethjson/src/uint.rs +++ b/crates/ethjson/src/uint.rs @@ -148,9 +148,9 @@ where #[cfg(test)] mod test { + use crate::uint::Uint; use ethereum_types::U256; use serde_json; - use uint::Uint; #[test] fn uint_deserialization() { diff --git a/crates/ethjson/src/vm/call.rs b/crates/ethjson/src/vm/call.rs index 7dbb46a1a3..14a1815aee 100644 --- a/crates/ethjson/src/vm/call.rs +++ b/crates/ethjson/src/vm/call.rs @@ -16,10 +16,7 @@ //! Vm call deserialization. -use bytes::Bytes; -use hash::Address; -use maybe::MaybeEmpty; -use uint::Uint; +use crate::{bytes::Bytes, hash::Address, maybe::MaybeEmpty, uint::Uint}; /// Vm call deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -37,13 +34,11 @@ pub struct Call { #[cfg(test)] mod tests { + use crate::{hash::Address, maybe::MaybeEmpty, uint::Uint, vm::Call}; use ethereum_types::{H160 as Hash160, U256}; - use hash::Address; - use maybe::MaybeEmpty; + use serde_json; use std::str::FromStr; - use uint::Uint; - use vm::Call; #[test] fn call_deserialization_empty_dest() { diff --git a/crates/ethjson/src/vm/env.rs b/crates/ethjson/src/vm/env.rs index 09bcda0d61..ad4caa6829 100644 --- a/crates/ethjson/src/vm/env.rs +++ b/crates/ethjson/src/vm/env.rs @@ -15,8 +15,7 @@ // along with OpenEthereum. If not, see . //! Vm environment. -use hash::Address; -use uint::Uint; +use crate::{hash::Address, uint::Uint}; /// Vm environment. #[derive(Debug, PartialEq, Deserialize)] @@ -40,8 +39,8 @@ pub struct Env { #[cfg(test)] mod tests { + use super::Env; use serde_json; - use vm::Env; #[test] fn env_deserialization() { diff --git a/crates/ethjson/src/vm/test.rs b/crates/ethjson/src/vm/test.rs index 7e40d8f228..96459e9299 100644 --- a/crates/ethjson/src/vm/test.rs +++ b/crates/ethjson/src/vm/test.rs @@ -16,9 +16,9 @@ //! Vm test deserializer. +use crate::vm::Vm; use serde_json::{self, Error}; use std::{collections::BTreeMap, io::Read}; -use vm::Vm; /// Vm test deserializer. #[derive(Debug, PartialEq, Deserialize)] diff --git a/crates/ethjson/src/vm/transaction.rs b/crates/ethjson/src/vm/transaction.rs index 87e79965b9..f1f128b163 100644 --- a/crates/ethjson/src/vm/transaction.rs +++ b/crates/ethjson/src/vm/transaction.rs @@ -15,9 +15,7 @@ // along with OpenEthereum. If not, see . //! Executed transaction. -use bytes::Bytes; -use hash::Address; -use uint::Uint; +use crate::{bytes::Bytes, hash::Address, uint::Uint}; /// Executed transaction. #[derive(Debug, PartialEq, Deserialize)] @@ -44,8 +42,8 @@ pub struct Transaction { #[cfg(test)] mod tests { + use super::Transaction; use serde_json; - use vm::Transaction; #[test] fn transaction_deserialization() { diff --git a/crates/ethjson/src/vm/vm.rs b/crates/ethjson/src/vm/vm.rs index 0945449e7e..bfffdd9a2f 100644 --- a/crates/ethjson/src/vm/vm.rs +++ b/crates/ethjson/src/vm/vm.rs @@ -16,11 +16,13 @@ //! Vm execution env. -use blockchain::State; -use bytes::Bytes; -use hash::H256; -use uint::Uint; -use vm::{Call, Env, Transaction}; +use crate::{ + blockchain::State, + bytes::Bytes, + hash::H256, + uint::Uint, + vm::{Call, Env, Transaction}, +}; /// Represents vm execution environment before and after execution of transaction. #[derive(Debug, PartialEq, Deserialize)] @@ -58,8 +60,8 @@ impl Vm { #[cfg(test)] mod tests { + use super::Vm; use serde_json; - use vm::Vm; #[test] fn vm_deserialization() { From b6b5129058039de533ff2a6b3fe889887564701a Mon Sep 17 00:00:00 2001 From: Karim Agha Date: Sun, 14 Mar 2021 10:25:14 +0100 Subject: [PATCH 091/107] Following up on PR #316, removing unused conversions that are now deadcode (#321) --- crates/ethjson/src/state/log.rs | 11 ------- crates/ethjson/src/transaction/transaction.rs | 32 ------------------- 2 files changed, 43 deletions(-) diff --git a/crates/ethjson/src/state/log.rs b/crates/ethjson/src/state/log.rs index 89e0f18e15..9f17871dfe 100644 --- a/crates/ethjson/src/state/log.rs +++ b/crates/ethjson/src/state/log.rs @@ -19,7 +19,6 @@ use crate::{ bytes::Bytes, hash::{Address, Bloom, H256}, }; -use common_types::log_entry::LogEntry; /// State test log deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -53,13 +52,3 @@ mod tests { // TODO: validate all fields } } - -impl From for LogEntry { - fn from(l: Log) -> Self { - LogEntry { - address: l.address.into(), - topics: l.topics.into_iter().map(Into::into).collect(), - data: l.data.into(), - } - } -} diff --git a/crates/ethjson/src/transaction/transaction.rs b/crates/ethjson/src/transaction/transaction.rs index 9d33b07162..edb15737a4 100644 --- a/crates/ethjson/src/transaction/transaction.rs +++ b/crates/ethjson/src/transaction/transaction.rs @@ -17,11 +17,6 @@ //! Transaction test transaction deserialization. use crate::{bytes::Bytes, hash::Address, maybe::MaybeEmpty, uint::Uint}; -use common_types::transaction::{ - signature, Action, SignatureComponents, Transaction as CoreTransaction, TypedTransaction, - UnverifiedTransaction, -}; -use ethereum_types::H256; /// Transaction test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -47,33 +42,6 @@ pub struct Transaction { pub v: Uint, } -impl From for UnverifiedTransaction { - fn from(t: Transaction) -> Self { - let to: Option
= t.to.into(); - UnverifiedTransaction { - unsigned: TypedTransaction::Legacy(CoreTransaction { - nonce: t.nonce.into(), - gas_price: t.gas_price.into(), - gas: t.gas_limit.into(), - action: match to { - Some(to) => Action::Call(to.into()), - None => Action::Create, - }, - value: t.value.into(), - data: t.data.into(), - }), - chain_id: signature::extract_chain_id_from_legacy_v(t.v.into()), - signature: SignatureComponents { - r: t.r.into(), - s: t.s.into(), - standard_v: signature::extract_standard_v(t.v.into()), - }, - hash: H256::zero(), - } - .compute_hash() - } -} - #[cfg(test)] mod tests { use super::Transaction; From 327c4bcb1442b587221098f6d2c371a84901baaa Mon Sep 17 00:00:00 2001 From: Karim Agha Date: Sun, 14 Mar 2021 10:25:45 +0100 Subject: [PATCH 092/107] Fixing outdated readme links (#322) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 86ccc0e16d..588b25bb33 100644 --- a/README.md +++ b/README.md @@ -297,9 +297,9 @@ Caching, Importing Blocks, and Block Information In addition to the OpenEthereum client, there are additional tools in this repository available: -- [evmbin](./evmbin) - OpenEthereum EVM Implementation. -- [ethstore](./accounts/ethstore) - OpenEthereum Key Management. -- [ethkey](./accounts/ethkey) - OpenEthereum Keys Generator. +- [evmbin](./bin/evmbin) - OpenEthereum EVM Implementation. +- [ethstore](./crates/accounts/ethstore) - OpenEthereum Key Management. +- [ethkey](./crates/accounts/ethkey) - OpenEthereum Keys Generator. The following tools are available in a separate repository: - [ethabi](https://github.com/openethereum/ethabi) - OpenEthereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi) From 33a3a9deec896c245935f5abf8d5e07bb8977939 Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 14 Mar 2021 11:18:38 +0100 Subject: [PATCH 093/107] Initial sync block stuck. Block import logs (#318) Co-authored-by: Karim Agha --- crates/ethcore/src/client/client.rs | 18 ++++++++++++++++-- crates/ethcore/src/verification/queue/mod.rs | 5 +++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 46b8eb4190..71966cd9c1 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -284,7 +284,9 @@ impl Importer { // t_nb 6.0 This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. + trace!(target: "block_import", "fn import_verified_blocks"); if !client.enabled.load(AtomicOrdering::SeqCst) { + self.block_queue.reset_verification_ready_signal(); return 0; } @@ -306,6 +308,8 @@ impl Importer { let _import_lock = self.import_lock.lock(); let blocks = self.block_queue.drain(max_blocks_to_import); if blocks.is_empty() { + debug!(target: "block_import", "block_queue is empty"); + self.block_queue.resignal_verification(); return 0; } trace_time!("import_verified_blocks"); @@ -318,6 +322,13 @@ impl Importer { let is_invalid = invalid_blocks.contains(header.parent_hash()); if is_invalid { + debug!( + target: "block_import", + "Refusing block #{}({}) with invalid parent {}", + header.number(), + header.hash(), + header.parent_hash() + ); invalid_blocks.insert(hash); continue; } @@ -326,7 +337,7 @@ impl Importer { Ok((closed_block, pending)) => { imported_blocks.push(hash); let transactions_len = closed_block.transactions.len(); - + trace!(target:"block_import","Block #{}({}) check pass",header.number(),header.hash()); // t_nb 8.0 commit block to db let route = self.commit_block( closed_block, @@ -335,6 +346,7 @@ impl Importer { pending, client, ); + trace!(target:"block_import","Block #{}({}) commited",header.number(),header.hash()); import_results.push(route); client .report @@ -368,6 +380,7 @@ impl Importer { { if !imported_blocks.is_empty() { + trace!(target:"block_import","Imported block, notify rest of system"); let route = ChainRoute::from(import_results.as_ref()); // t_nb 10 Notify miner about new included block. @@ -396,11 +409,12 @@ impl Importer { }); } } - + trace!(target:"block_import","Flush block to db"); let db = client.db.read(); db.key_value().flush().expect("DB flush failed."); self.block_queue.resignal_verification(); + trace!(target:"block_import","Resignal verifier"); imported } diff --git a/crates/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs index e4202c564a..8d1a416397 100644 --- a/crates/ethcore/src/verification/queue/mod.rs +++ b/crates/ethcore/src/verification/queue/mod.rs @@ -678,6 +678,11 @@ impl VerificationQueue { } } + /// Reset verification ready signal so that it allows other threads to send IoMessage to Client + pub fn reset_verification_ready_signal(&self) { + self.ready_signal.reset(); + } + /// Returns true if there is nothing currently in the queue. pub fn is_empty(&self) -> bool { let v = &self.verification; From 3317797285918d7fa3eb16696ecaeff37778dc47 Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 14 Mar 2021 11:18:38 +0100 Subject: [PATCH 094/107] Initial sync block stuck. Block import logs (#318) --- crates/ethcore/src/client/client.rs | 20 +++++++++++++++++--- crates/ethcore/src/verification/queue/mod.rs | 5 +++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 80531f7211..e6d6f56a9e 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -281,7 +281,9 @@ impl Importer { // t_nb 6.0 This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. - if !client.enabled.load(AtomicOrdering::Relaxed) { + trace!(target: "block_import", "fn import_verified_blocks"); + if !client.enabled.load(AtomicOrdering::SeqCst) { + self.block_queue.reset_verification_ready_signal(); return 0; } @@ -303,6 +305,8 @@ impl Importer { let _import_lock = self.import_lock.lock(); let blocks = self.block_queue.drain(max_blocks_to_import); if blocks.is_empty() { + debug!(target: "block_import", "block_queue is empty"); + self.block_queue.resignal_verification(); return 0; } trace_time!("import_verified_blocks"); @@ -315,6 +319,13 @@ impl Importer { let is_invalid = invalid_blocks.contains(header.parent_hash()); if is_invalid { + debug!( + target: "block_import", + "Refusing block #{}({}) with invalid parent {}", + header.number(), + header.hash(), + header.parent_hash() + ); invalid_blocks.insert(hash); continue; } @@ -323,7 +334,7 @@ impl Importer { Ok((closed_block, pending)) => { imported_blocks.push(hash); let transactions_len = closed_block.transactions.len(); - + trace!(target:"block_import","Block #{}({}) check pass",header.number(),header.hash()); // t_nb 8.0 commit block to db let route = self.commit_block( closed_block, @@ -332,6 +343,7 @@ impl Importer { pending, client, ); + trace!(target:"block_import","Block #{}({}) commited",header.number(),header.hash()); import_results.push(route); client .report @@ -365,6 +377,7 @@ impl Importer { { if !imported_blocks.is_empty() { + trace!(target:"block_import","Imported block, notify rest of system"); let route = ChainRoute::from(import_results.as_ref()); // t_nb 10 Notify miner about new included block. @@ -393,11 +406,12 @@ impl Importer { }); } } - + trace!(target:"block_import","Flush block to db"); let db = client.db.read(); db.key_value().flush().expect("DB flush failed."); self.block_queue.resignal_verification(); + trace!(target:"block_import","Resignal verifier"); imported } diff --git a/crates/ethcore/src/verification/queue/mod.rs b/crates/ethcore/src/verification/queue/mod.rs index cb67d689c4..01be5cfde4 100644 --- a/crates/ethcore/src/verification/queue/mod.rs +++ b/crates/ethcore/src/verification/queue/mod.rs @@ -683,6 +683,11 @@ impl VerificationQueue { } } + /// Reset verification ready signal so that it allows other threads to send IoMessage to Client + pub fn reset_verification_ready_signal(&self) { + self.ready_signal.reset(); + } + /// Returns true if there is nothing currently in the queue. pub fn is_empty(&self) -> bool { let v = &self.verification; From 504777e87969776d398c6db537b5eea02c0ed041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20M=C3=BCller?= Date: Tue, 16 Mar 2021 13:39:42 +0100 Subject: [PATCH 095/107] Implement the filter argument in parity_pendingTransactions (#295) * Add filters for pending transactions to RPC API Allow filtering results in the parity_pendingTransaction endpoint as described in the API docs. * Make arguments in parity_pendingTransactions work together filter and limit * fmt * Requested changes - filter in ethcore to avoid unneccessary copying - rename gas_price to gasPrice - implement requesting contract creation txs with "action" * Some beautifying Remove missing import and unneccessary dependency entry, add a comment and set right lint level on new module * fixed broken build after merge * fmt * fixing CI errors: type conversion Co-authored-by: Karim Agha --- Cargo.lock | 3 + crates/concensus/miner/Cargo.toml | 3 + crates/concensus/miner/src/lib.rs | 2 + crates/concensus/miner/src/pool/mod.rs | 1 + crates/concensus/miner/src/pool/queue.rs | 50 ++++++- .../miner/src/pool/transaction_filter.rs | 129 ++++++++++++++++++ crates/ethcore/src/miner/miner.rs | 34 +++-- crates/ethcore/src/miner/mod.rs | 24 +++- crates/rpc/src/v1/impls/parity.rs | 14 +- .../rpc/src/v1/tests/helpers/miner_service.rs | 14 +- crates/rpc/src/v1/tests/mocked/parity.rs | 81 ++++++++++- crates/rpc/src/v1/traits/parity.rs | 8 +- crates/rpc/src/v1/types/mod.rs | 62 ++++----- 13 files changed, 367 insertions(+), 58 deletions(-) create mode 100644 crates/concensus/miner/src/pool/transaction_filter.rs diff --git a/Cargo.lock b/Cargo.lock index 4baf2a7869..24a526d3b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1188,6 +1188,9 @@ dependencies = [ "price-info", "rlp", "rustc-hex 1.0.0", + "serde", + "serde_derive", + "serde_json", "trace-time", "transaction-pool", "url 2.1.0", diff --git a/crates/concensus/miner/Cargo.toml b/crates/concensus/miner/Cargo.toml index 0fae0fa7b7..f155005644 100644 --- a/crates/concensus/miner/Cargo.toml +++ b/crates/concensus/miner/Cargo.toml @@ -32,6 +32,9 @@ parity-util-mem = "0.7" parking_lot = "0.7" price-info = { path = "./price-info", optional = true } rlp = { version = "0.4.6" } +serde = { version = "1.0", features = ["derive"] } +serde_derive = "1.0" +serde_json = "1.0" trace-time = "0.1" transaction-pool = "2.0.1" diff --git a/crates/concensus/miner/src/lib.rs b/crates/concensus/miner/src/lib.rs index 46280c1520..4df0b185ae 100644 --- a/crates/concensus/miner/src/lib.rs +++ b/crates/concensus/miner/src/lib.rs @@ -44,6 +44,8 @@ extern crate error_chain; #[macro_use] extern crate log; #[macro_use] +extern crate serde_derive; +#[macro_use] extern crate trace_time; #[cfg(test)] diff --git a/crates/concensus/miner/src/pool/mod.rs b/crates/concensus/miner/src/pool/mod.rs index 1467a1f235..ee7b691a8e 100644 --- a/crates/concensus/miner/src/pool/mod.rs +++ b/crates/concensus/miner/src/pool/mod.rs @@ -29,6 +29,7 @@ pub mod client; pub mod local_transactions; pub mod replace; pub mod scoring; +pub mod transaction_filter; pub mod verifier; #[cfg(test)] diff --git a/crates/concensus/miner/src/pool/queue.rs b/crates/concensus/miner/src/pool/queue.rs index e2e0d15622..64c543c53a 100644 --- a/crates/concensus/miner/src/pool/queue.rs +++ b/crates/concensus/miner/src/pool/queue.rs @@ -32,7 +32,10 @@ use txpool::{self, Verifier}; use types::transaction; use pool::{ - self, client, listener, local_transactions::LocalTransactionsList, ready, replace, scoring, + self, client, listener, + local_transactions::LocalTransactionsList, + ready, replace, scoring, + transaction_filter::{match_filter, TransactionFilter}, verifier, PendingOrdering, PendingSettings, PrioritizationStrategy, }; @@ -120,6 +123,17 @@ impl CachedPending { current_timestamp: u64, nonce_cap: Option<&U256>, max_len: usize, + ) -> Option>> { + self.pending_filtered(block_number, current_timestamp, nonce_cap, max_len, None) + } + + pub fn pending_filtered( + &self, + block_number: u64, + current_timestamp: u64, + nonce_cap: Option<&U256>, + max_len: usize, + filter: Option, ) -> Option>> { // First check if we have anything in cache. let pending = self.pending.as_ref()?; @@ -149,7 +163,14 @@ impl CachedPending { return None; } - Some(pending.iter().take(max_len).cloned().collect()) + Some( + pending + .iter() + .filter(|tx| match_filter(&filter, tx)) + .take(max_len) + .cloned() + .collect(), + ) } } @@ -426,6 +447,31 @@ impl TransactionQueue { pending } + /// Returns current pending transactions filtered. + /// + /// Different to the pending() method, this one does not cache. + pub fn pending_filtered( + &self, + client: C, + settings: PendingSettings, + filter: &TransactionFilter, + ) -> Vec> + where + C: client::NonceClient, + { + self.collect_pending( + client, + settings.block_number, + settings.current_timestamp, + settings.nonce_cap, + |i| { + i.filter(|tx| filter.matches(tx)) + .take(settings.max_len) + .collect() + }, + ) + } + /// Collect pending transactions. /// /// NOTE This is re-computing the pending set and it might be expensive to do so. diff --git a/crates/concensus/miner/src/pool/transaction_filter.rs b/crates/concensus/miner/src/pool/transaction_filter.rs new file mode 100644 index 0000000000..b261fd08a8 --- /dev/null +++ b/crates/concensus/miner/src/pool/transaction_filter.rs @@ -0,0 +1,129 @@ +// Copyright 2015-2021 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! Filter options available in the parity_pendingTransaction endpoint of the JSONRPC API. + +#![allow(missing_docs)] + +use ethereum_types::{Address, U256}; + +use pool::VerifiedTransaction; +use types::transaction::Action; + +#[allow(non_camel_case_types)] +#[derive(Debug, Deserialize, Serialize)] +#[serde()] +pub enum SenderArgument { + eq(Address), + None, +} + +impl Default for SenderArgument { + fn default() -> Self { + Self::None + } +} + +impl SenderArgument { + fn matches(&self, value: &Address) -> bool { + match self { + Self::eq(expected) => value == expected, + Self::None => true, + } + } +} + +#[allow(non_camel_case_types)] +#[derive(Debug, Deserialize, Serialize)] +#[serde()] +pub enum ActionArgument { + eq(Address), + action(String), + None, +} + +impl Default for ActionArgument { + fn default() -> Self { + Self::None + } +} + +impl ActionArgument { + fn matches(&self, value: &Action) -> bool { + match self { + Self::eq(expected) => *value == Action::Call(*expected), + Self::action(name) => *value == Action::Create && name == "contract_creation", + Self::None => true, + } + } +} + +#[allow(non_camel_case_types)] +#[derive(Debug, Deserialize, Serialize)] +#[serde()] +pub enum ValueFilterArgument { + eq(U256), + lt(U256), + gt(U256), + None, +} + +impl Default for ValueFilterArgument { + fn default() -> Self { + Self::None + } +} + +impl ValueFilterArgument { + fn matches(&self, value: &U256) -> bool { + match self { + ValueFilterArgument::eq(expected) => value == expected, + ValueFilterArgument::lt(threshold) => value < threshold, + ValueFilterArgument::gt(threshold) => value > threshold, + ValueFilterArgument::None => true, + } + } +} + +#[derive(Debug, Default, Deserialize, Serialize)] +#[serde(default, rename_all = "camelCase")] +pub struct TransactionFilter { + from: SenderArgument, + to: ActionArgument, + gas: ValueFilterArgument, + gas_price: ValueFilterArgument, + value: ValueFilterArgument, + nonce: ValueFilterArgument, +} + +impl TransactionFilter { + pub fn matches(&self, transaction: &VerifiedTransaction) -> bool { + let tx = transaction.signed().tx(); + self.from.matches(&transaction.sender) + && self.to.matches(&tx.action) + && self.gas.matches(&tx.gas) + && self.gas_price.matches(&tx.gas_price) + && self.nonce.matches(&tx.nonce) + && self.value.matches(&tx.value) + } +} + +pub fn match_filter(filter: &Option, transaction: &VerifiedTransaction) -> bool { + match filter { + Some(f) => f.matches(transaction), + None => true, + } +} diff --git a/crates/ethcore/src/miner/miner.rs b/crates/ethcore/src/miner/miner.rs index 4335093c70..d56127d386 100644 --- a/crates/ethcore/src/miner/miner.rs +++ b/crates/ethcore/src/miner/miner.rs @@ -29,7 +29,11 @@ use ethcore_miner::work_notify::NotifyWork; use ethcore_miner::{ gas_pricer::GasPricer, local_accounts::LocalAccounts, - pool::{self, PrioritizationStrategy, QueueStatus, TransactionQueue, VerifiedTransaction}, + pool::{ + self, + transaction_filter::{match_filter, TransactionFilter}, + PrioritizationStrategy, QueueStatus, TransactionQueue, VerifiedTransaction, + }, service_transaction_checker::ServiceTransactionChecker, }; use ethereum_types::{Address, H256, U256}; @@ -1099,10 +1103,11 @@ impl miner::MinerService for Miner { } } - fn ready_transactions( + fn ready_transactions_filtered( &self, chain: &C, max_len: usize, + filter: Option, ordering: miner::PendingOrdering, ) -> Vec> where @@ -1116,16 +1121,20 @@ impl miner::MinerService for Miner { // those transactions are valid and will just be ready to be included in next block. let nonce_cap = None; - self.transaction_queue.pending( - CachedNonceClient::new(chain, &self.nonce_cache), - pool::PendingSettings { - block_number: chain_info.best_block_number, - current_timestamp: chain_info.best_block_timestamp, - nonce_cap, - max_len, - ordering, - }, - ) + let client = CachedNonceClient::new(chain, &self.nonce_cache); + let settings = pool::PendingSettings { + block_number: chain_info.best_block_number, + current_timestamp: chain_info.best_block_timestamp, + nonce_cap, + max_len, + ordering, + }; + + if let Some(ref f) = filter { + self.transaction_queue.pending_filtered(client, settings, f) + } else { + self.transaction_queue.pending(client, settings) + } }; let from_pending = || { @@ -1139,6 +1148,7 @@ impl miner::MinerService for Miner { signed.clone(), ) }) + .filter(|tx| match_filter(&filter, tx)) .map(Arc::new) .take(max_len) .collect() diff --git a/crates/ethcore/src/miner/mod.rs b/crates/ethcore/src/miner/mod.rs index c7eb0d056f..ddd0f76301 100644 --- a/crates/ethcore/src/miner/mod.rs +++ b/crates/ethcore/src/miner/mod.rs @@ -26,7 +26,10 @@ pub mod pool_client; pub mod stratum; pub use self::miner::{Author, AuthoringParams, Miner, MinerOptions, Penalization, PendingSet}; -pub use ethcore_miner::{local_accounts::LocalAccounts, pool::PendingOrdering}; +pub use ethcore_miner::{ + local_accounts::LocalAccounts, + pool::{transaction_filter::TransactionFilter, PendingOrdering}, +}; use std::{ collections::{BTreeMap, BTreeSet}, @@ -209,20 +212,35 @@ pub trait MinerService: Send + Sync { where C: ChainInfo + Sync; - /// Get a list of all ready transactions either ordered by priority or unordered (cheaper). + /// Get a list of all ready transactions either ordered by priority or unordered (cheaper), + /// and optionally filtered by sender, recipient, gas, gas price, value and/or nonce. /// /// Depending on the settings may look in transaction pool or only in pending block. /// If you don't need a full set of transactions, you can add `max_len` and create only a limited set of /// transactions. - fn ready_transactions( + fn ready_transactions_filtered( &self, chain: &C, max_len: usize, + filter: Option, ordering: PendingOrdering, ) -> Vec> where C: ChainInfo + Nonce + Sync; + /// Get an unfiltered list of all ready transactions. + fn ready_transactions( + &self, + chain: &C, + max_len: usize, + ordering: PendingOrdering, + ) -> Vec> + where + C: ChainInfo + Nonce + Sync, + { + self.ready_transactions_filtered(chain, max_len, None, ordering) + } + /// Get a list of all transactions in the pool (some of them might not be ready for inclusion yet). fn queued_transactions(&self) -> Vec>; diff --git a/crates/rpc/src/v1/impls/parity.rs b/crates/rpc/src/v1/impls/parity.rs index 2a4bc3e329..a41ae0a370 100644 --- a/crates/rpc/src/v1/impls/parity.rs +++ b/crates/rpc/src/v1/impls/parity.rs @@ -20,7 +20,7 @@ use std::{collections::BTreeMap, str::FromStr, sync::Arc}; use crypto::{publickey::ecies, DEFAULT_MAC}; use ethcore::{ client::{BlockChainClient, Call, StateClient}, - miner::{self, MinerService}, + miner::{self, MinerService, TransactionFilter}, snapshot::{RestorationStatus, SnapshotService}, state::StateInfo, }; @@ -32,8 +32,6 @@ use jsonrpc_core::{futures::future, BoxFuture, Result}; use stats::PrometheusMetrics; use sync::{ManageNetwork, SyncProvider}; use types::ids::BlockId; -use version::version_data; - use v1::{ helpers::{ self, @@ -50,6 +48,7 @@ use v1::{ Transaction, TransactionStats, }, }; +use version::version_data; use Host; /// Parity implementation. @@ -265,10 +264,15 @@ where .map(Into::into) } - fn pending_transactions(&self, limit: Option) -> Result> { - let ready_transactions = self.miner.ready_transactions( + fn pending_transactions( + &self, + limit: Option, + filter: Option, + ) -> Result> { + let ready_transactions = self.miner.ready_transactions_filtered( &*self.client, limit.unwrap_or_else(usize::max_value), + filter, miner::PendingOrdering::Priority, ); diff --git a/crates/rpc/src/v1/tests/helpers/miner_service.rs b/crates/rpc/src/v1/tests/helpers/miner_service.rs index 7e29f6dd70..eb49da6adf 100644 --- a/crates/rpc/src/v1/tests/helpers/miner_service.rs +++ b/crates/rpc/src/v1/tests/helpers/miner_service.rs @@ -30,7 +30,7 @@ use ethcore::{ }, engines::{signer::EngineSigner, EthEngine}, error::Error, - miner::{self, AuthoringParams, MinerService}, + miner::{self, AuthoringParams, MinerService, TransactionFilter}, }; use ethereum_types::{Address, H256, U256}; use miner::pool::{ @@ -264,13 +264,21 @@ impl MinerService for TestMinerService { .collect() } - fn ready_transactions( + fn ready_transactions_filtered( &self, _chain: &C, _max_len: usize, + filter: Option, _ordering: miner::PendingOrdering, ) -> Vec> { - self.queued_transactions() + match filter { + Some(f) => self + .queued_transactions() + .into_iter() + .filter(|tx| f.matches(tx)) + .collect(), + None => self.queued_transactions(), + } } fn pending_transaction_hashes(&self, _chain: &C) -> BTreeSet { diff --git a/crates/rpc/src/v1/tests/mocked/parity.rs b/crates/rpc/src/v1/tests/mocked/parity.rs index 49cd95a1d3..fae58a410e 100644 --- a/crates/rpc/src/v1/tests/mocked/parity.rs +++ b/crates/rpc/src/v1/tests/mocked/parity.rs @@ -19,7 +19,7 @@ use ethcore::client::{Executed, TestBlockChainClient, TransactionId}; use ethcore_logger::RotatingLogger; use ethereum_types::{Address, BigEndianHash, Bloom, H256, U256}; use miner::pool::local_transactions::Status as LocalTransactionStatus; -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use sync::ManageNetwork; use types::{ receipt::{LocalizedReceipt, TransactionOutcome}, @@ -290,6 +290,85 @@ fn rpc_parity_pending_transactions() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); } +fn assert_txs_filtered(io: &IoHandler, filter: &str, expected: Vec) { + let request = format!( + r#"{{"jsonrpc": "2.0", "method": "parity_pendingTransactions", + "params":[10, {}], "id": 1}}"#, + filter + ); + let response_str = io.handle_request_sync(&request).unwrap(); + let response = serde_json::Value::from_str(&response_str).unwrap(); + assert_eq!(response["result"].as_array().unwrap().len(), expected.len()); + for n in expected { + let expected_sender = format!("0x000000000000000000000000000000000000005{}", n); + assert!(response_str.contains(&expected_sender)); + } +} + +#[test] +fn rpc_parity_pending_transactions_with_filter() { + use types::transaction::{Action, Transaction, TypedTransaction}; + let deps = Dependencies::new(); + let io = deps.default_client(); + + for i in 1..6 { + let tx = TypedTransaction::Legacy(Transaction { + value: i.into(), + gas: (i + 0x10).into(), + gas_price: (i + 0x20).into(), + nonce: (i + 0x30).into(), + action: Action::Call(Address::from_low_u64_be(i + 0x40)), + data: vec![], + }) + .fake_sign(Address::from_low_u64_be(i + 0x50)); + deps.miner + .pending_transactions + .lock() + .insert(H256::from_low_u64_be(i + 0x60), tx); + } + + let tx = TypedTransaction::Legacy(Transaction { + value: 0.into(), + gas: 0x16.into(), + gas_price: 0x26.into(), + nonce: 0x36.into(), + action: Action::Create, + data: vec![0x01, 0x02, 0x03], + }) + .fake_sign(Address::from_low_u64_be(0x56)); + deps.miner + .pending_transactions + .lock() + .insert(H256::from_low_u64_be(0x66), tx); + + assert_txs_filtered( + &io, + r#"{"from":{"eq":"0x0000000000000000000000000000000000000052"}}"#, + vec![2], + ); + assert_txs_filtered( + &io, + r#"{"to":{"eq":"0x0000000000000000000000000000000000000041"}}"#, + vec![1], + ); + assert_txs_filtered(&io, r#"{"to":{"action":"contract_creation"}}"#, vec![6]); + assert_txs_filtered(&io, r#"{"gas":{"gt":"0x12"}}"#, vec![3, 4, 5, 6]); + assert_txs_filtered(&io, r#"{"gasPrice":{"eq":"0x24"}}"#, vec![4]); + assert_txs_filtered(&io, r#"{"nonce":{"lt":"0x33"}}"#, vec![1, 2]); + assert_txs_filtered(&io, r#"{"value":{"lt":"0x2"}}"#, vec![1, 6]); + assert_txs_filtered( + &io, + r#"{"value":{"gt":"0x1"},"gas":{"lt":"0x14"}}"#, + vec![2, 3], + ); + assert_txs_filtered(&io, r#"{"value":{"gt":"0x6"},"gas":{"gt":"0x1"}}"#, vec![]); + assert_txs_filtered( + &io, + r#"{"value":{"lt":"0x60"},"nonce":{"lt":"0x60"}}"#, + vec![1, 2, 3, 4, 5, 6], + ); +} + #[test] fn rpc_parity_encrypt() { let deps = Dependencies::new(); diff --git a/crates/rpc/src/v1/traits/parity.rs b/crates/rpc/src/v1/traits/parity.rs index d8d3746814..19449d0f11 100644 --- a/crates/rpc/src/v1/traits/parity.rs +++ b/crates/rpc/src/v1/traits/parity.rs @@ -21,6 +21,8 @@ use std::collections::BTreeMap; use ethereum_types::{H160, H256, H512, H64, U256, U64}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_derive::rpc; + +use ethcore::miner::TransactionFilter; use v1::types::{ BlockNumber, Bytes, CallRequest, ChainStatus, Histogram, LocalTransactionStatus, Peers, Receipt, RecoveredAccount, RichHeader, RpcSettings, Transaction, TransactionStats, @@ -132,7 +134,11 @@ pub trait Parity { /// Returns all pending transactions from transaction queue. #[rpc(name = "parity_pendingTransactions")] - fn pending_transactions(&self, _: Option) -> Result>; + fn pending_transactions( + &self, + _: Option, + _: Option, + ) -> Result>; /// Returns all transactions from transaction queue. /// diff --git a/crates/rpc/src/v1/types/mod.rs b/crates/rpc/src/v1/types/mod.rs index ce07f538a3..3b8138dcee 100644 --- a/crates/rpc/src/v1/types/mod.rs +++ b/crates/rpc/src/v1/types/mod.rs @@ -16,37 +16,6 @@ //! RPC types -#[cfg(test)] -mod eth_types; - -mod account_info; -mod block; -mod block_number; -mod bytes; -mod call_request; -mod confirmations; -mod derivation; -mod eip191; -mod filter; -mod histogram; -mod index; -mod log; -mod node_kind; -mod provenance; -mod receipt; -mod rpc_settings; -mod secretstore; -mod sync; -mod trace; -mod trace_filter; -mod transaction; -mod transaction_access_list; -mod transaction_condition; -mod transaction_request; -mod work; - -pub mod pubsub; - pub use self::{ account_info::{AccountInfo, EthAccount, ExtAccountInfo, RecoveredAccount, StorageProof}, block::{Block, BlockTransactions, Header, Rich, RichBlock, RichHeader}, @@ -82,6 +51,37 @@ pub use self::{ work::Work, }; +#[cfg(test)] +mod eth_types; + +mod account_info; +mod block; +mod block_number; +mod bytes; +mod call_request; +mod confirmations; +mod derivation; +mod eip191; +mod filter; +mod histogram; +mod index; +mod log; +mod node_kind; +mod provenance; +mod receipt; +mod rpc_settings; +mod secretstore; +mod sync; +mod trace; +mod trace_filter; +mod transaction; +mod transaction_access_list; +mod transaction_condition; +mod transaction_request; +mod work; + +pub mod pubsub; + // TODO [ToDr] Refactor to a proper type Vec of enums? /// Expected tracing type. pub type TraceOptions = Vec; From 5fdedf0858bf1ae95e718909a1476d8172845f6c Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 17 Mar 2021 09:46:36 +0100 Subject: [PATCH 096/107] Bump to v3.2.1. Changelog --- CHANGELOG.md | 4 ++++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/util/version/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea086927de..554b8c982d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## OpenEthereum v3.2.1 + +Hot fix issue, related to initial sync: +* Initial sync gets stuck. (#318) ## OpenEthereum v3.2.0 Bug fixes: diff --git a/Cargo.lock b/Cargo.lock index c232f77538..89f67a0624 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2825,7 +2825,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openethereum" -version = "3.2.0" +version = "3.2.1" dependencies = [ "ansi_term 0.10.2", "atty", @@ -3188,7 +3188,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "3.2.0" +version = "3.2.1" dependencies = [ "parity-bytes", "rlp 0.3.0", diff --git a/Cargo.toml b/Cargo.toml index 2906d1545c..3e966e5960 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "OpenEthereum" name = "openethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "3.2.0" +version = "3.2.1" license = "GPL-3.0" authors = [ "OpenEthereum developers", diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index 7fdef2e3b7..61c4cbaf46 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "parity-version" # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) -version = "3.2.0" +version = "3.2.1" authors = ["Parity Technologies "] build = "build.rs" From 37f529153891356656bb0caf3324833153f0128f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20M=C3=BCller?= Date: Thu, 18 Mar 2021 14:00:05 +0100 Subject: [PATCH 097/107] Add Nethermind to clients that accept service transactions (#324) * Add Nethermind to clients that accept service transactions * fmt --- crates/net/network/src/client_version.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/net/network/src/client_version.rs b/crates/net/network/src/client_version.rs index de3c257a4c..40f5e3d9ca 100644 --- a/crates/net/network/src/client_version.rs +++ b/crates/net/network/src/client_version.rs @@ -128,8 +128,8 @@ pub trait ClientCapabilities { /// if this version can handle requests for a large number of block bodies. fn can_handle_large_requests(&self) -> bool; - /// Service transactions are specific to parity. Query if this version - /// accepts them. + /// Service transactions are specific to parity and nethermind. Query if + /// this version accepts them. fn accepts_service_transaction(&self) -> bool; } @@ -146,7 +146,7 @@ impl ClientCapabilities for ClientVersion { match self { ClientVersion::ParityClient(_) => true, ClientVersion::ParityUnknownFormat(_) => true, - ClientVersion::Other(_) => false, + ClientVersion::Other(client_id) => is_nethermind(client_id), } } } @@ -156,6 +156,10 @@ fn is_parity(client_id: &str) -> bool { || client_id.starts_with(CURRENT_CLIENT_ID_PREFIX) } +fn is_nethermind(client_id: &str) -> bool { + client_id.starts_with("Nethermind") +} + /// Parse known parity formats. Recognizes either a short format with four fields /// or a long format which includes the same fields and an identity one. fn parse_parity_format(client_version: &str) -> Result { @@ -531,6 +535,15 @@ pub mod tests { ClientVersion::from("Parity-Ethereum/ABCDEFGH/v2.7.3/linux/rustc") .accepts_service_transaction() ); + assert!( + ClientVersion::from("OpenEthereum//v3.2.0/x86_64-linux-gnu/rustc1.49.0") + .accepts_service_transaction() + ); + assert!(ClientVersion::from("OpenEthereum/ABCDEFGH").accepts_service_transaction()); + assert!( + ClientVersion::from("Nethermind/v1.10.37-0-068e5c399-20210311/X64-Linux/5.0.4") + .accepts_service_transaction() + ) } #[test] From ee88247e71ef74414e0946d7200ccb879e4604f4 Mon Sep 17 00:00:00 2001 From: Karim Agha Date: Sun, 14 Mar 2021 10:25:45 +0100 Subject: [PATCH 098/107] Fixing outdated readme links (#322) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 86ccc0e16d..588b25bb33 100644 --- a/README.md +++ b/README.md @@ -297,9 +297,9 @@ Caching, Importing Blocks, and Block Information In addition to the OpenEthereum client, there are additional tools in this repository available: -- [evmbin](./evmbin) - OpenEthereum EVM Implementation. -- [ethstore](./accounts/ethstore) - OpenEthereum Key Management. -- [ethkey](./accounts/ethkey) - OpenEthereum Keys Generator. +- [evmbin](./bin/evmbin) - OpenEthereum EVM Implementation. +- [ethstore](./crates/accounts/ethstore) - OpenEthereum Key Management. +- [ethkey](./crates/accounts/ethkey) - OpenEthereum Keys Generator. The following tools are available in a separate repository: - [ethabi](https://github.com/openethereum/ethabi) - OpenEthereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi) From 5eacff59e86278ccf19c592496308f702b0f2d1a Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 22 Mar 2021 12:22:21 +0100 Subject: [PATCH 099/107] Revert "Remove eth/63 protocol version (#252)" This reverts commit bbecb0415ef1ffe5d1c15d9a0fd19de859f0eb1a. --- crates/ethcore/sync/src/api.rs | 5 +++-- crates/ethcore/sync/src/chain/handler.rs | 14 +++++++++----- crates/ethcore/sync/src/chain/mod.rs | 7 +++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/ethcore/sync/src/api.rs b/crates/ethcore/sync/src/api.rs index 74c132a828..cb75861de7 100644 --- a/crates/ethcore/sync/src/api.rs +++ b/crates/ethcore/sync/src/api.rs @@ -32,7 +32,8 @@ use std::{ use chain::{ fork_filter::ForkFilterApi, ChainSyncApi, SyncState, SyncStatus as EthSyncStatus, - ETH_PROTOCOL_VERSION_64, PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, + ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64, PAR_PROTOCOL_VERSION_1, + PAR_PROTOCOL_VERSION_2, }; use ethcore::{ client::{BlockChainClient, ChainMessageType, ChainNotify, NewBlocks}, @@ -563,7 +564,7 @@ impl ChainNotify for EthSync { .register_protocol( self.eth_handler.clone(), self.subprotocol_name, - &[ETH_PROTOCOL_VERSION_64], + &[ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64], ) .unwrap_or_else(|e| warn!("Error registering ethereum protocol: {:?}", e)); // register the warp sync subprotocol diff --git a/crates/ethcore/sync/src/chain/handler.rs b/crates/ethcore/sync/src/chain/handler.rs index 6938209b88..556c677b5a 100644 --- a/crates/ethcore/sync/src/chain/handler.rs +++ b/crates/ethcore/sync/src/chain/handler.rs @@ -42,8 +42,8 @@ use super::sync_packet::{ use super::{ BlockSet, ChainSync, ForkConfirmation, PacketProcessError, PeerAsking, PeerInfo, SyncRequester, - SyncState, ETH_PROTOCOL_VERSION_64, MAX_NEW_BLOCK_AGE, MAX_NEW_HASHES, PAR_PROTOCOL_VERSION_1, - PAR_PROTOCOL_VERSION_2, + SyncState, ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_64, MAX_NEW_BLOCK_AGE, MAX_NEW_HASHES, + PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, }; /// The Chain Sync Handler: handles responses from peers @@ -669,7 +669,7 @@ impl SyncHandler { .next() .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; - let _eth_protocol_version = io.protocol_version(ETH_PROTOCOL, peer_id); + let eth_protocol_version = io.protocol_version(ETH_PROTOCOL, peer_id); let warp_protocol_version = io.protocol_version(PAR_PROTOCOL, peer_id); let warp_protocol = warp_protocol_version != 0; @@ -691,7 +691,7 @@ impl SyncHandler { .next() .ok_or(rlp::DecoderError::RlpIsTooShort)? .as_val()?; - let forkid_validation_error = { + let forkid_validation_error = if eth_protocol_version >= ETH_PROTOCOL_VERSION_64.0 { let fork_id = r_iter .next() .ok_or(rlp::DecoderError::RlpIsTooShort)? @@ -700,6 +700,8 @@ impl SyncHandler { .is_compatible(io.chain(), fork_id) .err() .map(|e| (fork_id, e)) + } else { + None }; let snapshot_hash = if warp_protocol { Some( @@ -788,7 +790,9 @@ impl SyncHandler { || (warp_protocol && (peer.protocol_version < PAR_PROTOCOL_VERSION_1.0 || peer.protocol_version > PAR_PROTOCOL_VERSION_2.0)) - || (!warp_protocol && peer.protocol_version != ETH_PROTOCOL_VERSION_64.0) + || (!warp_protocol + && (peer.protocol_version < ETH_PROTOCOL_VERSION_63.0 + || peer.protocol_version > ETH_PROTOCOL_VERSION_64.0)) { trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, peer.protocol_version); return Err(DownloaderImportError::Invalid); diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index 4d04fe3885..1ccbc1f4f8 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -158,6 +158,8 @@ impl From for PacketProcessError { /// 64 version of Ethereum protocol. pub const ETH_PROTOCOL_VERSION_64: (u8, u8) = (64, 0x11); +/// 63 version of Ethereum protocol. +pub const ETH_PROTOCOL_VERSION_63: (u8, u8) = (63, 0x11); /// 1 version of OpenEthereum protocol and the packet count. pub const PAR_PROTOCOL_VERSION_1: (u8, u8) = (1, 0x15); /// 2 version of OpenEthereum protocol (consensus messages added). @@ -1308,8 +1310,9 @@ impl ChainSync { packet.append(&primitive_types07::U256(chain.total_difficulty.0)); packet.append(&primitive_types07::H256(chain.best_block_hash.0)); packet.append(&primitive_types07::H256(chain.genesis_hash.0)); - packet.append(&self.fork_filter.current(io.chain())); - + if eth_protocol_version >= ETH_PROTOCOL_VERSION_64.0 { + packet.append(&self.fork_filter.current(io.chain())); + } if warp_protocol { let manifest = io.snapshot_service().manifest(); let block_number = manifest.as_ref().map_or(0, |m| m.block_number); From 561ed8df3ccdd1c383dc482db56bb84a416f8af3 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 24 Mar 2021 15:15:10 +0100 Subject: [PATCH 100/107] fix miner_author by adding dummy msg --- bin/oe/account_utils.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/oe/account_utils.rs b/bin/oe/account_utils.rs index 405aa917cd..4b9415466b 100644 --- a/bin/oe/account_utils.rs +++ b/bin/oe/account_utils.rs @@ -71,7 +71,7 @@ mod accounts { #[cfg(feature = "accounts")] mod accounts { use super::*; - use crate::upgrade::upgrade_key_location; + use crate::{ethereum_types::H256, upgrade::upgrade_key_location}; use std::str::FromStr; pub use crate::accounts::AccountProvider; @@ -198,7 +198,8 @@ mod accounts { engine_signer, password.clone(), ); - if signer.sign(Default::default()).is_ok() { + // sign dummy msg to check if password and account can be used. + if signer.sign(H256::from_low_u64_be(1)).is_ok() { author = Some(::ethcore::miner::Author::Sealer(Box::new(signer))); } } From 85391f99ac9132c0202afbc619e10a594d2e5112 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 25 Mar 2021 14:37:01 +0100 Subject: [PATCH 101/107] Backport AuRa commits for xdai (#330) * Add SealingState; don't prepare block when not ready. (#10529) * Fix a few typos and unused warnings. #10803 * Configuration map of block reward contract addresses (#10875) * Step duration map configuration parameter ported from the POA Network fork (#10902) * Add a 2/3 quorum option to Authority Round. (#10909) * Additional arithmetic EVM opcode benchmarks (#10916) * RPC method for clearing the engine signer (#10920) * authority_round: Fix next_step_time_duration. (#11379) * Aura: Report malice on sibling blocks from the same validator (#11160) * TxPermissions ver 3: gas price & data (#11170) * Add randomness contract support to AuthorityRound. (#10946) * Set the block gas limit to the value returned by a contract call (#10928) * AuthorityEngine: Minor cleanups. (#11408) * Add POSDAO transition and malice report queue. (#11245) * PoA call validators on_close_block * Actualize spec files for POA Networks * Some fixes after merge * Crypto error desc * AuRa on_close_block Error::Old fix Co-authored-by: POA <33550681+poa@users.noreply.github.com> --- Cargo.lock | 1 + crates/accounts/ethkey/src/error.rs | 88 ++ crates/ethcore/Cargo.toml | 1 + crates/ethcore/res/chainspec/kovan.json | 104 +- crates/ethcore/res/chainspec/poacore.json | 51 +- crates/ethcore/res/chainspec/poasokol.json | 53 +- .../authority_round_randomness_contract.json | 100 ++ .../res/chainspec/test/contract_ver_3.sol | 60 + .../test/contract_ver_3_genesis.json | 44 + .../chainspec/test/validator_contract.json | 2 +- .../res/chainspec/test/validator_contract.sol | 119 ++ crates/ethcore/res/chainspec/xdai.json | 83 +- .../res/contracts/authority_round_random.json | 133 ++ .../res/contracts/block_gas_limit.json | 16 + .../test_authority_round_random.json | 265 ++++ .../contracts/test_authority_round_random.sol | 101 ++ .../res/contracts/tx_acl_gas_price.json | 83 ++ .../res/contracts/validator_report.json | 3 +- .../ethcore/res/contracts/validator_set.json | 54 +- crates/ethcore/src/client/client.rs | 61 +- crates/ethcore/src/client/test_client.rs | 38 +- crates/ethcore/src/client/traits.rs | 62 +- .../authority_round/block_gas_limit.rs | 39 + .../src/engines/authority_round/finality.rs | 231 ++- .../src/engines/authority_round/mod.rs | 1241 ++++++++++++++--- .../src/engines/authority_round/randomness.rs | 257 ++++ .../src/engines/authority_round/util.rs | 119 ++ crates/ethcore/src/engines/basic_authority.rs | 28 +- crates/ethcore/src/engines/clique/mod.rs | 21 +- crates/ethcore/src/engines/instant_seal.rs | 6 +- crates/ethcore/src/engines/mod.rs | 54 +- crates/ethcore/src/engines/signer.rs | 30 +- .../src/engines/validator_set/contract.rs | 145 +- .../ethcore/src/engines/validator_set/mod.rs | 45 +- .../src/engines/validator_set/multi.rs | 60 +- .../engines/validator_set/safe_contract.rs | 248 +++- .../src/engines/validator_set/simple_list.rs | 17 +- .../ethcore/src/engines/validator_set/test.rs | 33 +- crates/ethcore/src/lib.rs | 1 + crates/ethcore/src/miner/miner.rs | 146 +- crates/ethcore/src/miner/mod.rs | 2 +- crates/ethcore/src/snapshot/service.rs | 3 +- crates/ethcore/src/snapshot/tests/service.rs | 16 +- crates/ethcore/src/spec/spec.rs | 6 + crates/ethcore/src/test_helpers.rs | 10 +- crates/ethcore/src/trace/types/trace.rs | 4 +- crates/ethcore/src/tx_filter.rs | 98 +- .../ethcore/src/verification/verification.rs | 67 +- crates/ethcore/types/src/transaction/error.rs | 2 +- crates/ethjson/src/spec/authority_round.rs | 116 +- crates/ethjson/src/spec/mod.rs | 2 + crates/ethjson/src/spec/step_duration.rs | 36 + crates/rpc/src/v1/helpers/engine_signer.rs | 17 +- crates/rpc/src/v1/impls/parity_set.rs | 5 + .../rpc/src/v1/tests/helpers/miner_service.rs | 14 +- crates/rpc/src/v1/traits/parity_set.rs | 4 + crates/vm/evm/benches/basic.rs | 208 +++ 57 files changed, 4278 insertions(+), 575 deletions(-) create mode 100644 crates/accounts/ethkey/src/error.rs create mode 100644 crates/ethcore/res/chainspec/test/authority_round_randomness_contract.json create mode 100644 crates/ethcore/res/chainspec/test/contract_ver_3.sol create mode 100644 crates/ethcore/res/chainspec/test/contract_ver_3_genesis.json create mode 100644 crates/ethcore/res/chainspec/test/validator_contract.sol create mode 100644 crates/ethcore/res/contracts/authority_round_random.json create mode 100644 crates/ethcore/res/contracts/block_gas_limit.json create mode 100644 crates/ethcore/res/contracts/test_authority_round_random.json create mode 100644 crates/ethcore/res/contracts/test_authority_round_random.sol create mode 100644 crates/ethcore/res/contracts/tx_acl_gas_price.json create mode 100644 crates/ethcore/src/engines/authority_round/block_gas_limit.rs create mode 100644 crates/ethcore/src/engines/authority_round/randomness.rs create mode 100644 crates/ethcore/src/engines/authority_round/util.rs create mode 100644 crates/ethjson/src/spec/step_duration.rs diff --git a/Cargo.lock b/Cargo.lock index c2ade4a624..d3611b47a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -952,6 +952,7 @@ dependencies = [ "common-types", "criterion 0.2.11", "crossbeam-utils 0.6.6", + "derive_more", "eip-152", "env_logger", "error-chain", diff --git a/crates/accounts/ethkey/src/error.rs b/crates/accounts/ethkey/src/error.rs new file mode 100644 index 0000000000..6d26c1fbe1 --- /dev/null +++ b/crates/accounts/ethkey/src/error.rs @@ -0,0 +1,88 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +use crypto::Error as CryptoError; +use std::{error, fmt}; + +#[derive(Debug)] +/// Crypto error +pub enum Error { + /// Invalid secret key + InvalidSecret, + /// Invalid public key + InvalidPublic, + /// Invalid address + InvalidAddress, + /// Invalid EC signature + InvalidSignature, + /// Invalid AES message + InvalidMessage, + /// IO Error + Io(::std::io::Error), + /// Custom + Custom(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = match *self { + Error::InvalidSecret => "Invalid secret".into(), + Error::InvalidPublic => "Invalid public".into(), + Error::InvalidAddress => "Invalid address".into(), + Error::InvalidSignature => "Invalid EC signature".into(), + Error::InvalidMessage => "Invalid AES message".into(), + Error::Io(ref err) => format!("I/O error: {}", err), + Error::Custom(ref s) => s.clone(), + }; + + f.write_fmt(format_args!("Crypto error ({})", msg)) + } +} + +impl error::Error for Error { + fn description(&self) -> &str { + format!("{:?}", &self) + } +} + +impl Into for Error { + fn into(self) -> String { + format!("{}", self) + } +} + +impl From for Error { + fn from(e: CryptoError) -> Error { + Error::Custom(e.to_string()) + } +} + +impl From<::secp256k1::Error> for Error { + fn from(e: ::secp256k1::Error) -> Error { + match e { + ::secp256k1::Error::InvalidMessage => Error::InvalidMessage, + ::secp256k1::Error::InvalidPublicKey => Error::InvalidPublic, + ::secp256k1::Error::InvalidSecretKey => Error::InvalidSecret, + _ => Error::InvalidSignature, + } + } +} + +impl From<::std::io::Error> for Error { + fn from(err: ::std::io::Error) -> Error { + Error::Io(err) + } +} diff --git a/crates/ethcore/Cargo.toml b/crates/ethcore/Cargo.toml index 1d18f16489..e1b83ebc9f 100644 --- a/crates/ethcore/Cargo.toml +++ b/crates/ethcore/Cargo.toml @@ -76,6 +76,7 @@ using_queue = { path = "../concensus/miner/using-queue" } vm = { path = "../vm/vm" } walkdir = "2.3" wasm = { path = "../vm/wasm" } +derive_more = "0.99" scopeguard = "1.1.0" [dev-dependencies] diff --git a/crates/ethcore/res/chainspec/kovan.json b/crates/ethcore/res/chainspec/kovan.json index e41127c3c0..89e988c2e3 100644 --- a/crates/ethcore/res/chainspec/kovan.json +++ b/crates/ethcore/res/chainspec/kovan.json @@ -88,9 +88,13 @@ "builtin": { "name": "ecrecover", "pricing": { - "linear": { - "base": 3000, - "word": 0 + "0": { + "price": { + "linear": { + "base": 3000, + "word": 0 + } + } } } } @@ -100,9 +104,13 @@ "builtin": { "name": "sha256", "pricing": { - "linear": { - "base": 60, - "word": 12 + "0": { + "price": { + "linear": { + "base": 60, + "word": 12 + } + } } } } @@ -112,9 +120,13 @@ "builtin": { "name": "ripemd160", "pricing": { - "linear": { - "base": 600, - "word": 120 + "0": { + "price": { + "linear": { + "base": 600, + "word": 120 + } + } } } } @@ -124,9 +136,13 @@ "builtin": { "name": "identity", "pricing": { - "linear": { - "base": 15, - "word": 3 + "0": { + "price": { + "linear": { + "base": 15, + "word": 3 + } + } } } } @@ -134,10 +150,13 @@ "0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", - "activate_at": "0x4d50f8", "pricing": { - "modexp": { - "divisor": 20 + "0x4d50f8": { + "price": { + "modexp": { + "divisor": 20 + } + } } } } @@ -147,11 +166,19 @@ "name": "alt_bn128_add", "pricing": { "0x4d50f8": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "0xd751a5": { "info": "EIP 1108 transition at block 14_111_141 (0xd751a5)", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -161,11 +188,19 @@ "name": "alt_bn128_mul", "pricing": { "0x4d50f8": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "0xd751a5": { "info": "EIP 1108 transition at block 14_111_141 (0xd751a5)", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -175,11 +210,21 @@ "name": "alt_bn128_pairing", "pricing": { "0x4d50f8": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "0xd751a5": { "info": "EIP 1108 transition at block 14_111_141 (0xd751a5)", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } @@ -187,10 +232,13 @@ "0x0000000000000000000000000000000000000009": { "builtin": { "name": "blake2_f", - "activate_at": "0xd751a5", "pricing": { - "blake2_f": { - "gas_per_round": 1 + "0xd751a5": { + "price": { + "blake2_f": { + "gas_per_round": 1 + } + } } } } @@ -200,13 +248,9 @@ } }, "nodes": [ - "enode://f6e37b943bad3a78cb8589b1798d30d210ffd39cfcd2c8f2de4f098467fd49c667980100d919da7ca46cd50505d30989abda87f0b9339377de13d6592c22caf8@34.198.49.72:30303", "enode://16898006ba2cd4fa8bf9a3dfe32684c178fa861df144bfc21fe800dc4838a03e342056951fa9fd533dcb0be1219e306106442ff2cf1f7e9f8faa5f2fc1a3aa45@116.203.116.241:30303", "enode://2909846f78c37510cc0e306f185323b83bb2209e5ff4fdd279d93c60e3f365e3c6e62ad1d2133ff11f9fd6d23ad9c3dad73bb974d53a22f7d1ac5b7dea79d0b0@3.217.96.11:30303", - "enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303", - "enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303", - "enode://38e6e7fd416293ed120d567a2675fe078c0205ab0671abf16982ce969823bd1f3443d590c18b321dfae7dcbe1f6ba98ef8702f255c3c9822a188abb82c53adca@51.77.66.187:30303", - "enode://6f289111f7c77c68651b0f4803c3a47bcec801f9c618bb41231a1a24a6dbb9c76f2fdb63ba7a21357c41ebb7f6922c17397c1b5c8f71f7d3ef7965505d4945de@144.217.72.209:30303", - "enode://b6340eb94c3db1362ee517801389fe21cce6354275376b1006f8ce84f8a5cfa2b836268b3727be9db7cd3e581f356f39da39418c4ec1d63d959abc235d99cd86@145.239.7.213:30303" + "enode://740e1c8ea64e71762c71a463a04e2046070a0c9394fcab5891d41301dc473c0cff00ebab5a9bc87fbcb610ab98ac18225ff897bc8b7b38def5975d5ceb0a7d7c@108.61.170.124:30303", + "enode://2909846f78c37510cc0e306f185323b83bb2209e5ff4fdd279d93c60e3f365e3c6e62ad1d2133ff11f9fd6d23ad9c3dad73bb974d53a22f7d1ac5b7dea79d0b0@157.230.31.163:30303" ] } diff --git a/crates/ethcore/res/chainspec/poacore.json b/crates/ethcore/res/chainspec/poacore.json index ecdd04c51f..83591aee42 100644 --- a/crates/ethcore/res/chainspec/poacore.json +++ b/crates/ethcore/res/chainspec/poacore.json @@ -22,7 +22,10 @@ } }, "blockRewardContractAddress": "0x4d0153D434384128D17243409e02fca1B3EE21D6", - "blockRewardContractTransition": 5761140 + "blockRewardContractTransition": 5761140, + "randomnessContractAddress": { + "14350721": "0x67e90a54AeEA85f21949c645082FE95d77BC1E70" + } } } }, @@ -55,12 +58,12 @@ "gasLimit": "0x663BE0" }, "nodes": [ + "enode://b39c9c438c533ff7aed6aaefb1c116a350ee3acc3f37c2d6cb85d2a949296238174fe1cb9a04d6a1204b38ca12f63fe4827eaa860fd889a898735fbaba4cca58@178.128.175.244:30303", + "enode://24f3bf1307b8e9cd53abaaa339db5653aa3db64d579f7f37788b8a9b938420cc10004dc9af4edbb0f0611a57b741a4912dd081917b3d373e4409d788c422e7e6@134.209.22.144:30303", + "enode://b39c9c438c533ff7aed6aaefb1c116a350ee3acc3f37c2d6cb85d2a949296238174fe1cb9a04d6a1204b38ca12f63fe4827eaa860fd889a898735fbaba4cca58@142.93.3.70:30303", "enode://6e3d1b39cbd2a9c4f053a27e68fd90d0bac83691dfdc4a13c59f2555078a71e63c5daaee5a82aa6db500512760a5456f86076bf8bbe8011c27c82ed7d6f5fb26@45.77.140.210:30303", "enode://31dffed97f8fed1f34fe66453280a89cbeeda60cf28f6fbb212ebbefd7c7566a02c1c7d5c00bbbb49b9fa8a49f157e0f786f379ca9bcbf2fea24de70d70a22b6@206.156.242.61:30303", - "enode://6bdc7553ab2e4914cb47774c1e6d8c8f47ac7c3981891f85f65d06f208ea1bc4d3bf982b330950e0a0cd127efd7145c4df7113159a1d4a06ed722e6c16d0ac6c@45.32.215.190:30303", - "enode://872d82a24144bc007658fb6fac0dcdfb9b63aeb05ef563a06d0186f2d1e5ffbfc5c4f1244891a8a86ef70682b9d24382e654b305224883698862e2df647a4d23@45.76.236.247:30303", - "enode://b11fbc6cde81c80be69508aca8ffea8460680a25a9c151b683293f8617282062b8e8e139bf91e88cedf60068a3cf927b0d48832fda5169b58a8f7ce442de6fb4@206.189.76.132:30303", - "enode://96678da10ac83769ab3f63114a41b57b700476c5ac02719b878fa89909a936551bb7609aa09b068bf89903206fa03f23e1b5b9117ca278de304c2570b87dcb27@35.175.15.164:30303" + "enode://b39c9c438c533ff7aed6aaefb1c116a350ee3acc3f37c2d6cb85d2a949296238174fe1cb9a04d6a1204b38ca12f63fe4827eaa860fd889a898735fbaba4cca58@178.128.175.244:30303" ], "accounts": { "0x0000000000000000000000000000000000000005": { @@ -82,11 +85,19 @@ "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "12598600": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -96,11 +107,19 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "12598600": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -110,11 +129,21 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "12598600": { "info": "EIP 1108 transition", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } diff --git a/crates/ethcore/res/chainspec/poasokol.json b/crates/ethcore/res/chainspec/poasokol.json index 31fb85c49c..5629aaf993 100644 --- a/crates/ethcore/res/chainspec/poasokol.json +++ b/crates/ethcore/res/chainspec/poasokol.json @@ -25,7 +25,10 @@ } }, "blockRewardContractAddress": "0x3145197AD50D7083D0222DE4fCCf67d9BD05C30D", - "blockRewardContractTransition": 4639000 + "blockRewardContractTransition": 4639000, + "randomnessContractAddress": { + "13391641": "0x8f2b78169B0970F11a762e56659Db52B59CBCf1B" + } } } }, @@ -60,14 +63,10 @@ "gasLimit": "0x663BE0" }, "nodes": [ - "enode://bdcd6f875583df2bd8094f08ae58c7c2db6ed67795ca8c0e6415a30721d3657291aec9b933d15e17e0b36ad7a76424a1447ddbfc75809a04f7a0ffef5617dd56@3.91.206.172:30303", - "enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303", + "enode://f11a0f80939b49a28bf99581da9b351a592ec1504b9d32a7dfda79b36510a891e96631239c4166e5c73368c21e9bb3241e7fd6929b899772e5a8fe9a7b7c3af6@45.77.52.149:30303", + "enode://e08adce358fc26dfbe1f24ee578dceaa29575ca44a39d9041203131db5135aceba6241840a9b57b1540eeaf7b4eff1aead28a74641be43342c35af454abb31b3@199.247.18.10:30313", "enode://f1a5100a81cb73163ae450c584d06b1f644aa4fad4486c6aeb4c384b343c54bb66c744aa5f133af66ea1b25f0f4a454f04878f3e96ee4cd2390c047396d6357b@209.97.158.4:30303", - "enode://0d1e0372f63a3f0b82d66635ea101ecc0f6797788a078805cc933dd93e6a22f7c9fa51ab4e2d21da02d04480ef19f3bbb9a2b41dd1c262085d295a354bb8b0f9@18.217.47.209:30303", - "enode://875e1bd1b98019a5d6d588c23f68534b75462dd6ecbb3dd058221dbf7aa923f0ab782ab93bb82d42edc9996f7f0816a318bdc761e55c02b95e1169cef66f7edc@159.203.24.35:30303", - "enode://8e0af07c86ec36590bb6368e7ad0c45b6dc658f5fb66ec68889a614affddda5e021bd513bcf4fb2fae4a3bbe08cf0de84f037cd58478a89665dfce1ded2595c7@34.236.37.74:30303", - "enode://182ee200ca134dc4d6390f3d5aadbcd80df0f7f24335830335d142573eacce4eeb919d30e82c5df588034e167e6ba6dd11187502ac9264a71005127f6b146a99@159.203.95.241:30303", - "enode://b022ff70b5fcaf9596ae5efed99a8198b4ae0578ee9d17b733609d803a75cef95d3a2a18e50dca9a7c3b26139f158c59eaf8b5fb8d1d331c9a46934a78acabe8@206.189.76.128:30303" + "enode://f11a0f80939b49a28bf99581da9b351a592ec1504b9d32a7dfda79b36510a891e96631239c4166e5c73368c21e9bb3241e7fd6929b899772e5a8fe9a7b7c3af6@45.77.52.149:30303" ], "accounts": { "0000000000000000000000000000000000000005": { @@ -89,11 +88,19 @@ "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "12095200": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -103,11 +110,19 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "12095200": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -117,11 +132,21 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "12095200": { "info": "EIP 1108 transition", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } diff --git a/crates/ethcore/res/chainspec/test/authority_round_randomness_contract.json b/crates/ethcore/res/chainspec/test/authority_round_randomness_contract.json new file mode 100644 index 0000000000..2c820ee771 --- /dev/null +++ b/crates/ethcore/res/chainspec/test/authority_round_randomness_contract.json @@ -0,0 +1,100 @@ +{ + "name": "TestAuthorityRoundRandomnessContract", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "list": [ + "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e" + ] + }, + "immediateTransitions": true, + "maximumEmptySteps": "2", + "randomnessContractAddress": { + "0": "0x0000000000000000000000000000000000000042" + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" + }, + "accounts": { + "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "100000000000" }, + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { + "balance": "1", + "builtin": { + "name": "alt_bn128_add", + "pricing": { + "0x0": { + "price": { "linear": { "base": 500, "word": 0 }} + }, + "0x7fffffffffffff": { + "price": { "linear": { "base": 150, "word": 0 }} + } + } + } + }, + "0000000000000000000000000000000000000007": { + "balance": "1", + "builtin": { + "name": "alt_bn128_mul", + "pricing": { + "0x0": { + "price": { "linear": { "base": 40000, "word": 0 }} + }, + "0x7fffffffffffff": { + "price": { "linear": { "base": 6000, "word": 0 }} + } + } + } + }, + "0000000000000000000000000000000000000008": { + "balance": "1", + "builtin": { + "name": "alt_bn128_pairing", + "pricing": { + "0x0": { + "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + }, + "0x7fffffffffffff": { + "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + } + } + } + }, + "0000000000000000000000000000000000000042": { + "balance": "1", + "constructor": "608060405234801561001057600080fd5b50610820806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ec576000357c01000000000000000000000000000000000000000000000000000000009004806363f160e6116100a95780637a3e286b116100835780637a3e286b14610378578063baf11cab14610380578063c358ced0146103ac578063fe7d567d146103b4576100ec565b806363f160e614610285578063695e89f6146102c557806374ce906714610370576100ec565b806304fdb016146100f15780630b61ba8514610192578063209652551461020b5780632e8a8dd5146102255780633fa4f245146102515780635580e58b14610259575b600080fd5b61011d6004803603604081101561010757600080fd5b5080359060200135600160a060020a03166103d1565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015757818101518382015260200161013f565b50505050905090810190601f1680156101845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610209600480360360408110156101a857600080fd5b813591908101906040810160208201356401000000008111156101ca57600080fd5b8201836020820111156101dc57600080fd5b803590602001918460018302840111640100000000831117156101fe57600080fd5b509092509050610475565b005b6102136104fa565b60408051918252519081900360200190f35b6102136004803603604081101561023b57600080fd5b5080359060200135600160a060020a0316610501565b61021361051b565b6102136004803603604081101561026f57600080fd5b5080359060200135600160a060020a0316610521565b6102b16004803603604081101561029b57600080fd5b5080359060200135600160a060020a031661053e565b604080519115158252519081900360200190f35b6102f1600480360360408110156102db57600080fd5b5080359060200135600160a060020a0316610568565b6040518083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561033457818101518382015260200161031c565b50505050905090810190601f1680156103615780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b6102b1610639565b610213610649565b6102b16004803603604081101561039657600080fd5b5080359060200135600160a060020a0316610654565b6102b161067c565b610209600480360360208110156103ca57600080fd5b5035610687565b600160208181526000938452604080852082529284529282902080548351600293821615610100026000190190911692909204601f8101859004850283018501909352828252909290919083018282801561046d5780601f106104425761010080835404028352916020019161046d565b820191906000526020600020905b81548152906001019060200180831161045057829003601f168201915b505050505081565b41331461048157600080fd5b61048d60014303610735565b61049657600080fd5b60006104a460014303610740565b90506104b08133610654565b156104ba57600080fd5b600081815260208181526040808320338085529083528184208890558484526001835281842090845290915290206104f3908484610753565b5050505050565b6003545b90565b600060208181529281526040808220909352908152205481565b60035481565b600260209081526000928352604080842090915290825290205481565b6000918252600260209081526040808420600160a060020a03939093168452919052902054151590565b600082815260208181526040808320600160a060020a03851680855290835281842054868552600180855283862092865291845282852080548451600294821615610100026000190190911693909304601f810186900486028401860190945283835260609491939092918391908301828280156106275780601f106105fc57610100808354040283529160200191610627565b820191906000526020600020905b81548152906001019060200180831161060a57829003601f168201915b50505050509050915091509250929050565b600061064443610735565b905090565b600061064443610740565b600091825260208281526040808420600160a060020a03939093168452919052902054151590565b600061064443610747565b41331461069357600080fd5b61069f60014303610747565b6106a857600080fd5b60006106b660014303610740565b90506106c2813361053e565b156106cc57600080fd5b60408051602080820185905282518083038201815291830183528151918101919091206000848152808352838120338252909252919020541461070e57600080fd5b60009081526002602090815260408083203384529091529020819055600380549091189055565b600360069091061090565b6006900490565b60036006909106101590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106107945782800160ff198235161785556107c1565b828001600101855582156107c1579182015b828111156107c15782358255916020019190600101906107a6565b506107cd9291506107d1565b5090565b6104fe91905b808211156107cd57600081556001016107d756fea265627a7a7230582008bb7311af9026bd70ddb998741333d414a366275b9b433a2943bbd6bedc27ae64736f6c634300050a0032" + } + } +} \ No newline at end of file diff --git a/crates/ethcore/res/chainspec/test/contract_ver_3.sol b/crates/ethcore/res/chainspec/test/contract_ver_3.sol new file mode 100644 index 0000000000..dd28c8e330 --- /dev/null +++ b/crates/ethcore/res/chainspec/test/contract_ver_3.sol @@ -0,0 +1,60 @@ +pragma solidity ^0.4.20; + +// Adapted from https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f +// and: https://github.com/poanetwork/posdao-contracts/blob/master/contracts/TxPermission.sol + +contract TxPermission { + /// Allowed transaction types mask + uint32 constant None = 0; + uint32 constant All = 0xffffffff; + uint32 constant Basic = 0x01; + uint32 constant Call = 0x02; + uint32 constant Create = 0x04; + uint32 constant Private = 0x08; + + /// Contract name + function contractName() public constant returns (string) { + return "TX_PERMISSION_CONTRACT"; + } + + /// Contract name hash + function contractNameHash() public constant returns (bytes32) { + return keccak256(contractName()); + } + + /// Contract version + function contractVersion() public constant returns (uint256) { + return 3; + } + + /// @dev Defines the allowed transaction types which may be initiated by the specified sender with + /// the specified gas price and data. Used by the Parity engine each time a transaction is about to be + /// included into a block. See https://wiki.parity.io/Permissioning.html#how-it-works-1 + /// @param _sender Transaction sender address. + /// @param _to Transaction recipient address. If creating a contract, the `_to` address is zero. + /// @param _value Transaction amount in wei. + /// @param _gasPrice Gas price in wei for the transaction. + /// @param _data Transaction data. + /// @return `uint32 typesMask` - Set of allowed transactions for `_sender` depending on tx `_to` address, + /// `_gasPrice`, and `_data`. The result is represented as a set of flags: + /// 0x01 - basic transaction (e.g. ether transferring to user wallet); + /// 0x02 - contract call; + /// 0x04 - contract creation; + /// 0x08 - private transaction. + /// `bool cache` - If `true` is returned, the same permissions will be applied from the same + /// `_sender` without calling this contract again. + function allowedTxTypes( + address _sender, + address _to, + uint256 _value, + uint256 _gasPrice, + bytes memory _data + ) + public + view + returns(uint32 typesMask, bool cache) + { + if (_gasPrice > 0 || _data.length < 4) return (All, false); + return (None, false); + } +} \ No newline at end of file diff --git a/crates/ethcore/res/chainspec/test/contract_ver_3_genesis.json b/crates/ethcore/res/chainspec/test/contract_ver_3_genesis.json new file mode 100644 index 0000000000..28c44d8de5 --- /dev/null +++ b/crates/ethcore/res/chainspec/test/contract_ver_3_genesis.json @@ -0,0 +1,44 @@ +{ + "name": "TestNodeFilterContract", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "contract": "0x0000000000000000000000000000000000000000" + } + } + } + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69", + "gasLimitBoundDivisor": "0x0400", + "transactionPermissionContract": "0x0000000000000000000000000000000000000005", + "transactionPermissionContractTransition": "1" + }, + "genesis": { + "seal": { + "generic": "0xc180" + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { + "balance": "1", + "constructor": "6060604052341561000f57600080fd5b61035e8061001e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063469ab1e31461006757806375d0c0dc14610098578063a0a8e46014610126578063b9056afa1461014f575b600080fd5b341561007257600080fd5b61007a610227565b60405180826000191660001916815260200191505060405180910390f35b34156100a357600080fd5b6100ab610298565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100eb5780820151818401526020810190506100d0565b50505050905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013157600080fd5b6101396102db565b6040518082815260200191505060405180910390f35b341561015a57600080fd5b6101fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506102e4565b604051808363ffffffff1663ffffffff168152602001821515151581526020019250505060405180910390f35b6000610231610298565b6040518082805190602001908083835b6020831015156102665780518252602082019150602081019050602083039250610241565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905090565b6102a061031e565b6040805190810160405280601681526020017f54585f5045524d495353494f4e5f434f4e545241435400000000000000000000815250905090565b60006003905090565b60008060008411806102f7575060048351105b1561030c5763ffffffff600091509150610314565b600080915091505b9550959350505050565b6020604051908101604052806000815250905600a165627a7a72305820be61565bc09fec6e9223a1fecd2e94783ca5c6f506c03f71d479a8c3285493310029" + } + } +} \ No newline at end of file diff --git a/crates/ethcore/res/chainspec/test/validator_contract.json b/crates/ethcore/res/chainspec/test/validator_contract.json index 9d007ac23e..841fd22490 100644 --- a/crates/ethcore/res/chainspec/test/validator_contract.json +++ b/crates/ethcore/res/chainspec/test/validator_contract.json @@ -37,7 +37,7 @@ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", - "constructor": "60a06040819052737d577a597b2742b498cb5cf0c26cdcd726d39e6e60609081527382a978b3f5962a5b0957d9ee9eef472ee55b42f1608052600080546002825581805290927f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639182019291905b828111156100a25782518254600160a060020a031916600160a060020a0390911617825560209092019160019091019061006d565b5b506100cd9291505b808211156100c9578054600160a060020a03191681556001016100ab565b5090565b505034610000575b60005b60005481101561012f578060016000600084815481101561000057906000526020600020900160005b9054600160a060020a036101009290920a90041681526020810191909152604001600020555b6001016100d8565b5b505b610453806101416000396000f3006060604052361561005c5763ffffffff60e060020a60003504166335aa2e4481146100615780634d238c8e1461008d578063b7ab4db5146100a8578063c476dd4014610110578063d69f13bb14610172578063d8f2e0bf14610190575b610000565b34610000576100716004356101b9565b60408051600160a060020a039092168252519081900360200190f35b34610000576100a6600160a060020a03600435166101e9565b005b34610000576100b5610260565b60408051602080825283518183015283519192839290830191858101910280838382156100fd575b8051825260208311156100fd57601f1990920191602091820191016100dd565b5050509050019250505060405180910390f35b3461000057604080516020600460443581810135601f81018490048402850184019095528484526100a6948235600160a060020a03169460248035956064949293919092019181908401838280828437509496506102ca95505050505050565b005b34610000576100a6600160a060020a03600435166024356103eb565b005b3461000057610071610418565b60408051600160a060020a039092168252519081900360200190f35b600081815481101561000057906000526020600020900160005b915054906101000a9004600160a060020a031681565b6000805480600101828181548183558181151161022b5760008381526020902061022b9181019083015b808211156102275760008155600101610213565b5090565b5b505050916000526020600020900160005b8154600160a060020a038086166101009390930a92830292021916179055505b50565b60408051602081810183526000808352805484518184028101840190955280855292939290918301828280156102bf57602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116102a1575b505050505090505b90565b6000805460001981019081101561000057906000526020600020900160005b9054906101000a9004600160a060020a031660006001600086600160a060020a0316600160a060020a0316815260200190815260200160002054815481101561000057906000526020600020900160005b8154600160a060020a039384166101009290920a918202918402191617905583166000908152600160205260408120819055805460001981019081101561000057906000526020600020900160005b6101000a815490600160a060020a03021916905560008054809190600190038154818355818115116103e0576000838152602090206103e09181019083015b808211156102275760008155600101610213565b5090565b5b505050505b505050565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0384161790555b5050565b600254600160a060020a0316815600a165627a7a72305820f7876e17abd5f0927fff16788b4b3c9028ed64e6db740d788b07fc5f0a8f10920029" + "constructor": "60c0604052737d577a597b2742b498cb5cf0c26cdcd726d39e6e60809081527382a978b3f5962a5b0957d9ee9eef472ee55b42f160a05261004390600290816100a3565b5034801561005057600080fd5b5060005b60025481101561009d5780600560006002848154811061007057fe5b6000918252602080832090910154600160a060020a03168352820192909252604001902055600101610054565b5061012f565b8280548282559060005260206000209081019282156100f8579160200282015b828111156100f85782518254600160a060020a031916600160a060020a039091161782556020909201916001909101906100c3565b50610104929150610108565b5090565b61012c91905b80821115610104578054600160a060020a031916815560010161010e565b90565b6108e28061013e6000396000f3fe608060405234801561001057600080fd5b50600436106100d1576000357c010000000000000000000000000000000000000000000000000000000090048063b56b366b1161008e578063b56b366b14610206578063b7ab4db514610282578063c476dd401461028a578063cbd2d5281461030f578063d69f13bb14610345578063d8f2e0bf14610371576100d1565b806335aa2e44146100d65780633d3b54581461010f578063752862111461012b5780639300c9261461013557806393b4e25e146101d8578063a92252ae146101e0575b600080fd5b6100f3600480360360208110156100ec57600080fd5b5035610379565b60408051600160a060020a039092168252519081900360200190f35b6101176103a0565b604080519115158252519081900360200190f35b6101336103a7565b005b6101336004803603602081101561014b57600080fd5b81019060208101813564010000000081111561016657600080fd5b82018360208201111561017857600080fd5b8035906020019184602083028401116401000000008311171561019a57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506103a9945050505050565b6101336103c8565b610117600480360360208110156101f657600080fd5b5035600160a060020a031661044f565b6102326004803603604081101561021c57600080fd5b50600160a060020a038135169060200135610464565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561026e578181015183820152602001610256565b505050509050019250505060405180910390f35b6102326104e3565b610133600480360360608110156102a057600080fd5b600160a060020a03823516916020810135918101906060810160408201356401000000008111156102d057600080fd5b8201836020820111156102e257600080fd5b8035906020019184600183028401116401000000008311171561030457600080fd5b509092509050610545565b6101176004803603606081101561032557600080fd5b50600160a060020a038135811691602081013590911690604001356106eb565b6101336004803603604081101561035b57600080fd5b50600160a060020a038135169060200135610788565b6100f36107b8565b6002818154811061038657fe5b600091825260209091200154600160a060020a0316905081565b4315155b90565b565b80516103bc9060029060208401906107c7565b506103c56103c8565b50565b60014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c8960026040518080602001828103825283818154815260200191508054801561043f57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610421575b50509250505060405180910390a2565b60016020526000908152604090205460ff1681565b600160a060020a03821660009081526003602090815260408083208484528252918290208054835181840281018401909452808452606093928301828280156104d657602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116104b8575b5050505050905092915050565b6060600280548060200260200160405190810160405280929190818152602001828054801561053b57602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831161051d575b5050505050905090565b600160a060020a0384166000818152600360209081526040808320878452825280832080546001818101835591855283852001805473ffffffffffffffffffffffffffffffffffffffff1916339081179091558585526004845282852089865284528285208186528452828520805460ff19908116841790915586865282855283862080549091169092179091556005909252909120546002805492939290919081106105ee57fe5b600091825260209091200154600160a060020a031614156106e45760028054600019810190811061061b57fe5b6000918252602080832090910154600160a060020a038881168452600590925260409092205460028054929093169291811061065357fe5b6000918252602080832091909101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039485161790559187168152600590915260408120556002805460001981019081106106a957fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916905560028054906106e2906000198301610839565b505b5050505050565b60004380831115610700576000915050610781565b60648111801561071257508260648203115b15610721576000915050610781565b600160a060020a03841660009081526001602052604090205460ff161561074c576000915050610781565b5050600160a060020a03808316600090815260046020908152604080832085845282528083209387168352929052205460ff16155b9392505050565b506000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600054600160a060020a031681565b828054828255906000526020600020908101928215610829579160200282015b82811115610829578251825473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039091161782556020909201916001909101906107e7565b50610835929150610862565b5090565b81548183558181111561085d5760008381526020902061085d918101908301610893565b505050565b6103a491905b8082111561083557805473ffffffffffffffffffffffffffffffffffffffff19168155600101610868565b6103a491905b80821115610835576000815560010161089956fea265627a7a7231582073e77a97d79ab4382d5a28644654c335489310e72aa6c8f737e424bdb6c2bbd664736f6c63430005100032" }, "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } diff --git a/crates/ethcore/res/chainspec/test/validator_contract.sol b/crates/ethcore/res/chainspec/test/validator_contract.sol new file mode 100644 index 0000000000..568c8dd363 --- /dev/null +++ b/crates/ethcore/res/chainspec/test/validator_contract.sol @@ -0,0 +1,119 @@ +// Source for the test AuRa validator set contract. DO NOT USE IN PRODUCTION. +// +// Contains POSDAO features. The full POSDAO ValidatorSet contract production code is available at +// https://github.com/poanetwork/posdao-contracts/blob/master/contracts/ValidatorSetAuRa.sol +// +// The bytecode of this contract is included in `validator_contract.json` as the +// constructor of address `0x0000..0005`. + +pragma solidity ^0.5.0; + +contract TestValidatorSet { + + address public disliked; // contains the address of validator reported by `reportBenign` + mapping(address => bool) public isValidatorBanned; // if the validator is banned by `reportMalicious` + + // The initial set of validators + address[] public validators = [ + 0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e, + 0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1 + ]; + + // The mappings used by POSDAO features testing (see `reportMalicious` and `shouldValidatorReport` functions below) + mapping(address => mapping(uint256 => address[])) private _maliceReportedForBlock; + mapping(address => mapping(uint256 => mapping(address => bool))) private _maliceReportedForBlockMapped; + mapping(address => uint256) private _validatorIndex; + + // The standard event to notify the engine about the validator set changing in the contract + event InitiateChange(bytes32 indexed parentHash, address[] newSet); + + constructor() public { + // Initialize validator indices to be able to correctly remove + // a malicious validator from the validator set later + for (uint i = 0; i < validators.length; i++) { + _validatorIndex[validators[i]] = i; + } + } + + // Emits an `InitiateChange` event with the current (or new) validator set + function emitInitiateChange() public { + emit InitiateChange(blockhash(block.number - 1), validators); + } + + // Applies a validator set change in production code. Does nothing in the test + function finalizeChange() pure public {} + + // Benign validator behaviour report. Kept here for regression testing + function reportBenign(address _validator, uint256) public { + disliked = _validator; + } + + // Removes a malicious validator from the list + function reportMalicious(address _validator, uint256 _blockNum, bytes calldata) external { + address reportingValidator = msg.sender; + + // Mark the `_validator` as reported by `reportingValidator` for the block `_blockNum` + _maliceReportedForBlock[_validator][_blockNum].push(reportingValidator); + _maliceReportedForBlockMapped[_validator][_blockNum][reportingValidator] = true; + isValidatorBanned[_validator] = true; + + // If the passed validator is in the validator set + if (validators[_validatorIndex[_validator]] == _validator) { + // Remove the validator from the set + validators[_validatorIndex[_validator]] = validators[validators.length - 1]; + delete _validatorIndex[_validator]; + delete validators[validators.length - 1]; + validators.length--; + } + } + + // Tests validator set changing and emitting the `InitiateChange` event + function setValidators(address[] memory _validators) public { + validators = _validators; + emitInitiateChange(); + } + + // Checks if `emitInitiateChange` can be called (used by POSDAO tests) + function emitInitiateChangeCallable() view public returns(bool) { + return block.number > 0; + } + + // Returns the current validator set + function getValidators() public view returns(address[] memory) { + return validators; + } + + // Returns the list of all validators that reported the given validator + // as malicious for the given block. Used by POSDAO tests + function maliceReportedForBlock(address _validator, uint256 _blockNum) public view returns(address[] memory) { + return _maliceReportedForBlock[_validator][_blockNum]; + } + + // Returns a boolean flag indicating whether the specified validator + // should report about some validator's misbehaviour at the specified block. + // Used by POSDAO tests. + // `_reportingValidator` is the address of validator who reports. + // `_maliciousValidator` is the address of malicious validator. + // `_blockNumber` is the block number at which the malicious validator misbehaved. + function shouldValidatorReport( + address _reportingValidator, + address _maliciousValidator, + uint256 _blockNumber + ) public view returns(bool) { + uint256 currentBlock = block.number; + if (_blockNumber > currentBlock) { + return false; + } + if (currentBlock > 100 && currentBlock - 100 > _blockNumber) { + return false; + } + if (isValidatorBanned[_maliciousValidator]) { + // We shouldn't report the malicious validator + // as it has already been reported and banned + return false; + } + // Return `false` if already reported by the same `_reportingValidator` for the same `_blockNumber` + return !_maliceReportedForBlockMapped[_maliciousValidator][_blockNumber][_reportingValidator]; + } + +} \ No newline at end of file diff --git a/crates/ethcore/res/chainspec/xdai.json b/crates/ethcore/res/chainspec/xdai.json index cecc79171a..2bb2d24804 100644 --- a/crates/ethcore/res/chainspec/xdai.json +++ b/crates/ethcore/res/chainspec/xdai.json @@ -11,15 +11,27 @@ "validators": { "multi": { "0": { - "list": ["0xcace5b3c29211740e595850e80478416ee77ca21"] + "list": [ + "0xcace5b3c29211740e595850e80478416ee77ca21" + ] }, "1300": { "safeContract": "0x22e1229a2c5b95a60983b5577f745a603284f535" + }, + "9186425": { + "contract": "0xB87BE9f7196F2AE084Ca1DE6af5264292976e013" } } }, "blockRewardContractAddress": "0x867305d19606aadba405ce534e303d0e225f9556", - "blockRewardContractTransition": 1310 + "blockRewardContractTransition": 1310, + "blockRewardContractTransitions": { + "9186425": "0x481c034c6d9441db23Ea48De68BCAe812C5d39bA" + }, + "randomnessContractAddress": { + "9186425": "0x5870b0527DeDB1cFBD9534343Feda1a41Ce47766" + }, + "posdaoTransition": 9186425 } } }, @@ -42,7 +54,9 @@ "eip1706Transition": 7298030, "eip1884Transition": 7298030, "eip2028Transition": 7298030, - "registrar": "0x1ec97dc137f5168af053c24460a1200502e1a9d2" + "registrar": "0x6B53721D4f2Fb9514B85f5C49b197D857e36Cf03", + "transactionPermissionContract": "0x7Dd7032AA75A37ea0b150f57F899119C7379A78b", + "transactionPermissionContractTransition": 9186425 }, "genesis": { "seal": { @@ -54,6 +68,25 @@ "difficulty": "0x20000", "gasLimit": "0x989680" }, + "nodes": [ + "enode://4716883567b5317aad93ea28e707fad0631fb4aa5ac7c5fbd485380b01d8801c21a8cbf4d6ee3a2c9b2b070a270a49d4a2a0da9e1d47a1f433dafbaf7b2edd06@157.245.92.222:30303", + "enode://ab7f6c633ba2dc54795dfd2c739ba7d964f499541c0b8d8ba9d275bd3df1b789470a21a921a469fa515a3dfccc96a434a3fd016a169d88d0043fc6744f34288e@67.205.180.17:30303", + "enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@67.205.145.143:30303", + "enode://bd75111424c42c349fc255db017ac0be370b37b558627e3bbc41319071ef7642c04cdbd2b674193a99aa35d67a83016ab293b8ab87ed4a4606e69f114ac95535@157.230.185.80:30303", + "enode://bd75111424c42c349fc255db017ac0be370b37b558627e3bbc41319071ef7642c04cdbd2b674193a99aa35d67a83016ab293b8ab87ed4a4606e69f114ac95535@161.35.51.60:30303", + "enode://ef94ffb10c440dd990c5c4be1c85046f5f7329ba60d23db7a68c8b91b6a721081f8190369f3a32f3c02d213127b2066eb42ee0444998d354ba0923378522acb3@161.35.62.72:30303", + "enode://4a0eadf22d6a37c5596fd2df2a53a26a5b59dd863e67246ab94e6a81b31765e08d9f70a4dd9683221e63cc2120c8a808a6a457455bd658bdf49c688c62db2011@51.81.244.170:30303", + "enode://e75a1e9f080bd6012b39321c0f2d984567172625280b3e7362e962a42578c5e79c847b3eb83aa7e2a4cdeefbfadf0c36ed2719cad1d5e6377ccd6ebe314cc6bc@64.227.97.130:30303", + "enode://6674773f7aac78d5527fa90c847dcbca198de4081306406a8fec5c15f7a2e141362344041291dd10d0aafa7706a3d8f21a08b6f6834a5b1aab9cccd8ca35ccee@143.110.226.15:30303", + "enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@134.122.24.231:30303", + "enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@67.205.145.143:30303", + "enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@162.243.164.98:30303", + "enode://0caa2d84aef00d0bc5de6cf9db3e736da245d882ec8f91e201b3e1635960e62cbb2f8bfc57e679ff3e1d53da2773e31df624a56b2f457ecb51d09fdf9970c86b@167.99.4.175:30303", + "enode://da2449aaba873c40c6daf764de55f4b9eae24c4738daec893ef95b6ada96463c6b9624f8e376e1073d21dd820c5bb361e14575121b09bbd7735b6b556ee1b768@67.205.176.117:30303", + "enode://e8c7a0db430429bb374c981438c0dbd95e565088a483388aa46d8377a3bd62f02cd83d7e2c7e5fc77606141bfef29d23d4285a7c1d9b7e743cf3029314506df7@80.240.16.221:30303", + "enode://2cde5ae04ed57bba5bac8311a97be056838d5304bc3bcee698066e5fc532e846f785198f87e8b84b57b03622a22aac5dd2853c5203d1ece2c9f25b48487d145b@149.28.57.8:30303", + "enode://90b0a0e74a9a1ad258531b4ceec25587d8b52ff2cfb36206a34bf6ba1a8d21b2abd20da13260102508a2ac67afbeb2d2ab7a5e9d6bea3bce845cd81e655585cc@45.77.110.159:30303" + ], "accounts": { "0x0000000000000000000000000000000000000005": { "builtin": { @@ -74,11 +107,19 @@ "name": "alt_bn128_add", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 500 }} + "price": { + "alt_bn128_const_operations": { + "price": 500 + } + } }, "7298030": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 150 }} + "price": { + "alt_bn128_const_operations": { + "price": 150 + } + } } } } @@ -88,11 +129,19 @@ "name": "alt_bn128_mul", "pricing": { "0": { - "price": { "alt_bn128_const_operations": { "price": 40000 }} + "price": { + "alt_bn128_const_operations": { + "price": 40000 + } + } }, "7298030": { "info": "EIP 1108 transition", - "price": { "alt_bn128_const_operations": { "price": 6000 }} + "price": { + "alt_bn128_const_operations": { + "price": 6000 + } + } } } } @@ -102,11 +151,21 @@ "name": "alt_bn128_pairing", "pricing": { "0": { - "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} + "price": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000 + } + } }, "7298030": { "info": "EIP 1108 transition", - "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} + "price": { + "alt_bn128_pairing": { + "base": 45000, + "pair": 34000 + } + } } } } @@ -190,10 +249,6 @@ } } } - }, - "nodes": [ - "enode://1c19ba0a77dd663b843c33beb9020e7eb41fc34b47b98424dbc427f74692115d74c7c27b6c0aa2b59bb1d8f710650cae1090153d10b6909ca7bdcdfb183b1c59@54.39.190.172:30303", - "enode://c1c3a604950119f82d78189792b73f5a82a239017c77465e3c32fc51c1d758a9a772ffddd58436d465342f2cfa6d4a442a49e526743f4d8354d7c5ce794c3ee5@95.179.222.48:30303" - ] + } } diff --git a/crates/ethcore/res/contracts/authority_round_random.json b/crates/ethcore/res/contracts/authority_round_random.json new file mode 100644 index 0000000000..5b41014a57 --- /dev/null +++ b/crates/ethcore/res/contracts/authority_round_random.json @@ -0,0 +1,133 @@ +[{ + "constant": false, + "inputs": [{ + "name": "_secretHash", + "type": "bytes32" + }, + { + "name": "_cipher", + "type": "bytes" + } + ], + "name": "commitHash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" +}, +{ + "constant": false, + "inputs": [{ + "name": "_number", + "type": "uint256" + }], + "name": "revealNumber", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" +}, +{ + "constant": true, + "inputs": [], + "name": "currentCollectRound", + "outputs": [{ + "name": "", + "type": "uint256" + }], + "payable": false, + "stateMutability": "view", + "type": "function" +}, +{ + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCommitAndCipher", + "outputs": [ + { + "name": "", + "type": "bytes32" + }, + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" +}, +{ + "constant": true, + "inputs": [{ + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_validator", + "type": "address" + } + ], + "name": "isCommitted", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" +}, +{ + "constant": true, + "inputs": [], + "name": "isCommitPhase", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" +}, +{ + "constant": true, + "inputs": [], + "name": "isRevealPhase", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" +}, +{ + "constant": true, + "inputs": [{ + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_validator", + "type": "address" + } + ], + "name": "sentReveal", + "outputs": [{ + "name": "", + "type": "bool" + }], + "payable": false, + "stateMutability": "view", + "type": "function" +} +] \ No newline at end of file diff --git a/crates/ethcore/res/contracts/block_gas_limit.json b/crates/ethcore/res/contracts/block_gas_limit.json new file mode 100644 index 0000000000..8ca9cf9694 --- /dev/null +++ b/crates/ethcore/res/contracts/block_gas_limit.json @@ -0,0 +1,16 @@ +[ + { + "constant": true, + "inputs": [], + "name": "blockGasLimit", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/crates/ethcore/res/contracts/test_authority_round_random.json b/crates/ethcore/res/contracts/test_authority_round_random.json new file mode 100644 index 0000000000..beab82ab48 --- /dev/null +++ b/crates/ethcore/res/contracts/test_authority_round_random.json @@ -0,0 +1,265 @@ +[ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "ciphers", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCipher", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_secretHash", + "type": "bytes32" + }, + { + "name": "_cipher", + "type": "bytes" + } + ], + "name": "commitHash", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getValue", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "hashes", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "value", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "address" + } + ], + "name": "secrets", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "sentReveal", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isCommitPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_number", + "type": "uint256" + } + ], + "name": "revealNumber", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getRound", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "isCommitted", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isRevealPhase", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_collectRound", + "type": "uint256" + }, + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "getCommit", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/crates/ethcore/res/contracts/test_authority_round_random.sol b/crates/ethcore/res/contracts/test_authority_round_random.sol new file mode 100644 index 0000000000..66c9717863 --- /dev/null +++ b/crates/ethcore/res/contracts/test_authority_round_random.sol @@ -0,0 +1,101 @@ +pragma solidity 0.5.10; + +/// @dev Randomness test contract based on https://github.com/poanetwork/posdao-contracts. +/// Generates and stores random numbers in a RANDAO manner and accumulates a random seed. +contract Random { + mapping(uint256 => mapping(address => bytes32)) public hashes; + mapping(uint256 => mapping(address => bytes)) public ciphers; + mapping(uint256 => mapping(address => uint256)) public secrets; + uint256 public value; + + /// @dev Called by the validator's node to store a hash and a cipher of the validator's secret on each collection + /// round. The validator's node must use its mining address to call this function. + /// This function can only be called once per collection round (during the `commits phase`). + /// @param _secretHash The Keccak-256 hash of the validator's secret. + /// @param _cipher The cipher of the validator's secret. Can be used by the node to decrypt and reveal. + function commitHash(bytes32 _secretHash, bytes calldata _cipher) external { + require(block.coinbase == msg.sender); + require(_isCommitPhase(block.number - 1)); + uint256 round = _collectRound(block.number - 1); + require(!isCommitted(round, msg.sender)); + hashes[round][msg.sender] = _secretHash; + ciphers[round][msg.sender] = _cipher; + } + + /// @dev Called by the validator's node to XOR its secret with the current random seed. + /// The validator's node must use its mining address to call this function. + /// This function can only be called once per collection round (during the `reveals phase`). + /// @param _number The validator's secret. + function revealNumber(uint256 _number) external { + require(block.coinbase == msg.sender); + require(_isRevealPhase(block.number - 1)); + uint256 round = _collectRound(block.number - 1); + require(!sentReveal(round, msg.sender)); + require(hashes[round][msg.sender] == keccak256(abi.encodePacked(_number))); + secrets[round][msg.sender] = _number; + value ^= _number; + } + + /// @dev Returns the Keccak-256 hash and cipher of the validator's secret for the specified collection round + /// and the specified validator stored by the validator through the `commitHash` function. + /// @param _collectRound The serial number of the collection round for which hash and cipher should be retrieved. + /// @param _miningAddress The mining address of validator. + function getCommitAndCipher( + uint256 _collectRound, + address _miningAddress + ) public view returns(bytes32, bytes memory) { + return (hashes[_collectRound][_miningAddress], ciphers[_collectRound][_miningAddress]); + } + + /// @dev Returns a boolean flag indicating whether the specified validator has committed their secret's hash for the + /// specified collection round. + /// @param _collectRound The serial number of the collection round for which the checkup should be done. + /// @param _miningAddress The mining address of the validator. + function isCommitted(uint256 _collectRound, address _miningAddress) public view returns(bool) { + return hashes[_collectRound][_miningAddress] != bytes32(0); + } + + /// @dev Returns a boolean flag indicating whether the current phase of the current collection round + /// is a `commits phase`. Used by the validator's node to determine if it should commit the hash of + /// the secret during the current collection round. + function isCommitPhase() public view returns(bool) { + return _isCommitPhase(block.number); + } + + /// @dev Returns a boolean flag indicating whether the current phase of the current collection round + /// is a `reveals phase`. Used by the validator's node to determine if it should reveal the secret during + /// the current collection round. + function isRevealPhase() public view returns(bool) { + return _isRevealPhase(block.number); + } + + /// @dev Returns a boolean flag of whether the specified validator has revealed their secret for the + /// specified collection round. + /// @param _collectRound The serial number of the collection round for which the checkup should be done. + /// @param _miningAddress The mining address of the validator. + function sentReveal(uint256 _collectRound, address _miningAddress) public view returns(bool) { + return secrets[_collectRound][_miningAddress] != uint256(0); + } + + /// @dev Returns the current collect round number. + function currentCollectRound() public view returns(uint256) { + return _collectRound(block.number); + } + + /// @dev Returns the current random value. + function getValue() public view returns(uint256) { + return value; + } + + function _collectRound(uint256 blockNumber) private pure returns(uint256) { + return blockNumber / 6; + } + + function _isCommitPhase(uint256 blockNumber) private pure returns(bool) { + return blockNumber % 6 < 3; + } + + function _isRevealPhase(uint256 blockNumber) private pure returns(bool) { + return blockNumber % 6 >= 3; + } +} diff --git a/crates/ethcore/res/contracts/tx_acl_gas_price.json b/crates/ethcore/res/contracts/tx_acl_gas_price.json new file mode 100644 index 0000000000..37b08e9f0d --- /dev/null +++ b/crates/ethcore/res/contracts/tx_acl_gas_price.json @@ -0,0 +1,83 @@ +[ + { + "constant": true, + "inputs": [], + "name": "contractNameHash", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractName", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractVersion", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "sender", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "allowedTxTypes", + "outputs": [ + { + "name": "", + "type": "uint32" + }, + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/crates/ethcore/res/contracts/validator_report.json b/crates/ethcore/res/contracts/validator_report.json index 093f4bebdf..e0c0114326 100644 --- a/crates/ethcore/res/contracts/validator_report.json +++ b/crates/ethcore/res/contracts/validator_report.json @@ -1,4 +1,5 @@ [ {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"},{"name":"proof","type":"bytes"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"}, - {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"} + {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"}, + {"constant": true, "inputs": [ { "name": "validator", "type": "address" }, { "name": "blockNum", "type": "uint256" } ], "name": "maliceReportedForBlock", "outputs": [ { "name": "", "type": "address[]" } ], "payable": false, "stateMutability": "view", "type": "function" } ] diff --git a/crates/ethcore/res/contracts/validator_set.json b/crates/ethcore/res/contracts/validator_set.json index d861e16fdb..660e8b614b 100644 --- a/crates/ethcore/res/contracts/validator_set.json +++ b/crates/ethcore/res/contracts/validator_set.json @@ -1,5 +1,55 @@ [ {"constant":false,"inputs":[],"name":"finalizeChange","outputs":[],"payable":false,"type":"function"}, {"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"validators","type":"address[]"}],"payable":false,"type":"function"}, - {"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"} -] + {"anonymous":false,"inputs":[{"indexed":true,"name":"_parent_hash","type":"bytes32"},{"indexed":false,"name":"_new_set","type":"address[]"}],"name":"InitiateChange","type":"event"}, + { + "constant": true, + "inputs": [], + "name": "emitInitiateChangeCallable", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "emitInitiateChange", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_reportingValidator", + "type": "address" + }, + { + "name": "_maliciousValidator", + "type": "address" + }, + { + "name": "_blockNumber", + "type": "uint256" + } + ], + "name": "shouldValidatorReport", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] \ No newline at end of file diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 71966cd9c1..7f707a915b 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -64,17 +64,20 @@ use ansi_term::Colour; use block::{enact_verified, ClosedBlock, Drain, LockedBlock, OpenBlock, SealedBlock}; use call_contract::RegistryInfo; use client::{ - ancient_import::AncientVerifier, bad_blocks, traits::ForceUpdateSealing, AccountData, - BadBlocks, Balance, BlockChain as BlockChainTrait, BlockChainClient, BlockChainReset, BlockId, - BlockInfo, BlockProducer, BroadcastProposalBlock, Call, CallAnalytics, ChainInfo, - ChainMessageType, ChainNotify, ChainRoute, ClientConfig, ClientIoMessage, EngineInfo, - ImportBlock, ImportExportBlocks, ImportSealedBlock, IoClient, Mode, NewBlocks, Nonce, - PrepareOpenBlock, ProvingBlockChainClient, PruningInfo, ReopenBlock, ScheduleInfo, - SealedBlockImporter, StateClient, StateInfo, StateOrBlock, TraceFilter, TraceId, TransactionId, - TransactionInfo, UncleId, + ancient_import::AncientVerifier, + bad_blocks, + traits::{ForceUpdateSealing, TransactionRequest}, + AccountData, BadBlocks, Balance, BlockChain as BlockChainTrait, BlockChainClient, + BlockChainReset, BlockId, BlockInfo, BlockProducer, BroadcastProposalBlock, Call, + CallAnalytics, ChainInfo, ChainMessageType, ChainNotify, ChainRoute, ClientConfig, + ClientIoMessage, EngineInfo, ImportBlock, ImportExportBlocks, ImportSealedBlock, IoClient, + Mode, NewBlocks, Nonce, PrepareOpenBlock, ProvingBlockChainClient, PruningInfo, ReopenBlock, + ScheduleInfo, SealedBlockImporter, StateClient, StateInfo, StateOrBlock, TraceFilter, TraceId, + TransactionId, TransactionInfo, UncleId, }; use engines::{ - epoch::PendingTransition, EngineError, EpochTransition, EthEngine, ForkChoice, MAX_UNCLE_AGE, + epoch::PendingTransition, EngineError, EpochTransition, EthEngine, ForkChoice, SealingState, + MAX_UNCLE_AGE, }; use error::{ BlockError, CallError, Error as EthcoreError, ErrorKind as EthcoreErrorKind, EthcoreResult, @@ -2613,31 +2616,46 @@ impl BlockChainClient for Client { } } - fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> { + fn create_transaction( + &self, + TransactionRequest { + action, + data, + gas, + gas_price, + nonce, + }: TransactionRequest, + ) -> Result { let authoring_params = self.importer.miner.authoring_params(); let service_transaction_checker = self.importer.miner.service_transaction_checker(); let gas_price = if let Some(checker) = service_transaction_checker { match checker.check_address(self, authoring_params.author) { Ok(true) => U256::zero(), - _ => self.importer.miner.sensible_gas_price(), + _ => gas_price.unwrap_or_else(|| self.importer.miner.sensible_gas_price()), } } else { self.importer.miner.sensible_gas_price() }; let transaction = TypedTransaction::Legacy(transaction::Transaction { - nonce: self.latest_nonce(&authoring_params.author), - action: Action::Call(address), - gas: self.importer.miner.sensible_gas_limit(), + nonce: nonce.unwrap_or_else(|| self.latest_nonce(&authoring_params.author)), + action, + gas: gas.unwrap_or_else(|| self.importer.miner.sensible_gas_limit()), gas_price, value: U256::zero(), - data: data, + data, }); let chain_id = self.engine.signing_chain_id(&self.latest_env_info()); let signature = self .engine .sign(transaction.signature_hash(chain_id)) .map_err(|e| transaction::Error::InvalidSignature(e.to_string()))?; - let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; + Ok(SignedTransaction::new( + transaction.with_signature(signature, chain_id), + )?) + } + + fn transact(&self, tx_request: TransactionRequest) -> Result<(), transaction::Error> { + let signed = self.create_transaction(tx_request)?; self.importer .miner .import_own_transaction(self, signed.into()) @@ -2906,7 +2924,7 @@ impl ImportSealedBlock for Client { &[], route.enacted(), route.retracted(), - self.engine.seals_internally().is_some(), + self.engine.sealing_state() != SealingState::External, ); self.notify(|notify| { notify.new_blocks(NewBlocks::new( @@ -3599,8 +3617,13 @@ mod tests { #[test] fn should_mark_finalization_correctly_for_parent() { - let client = - generate_dummy_client_with_spec_and_data(Spec::new_test_with_finality, 2, 0, &[]); + let client = generate_dummy_client_with_spec_and_data( + Spec::new_test_with_finality, + 2, + 0, + &[], + false, + ); let chain = client.chain(); let block1_details = chain.block_hash(1).and_then(|h| chain.block_details(&h)); diff --git a/crates/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs index e59b186314..09e8807461 100644 --- a/crates/ethcore/src/client/test_client.rs +++ b/crates/ethcore/src/client/test_client.rs @@ -59,12 +59,12 @@ use vm::Schedule; use block::{ClosedBlock, OpenBlock, SealedBlock}; use call_contract::{CallContract, RegistryInfo}; use client::{ - traits::ForceUpdateSealing, AccountData, BadBlocks, Balance, BlockChain, BlockChainClient, - BlockChainInfo, BlockId, BlockInfo, BlockProducer, BlockStatus, BroadcastProposalBlock, Call, - CallAnalytics, ChainInfo, EngineInfo, ImportBlock, ImportSealedBlock, IoClient, LastHashes, - Mode, Nonce, PrepareOpenBlock, ProvingBlockChainClient, ReopenBlock, ScheduleInfo, - SealedBlockImporter, StateClient, StateOrBlock, TraceFilter, TraceId, TransactionId, - TransactionInfo, UncleId, + traits::{ForceUpdateSealing, TransactionRequest}, + AccountData, BadBlocks, Balance, BlockChain, BlockChainClient, BlockChainInfo, BlockId, + BlockInfo, BlockProducer, BlockStatus, BroadcastProposalBlock, Call, CallAnalytics, ChainInfo, + EngineInfo, ImportBlock, ImportSealedBlock, IoClient, LastHashes, Mode, Nonce, + PrepareOpenBlock, ProvingBlockChainClient, ReopenBlock, ScheduleInfo, SealedBlockImporter, + StateClient, StateOrBlock, TraceFilter, TraceId, TransactionId, TransactionInfo, UncleId, }; use engines::EthEngine; use error::{Error, EthcoreResult}; @@ -1039,12 +1039,22 @@ impl BlockChainClient for TestBlockChainClient { } } - fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> { + fn create_transaction( + &self, + TransactionRequest { + action, + data, + gas, + gas_price, + nonce, + }: TransactionRequest, + ) -> Result { let transaction = TypedTransaction::Legacy(Transaction { - nonce: self.latest_nonce(&self.miner.authoring_params().author), - action: Action::Call(address), - gas: self.spec.gas_limit, - gas_price: U256::zero(), + nonce: nonce + .unwrap_or_else(|| self.latest_nonce(&self.miner.authoring_params().author)), + action, + gas: gas.unwrap_or(self.spec.gas_limit), + gas_price: gas_price.unwrap_or_else(U256::zero), value: U256::default(), data: data, }); @@ -1054,7 +1064,11 @@ impl BlockChainClient for TestBlockChainClient { .engine .sign(transaction.signature_hash(chain_id)) .unwrap(); - let signed = SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap(); + Ok(SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap()) + } + + fn transact(&self, tx_request: TransactionRequest) -> Result<(), transaction::Error> { + let signed = self.create_transaction(tx_request)?; self.miner.import_own_transaction(self, signed.into()) } diff --git a/crates/ethcore/src/client/traits.rs b/crates/ethcore/src/client/traits.rs index 62ce8ef38d..f314741e49 100644 --- a/crates/ethcore/src/client/traits.rs +++ b/crates/ethcore/src/client/traits.rs @@ -40,7 +40,7 @@ use types::{ pruning_info::PruningInfo, receipt::LocalizedReceipt, trace_filter::Filter as TraceFilter, - transaction::{self, LocalizedTransaction, SignedTransaction}, + transaction::{self, Action, LocalizedTransaction, SignedTransaction}, BlockNumber, }; use vm::LastHashes; @@ -427,8 +427,15 @@ pub trait BlockChainClient: /// Returns information about pruning/data availability. fn pruning_info(&self) -> PruningInfo; - /// Schedule state-altering transaction to be executed on the next pending block. - fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error>; + /// Returns a transaction signed with the key configured in the engine signer. + fn create_transaction( + &self, + tx_request: TransactionRequest, + ) -> Result; + + /// Schedule state-altering transaction to be executed on the next pending + /// block with the given gas and nonce parameters. + fn transact(&self, tx_request: TransactionRequest) -> Result<(), transaction::Error>; /// Get the address of the registry itself. fn registrar_address(&self) -> Option
; @@ -437,6 +444,55 @@ pub trait BlockChainClient: fn is_processing_fork(&self) -> bool; } +/// The data required for a `Client` to create a transaction. +/// +/// Gas limit, gas price, or nonce can be set explicitly, e.g. to create service +/// transactions with zero gas price, or sequences of transactions with consecutive nonces. +/// Added for AuRa needs. +pub struct TransactionRequest { + /// Transaction action + pub action: Action, + /// Transaction data + pub data: Bytes, + /// Transaction gas usage + pub gas: Option, + /// Transaction gas price + pub gas_price: Option, + /// Transaction nonce + pub nonce: Option, +} + +impl TransactionRequest { + /// Creates a request to call a contract at `address` with the specified call data. + pub fn call(address: Address, data: Bytes) -> TransactionRequest { + TransactionRequest { + action: Action::Call(address), + data, + gas: None, + gas_price: None, + nonce: None, + } + } + + /// Sets a gas limit. If this is not specified, a sensible default is used. + pub fn gas(mut self, gas: U256) -> TransactionRequest { + self.gas = Some(gas); + self + } + + /// Sets a gas price. If this is not specified or `None`, a sensible default is used. + pub fn gas_price>>(mut self, gas_price: T) -> TransactionRequest { + self.gas_price = gas_price.into(); + self + } + + /// Sets a nonce. If this is not specified, the appropriate latest nonce for the author is used. + pub fn nonce(mut self, nonce: U256) -> TransactionRequest { + self.nonce = Some(nonce); + self + } +} + /// Provides `reopen_block` method pub trait ReopenBlock { /// Reopens an OpenBlock and updates uncles. diff --git a/crates/ethcore/src/engines/authority_round/block_gas_limit.rs b/crates/ethcore/src/engines/authority_round/block_gas_limit.rs new file mode 100644 index 0000000000..b4f98dc75d --- /dev/null +++ b/crates/ethcore/src/engines/authority_round/block_gas_limit.rs @@ -0,0 +1,39 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Ethereum. If not, see . + +//! A client interface for interacting with the block gas limit contract. + +use client::{BlockChainClient, BlockId}; +use types::header::Header; +use ethabi::FunctionOutputDecoder; +use ethabi_contract::use_contract; +use ethereum_types::{Address, U256}; +use log::{debug, error}; + +use_contract!(contract, "res/contracts/block_gas_limit.json"); + +pub fn block_gas_limit(full_client: &dyn BlockChainClient, header: &Header, address: Address) -> Option { + let (data, decoder) = contract::functions::block_gas_limit::call(); + let value = full_client.call_contract(BlockId::Hash(*header.parent_hash()), address, data).map_err(|err| { + error!(target: "block_gas_limit", "Contract call failed. Not changing the block gas limit. {:?}", err); + }).ok()?; + if value.is_empty() { + debug!(target: "block_gas_limit", "Contract call returned nothing. Not changing the block gas limit."); + None + } else { + decoder.decode(&value).ok() + } +} \ No newline at end of file diff --git a/crates/ethcore/src/engines/authority_round/finality.rs b/crates/ethcore/src/engines/authority_round/finality.rs index b754252543..cd7e9128db 100644 --- a/crates/ethcore/src/engines/authority_round/finality.rs +++ b/crates/ethcore/src/engines/authority_round/finality.rs @@ -22,6 +22,7 @@ use std::collections::{ }; use ethereum_types::{Address, H256}; +use types::BlockNumber; use engines::validator_set::SimpleList; @@ -32,20 +33,23 @@ pub struct UnknownValidator; /// Rolling finality checker for authority round consensus. /// Stores a chain of unfinalized hashes that can be pushed onto. pub struct RollingFinality { - headers: VecDeque<(H256, Vec
)>, + headers: VecDeque<(H256, BlockNumber, Vec
)>, signers: SimpleList, sign_count: HashMap, last_pushed: Option, + /// First block for which a 2/3 quorum (instead of 1/2) is required. + two_thirds_majority_transition: BlockNumber, } impl RollingFinality { /// Create a blank finality checker under the given validator set. - pub fn blank(signers: Vec
) -> Self { + pub fn blank(signers: Vec
, two_thirds_majority_transition: BlockNumber) -> Self { RollingFinality { headers: VecDeque::new(), signers: SimpleList::new(signers), sign_count: HashMap::new(), last_pushed: None, + two_thirds_majority_transition, } } @@ -55,45 +59,35 @@ impl RollingFinality { /// Fails if any provided signature isn't part of the signers set. pub fn build_ancestry_subchain(&mut self, iterable: I) -> Result<(), UnknownValidator> where - I: IntoIterator)>, + I: IntoIterator)>, { self.clear(); - for (hash, signers) in iterable { + for (hash, number, signers) in iterable { if signers.iter().any(|s| !self.signers.contains(s)) { return Err(UnknownValidator); } if self.last_pushed.is_none() { self.last_pushed = Some(hash) } - + self.add_signers(&signers); + self.headers.push_front((hash, number, signers)); // break when we've got our first finalized block. - { - let current_signed = self.sign_count.len(); - - let new_signers = signers - .iter() - .filter(|s| !self.sign_count.contains_key(s)) - .count(); - let would_be_finalized = (current_signed + new_signers) * 2 > self.signers.len(); - - if would_be_finalized { - trace!(target: "finality", "Encountered already finalized block {}", hash); - break; - } - - for signer in signers.iter() { - *self.sign_count.entry(*signer).or_insert(0) += 1; - } + if self.is_finalized() { + let (hash, _, signers) = self + .headers + .pop_front() + .expect("we just pushed a block; qed"); + self.remove_signers(&signers); + trace!(target: "finality", "Encountered already finalized block {}", hash); + break; } - - self.headers.push_front((hash, signers)); } trace!(target: "finality", "Rolling finality state: {:?}", self.headers); Ok(()) } - /// Clear the finality status, but keeps the validator set. + /// Clears the finality status, but keeps the validator set. pub fn clear(&mut self) { self.headers.clear(); self.sign_count.clear(); @@ -108,7 +102,7 @@ impl RollingFinality { /// Get an iterator over stored hashes in order. #[cfg(test)] pub fn unfinalized_hashes(&self) -> impl Iterator { - self.headers.iter().map(|(h, _)| h) + self.headers.iter().map(|(h, _, _)| h) } /// Get the validator set. @@ -124,41 +118,26 @@ impl RollingFinality { pub fn push_hash( &mut self, head: H256, + number: BlockNumber, signers: Vec
, ) -> Result, UnknownValidator> { if signers.iter().any(|s| !self.signers.contains(s)) { return Err(UnknownValidator); } - for signer in signers.iter() { - *self.sign_count.entry(*signer).or_insert(0) += 1; - } - - self.headers.push_back((head, signers)); + self.add_signers(&signers); + self.headers.push_back((head, number, signers)); let mut newly_finalized = Vec::new(); - while self.sign_count.len() * 2 > self.signers.len() { - let (hash, signers) = self + while self.is_finalized() { + let (hash, _, signers) = self .headers .pop_front() .expect("headers length always greater than sign count length; qed"); + self.remove_signers(&signers); newly_finalized.push(hash); - - for signer in signers { - match self.sign_count.entry(signer) { - Entry::Occupied(mut entry) => { - // decrement count for this signer and purge on zero. - *entry.get_mut() -= 1; - - if *entry.get() == 0 { - entry.remove(); - } - } - Entry::Vacant(_) => panic!("all hashes in `header` should have entries in `sign_count` for their signers; qed"), - } - } } trace!(target: "finality", "Blocks finalized by {:?}: {:?}", head, newly_finalized); @@ -166,19 +145,62 @@ impl RollingFinality { self.last_pushed = Some(head); Ok(newly_finalized) } + + /// Returns the first block for which a 2/3 quorum (instead of 1/2) is required. + pub fn two_thirds_majority_transition(&self) -> BlockNumber { + self.two_thirds_majority_transition + } + + /// Returns whether the first entry in `self.headers` is finalized. + fn is_finalized(&self) -> bool { + match self.headers.front() { + None => false, + Some((_, number, _)) if *number < self.two_thirds_majority_transition => { + self.sign_count.len() * 2 > self.signers.len() + } + Some((_, _, _)) => self.sign_count.len() * 3 > self.signers.len() * 2, + } + } + + /// Adds the signers to the sign count. + fn add_signers(&mut self, signers: &[Address]) { + for signer in signers { + *self.sign_count.entry(*signer).or_insert(0) += 1; + } + } + + /// Removes the signers from the sign count. + fn remove_signers(&mut self, signers: &[Address]) { + for signer in signers { + match self.sign_count.entry(*signer) { + Entry::Occupied(mut entry) => { + // decrement count for this signer and purge on zero. + if *entry.get() <= 1 { + entry.remove(); + } else { + *entry.get_mut() -= 1; + } + } + Entry::Vacant(_) => { + panic!("all hashes in `header` should have entries in `sign_count` for their signers; qed"); + } + } + } + } } #[cfg(test)] mod tests { use super::RollingFinality; use ethereum_types::{Address, H256}; + use types::BlockNumber; #[test] fn rejects_unknown_signers() { let signers = (0..3).map(|_| Address::random()).collect::>(); - let mut finality = RollingFinality::blank(signers.clone()); + let mut finality = RollingFinality::blank(signers.clone(), BlockNumber::max_value()); assert!(finality - .push_hash(H256::random(), vec![signers[0], Address::random()]) + .push_hash(H256::random(), 0, vec![signers[0], Address::random()]) .is_err()); } @@ -186,19 +208,25 @@ mod tests { fn finalize_multiple() { let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); - let mut finality = RollingFinality::blank(signers.clone()); + let mut finality = RollingFinality::blank(signers.clone(), BlockNumber::max_value()); let hashes: Vec<_> = (0..7).map(|_| H256::random()).collect(); // 3 / 6 signers is < 51% so no finality. for (i, hash) in hashes.iter().take(6).cloned().enumerate() { let i = i % 3; - assert!(finality.push_hash(hash, vec![signers[i]]).unwrap().len() == 0); + assert!( + finality + .push_hash(hash, i as u64, vec![signers[i]]) + .unwrap() + .len() + == 0 + ); } // after pushing a block signed by a fourth validator, the first four // blocks of the unverified chain become verified. assert_eq!( - finality.push_hash(hashes[6], vec![signers[4]]).unwrap(), + finality.push_hash(hashes[6], 6, vec![signers[4]]).unwrap(), vec![hashes[0], hashes[1], hashes[2], hashes[3]] ); } @@ -206,12 +234,12 @@ mod tests { #[test] fn finalize_multiple_signers() { let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); - let mut finality = RollingFinality::blank(signers.clone()); + let mut finality = RollingFinality::blank(signers.clone(), BlockNumber::max_value()); let hash = H256::random(); // after pushing a block signed by four validators, it becomes verified right away. assert_eq!( - finality.push_hash(hash, signers[0..4].to_vec()).unwrap(), + finality.push_hash(hash, 0, signers[0..4].to_vec()).unwrap(), vec![hash] ); } @@ -220,10 +248,9 @@ mod tests { fn from_ancestry() { let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); let hashes: Vec<_> = (0..12) - .map(|i| (H256::random(), vec![signers[i % 6]])) + .map(|i| (H256::random(), i as u64, vec![signers[i % 6]])) .collect(); - - let mut finality = RollingFinality::blank(signers.clone()); + let mut finality = RollingFinality::blank(signers.clone(), BlockNumber::max_value()); finality .build_ancestry_subchain(hashes.iter().rev().cloned()) .unwrap(); @@ -239,12 +266,13 @@ mod tests { .map(|i| { ( H256::random(), + i as u64, vec![signers[i % 6], signers[(i + 1) % 6], signers[(i + 2) % 6]], ) }) .collect(); - let mut finality = RollingFinality::blank(signers.clone()); + let mut finality = RollingFinality::blank(signers.clone(), BlockNumber::max_value()); finality .build_ancestry_subchain(hashes.iter().rev().cloned()) .unwrap(); @@ -254,4 +282,91 @@ mod tests { assert_eq!(finality.unfinalized_hashes().next(), Some(&hashes[11].0)); assert_eq!(finality.subchain_head(), Some(hashes[11].0)); } + + #[test] + fn rejects_unknown_signers_2_3() { + let signers = (0..3).map(|_| Address::random()).collect::>(); + let mut finality = RollingFinality::blank(signers.clone(), 0); + assert!(finality + .push_hash(H256::random(), 0, vec![signers[0], Address::random()]) + .is_err()); + } + + #[test] + fn finalize_multiple_2_3() { + let signers: Vec<_> = (0..7).map(|_| Address::random()).collect(); + + let mut finality = RollingFinality::blank(signers.clone(), 0); + let hashes: Vec<_> = (0..9).map(|_| H256::random()).collect(); + + // 4 / 7 signers is < 67% so no finality. + for (i, hash) in hashes.iter().take(8).cloned().enumerate() { + let i = i % 4; + assert!( + finality + .push_hash(hash, i as u64, vec![signers[i]]) + .unwrap() + .len() + == 0 + ); + } + + // after pushing a block signed by a fifth validator, the first five + // blocks of the unverified chain become verified. + assert_eq!( + finality.push_hash(hashes[8], 8, vec![signers[4]]).unwrap(), + vec![hashes[0], hashes[1], hashes[2], hashes[3], hashes[4]] + ); + } + + #[test] + fn finalize_multiple_signers_2_3() { + let signers: Vec<_> = (0..5).map(|_| Address::random()).collect(); + let mut finality = RollingFinality::blank(signers.clone(), 0); + let hash = H256::random(); + + // after pushing a block signed by four validators, it becomes verified right away. + assert_eq!( + finality.push_hash(hash, 0, signers[0..4].to_vec()).unwrap(), + vec![hash] + ); + } + + #[test] + fn from_ancestry_2_3() { + let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); + let hashes: Vec<_> = (0..12) + .map(|i| (H256::random(), i as u64, vec![signers[i % 6]])) + .collect(); + + let mut finality = RollingFinality::blank(signers, 0); + finality + .build_ancestry_subchain(hashes.iter().rev().cloned()) + .unwrap(); + + // The last four hashes, with index 11, 10, 9, and 8, have been pushed. 7 would have finalized a block. + assert_eq!(finality.unfinalized_hashes().count(), 4); + assert_eq!(finality.subchain_head(), Some(hashes[11].0)); + } + + #[test] + fn from_ancestry_multiple_signers_2_3() { + let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); + let hashes: Vec<_> = (0..12) + .map(|i| { + let hash_signers = signers.iter().cycle().skip(i).take(4).cloned().collect(); + (H256::random(), i as u64, hash_signers) + }) + .collect(); + + let mut finality = RollingFinality::blank(signers.clone(), 0); + finality + .build_ancestry_subchain(hashes.iter().rev().cloned()) + .unwrap(); + + // only the last hash has < 67% of authorities' signatures + assert_eq!(finality.unfinalized_hashes().count(), 1); + assert_eq!(finality.unfinalized_hashes().next(), Some(&hashes[11].0)); + assert_eq!(finality.subchain_head(), Some(hashes[11].0)); + } } diff --git a/crates/ethcore/src/engines/authority_round/mod.rs b/crates/ethcore/src/engines/authority_round/mod.rs index 9afdedfc03..4591e5e257 100644 --- a/crates/ethcore/src/engines/authority_round/mod.rs +++ b/crates/ethcore/src/engines/authority_round/mod.rs @@ -15,32 +15,52 @@ // along with OpenEthereum. If not, see . //! A blockchain engine that supports a non-instant BFT proof-of-authority. +//! +//! It is recommended to use the `two_thirds_majority_transition` option, to defend against the +//! ["Attack of the Clones"](https://arxiv.org/pdf/1902.10244.pdf). Newly started networks can +//! set this option to `0`, to use a 2/3 quorum from the beginning. +//! +//! To support on-chain governance, the [ValidatorSet] is pluggable: Aura supports simple +//! constant lists of validators as well as smart contract-based dynamic validator sets. +//! Misbehavior is reported to the [ValidatorSet] as well, so that e.g. governance contracts +//! can penalize or ban attacker's nodes. +//! +//! * "Benign" misbehavior are faults that can happen in normal operation, like failing +//! to propose a block in your slot, which could be due to a temporary network outage, or +//! wrong timestamps (due to out-of-sync clocks). +//! * "Malicious" reports are made only if the sender misbehaved deliberately (or due to a +//! software bug), e.g. if they proposed multiple blocks with the same step number. use std::{ cmp, collections::{BTreeMap, BTreeSet, HashSet}, fmt, - iter::FromIterator, + iter::{self, FromIterator}, ops::Deref, sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}, + atomic::{AtomicBool, AtomicU64, Ordering as AtomicOrdering}, Arc, Weak, }, time::{Duration, UNIX_EPOCH}, + u64, }; use self::finality::RollingFinality; use super::{ signer::EngineSigner, - validator_set::{new_validator_set, SimpleList, ValidatorSet}, + validator_set::{new_validator_set_posdao, SimpleList, ValidatorSet}, }; use block::*; -use client::{traits::ForceUpdateSealing, EngineClient}; +use bytes::Bytes; +use client::{ + traits::{ForceUpdateSealing, TransactionRequest}, + EngineClient, +}; use crypto::publickey::{self, Signature}; use engines::{ block_reward, block_reward::{BlockRewardContract, RewardKind}, - ConstructedVerifier, Engine, EngineError, Seal, + ConstructedVerifier, Engine, EngineError, Seal, SealingState, }; use error::{BlockError, Error, ErrorKind}; use ethereum_types::{Address, H256, H520, U128, U256}; @@ -49,27 +69,35 @@ use ethjson::{self, uint::Uint}; use hash::keccak; use io::{IoContext, IoHandler, IoService, TimerToken}; use itertools::{self, Itertools}; +use lru_cache::LruCache; use machine::{AuxiliaryData, Call, EthereumMachine}; use parking_lot::{Mutex, RwLock}; +use rand::rngs::OsRng; use rlp::{encode, Decodable, DecoderError, Encodable, Rlp, RlpStream}; use time_utils::CheckedSystemTime; use types::{ ancestry_action::AncestryAction, header::{ExtendedHeader, Header}, + ids::BlockId, + transaction::SignedTransaction, BlockNumber, }; use unexpected::{Mismatch, OutOfBounds}; +//mod block_gas_limit as crate_block_gas_limit; mod finality; +mod randomness; +pub(crate) mod util; /// `AuthorityRound` params. pub struct AuthorityRoundParams { - /// Time to wait before next block or authority switching, - /// in seconds. + /// A map defining intervals of blocks with the given times (in seconds) to wait before next + /// block or authority switching. The keys in the map are steps of starting blocks of those + /// periods. The entry at `0` should be defined. /// - /// Deliberately typed as u16 as too high of a value leads - /// to slow block issuance. - pub step_duration: u16, + /// Wait times (durations) are additionally required to be less than 65535 since larger values + /// lead to slow block issuance. + pub step_durations: BTreeMap, /// Starting step, pub start_step: Option, /// Valid validators. @@ -82,34 +110,110 @@ pub struct AuthorityRoundParams { pub immediate_transitions: bool, /// Block reward in base units. pub block_reward: BTreeMap, - /// Block reward contract transition block. - pub block_reward_contract_transition: u64, - /// Block reward contract. - pub block_reward_contract: Option, + /// Block reward contract addresses with their associated starting block numbers. + pub block_reward_contract_transitions: BTreeMap, /// Number of accepted uncles transition block. pub maximum_uncle_count_transition: u64, /// Number of accepted uncles. pub maximum_uncle_count: usize, /// Empty step messages transition block. pub empty_steps_transition: u64, + /// First block for which a 2/3 quorum (instead of 1/2) is required. + pub two_thirds_majority_transition: BlockNumber, /// Number of accepted empty steps. pub maximum_empty_steps: usize, /// Transition block to strict empty steps validation. pub strict_empty_steps_transition: u64, + /// If set, enables random number contract integration. It maps the transition block to the contract address. + pub randomness_contract_address: BTreeMap, + /// The addresses of contracts that determine the block gas limit with their associated block + /// numbers. + pub block_gas_limit_contract_transitions: BTreeMap, + /// If set, this is the block number at which the consensus engine switches from AuRa to AuRa + /// with POSDAO modifications. + pub posdao_transition: Option, } const U16_MAX: usize = ::std::u16::MAX as usize; +/// The number of recent block hashes for which the gas limit override is memoized. +const GAS_LIMIT_OVERRIDE_CACHE_CAPACITY: usize = 10; + impl From for AuthorityRoundParams { fn from(p: ethjson::spec::AuthorityRoundParams) -> Self { - let mut step_duration_usize: usize = p.step_duration.into(); - if step_duration_usize > U16_MAX { - step_duration_usize = U16_MAX; - warn!(target: "engine", "step_duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX); + let map_step_duration = |u: ethjson::uint::Uint| { + let mut step_duration_usize: usize = u.into(); + if step_duration_usize == 0 { + panic!("AuthorityRoundParams: step duration cannot be 0"); + } + if step_duration_usize > U16_MAX { + warn!(target: "engine", "step duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX); + step_duration_usize = U16_MAX; + } + step_duration_usize as u64 + }; + let step_durations: BTreeMap<_, _> = match p.step_duration { + ethjson::spec::StepDuration::Single(u) => { + iter::once((0, map_step_duration(u))).collect() + } + ethjson::spec::StepDuration::Transitions(tr) => { + if tr.is_empty() { + panic!("AuthorityRoundParams: step duration transitions cannot be empty"); + } + tr.into_iter() + .map(|(timestamp, u)| (timestamp.into(), map_step_duration(u))) + .collect() + } + }; + let transition_block_num = p.block_reward_contract_transition.map_or(0, Into::into); + let mut br_transitions: BTreeMap<_, _> = p + .block_reward_contract_transitions + .unwrap_or_default() + .into_iter() + .map(|(block_num, address)| { + ( + block_num.into(), + BlockRewardContract::new_from_address(address.into()), + ) + }) + .collect(); + if (p.block_reward_contract_code.is_some() || p.block_reward_contract_address.is_some()) + && br_transitions + .keys() + .next() + .map_or(false, |&block_num| block_num <= transition_block_num) + { + let s = "blockRewardContractTransition"; + panic!("{} should be less than any of the keys in {}s", s, s); } + if let Some(code) = p.block_reward_contract_code { + br_transitions.insert( + transition_block_num, + BlockRewardContract::new_from_code(Arc::new(code.into())), + ); + } else if let Some(address) = p.block_reward_contract_address { + br_transitions.insert( + transition_block_num, + BlockRewardContract::new_from_address(address.into()), + ); + } + let randomness_contract_address = + p.randomness_contract_address + .map_or_else(BTreeMap::new, |transitions| { + transitions + .into_iter() + .map(|(ethjson::uint::Uint(block), addr)| (block.as_u64(), addr.into())) + .collect() + }); + let block_gas_limit_contract_transitions: BTreeMap<_, _> = p + .block_gas_limit_contract_transitions + .unwrap_or_default() + .into_iter() + .map(|(block_num, address)| (block_num.into(), address.into())) + .collect(); AuthorityRoundParams { - step_duration: step_duration_usize as u16, - validators: new_validator_set(p.validators), + step_durations, + validators: new_validator_set_posdao(p.validators, p.posdao_transition.map(Into::into)), start_step: p.start_step.map(Into::into), validate_score_transition: p.validate_score_transition.map_or(0, Into::into), validate_step_transition: p.validate_step_transition.map_or(0, Into::into), @@ -141,77 +245,122 @@ impl From for AuthorityRoundParams { } }, ), - block_reward_contract_transition: p - .block_reward_contract_transition - .map_or(0, Into::into), - block_reward_contract: match ( - p.block_reward_contract_code, - p.block_reward_contract_address, - ) { - (Some(code), _) => Some(BlockRewardContract::new_from_code(Arc::new(code.into()))), - (_, Some(address)) => Some(BlockRewardContract::new_from_address(address.into())), - (None, None) => None, - }, + block_reward_contract_transitions: br_transitions, maximum_uncle_count_transition: p.maximum_uncle_count_transition.map_or(0, Into::into), maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into), empty_steps_transition: p .empty_steps_transition .map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)), maximum_empty_steps: p.maximum_empty_steps.map_or(0, Into::into), + two_thirds_majority_transition: p + .two_thirds_majority_transition + .map_or_else(BlockNumber::max_value, Into::into), strict_empty_steps_transition: p.strict_empty_steps_transition.map_or(0, Into::into), + randomness_contract_address, + block_gas_limit_contract_transitions, + posdao_transition: p.posdao_transition.map(Into::into), } } } -// Helper for managing the step. +/// A triple containing the first step number and the starting timestamp of the given step duration. +#[derive(Clone, Copy, Debug)] +struct StepDurationInfo { + transition_step: u64, + transition_timestamp: u64, + step_duration: u64, +} + +/// Helper for managing the step. #[derive(Debug)] struct Step { calibrate: bool, // whether calibration is enabled. - inner: AtomicUsize, - duration: u16, + inner: AtomicU64, + /// Planned durations of steps. + durations: Vec, } impl Step { fn load(&self) -> u64 { - self.inner.load(AtomicOrdering::SeqCst) as u64 + self.inner.load(AtomicOrdering::SeqCst) } + fn duration_remaining(&self) -> Duration { - let now = unix_now(); - let expected_seconds = self - .load() - .checked_add(1) - .and_then(|ctr| ctr.checked_mul(self.duration as u64)) - .map(Duration::from_secs); - - match expected_seconds { - Some(step_end) if step_end > now => step_end - now, - Some(_) => Duration::from_secs(0), - None => { - let ctr = self.load(); - error!(target: "engine", "Step counter is too high: {}, aborting", ctr); - panic!("step counter is too high: {}", ctr) - } - } + self.opt_duration_remaining().unwrap_or_else(|| { + let ctr = self.load(); + error!(target: "engine", "Step counter under- or overflow: {}, aborting", ctr); + panic!("step counter under- or overflow: {}", ctr) + }) } + /// Finds the remaining duration of the current step. Returns `None` if there was a counter + /// under- or overflow. + fn opt_duration_remaining(&self) -> Option { + let next_step = self.load().checked_add(1)?; + let StepDurationInfo { + transition_step, + transition_timestamp, + step_duration, + } = self + .durations + .iter() + .take_while(|info| info.transition_step < next_step) + .last() + .expect("durations cannot be empty") + .clone(); + let next_time = transition_timestamp.checked_add( + next_step + .checked_sub(transition_step)? + .checked_mul(step_duration)?, + )?; + Some(Duration::from_secs( + next_time.saturating_sub(unix_now().as_secs()), + )) + } + + /// Increments the step number. + /// + /// Panics if the new step number is `u64::MAX`. fn increment(&self) { - use std::usize; // fetch_add won't panic on overflow but will rather wrap // around, leading to zero as the step counter, which might // lead to unexpected situations, so it's better to shut down. - if self.inner.fetch_add(1, AtomicOrdering::SeqCst) == usize::MAX { - error!(target: "engine", "Step counter is too high: {}, aborting", usize::MAX); - panic!("step counter is too high: {}", usize::MAX); + if self.inner.fetch_add(1, AtomicOrdering::SeqCst) == u64::MAX { + error!(target: "engine", "Step counter is too high: {}, aborting", u64::MAX); + panic!("step counter is too high: {}", u64::MAX); } } fn calibrate(&self) { if self.calibrate { - let new_step = unix_now().as_secs() / (self.duration as u64); - self.inner.store(new_step as usize, AtomicOrdering::SeqCst); + if self.opt_calibrate().is_none() { + let ctr = self.load(); + error!(target: "engine", "Step counter under- or overflow: {}, aborting", ctr); + panic!("step counter under- or overflow: {}", ctr) + } } } + /// Calibrates the AuRa step number according to the current time. + fn opt_calibrate(&self) -> Option<()> { + let now = unix_now().as_secs(); + let StepDurationInfo { + transition_step, + transition_timestamp, + step_duration, + } = self + .durations + .iter() + .take_while(|info| info.transition_timestamp < now) + .last() + .expect("durations cannot be empty") + .clone(); + let new_step = (now.checked_sub(transition_timestamp)? / step_duration) + .checked_add(transition_step)?; + self.inner.store(new_step, AtomicOrdering::SeqCst); + Some(()) + } + fn check_future(&self, given: u64) -> Result<(), Option>> { const REJECTED_STEP_DRIFT: u64 = 4; @@ -229,7 +378,13 @@ impl Step { Err(None) // wait a bit for blocks in near future } else if given > current { - let d = self.duration as u64; + let d = self + .durations + .iter() + .take_while(|info| info.transition_step <= current) + .last() + .expect("Duration map has at least a 0 entry.") + .step_duration; Err(Some(OutOfBounds { min: None, max: Some(d * current), @@ -255,24 +410,24 @@ struct EpochManager { } impl EpochManager { - fn blank() -> Self { + fn blank(two_thirds_majority_transition: BlockNumber) -> Self { EpochManager { epoch_transition_hash: H256::default(), epoch_transition_number: 0, - finality_checker: RollingFinality::blank(Vec::new()), + finality_checker: RollingFinality::blank(Vec::new(), two_thirds_majority_transition), force: true, } } - // zoom to epoch for given header. returns true if succeeded, false otherwise. - fn zoom_to( + /// Zooms to the epoch after the header with the given hash. Returns true if succeeded, false otherwise. + fn zoom_to_after( &mut self, client: &dyn EngineClient, machine: &EthereumMachine, validators: &dyn ValidatorSet, - header: &Header, + hash: H256, ) -> bool { - let last_was_parent = self.finality_checker.subchain_head() == Some(*header.parent_hash()); + let last_was_parent = self.finality_checker.subchain_head() == Some(hash); // early exit for current target == chain head, but only if the epochs are // the same. @@ -281,13 +436,13 @@ impl EpochManager { } self.force = false; - debug!(target: "engine", "Zooming to epoch for block {}", header.hash()); + debug!(target: "engine", "Zooming to epoch after block {}", hash); // epoch_transition_for can be an expensive call, but in the absence of // forks it will only need to be called for the block directly after // epoch transition, in which case it will be O(1) and require a single // DB lookup. - let last_transition = match client.epoch_transition_for(*header.parent_hash()) { + let last_transition = match client.epoch_transition_for(hash) { Some(t) => t, None => { // this really should never happen unless the block passed @@ -302,22 +457,31 @@ impl EpochManager { let (signal_number, set_proof, _) = destructure_proofs(&last_transition.proof) .expect("proof produced by this engine; therefore it is valid; qed"); - trace!(target: "engine", "extracting epoch set for epoch ({}, {}) signalled at #{}", - last_transition.block_number, last_transition.block_hash, signal_number); + trace!( + target: "engine", + "extracting epoch validator set for epoch ({}, {}) signalled at #{}", + last_transition.block_number, last_transition.block_hash, signal_number + ); let first = signal_number == 0; - let epoch_set = validators + let (list, _) = validators .epoch_set( first, machine, signal_number, // use signal number so multi-set first calculation is correct. set_proof, ) - .ok() - .map(|(list, _)| list.into_inner()) .expect("proof produced by this engine; therefore it is valid; qed"); - - self.finality_checker = RollingFinality::blank(epoch_set); + trace!( + target: "engine", + "Updating finality checker with new validator set extracted from epoch ({}, {}): {:?}", + last_transition.block_number, last_transition.block_hash, &list + ); + let epoch_set = list.into_inner(); + let two_thirds_majority_transition = + self.finality_checker.two_thirds_majority_transition(); + self.finality_checker = + RollingFinality::blank(epoch_set, two_thirds_majority_transition); } self.epoch_transition_hash = last_transition.block_hash; @@ -342,10 +506,22 @@ impl EpochManager { /// A message broadcast by authorities when it's their turn to seal a block but there are no /// transactions. Other authorities accumulate these messages and later include them in the seal as /// proof. +/// +/// An empty step message is created _instead of_ a block if there are no pending transactions. +/// It cannot itself be a parent, and `parent_hash` always points to the most recent block. E.g.: +/// * Validator A creates block `bA`. +/// * Validator B has no pending transactions, so it signs an empty step message `mB` +/// instead whose hash points to block `bA`. +/// * Validator C also has no pending transactions, so it also signs an empty step message `mC` +/// instead whose hash points to block `bA`. +/// * Validator D creates block `bD`. The parent is block `bA`, and the header includes `mB` and `mC`. #[derive(Clone, Debug, PartialEq, Eq)] struct EmptyStep { + /// The signature of the other two fields, by the message's author. signature: H520, + /// This message's step number. step: u64, + /// The hash of the most recent block. parent_hash: H256, } @@ -354,6 +530,7 @@ impl PartialOrd for EmptyStep { Some(self.cmp(other)) } } + impl Ord for EmptyStep { fn cmp(&self, other: &Self) -> cmp::Ordering { self.step @@ -375,6 +552,7 @@ impl EmptyStep { } } + /// Returns `true` if the message has a valid signature by the expected proposer in the message's step. fn verify(&self, validators: &dyn ValidatorSet) -> Result { let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); let correct_proposer = step_proposer(validators, &self.parent_hash, self.step); @@ -485,14 +663,26 @@ pub struct AuthorityRound { epoch_manager: Mutex, immediate_transitions: bool, block_reward: BTreeMap, - block_reward_contract_transition: u64, - block_reward_contract: Option, + block_reward_contract_transitions: BTreeMap, maximum_uncle_count_transition: u64, maximum_uncle_count: usize, empty_steps_transition: u64, strict_empty_steps_transition: u64, + two_thirds_majority_transition: BlockNumber, maximum_empty_steps: usize, machine: EthereumMachine, + /// History of step hashes recently received from peers. + received_step_hashes: RwLock>, + /// If set, enables random number contract integration. It maps the transition block to the contract address. + randomness_contract_address: BTreeMap, + /// The addresses of contracts that determine the block gas limit. + block_gas_limit_contract_transitions: BTreeMap, + /// Memoized gas limit overrides, by block hash. + gas_limit_override_cache: Mutex>>, + /// The block number at which the consensus engine switches from AuRa to AuRa with POSDAO + /// modifications. For details about POSDAO, see the whitepaper: + /// https://www.xdaichain.com/for-validators/posdao-whitepaper + posdao_transition: Option, } // header-chain validator. @@ -500,6 +690,8 @@ struct EpochVerifier { step: Arc, subchain_validators: SimpleList, empty_steps_transition: u64, + /// First block for which a 2/3 quorum (instead of 1/2) is required. + two_thirds_majority_transition: BlockNumber, } impl super::EpochVerifier for EpochVerifier { @@ -519,8 +711,9 @@ impl super::EpochVerifier for EpochVerifier { } fn check_finality_proof(&self, proof: &[u8]) -> Option> { + let signers = self.subchain_validators.clone().into_inner(); let mut finality_checker = - RollingFinality::blank(self.subchain_validators.clone().into_inner()); + RollingFinality::blank(signers, self.two_thirds_majority_transition); let mut finalized = Vec::new(); let headers: Vec
= Rlp::new(proof).as_list().ok()?; @@ -557,7 +750,7 @@ impl super::EpochVerifier for EpochVerifier { signers.push(*parent_header.author()); let newly_finalized = finality_checker - .push_hash(parent_header.hash(), signers) + .push_hash(parent_header.hash(), parent_header.number(), signers) .ok()?; finalized.extend(newly_finalized); @@ -602,8 +795,8 @@ fn header_expected_seal_fields(header: &Header, empty_steps_transition: u64) -> fn header_step(header: &Header, empty_steps_transition: u64) -> Result { Rlp::new(&header.seal().get(0).unwrap_or_else(|| - panic!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec - file has a correct genesis seal)", header_expected_seal_fields(header, empty_steps_transition)) + panic!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec \ + file has a correct genesis seal)", header_expected_seal_fields(header, empty_steps_transition)) )) .as_val() } @@ -733,7 +926,7 @@ fn verify_external( } fn combine_proofs(signal_number: BlockNumber, set_proof: &[u8], finality_proof: &[u8]) -> Vec { - let mut stream = ::rlp::RlpStream::new_list(3); + let mut stream = RlpStream::new_list(3); stream .append(&signal_number) .append(&set_proof) @@ -782,22 +975,52 @@ impl AuthorityRound { our_params: AuthorityRoundParams, machine: EthereumMachine, ) -> Result, Error> { - if our_params.step_duration == 0 { - error!(target: "engine", "Authority Round step duration can't be zero, aborting"); - panic!("authority_round: step duration can't be zero") + if !our_params.step_durations.contains_key(&0) { + error!(target: "engine", "Authority Round step 0 duration is undefined, aborting"); + return Err(Error::from_kind(ErrorKind::Engine(EngineError::Custom( + String::from("step 0 duration is undefined"), + )))); } + if our_params.step_durations.values().any(|v| *v == 0) { + error!(target: "engine", "Authority Round step duration cannot be 0"); + return Err(Error::from_kind(ErrorKind::Engine(EngineError::Custom( + String::from("step duration cannot be 0"), + )))); + } + let should_timeout = our_params.start_step.is_none(); - let initial_step = our_params - .start_step - .unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))); + + let initial_step = our_params.start_step.unwrap_or(0); + + let mut durations = Vec::new(); + { + let mut dur_info = StepDurationInfo { + transition_step: 0u64, + transition_timestamp: 0u64, + step_duration: our_params.step_durations[&0], + }; + durations.push(dur_info); + for (time, dur) in our_params.step_durations.iter().skip(1) { + let (step, time) = next_step_time_duration(dur_info, *time) + .ok_or(BlockError::TimestampOverflow)?; + dur_info.transition_step = step; + dur_info.transition_timestamp = time; + dur_info.step_duration = *dur; + durations.push(dur_info); + } + } + + let step = Step { + inner: AtomicU64::new(initial_step), + calibrate: our_params.start_step.is_none(), + durations, + }; + step.calibrate(); + let engine = Arc::new(AuthorityRound { transition_service: IoService::<()>::start("AuRa")?, step: Arc::new(PermissionedStep { - inner: Step { - inner: AtomicUsize::new(initial_step as usize), - calibrate: our_params.start_step.is_none(), - duration: our_params.step_duration, - }, + inner: step, can_propose: AtomicBool::new(true), }), client: Arc::new(RwLock::new(None)), @@ -806,17 +1029,24 @@ impl AuthorityRound { validate_score_transition: our_params.validate_score_transition, validate_step_transition: our_params.validate_step_transition, empty_steps: Default::default(), - epoch_manager: Mutex::new(EpochManager::blank()), + epoch_manager: Mutex::new(EpochManager::blank( + our_params.two_thirds_majority_transition, + )), immediate_transitions: our_params.immediate_transitions, block_reward: our_params.block_reward, - block_reward_contract_transition: our_params.block_reward_contract_transition, - block_reward_contract: our_params.block_reward_contract, + block_reward_contract_transitions: our_params.block_reward_contract_transitions, maximum_uncle_count_transition: our_params.maximum_uncle_count_transition, maximum_uncle_count: our_params.maximum_uncle_count, empty_steps_transition: our_params.empty_steps_transition, maximum_empty_steps: our_params.maximum_empty_steps, + two_thirds_majority_transition: our_params.two_thirds_majority_transition, strict_empty_steps_transition: our_params.strict_empty_steps_transition, machine: machine, + received_step_hashes: RwLock::new(Default::default()), + randomness_contract_address: our_params.randomness_contract_address, + block_gas_limit_contract_transitions: our_params.block_gas_limit_contract_transitions, + gas_limit_override_cache: Mutex::new(LruCache::new(GAS_LIMIT_OVERRIDE_CACHE_CAPACITY)), + posdao_transition: our_params.posdao_transition, }); // Do not initialize timeouts for tests. @@ -842,15 +1072,14 @@ impl AuthorityRound { (CowLike::Borrowed(&*self.validators), header.number()) } else { let mut epoch_manager = self.epoch_manager.lock(); - let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { - Some(client) => client, - None => { - debug!(target: "engine", "Unable to verify sig: missing client ref."); - return Err(EngineError::RequiresClient.into()); - } - }; + let client = self.upgrade_client_or("Unable to verify sig")?; - if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, header) { + if !epoch_manager.zoom_to_after( + &*client, + &self.machine, + &*self.validators, + *header.parent_hash(), + ) { debug!(target: "engine", "Unable to zoom to epoch."); return Err(EngineError::RequiresClient.into()); } @@ -923,10 +1152,8 @@ impl AuthorityRound { } fn broadcast_message(&self, message: Vec) { - if let Some(ref weak) = *self.client.read() { - if let Some(c) = weak.upgrade() { - c.broadcast_consensus_message(message); - } + if let Ok(c) = self.upgrade_client_or(None) { + c.broadcast_consensus_message(message); } } @@ -958,6 +1185,12 @@ impl AuthorityRound { if !reported.insert(skipped_primary) { break; } + trace!( + target: "engine", + "Reporting benign misbehaviour (cause: skipped step) at block #{}, \ + epoch set number {}, step proposer={:#x}. Own address: {}", + header.number(), set_number, skipped_primary, me + ); self.validators .report_benign(&skipped_primary, set_number, header.number()); } @@ -975,16 +1208,18 @@ impl AuthorityRound { return Vec::new(); } - let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { - Some(client) => client, - None => { - warn!(target: "engine", "Unable to apply ancestry actions: missing client ref."); - return Vec::new(); - } + let client = match self.upgrade_client_or("Unable to apply ancestry actions") { + Ok(client) => client, + Err(_) => return Vec::new(), }; let mut epoch_manager = self.epoch_manager.lock(); - if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, chain_head) { + if !epoch_manager.zoom_to_after( + &*client, + &self.machine, + &*self.validators, + *chain_head.parent_hash(), + ) { return Vec::new(); } @@ -1012,7 +1247,7 @@ impl AuthorityRound { signers.extend(parent_empty_steps_signers.drain(..)); if let Ok(empty_step_signers) = header_empty_steps_signers(&header, self.empty_steps_transition) { - let res = (header.hash(), signers); + let res = (header.hash(), header.number(), signers); trace!(target: "finality", "Ancestry iteration: yielding {:?}", res); parent_empty_steps_signers = empty_step_signers; @@ -1025,7 +1260,7 @@ impl AuthorityRound { } }) .while_some() - .take_while(|&(h, _)| h != epoch_transition_hash); + .take_while(|&(h, _, _)| h != epoch_transition_hash); if let Err(e) = epoch_manager .finality_checker @@ -1036,11 +1271,140 @@ impl AuthorityRound { } } - let finalized = epoch_manager - .finality_checker - .push_hash(chain_head.hash(), vec![*chain_head.author()]); + let finalized = epoch_manager.finality_checker.push_hash( + chain_head.hash(), + chain_head.number(), + vec![*chain_head.author()], + ); finalized.unwrap_or_default() } + + fn address(&self) -> Option
{ + self.signer.read().as_ref().map(|s| s.address()) + } + + /// Make calls to the randomness contract. + fn run_randomness_phase(&self, block: &ExecutedBlock) -> Result, Error> { + let contract_addr = match self + .randomness_contract_address + .range(..=block.header.number()) + .last() + { + Some((_, &contract_addr)) => contract_addr, + None => return Ok(Vec::new()), // No randomness contract. + }; + + let opt_signer = self.signer.read(); + let signer = match opt_signer.as_ref() { + Some(signer) => signer, + None => return Ok(Vec::new()), // We are not a validator, so we shouldn't call the contracts. + }; + let our_addr = signer.address(); + let client = self.upgrade_client_or("Unable to prepare block")?; + let full_client = client.as_full_client().ok_or_else(|| { + EngineError::FailedSystemCall("Failed to upgrade to BlockchainClient.".to_string()) + })?; + + // Random number generation + let contract = util::BoundContract::new(&*client, BlockId::Latest, contract_addr); + let phase = randomness::RandomnessPhase::load(&contract, our_addr) + .map_err(|err| EngineError::Custom(format!("Randomness error in load(): {:?}", err)))?; + let data = match phase + .advance(&contract, &mut OsRng, signer.as_ref()) + .map_err(|err| { + EngineError::Custom(format!("Randomness error in advance(): {:?}", err)) + })? { + Some(data) => data, + None => return Ok(Vec::new()), // Nothing to commit or reveal at the moment. + }; + + let nonce = block.state.nonce(&our_addr)?; + let tx_request = TransactionRequest::call(contract_addr, data) + .gas_price(U256::zero()) + .nonce(nonce); + Ok(vec![full_client.create_transaction(tx_request)?]) + } + + /// Returns the reference to the client, if registered. + fn upgrade_client_or<'a, T>( + &self, + opt_error_msg: T, + ) -> Result, EngineError> + where + T: Into>, + { + self.client + .read() + .as_ref() + .and_then(|weak| weak.upgrade()) + .ok_or_else(|| { + if let Some(error_msg) = opt_error_msg.into() { + debug!(target: "engine", "{}: missing client ref.", error_msg); + } + EngineError::RequiresClient + }) + } + + fn run_posdao( + &self, + block: &ExecutedBlock, + nonce: Option, + ) -> Result, Error> { + // Skip the rest of the function unless there has been a transition to POSDAO AuRa. + if self + .posdao_transition + .map_or(true, |posdao_block| block.header.number() < posdao_block) + { + trace!(target: "engine", "Skipping POSDAO calls to validator set contracts"); + return Ok(Vec::new()); + } + + let opt_signer = self.signer.read(); + let signer = match opt_signer.as_ref() { + Some(signer) => signer, + None => return Ok(Vec::new()), // We are not a validator, so we shouldn't call the contracts. + }; + let our_addr = signer.address(); + let client = self.upgrade_client_or("Unable to prepare block")?; + let full_client = client.as_full_client().ok_or_else(|| { + EngineError::FailedSystemCall("Failed to upgrade to BlockchainClient.".to_string()) + })?; + + // Makes a constant contract call. + let mut call = |to: Address, data: Bytes| { + full_client + .call_contract(BlockId::Latest, to, data) + .map_err(|e| format!("{}", e)) + }; + + // Our current account nonce. The transactions must have consecutive nonces, starting with this one. + let mut tx_nonce = if let Some(tx_nonce) = nonce { + tx_nonce + } else { + block.state.nonce(&our_addr)? + }; + let mut transactions = Vec::new(); + + // Creates and signs a transaction with the given contract call. + let mut make_transaction = |to: Address, data: Bytes| -> Result { + let tx_request = TransactionRequest::call(to, data) + .gas_price(U256::zero()) + .nonce(tx_nonce); + tx_nonce += U256::one(); // Increment the nonce for the next transaction. + Ok(full_client.create_transaction(tx_request)?) + }; + + // Genesis is never a new block, but might as well check. + let first = block.header.number() == 0; + for (addr, data) in + self.validators + .generate_engine_transactions(first, &block.header, &mut call)? + { + transactions.push(make_transaction(addr, data)?); + } + + Ok(transactions) + } } fn unix_now() -> Duration { @@ -1080,8 +1444,10 @@ impl IoHandler<()> for TransitionHandler { } } - let next_run_at = AsMillis::as_millis(&self.step.inner.duration_remaining()) >> 2; - io.register_timer_once(ENGINE_TIMEOUT_TOKEN, Duration::from_millis(next_run_at)) + let next_run_at = Duration::from_millis( + AsMillis::as_millis(&self.step.inner.duration_remaining()) >> 2, + ); + io.register_timer_once(ENGINE_TIMEOUT_TOKEN, next_run_at) .unwrap_or_else( |e| warn!(target: "engine", "Failed to restart consensus step timer: {}.", e), ) @@ -1107,10 +1473,8 @@ impl Engine for AuthorityRound { fn step(&self) { self.step.inner.increment(); self.step.can_propose.store(true, AtomicOrdering::SeqCst); - if let Some(ref weak) = *self.client.read() { - if let Some(c) = weak.upgrade() { - c.update_sealing(ForceUpdateSealing::No); - } + if let Ok(c) = self.upgrade_client_or(None) { + c.update_sealing(ForceUpdateSealing::No); } } @@ -1179,15 +1543,67 @@ impl Engine for AuthorityRound { let score = calculate_score(parent_step, current_step, current_empty_steps_len); header.set_difficulty(score); + if let Some(gas_limit) = self.gas_limit_override(header) { + trace!(target: "engine", "Setting gas limit to {} for block {}.", gas_limit, header.number()); + let parent_gas_limit = *parent.gas_limit(); + header.set_gas_limit(gas_limit); + if parent_gas_limit != gas_limit { + info!(target: "engine", "Block gas limit was changed from {} to {}.", parent_gas_limit, gas_limit); + } + } } - fn seals_internally(&self) -> Option { - // TODO: accept a `&Call` here so we can query the validator set. - Some(self.signer.read().is_some()) + fn sealing_state(&self) -> SealingState { + let our_addr = match *self.signer.read() { + Some(ref signer) => signer.address(), + None => { + warn!(target: "engine", "Not preparing block; cannot sign."); + return SealingState::NotReady; + } + }; + + let client = match self.upgrade_client_or("Not preparing block") { + Ok(client) => client, + Err(_) => return SealingState::NotReady, + }; + + let parent = match client.as_full_client() { + Some(full_client) => full_client.best_block_header(), + None => { + debug!(target: "engine", "Not preparing block: not a full client."); + return SealingState::NotReady; + } + }; + + let validators = if self.immediate_transitions { + CowLike::Borrowed(&*self.validators) + } else { + let mut epoch_manager = self.epoch_manager.lock(); + if !epoch_manager.zoom_to_after( + &*client, + &self.machine, + &*self.validators, + parent.hash(), + ) { + debug!(target: "engine", "Not preparing block: Unable to zoom to epoch."); + return SealingState::NotReady; + } + CowLike::Owned(epoch_manager.validators().clone()) + }; + + let step = self.step.inner.load(); + + if !is_step_proposer(&*validators, &parent.hash(), step, &our_addr) { + trace!(target: "engine", "Not preparing block: not a proposer for step {}. (Our address: {})", + step, our_addr); + return SealingState::NotReady; + } + + SealingState::Ready } fn handle_message(&self, rlp: &[u8]) -> Result<(), EngineError> { - fn fmt_err(x: T) -> EngineError { + fn fmt_err(x: T) -> EngineError { EngineError::MalformedMessage(format!("{:?}", x)) } @@ -1370,6 +1786,11 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let mut beneficiaries = Vec::new(); + + if block.header.number() == self.two_thirds_majority_transition { + info!(target: "engine", "Block {}: Transitioning to 2/3 quorum.", self.two_thirds_majority_transition); + } + if block.header.number() >= self.empty_steps_transition { let empty_steps = if block.header.seal().is_empty() { // this is a new block, calculate rewards based on the empty steps messages we have accumulated @@ -1404,33 +1825,52 @@ impl Engine for AuthorityRound { let number = block.header.number(); beneficiaries.push((author, RewardKind::Author)); - let rewards: Vec<_> = match self.block_reward_contract { - Some(ref c) if number >= self.block_reward_contract_transition => { - let mut call = super::default_system_or_code_call(&self.machine, block); - - let rewards = c.reward(&beneficiaries, &mut call)?; - rewards - .into_iter() - .map(|(author, amount)| (author, RewardKind::External, amount)) - .collect() - } - _ => { - let (_, reward) = self.block_reward.iter() + let block_reward_contract_transition = self + .block_reward_contract_transitions + .range(..=block.header.number()) + .last(); + let rewards: Vec<_> = if let Some((_, contract)) = block_reward_contract_transition { + let mut call = crate::engines::default_system_or_code_call(&self.machine, block); + let rewards = contract.reward(&beneficiaries, &mut call)?; + rewards + .into_iter() + .map(|(author, amount)| (author, RewardKind::External, amount)) + .collect() + } else { + let (_, reward) = self + .block_reward + .iter() .rev() .find(|&(block, _)| *block <= number) - .expect("Current block's reward is not found; this indicates a chain config error; qed"); - let reward = *reward; + .expect( + "Current block's reward is not found; this indicates a chain config error; qed", + ); + let reward = *reward; - beneficiaries - .into_iter() - .map(|(author, reward_kind)| (author, reward_kind, reward)) - .collect() - } + beneficiaries + .into_iter() + .map(|(author, reward_kind)| (author, reward_kind, reward)) + .collect() }; + if let Some(signer) = self.signer.read().as_ref() { + let our_addr = signer.address(); + self.validators.on_close_block(&block.header, &our_addr)? + } + block_reward::apply_block_rewards(&rewards, block, &self.machine) } + fn generate_engine_transactions( + &self, + block: &ExecutedBlock, + ) -> Result, Error> { + let mut transactions = self.run_randomness_phase(block)?; + let nonce = transactions.last().map(|tx| tx.tx().nonce + U256::one()); + transactions.extend(self.run_posdao(block, nonce)?); + Ok(transactions) + } + /// Check the number of seal fields. fn verify_block_basic(&self, header: &Header) -> Result<(), Error> { if header.number() >= self.validate_score_transition @@ -1491,6 +1931,38 @@ impl Engine for AuthorityRound { Err(EngineError::DoubleVote(*header.author()))?; } + // Report malice if the validator produced other sibling blocks in the same step. + let received_step_key = (step, *header.author()); + let new_hash = header.hash(); + if self + .received_step_hashes + .read() + .get(&received_step_key) + .map_or(false, |h| *h != new_hash) + { + trace!(target: "engine", "Validator {} produced sibling blocks in the same step", header.author()); + self.validators.report_malicious( + header.author(), + set_number, + header.number(), + Default::default(), + ); + } else { + self.received_step_hashes + .write() + .insert(received_step_key, new_hash); + } + + // Remove hash records older than two full rounds of steps (picked as a reasonable trade-off between + // memory consumption and fault-tolerance). + let sibling_malice_detection_period = 2 * validators.count(&parent.hash()) as u64; + let oldest_step = parent_step.saturating_sub(sibling_malice_detection_period); + if oldest_step > 0 { + let mut rsh = self.received_step_hashes.write(); + let new_rsh = rsh.split_off(&(oldest_step, Address::zero())); + *rsh = new_rsh; + } + // If empty step messages are enabled we will validate the messages in the seal, missing messages are not // reported as there's no way to tell whether the empty step message was never sent or simply not included. let empty_steps_len = if header.number() >= self.empty_steps_transition { @@ -1545,6 +2017,12 @@ impl Engine for AuthorityRound { match validate_empty_steps() { Ok(len) => len, Err(err) => { + trace!( + target: "engine", + "Reporting benign misbehaviour (cause: invalid empty steps) \ + at block #{}, epoch set number {}. Own address: {}", + header.number(), set_number, self.address().unwrap_or_default() + ); self.validators .report_benign(header.author(), set_number, header.number()); return Err(err); @@ -1579,6 +2057,11 @@ impl Engine for AuthorityRound { let res = verify_external(header, &*validators, self.empty_steps_transition); match res { Err(Error(ErrorKind::Engine(EngineError::NotProposer(_)), _)) => { + trace!( + target: "engine", + "Reporting benign misbehaviour (cause: block from incorrect proposer) \ + at block #{}, epoch set number {}. Own address: {}", + header.number(), set_number, self.address().unwrap_or_default()); self.validators .report_benign(header.author(), set_number, header.number()); } @@ -1627,7 +2110,11 @@ impl Engine for AuthorityRound { // Apply transitions that don't require finality and should be enacted immediately (e.g from chain spec) if let Some(change) = self.validators.is_epoch_end(first, chain_head) { - info!(target: "engine", "Immediately applying validator set change signalled at block {}", chain_head.number()); + info!( + target: "engine", + "Immediately applying validator set change signalled at block {}", + chain_head.number() + ); self.epoch_manager.lock().note_new_epoch(); let change = combine_proofs(chain_head.number(), &change, &[]); return Some(change); @@ -1712,6 +2199,7 @@ impl Engine for AuthorityRound { step: self.step.clone(), subchain_validators: list, empty_steps_transition: self.empty_steps_transition, + two_thirds_majority_transition: self.two_thirds_majority_transition, }); match finalize { @@ -1730,8 +2218,8 @@ impl Engine for AuthorityRound { self.validators.register_client(client); } - fn set_signer(&self, signer: Box) { - *self.signer.write() = Some(signer); + fn set_signer(&self, signer: Option>) { + *self.signer.write() = signer; } fn sign(&self, hash: H256) -> Result { @@ -1774,35 +2262,84 @@ impl Engine for AuthorityRound { .map(AncestryAction::MarkFinalized) .collect() } + + fn gas_limit_override(&self, header: &Header) -> Option { + let (_, &address) = self + .block_gas_limit_contract_transitions + .range(..=header.number()) + .last()?; + let client = self.upgrade_client_or("Unable to prepare block").ok()?; + let full_client = match client.as_full_client() { + Some(full_client) => full_client, + None => { + error!(target: "engine", "Failed to upgrade to BlockchainClient."); + return None; + } + }; + if let Some(limit) = self.gas_limit_override_cache.lock().get_mut(&header.hash()) { + return *limit; + } + let limit = util::block_gas_limit(full_client, header, address); + self.gas_limit_override_cache + .lock() + .insert(header.hash(), limit); + limit + } +} + +/// A helper accumulator function mapping a step duration and a step duration transition timestamp +/// to the corresponding step number and the correct starting second of the step. +fn next_step_time_duration(info: StepDurationInfo, time: u64) -> Option<(u64, u64)> { + let step_diff = time + .checked_add(info.step_duration)? + .checked_sub(1)? + .checked_sub(info.transition_timestamp)? + .checked_div(info.step_duration)?; + let time_diff = step_diff.checked_mul(info.step_duration)?; + Some(( + info.transition_step.checked_add(step_diff)?, + info.transition_timestamp.checked_add(time_diff)?, + )) } #[cfg(test)] mod tests { use super::{ - calculate_score, AuthorityRound, AuthorityRoundParams, EmptyStep, SealedEmptyStep, + calculate_score, next_step_time_duration, util::BoundContract, AuthorityRound, + AuthorityRoundParams, EmptyStep, SealedEmptyStep, StepDurationInfo, }; use accounts::AccountProvider; use block::*; use crypto::publickey::Signature; use engines::{ + block_reward::BlockRewardContract, validator_set::{SimpleList, TestSet}, Engine, EngineError, EthEngine, Seal, }; use error::{Error, ErrorKind}; + use ethabi_contract::use_contract; use ethereum_types::{Address, H256, H520, U256}; + use ethjson; use hash::keccak; + use miner::{Author, MinerService}; use rlp::encode; use spec::Spec; use std::{ collections::BTreeMap, + str::FromStr, sync::{ - atomic::{AtomicUsize, Ordering as AtomicOrdering}, + atomic::{AtomicU64, AtomicUsize, Ordering as AtomicOrdering}, Arc, }, + time::Duration, + }; + use test_helpers::{ + generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data, + get_temp_state_db, TestNotify, }; - use test_helpers::{generate_dummy_client_with_spec, get_temp_state_db, TestNotify}; use types::{ header::Header, + ids::BlockId, transaction::{Action, Transaction, TypedTransaction}, }; @@ -1811,7 +2348,7 @@ mod tests { F: FnOnce(&mut AuthorityRoundParams), { let mut params = AuthorityRoundParams { - step_duration: 1, + step_durations: [(0, 1)].to_vec().into_iter().collect(), start_step: Some(1), validators: Box::new(TestSet::default()), validate_score_transition: 0, @@ -1822,9 +2359,12 @@ mod tests { empty_steps_transition: u64::max_value(), maximum_empty_steps: 0, block_reward: Default::default(), - block_reward_contract_transition: 0, - block_reward_contract: Default::default(), + block_reward_contract_transitions: Default::default(), strict_empty_steps_transition: 0, + two_thirds_majority_transition: 0, + randomness_contract_address: BTreeMap::new(), + block_gas_limit_contract_transitions: BTreeMap::new(), + posdao_transition: Some(0), }; // mutate aura params @@ -1837,6 +2377,22 @@ mod tests { AuthorityRound::new(params, machine).unwrap() } + #[test] + fn test_next_step_time_duration() { + // At step 7 (time 1000), we transitioned to step duration 10. + let info = StepDurationInfo { + step_duration: 10, + transition_step: 7, + transition_timestamp: 1000, + }; + // So the next transition can happen e.g. at step 12 (time 1050) or 13 (time 1060). + assert_eq!(Some((12, 1050)), next_step_time_duration(info, 1050)); + assert_eq!(Some((13, 1060)), next_step_time_duration(info, 1051)); + assert_eq!(Some((13, 1060)), next_step_time_duration(info, 1055)); + // The next transition could also happen immediately. + assert_eq!(Some((7, 1000)), next_step_time_duration(info, 1000)); + } + #[test] fn has_valid_metadata() { let engine = Spec::new_test_round().engine; @@ -1865,7 +2421,6 @@ mod tests { fn generates_seal_and_does_not_double_propose() { let tap = Arc::new(AccountProvider::transient_provider()); let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); - let addr2 = tap.insert_account(keccak("2").into(), &"2".into()).unwrap(); let spec = Spec::new_test_round(); let engine = &*spec.engine; @@ -1873,9 +2428,6 @@ mod tests { let db1 = spec .ensure_db_good(get_temp_state_db(), &Default::default()) .unwrap(); - let db2 = spec - .ensure_db_good(get_temp_state_db(), &Default::default()) - .unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b1 = OpenBlock::new( engine, @@ -1892,34 +2444,93 @@ mod tests { ) .unwrap(); let b1 = b1.close_and_lock().unwrap(); - let b2 = OpenBlock::new( + + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); + if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) { + assert!(b1.clone().try_seal(engine, seal).is_ok()); + // Second proposal is forbidden. + assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None); + } else { + panic!("block 1 not sealed"); + } + } + + #[test] + fn generates_seal_iff_sealer_is_set() { + let tap = Arc::new(AccountProvider::transient_provider()); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + let spec = Spec::new_test_round(); + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db1 = spec + .ensure_db_good(get_temp_state_db(), &Default::default()) + .unwrap(); + let last_hashes = Arc::new(vec![genesis_header.hash()]); + let b1 = OpenBlock::new( engine, Default::default(), false, - db2, + db1, &genesis_header, - last_hashes, - addr2, + last_hashes.clone(), + addr1, (3141562.into(), 31415620.into()), vec![], false, None, ) + .unwrap() + .close_and_lock() .unwrap(); - let b2 = b2.close_and_lock().unwrap(); - - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + // Not a signer. A seal cannot be generated. + assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None); + // Become a signer. + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) { assert!(b1.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None); + } else { + panic!("block 1 not sealed"); } - - engine.set_signer(Box::new((tap, addr2, "2".into()))); - if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { + // Stop being a signer. + engine.set_signer(None); + // Make a step first and then create a new block in that new step. + engine.step(); + let addr2 = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); + let mut header2 = genesis_header.clone(); + header2.set_number(2); + header2.set_author(addr2); + header2.set_parent_hash(header2.hash()); + let db2 = spec + .ensure_db_good(get_temp_state_db(), &Default::default()) + .unwrap(); + let b2 = OpenBlock::new( + engine, + Default::default(), + false, + db2, + &header2, + last_hashes, + addr2, + (3141562.into(), 31415620.into()), + vec![], + false, + None, + ) + .unwrap() + .close_and_lock() + .unwrap(); + // Not a signer. A seal cannot be generated. + assert!(engine.generate_seal(&b2, &header2) == Seal::None); + // Become a signer once more. + engine.set_signer(Some(Box::new((tap, addr2, "0".into())))); + if let Seal::Regular(seal) = engine.generate_seal(&b2, &header2) { assert!(b2.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. - assert!(engine.generate_seal(&b2, &genesis_header) == Seal::None); + assert!(engine.generate_seal(&b2, &header2) == Seal::None); + } else { + panic!("block 2 not sealed"); } } @@ -1972,13 +2583,13 @@ mod tests { .unwrap(); let b2 = b2.close_and_lock().unwrap(); - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); match engine.generate_seal(&b1, &genesis_header) { Seal::None | Seal::Proposal(_) => panic!("wrong seal"), Seal::Regular(_) => { engine.step(); - engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr2, "0".into())))); match engine.generate_seal(&b2, &genesis_header) { Seal::Regular(_) | Seal::Proposal(_) => { panic!("sealed despite wrong difficulty") @@ -2096,11 +2707,11 @@ mod tests { assert!(aura.verify_block_family(&header, &parent_header).is_ok()); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0); - aura.set_signer(Box::new(( + aura.set_signer(Some(Box::new(( Arc::new(AccountProvider::transient_provider()), Default::default(), "".into(), - ))); + )))); // Do not report on steps skipped between genesis and first block. header.set_number(1); @@ -2113,6 +2724,38 @@ mod tests { assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 2); } + #[test] + fn reports_multiple_blocks_per_step() { + let tap = AccountProvider::transient_provider(); + let addr0 = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + + let validator_set = TestSet::from_validators(vec![addr0, addr1]); + let aura = aura(|p| p.validators = Box::new(validator_set.clone())); + + aura.set_signer(Some(Box::new((Arc::new(tap), addr0, "0".into())))); + + let mut parent_header: Header = Header::default(); + parent_header.set_number(2); + parent_header.set_seal(vec![encode(&1usize)]); + parent_header.set_gas_limit("222222".parse::().unwrap()); + let mut header: Header = Header::default(); + header.set_number(3); + header.set_difficulty(calculate_score(1, 2, 0)); + header.set_gas_limit("222222".parse::().unwrap()); + header.set_seal(vec![encode(&2usize)]); + header.set_author(addr1); + + // First sibling block. + assert!(aura.verify_block_family(&header, &parent_header).is_ok()); + assert_eq!(validator_set.last_malicious(), 0); + + // Second sibling block: should be reported. + header.set_gas_limit("222223".parse::().unwrap()); + assert!(aura.verify_block_family(&header, &parent_header).is_ok()); + assert_eq!(validator_set.last_malicious(), 3); + } + #[test] fn test_uncles_transition() { let aura = aura(|params| { @@ -2130,29 +2773,88 @@ mod tests { use super::Step; let step = Step { calibrate: false, - inner: AtomicUsize::new(::std::usize::MAX), - duration: 1, + inner: AtomicU64::new(::std::u64::MAX), + durations: [StepDurationInfo { + transition_step: 0, + transition_timestamp: 0, + step_duration: 1, + }] + .to_vec() + .into_iter() + .collect(), }; step.increment(); } #[test] - #[should_panic(expected = "counter is too high")] + #[should_panic(expected = "step counter under- or overflow")] fn test_counter_duration_remaining_too_high() { use super::Step; let step = Step { calibrate: false, - inner: AtomicUsize::new(::std::usize::MAX), - duration: 1, + inner: AtomicU64::new(::std::u64::MAX), + durations: [StepDurationInfo { + transition_step: 0, + transition_timestamp: 0, + step_duration: 1, + }] + .to_vec() + .into_iter() + .collect(), }; step.duration_remaining(); } #[test] - #[should_panic(expected = "authority_round: step duration can't be zero")] + fn test_change_step_duration() { + use super::Step; + use std::thread; + + let now = super::unix_now().as_secs(); + let step = Step { + calibrate: true, + inner: AtomicU64::new(::std::u64::MAX), + durations: [ + StepDurationInfo { + transition_step: 0, + transition_timestamp: 0, + step_duration: 1, + }, + StepDurationInfo { + transition_step: now, + transition_timestamp: now, + step_duration: 2, + }, + StepDurationInfo { + transition_step: now + 1, + transition_timestamp: now + 2, + step_duration: 4, + }, + ] + .to_vec() + .into_iter() + .collect(), + }; + // calibrated step `now` + step.calibrate(); + let duration_remaining = step.duration_remaining(); + assert_eq!(step.inner.load(AtomicOrdering::SeqCst), now); + assert!(duration_remaining <= Duration::from_secs(2)); + thread::sleep(duration_remaining); + step.increment(); + // calibrated step `now + 1` + step.calibrate(); + let duration_remaining = step.duration_remaining(); + assert_eq!(step.inner.load(AtomicOrdering::SeqCst), now + 1); + assert!(duration_remaining > Duration::from_secs(2)); + assert!(duration_remaining <= Duration::from_secs(4)); + } + + #[test] + #[should_panic] fn test_step_duration_zero() { aura(|params| { - params.step_duration = 0; + params.step_durations = [(0, 0)].to_vec().into_iter().collect(); }); } @@ -2198,7 +2900,7 @@ mod tests { ]); } - fn assert_insufficient_proof(result: Result, contains: &str) { + fn assert_insufficient_proof(result: Result, contains: &str) { match result { Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _)) => { assert!( @@ -2231,7 +2933,7 @@ mod tests { client.add_notify(notify.clone()); engine.register_client(Arc::downgrade(&client) as _); - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); let b1 = OpenBlock::new( engine, @@ -2305,7 +3007,7 @@ mod tests { let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); @@ -2340,9 +3042,9 @@ mod tests { let b2 = b2.close_and_lock().unwrap(); // we will now seal a block with 1tx and include the accumulated empty step message - engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr2, "0".into())))); if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); let empty_steps = ::rlp::encode_list(&vec![empty_step2]); @@ -2395,7 +3097,7 @@ mod tests { let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); @@ -2415,7 +3117,7 @@ mod tests { ) .unwrap(); let b2 = b2.close_and_lock().unwrap(); - engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr2, "0".into())))); assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None); engine.step(); @@ -2437,10 +3139,10 @@ mod tests { .unwrap(); let b3 = b3.close_and_lock().unwrap(); - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); if let Seal::Regular(seal) = engine.generate_seal(&b3, &genesis_header) { let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); - engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr2, "0".into())))); let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash()); let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]); @@ -2488,7 +3190,7 @@ mod tests { let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); @@ -2563,7 +3265,7 @@ mod tests { ); // empty step with valid signature from incorrect proposer for step - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())]; set_empty_steps_seal(&mut header, 2, &signature, &empty_steps); @@ -2573,9 +3275,9 @@ mod tests { ); // valid empty steps - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); let empty_step2 = sealed_empty_step(engine, 2, &parent_header.hash()); - engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr2, "0".into())))); let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash()); let empty_steps = vec![empty_step2, empty_step3]; @@ -2627,7 +3329,7 @@ mod tests { let b1 = b1.close_and_lock().unwrap(); // since the block is empty it isn't sealed and we generate empty steps - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); @@ -2660,13 +3362,75 @@ mod tests { ) } + #[test] + fn randomness_contract() -> Result<(), super::util::CallError> { + use_contract!( + rand_contract, + "res/contracts/test_authority_round_random.json" + ); + + env_logger::init(); + + let contract_addr = Address::from_str("0000000000000000000000000000000000000042").unwrap(); + let client = generate_dummy_client_with_spec_and_data( + Spec::new_test_round_randomness_contract, + 0, + 0, + &[], + true, + ); + + let tap = Arc::new(AccountProvider::transient_provider()); + + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + // Unlock account so that the engine can decrypt the secret. + tap.unlock_account_permanently(addr1, "1".into()) + .expect("unlock"); + + let signer = Box::new((tap.clone(), addr1, "1".into())); + client.miner().set_author(Author::Sealer(signer.clone())); + client + .miner() + .set_gas_range_target((U256::from(1000000), U256::from(1000000))); + + let engine = client.engine(); + engine.set_signer(Some(signer)); + engine.register_client(Arc::downgrade(&client) as _); + let bc = BoundContract::new(&*client, BlockId::Latest, contract_addr); + + // First the contract is in the commit phase, and we haven't committed yet. + assert!(bc.call_const(rand_contract::functions::is_commit_phase::call())?); + assert!(!bc.call_const(rand_contract::functions::is_committed::call(0, addr1))?); + + // We produce a block and commit. + engine.step(); + assert!(bc.call_const(rand_contract::functions::is_committed::call(0, addr1))?); + + // After two more blocks we are in the reveal phase... + engine.step(); + engine.step(); + assert!(bc.call_const(rand_contract::functions::is_reveal_phase::call())?); + assert!(!bc.call_const(rand_contract::functions::sent_reveal::call(0, addr1))?); + assert!(bc + .call_const(rand_contract::functions::get_value::call())? + .is_zero()); + + // ...so in the next step, we reveal our random value, and the contract's random value is not zero anymore. + engine.step(); + assert!(bc.call_const(rand_contract::functions::sent_reveal::call(0, addr1))?); + assert!(!bc + .call_const(rand_contract::functions::get_value::call())? + .is_zero()); + Ok(()) + } + #[test] fn extra_info_from_seal() { let (spec, tap, accounts) = setup_empty_steps(); let engine = &*spec.engine; let addr1 = accounts[0]; - engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), addr1, "1".into())))); let mut header: Header = Header::default(); let empty_step = empty_step(engine, 1, &header.parent_hash()); @@ -2699,7 +3463,7 @@ mod tests { #[test] fn test_empty_steps() { let engine = aura(|p| { - p.step_duration = 4; + p.step_durations = [(0, 4)].to_vec().into_iter().collect(); p.empty_steps_transition = 0; p.maximum_empty_steps = 0; }); @@ -2736,7 +3500,7 @@ mod tests { let (_spec, tap, accounts) = setup_empty_steps(); let engine = aura(|p| { p.validators = Box::new(SimpleList::new(accounts.clone())); - p.step_duration = 4; + p.step_durations = [(0, 4)].to_vec().into_iter().collect(); p.empty_steps_transition = 0; p.maximum_empty_steps = 0; }); @@ -2750,7 +3514,7 @@ mod tests { header.set_author(accounts[0]); // when - engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), accounts[1], "0".into())))); let empty_steps = vec![ sealed_empty_step(&*engine, 1, &parent.hash()), sealed_empty_step(&*engine, 1, &parent.hash()), @@ -2775,7 +3539,7 @@ mod tests { let (_spec, tap, accounts) = setup_empty_steps(); let engine = aura(|p| { p.validators = Box::new(SimpleList::new(accounts.clone())); - p.step_duration = 4; + p.step_durations = [(0, 4)].to_vec().into_iter().collect(); p.empty_steps_transition = 0; p.maximum_empty_steps = 0; }); @@ -2789,9 +3553,9 @@ mod tests { header.set_author(accounts[0]); // when - engine.set_signer(Box::new((tap.clone(), accounts[1], "0".into()))); + engine.set_signer(Some(Box::new((tap.clone(), accounts[1], "0".into())))); let es1 = sealed_empty_step(&*engine, 1, &parent.hash()); - engine.set_signer(Box::new((tap.clone(), accounts[0], "1".into()))); + engine.set_signer(Some(Box::new((tap.clone(), accounts[0], "1".into())))); let es2 = sealed_empty_step(&*engine, 2, &parent.hash()); let mut empty_steps = vec![es2, es1]; @@ -2814,4 +3578,75 @@ mod tests { set_empty_steps_seal(&mut header, step, &signature, &empty_steps); assert_eq!(engine.verify_block_family(&header, &parent).unwrap(), ()); } + + #[test] + fn should_collect_block_reward_transitions() { + let config = r#"{ + "params": { + "stepDuration": "5", + "validators": { + "list" : ["0x1000000000000000000000000000000000000001"] + }, + "blockRewardContractTransition": "0", + "blockRewardContractAddress": "0x2000000000000000000000000000000000000002", + "blockRewardContractTransitions": { + "7": "0x3000000000000000000000000000000000000003", + "42": "0x4000000000000000000000000000000000000004" + } + } + }"#; + let deserialized: ethjson::spec::AuthorityRound = serde_json::from_str(config).unwrap(); + let params = AuthorityRoundParams::from(deserialized.params); + for ((block_num1, address1), (block_num2, address2)) in + params.block_reward_contract_transitions.iter().zip( + [ + ( + 0u64, + BlockRewardContract::new_from_address( + Address::from_str("2000000000000000000000000000000000000002").unwrap(), + ), + ), + ( + 7u64, + BlockRewardContract::new_from_address( + Address::from_str("3000000000000000000000000000000000000003").unwrap(), + ), + ), + ( + 42u64, + BlockRewardContract::new_from_address( + Address::from_str("4000000000000000000000000000000000000004").unwrap(), + ), + ), + ] + .iter(), + ) + { + assert_eq!(block_num1, block_num2); + assert_eq!(address1, address2); + } + } + + #[test] + #[should_panic( + expected = "blockRewardContractTransition should be less than any of the keys in blockRewardContractTransitions" + )] + fn should_reject_out_of_order_block_reward_transition() { + let config = r#"{ + "params": { + "stepDuration": "5", + "validators": { + "list" : ["0x1000000000000000000000000000000000000001"] + }, + "blockRewardContractTransition": "7", + "blockRewardContractAddress": "0x2000000000000000000000000000000000000002", + "blockRewardContractTransitions": { + "0": "0x3000000000000000000000000000000000000003", + "42": "0x4000000000000000000000000000000000000004" + } + } + }"#; + let deserialized: ethjson::spec::AuthorityRound = serde_json::from_str(config).unwrap(); + AuthorityRoundParams::from(deserialized.params); + } } diff --git a/crates/ethcore/src/engines/authority_round/randomness.rs b/crates/ethcore/src/engines/authority_round/randomness.rs new file mode 100644 index 0000000000..0113d80416 --- /dev/null +++ b/crates/ethcore/src/engines/authority_round/randomness.rs @@ -0,0 +1,257 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! On-chain randomness generation for authority round +//! +//! This module contains the support code for the on-chain randomness generation used by AuRa. Its +//! core is the finite state machine `RandomnessPhase`, which can be loaded from the blockchain +//! state, then asked to perform potentially necessary transaction afterwards using the `advance()` +//! method. +//! +//! No additional state is kept inside the `RandomnessPhase`, it must be passed in each time. +//! +//! The process of generating random numbers is a simple finite state machine: +//! +//! ```text +//! + +//! | +//! | +//! | +//! +--------------+ +-------v-------+ +//! | | | | +//! | BeforeCommit <------------------------------+ Waiting | +//! | | enter commit phase | | +//! +------+-------+ +-------^-------+ +//! | | +//! | call | +//! | `commitHash()` | call +//! | | `revealNumber()` +//! | | +//! +------v-------+ +-------+-------+ +//! | | | | +//! | Committed +------------------------------> Reveal | +//! | | enter reveal phase | | +//! +--------------+ +---------------+ +//! ``` +//! +//! Phase transitions are performed by the smart contract and simply queried by the engine. +//! +//! Randomness generation works as follows: +//! * During the commit phase, all validators locally generate a random number, and commit that number's hash to the +//! contract. +//! * During the reveal phase, all validators reveal their local random number to the contract. The contract should +//! verify that it matches the committed hash. +//! * Finally, the XOR of all revealed numbers is used as an on-chain random number. +//! +//! An adversary can only influence that number by either controlling _all_ validators who committed, or, to a lesser +//! extent, by not revealing committed numbers. +//! The length of the commit and reveal phases, as well as any penalties for failure to reveal, are defined by the +//! contract. +//! +//! A typical case of using `RandomnessPhase` is: +//! +//! 1. `RandomnessPhase::load()` the phase from the blockchain data. +//! 2. Call `RandomnessPhase::advance()`. +//! +//! A production implementation of a randomness contract can be found here: +//! https://github.com/poanetwork/posdao-contracts/blob/4fddb108993d4962951717b49222327f3d94275b/contracts/RandomAuRa.sol + +use bytes::Bytes; +use crypto::publickey::{ecies, Error as CryptoError}; +use derive_more::Display; +use engines::signer::EngineSigner; +use ethabi::Hash; +use ethabi_contract::use_contract; +use ethereum_types::{Address, H256, U256}; +use hash::keccak; +use log::{debug, error}; +use rand::Rng; + +use super::util::{BoundContract, CallError}; + +/// Random number type expected by the contract: This is generated locally, kept secret during the commit phase, and +/// published in the reveal phase. +pub type RandNumber = H256; + +use_contract!(aura_random, "res/contracts/authority_round_random.json"); + +/// Validated randomness phase state. +#[derive(Debug)] +pub enum RandomnessPhase { + // NOTE: Some states include information already gathered during `load` (e.g. `our_address`, + // `round`) for efficiency reasons. + /// Waiting for the next phase. + /// + /// This state indicates either the successful revelation in this round or having missed the + /// window to make a commitment, i.e. having failed to commit during the commit phase. + Waiting, + /// Indicates a commitment is possible, but still missing. + BeforeCommit, + /// Indicates a successful commitment, waiting for the commit phase to end. + Committed, + /// Indicates revealing is expected as the next step. + Reveal { our_address: Address, round: U256 }, +} + +/// Phase loading error for randomness generation state machine. +/// +/// This error usually indicates a bug in either the smart contract, the phase loading function or +/// some state being lost. +/// +/// `BadRandNumber` will usually result in punishment by the contract or the other validators. +#[derive(Debug, Display)] +pub enum PhaseError { + /// The smart contract reported that we already revealed something while still being in the + /// commit phase. + #[display(fmt = "Revealed during commit phase")] + RevealedInCommit, + /// Failed to load contract information. + #[display(fmt = "Error loading randomness contract information: {:?}", _0)] + LoadFailed(CallError), + /// Failed to load the stored encrypted random number. + #[display(fmt = "Failed to load random number from the randomness contract")] + BadRandNumber, + /// Failed to encrypt random number. + #[display(fmt = "Failed to encrypt random number: {}", _0)] + Crypto(CryptoError), + /// Failed to get the engine signer's public key. + #[display(fmt = "Failed to get the engine signer's public key")] + MissingPublicKey, +} + +impl From for PhaseError { + fn from(err: CryptoError) -> PhaseError { + PhaseError::Crypto(err) + } +} + +impl RandomnessPhase { + /// Determine randomness generation state from the contract. + /// + /// Calls various constant contract functions to determine the precise state that needs to be + /// handled (that is, the phase and whether or not the current validator still needs to send + /// commitments or reveal random numbers). + pub fn load( + contract: &BoundContract, + our_address: Address, + ) -> Result { + // Determine the current round and which phase we are in. + let round = contract + .call_const(aura_random::functions::current_collect_round::call()) + .map_err(PhaseError::LoadFailed)?; + let is_commit_phase = contract + .call_const(aura_random::functions::is_commit_phase::call()) + .map_err(PhaseError::LoadFailed)?; + + // Ensure we are not committing or revealing twice. + let committed = contract + .call_const(aura_random::functions::is_committed::call( + round, + our_address, + )) + .map_err(PhaseError::LoadFailed)?; + let revealed: bool = contract + .call_const(aura_random::functions::sent_reveal::call( + round, + our_address, + )) + .map_err(PhaseError::LoadFailed)?; + + // With all the information known, we can determine the actual state we are in. + if is_commit_phase { + if revealed { + return Err(PhaseError::RevealedInCommit); + } + + if !committed { + Ok(RandomnessPhase::BeforeCommit) + } else { + Ok(RandomnessPhase::Committed) + } + } else { + if !committed { + // We apparently entered too late to make a commitment, wait until we get a chance again. + return Ok(RandomnessPhase::Waiting); + } + + if !revealed { + Ok(RandomnessPhase::Reveal { our_address, round }) + } else { + Ok(RandomnessPhase::Waiting) + } + } + } + + /// Advance the random seed construction process as far as possible. + /// + /// Returns the encoded contract call necessary to advance the randomness contract's state. + /// + /// **Warning**: After calling the `advance()` function, wait until the returned transaction has been included in + /// a block before calling it again; otherwise spurious transactions resulting in punishments might be executed. + pub fn advance( + self, + contract: &BoundContract, + rng: &mut R, + signer: &dyn EngineSigner, + ) -> Result, PhaseError> { + match self { + RandomnessPhase::Waiting | RandomnessPhase::Committed => Ok(None), + RandomnessPhase::BeforeCommit => { + // Generate a new random number, but don't reveal it yet. Instead, we publish its hash to the + // randomness contract, together with the number encrypted to ourselves. That way we will later be + // able to decrypt and reveal it, and other parties are able to verify it against the hash. + let number: RandNumber = rng.gen(); + let number_hash: Hash = keccak(number.0); + let public = signer.public().ok_or(PhaseError::MissingPublicKey)?; + let cipher = ecies::encrypt(&public, number_hash.as_bytes(), number.as_bytes())?; + + debug!(target: "engine", "Randomness contract: committing {}.", number_hash); + // Return the call data for the transaction that commits the hash and the encrypted number. + let (data, _decoder) = + aura_random::functions::commit_hash::call(number_hash, cipher); + Ok(Some(data)) + } + RandomnessPhase::Reveal { round, our_address } => { + // Load the hash and encrypted number that we stored in the commit phase. + let call = aura_random::functions::get_commit_and_cipher::call(round, our_address); + let (committed_hash, cipher) = + contract.call_const(call).map_err(PhaseError::LoadFailed)?; + + // Decrypt the number and check against the hash. + let number_bytes = signer.decrypt(&committed_hash.0, &cipher)?; + let number = if number_bytes.len() == 32 { + RandNumber::from_slice(&number_bytes) + } else { + // This can only happen if there is a bug in the smart contract, + // or if the entire network goes awry. + error!(target: "engine", "Decrypted random number has the wrong length."); + return Err(PhaseError::BadRandNumber); + }; + let number_hash: Hash = keccak(number.0); + if number_hash != committed_hash { + error!(target: "engine", "Decrypted random number doesn't agree with the hash."); + return Err(PhaseError::BadRandNumber); + } + + debug!(target: "engine", "Randomness contract: scheduling tx to reveal our random number {} (round={}, our_address={}).", number_hash, round, our_address); + // We are now sure that we have the correct secret and can reveal it. So we return the call data for the + // transaction that stores the revealed random bytes on the contract. + let (data, _decoder) = aura_random::functions::reveal_number::call(number.0); + Ok(Some(data)) + } + } + } +} diff --git a/crates/ethcore/src/engines/authority_round/util.rs b/crates/ethcore/src/engines/authority_round/util.rs new file mode 100644 index 0000000000..3b50a087f2 --- /dev/null +++ b/crates/ethcore/src/engines/authority_round/util.rs @@ -0,0 +1,119 @@ +// Copyright 2015-2020 Parity Technologies (UK) Ltd. +// This file is part of OpenEthereum. + +// OpenEthereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// OpenEthereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with OpenEthereum. If not, see . + +//! Utility functions. +//! +//! Contains small functions used by the AuRa engine that are not strictly limited to that scope. + +use std::fmt; + +use client::{traits::EngineClient, BlockChainClient}; +use ethabi::{self, FunctionOutputDecoder}; +use ethabi_contract::use_contract; +use ethereum_types::{Address, U256}; +use log::{debug, error}; +use types::{header::Header, ids::BlockId}; + +/// A contract bound to a client and block number. +/// +/// A bound contract is a combination of a `Client` reference, a `BlockId` and a contract `Address`. +/// These three parts are enough to call a contract's function; return values are automatically +/// decoded. +pub struct BoundContract<'a> { + client: &'a dyn EngineClient, + block_id: BlockId, + contract_addr: Address, +} + +/// Contract call failed error. +#[derive(Debug)] +pub enum CallError { + /// The call itself failed. + CallFailed(String), + /// Decoding the return value failed or the decoded value was a failure. + DecodeFailed(ethabi::Error), + /// The passed in client reference could not be upgraded to a `BlockchainClient`. + NotFullClient, +} + +impl<'a> fmt::Debug for BoundContract<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("BoundContract") + .field("client", &(self.client as *const dyn EngineClient)) + .field("block_id", &self.block_id) + .field("contract_addr", &self.contract_addr) + .finish() + } +} + +impl<'a> BoundContract<'a> { + /// Create a new `BoundContract`. + pub fn new( + client: &dyn EngineClient, + block_id: BlockId, + contract_addr: Address, + ) -> BoundContract { + BoundContract { + client, + block_id, + contract_addr, + } + } + + /// Perform a function call to an Ethereum machine that doesn't create a transaction or change the state. + /// + /// Runs a constant function call on `client`. The `call` value can be serialized by calling any + /// api function generated by the `use_contract!` macro. This does not create any transactions, it only produces a + /// result based on the state at the current block: It is constant in the sense that it does not alter the EVM + /// state. + pub fn call_const(&self, call: (ethabi::Bytes, D)) -> Result + where + D: ethabi::FunctionOutputDecoder, + { + let (data, output_decoder) = call; + + let call_return = self + .client + .as_full_client() + .ok_or(CallError::NotFullClient)? + .call_contract(self.block_id, self.contract_addr, data) + .map_err(CallError::CallFailed)?; + + // Decode the result and return it. + output_decoder + .decode(call_return.as_slice()) + .map_err(CallError::DecodeFailed) + } +} + +use_contract!(contract, "res/contracts/block_gas_limit.json"); + +pub fn block_gas_limit( + full_client: &dyn BlockChainClient, + header: &Header, + address: Address, +) -> Option { + let (data, decoder) = contract::functions::block_gas_limit::call(); + let value = full_client.call_contract(BlockId::Hash(*header.parent_hash()), address, data).map_err(|err| { + error!(target: "block_gas_limit", "Contract call failed. Not changing the block gas limit. {:?}", err); + }).ok()?; + if value.is_empty() { + debug!(target: "block_gas_limit", "Contract call returned nothing. Not changing the block gas limit."); + None + } else { + decoder.decode(&value).ok() + } +} diff --git a/crates/ethcore/src/engines/basic_authority.rs b/crates/ethcore/src/engines/basic_authority.rs index f1b9e7baf9..91add1a8b7 100644 --- a/crates/ethcore/src/engines/basic_authority.rs +++ b/crates/ethcore/src/engines/basic_authority.rs @@ -20,7 +20,7 @@ use super::validator_set::{new_validator_set, SimpleList, ValidatorSet}; use block::*; use client::EngineClient; use crypto::publickey::{self, Signature}; -use engines::{signer::EngineSigner, ConstructedVerifier, Engine, EngineError, Seal}; +use engines::{signer::EngineSigner, ConstructedVerifier, Engine, EngineError, Seal, SealingState}; use error::{BlockError, Error}; use ethereum_types::{H256, H520}; use ethjson; @@ -104,8 +104,12 @@ impl Engine for BasicAuthority { 1 } - fn seals_internally(&self) -> Option { - Some(self.signer.read().is_some()) + fn sealing_state(&self) -> SealingState { + if self.signer.read().is_some() { + SealingState::Ready + } else { + SealingState::NotReady + } } /// Attempt to seal the block internally. @@ -197,8 +201,8 @@ impl Engine for BasicAuthority { self.validators.register_client(client); } - fn set_signer(&self, signer: Box) { - *self.signer.write() = Some(signer); + fn set_signer(&self, signer: Option>) { + *self.signer.write() = signer; } fn sign(&self, hash: H256) -> Result { @@ -223,7 +227,7 @@ impl Engine for BasicAuthority { mod tests { use accounts::AccountProvider; use block::*; - use engines::Seal; + use engines::{Seal, SealingState}; use ethereum_types::H520; use hash::keccak; use spec::Spec; @@ -269,7 +273,7 @@ mod tests { let spec = new_test_authority(); let engine = &*spec.engine; - engine.set_signer(Box::new((Arc::new(tap), addr, "".into()))); + engine.set_signer(Some(Box::new((Arc::new(tap), addr, "".into())))); let genesis_header = spec.genesis_header(); let db = spec .ensure_db_good(get_temp_state_db(), &Default::default()) @@ -296,13 +300,15 @@ mod tests { } #[test] - fn seals_internally() { + fn sealing_state() { let tap = AccountProvider::transient_provider(); let authority = tap.insert_account(keccak("").into(), &"".into()).unwrap(); let engine = new_test_authority().engine; - assert!(!engine.seals_internally().unwrap()); - engine.set_signer(Box::new((Arc::new(tap), authority, "".into()))); - assert!(engine.seals_internally().unwrap()); + assert_eq!(SealingState::NotReady, engine.sealing_state()); + engine.set_signer(Some(Box::new((Arc::new(tap), authority, "".into())))); + assert_eq!(SealingState::Ready, engine.sealing_state()); + engine.set_signer(None); + assert_eq!(SealingState::NotReady, engine.sealing_state()); } } diff --git a/crates/ethcore/src/engines/clique/mod.rs b/crates/ethcore/src/engines/clique/mod.rs index 9952e87a17..6ab84f6d85 100644 --- a/crates/ethcore/src/engines/clique/mod.rs +++ b/crates/ethcore/src/engines/clique/mod.rs @@ -38,8 +38,8 @@ /// /// 1. Set a signer using `Engine::set_signer()`. If a miner account was set up through /// a config file or CLI flag `MinerService::set_author()` will eventually set the signer -/// 2. We check that the engine seals internally through `Clique::seals_internally()` -/// Note: This is always true for Clique +/// 2. We check that the engine is ready for sealing through `Clique::sealing_state()` +/// Note: This is always `SealingState::Ready` for Clique /// 3. Calling `Clique::new()` will spawn a `StepService` thread. This thread will call `Engine::step()` /// periodically. Internally, the Clique `step()` function calls `Client::update_sealing()`, which is /// what makes and seals a block. @@ -71,7 +71,7 @@ use client::{traits::ForceUpdateSealing, BlockId, EngineClient}; use crypto::publickey::Signature; use engines::{ clique::util::{extract_signers, recover_creator}, - Engine, EngineError, Seal, + Engine, EngineError, Seal, SealingState, }; use error::{BlockError, Error}; use ethereum_types::{Address, H160, H256, H64, U256}; @@ -476,8 +476,8 @@ impl Engine for Clique { } /// Clique doesn't require external work to seal, so we always return true here. - fn seals_internally(&self) -> Option { - Some(true) + fn sealing_state(&self) -> SealingState { + SealingState::Ready } /// Returns if we are ready to seal, the real sealing (signing extra_data) is actually done in `on_seal_block()`. @@ -766,9 +766,14 @@ impl Engine for Clique { } } - fn set_signer(&self, signer: Box) { - trace!(target: "engine", "set_signer: {}", signer.address()); - *self.signer.write() = Some(signer); + fn set_signer(&self, signer: Option>) { + let mut current_signer = self.signer.write(); + if let Some(signer) = signer.as_ref() { + trace!(target: "engine", "set_signer: {:?}", signer.address()); + } else if let Some(signer) = &*current_signer { + trace!(target: "engine", "set_signer: cleared; previous signer: {:?})", signer.address()); + } + *current_signer = signer; } fn register_client(&self, client: Weak) { diff --git a/crates/ethcore/src/engines/instant_seal.rs b/crates/ethcore/src/engines/instant_seal.rs index 6d944a52ff..8410476d8b 100644 --- a/crates/ethcore/src/engines/instant_seal.rs +++ b/crates/ethcore/src/engines/instant_seal.rs @@ -15,7 +15,7 @@ // along with OpenEthereum. If not, see . use block::ExecutedBlock; -use engines::{Engine, Seal}; +use engines::{Engine, Seal, SealingState}; use machine::Machine; use std::sync::atomic::{AtomicU64, Ordering}; use types::header::{ExtendedHeader, Header}; @@ -63,8 +63,8 @@ impl Engine for InstantSeal { &self.machine } - fn seals_internally(&self) -> Option { - Some(true) + fn sealing_state(&self) -> SealingState { + SealingState::Ready } fn should_reseal_on_update(&self) -> bool { diff --git a/crates/ethcore/src/engines/mod.rs b/crates/ethcore/src/engines/mod.rs index f2c2f66aec..aff6c5e7b4 100644 --- a/crates/ethcore/src/engines/mod.rs +++ b/crates/ethcore/src/engines/mod.rs @@ -89,6 +89,10 @@ pub enum EngineError { InsufficientProof(String), /// Failed system call. FailedSystemCall(String), + /// Failed to decode the result of a system call. + SystemCallResultDecoding(String), + /// The result of a system call is invalid. + SystemCallResultInvalid(String), /// Malformed consensus message. MalformedMessage(String), /// Requires client ref, but none registered. @@ -153,6 +157,12 @@ impl fmt::Display for EngineError { BadSealFieldSize(ref oob) => format!("Seal field has an unexpected length: {}", oob), InsufficientProof(ref msg) => format!("Insufficient validation proof: {}", msg), FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg), + SystemCallResultDecoding(ref msg) => { + format!("Failed to decode the result of a system call: {}", msg) + } + SystemCallResultInvalid(ref msg) => { + format!("The result of a system call is invalid: {}", msg) + } MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg), RequiresClient => format!("Call requires client but none registered"), RequiresSigner => format!("Call requires signer but none registered"), @@ -180,6 +190,17 @@ pub enum Seal { None, } +/// The type of sealing the engine is currently able to perform. +#[derive(Debug, PartialEq, Eq)] +pub enum SealingState { + /// The engine is ready to seal a block. + Ready, + /// The engine can't seal at the moment, and no block should be prepared and queued. + NotReady, + /// The engine does not seal internally. + External, +} + /// A system-calling closure. Enacts calls on a block's state from the system address. pub type SystemCall<'a> = dyn FnMut(Address, Vec) -> Result, String> + 'a; @@ -329,11 +350,9 @@ pub trait Engine: Sync + Send { Ok(()) } - /// None means that it requires external input (e.g. PoW) to seal a block. - /// Some(true) means the engine is currently prime for seal generation (i.e. node is the current validator). - /// Some(false) means that the node might seal internally but is not qualified now. - fn seals_internally(&self) -> Option { - None + /// Returns the engine's current sealing state. + fn sealing_state(&self) -> SealingState { + SealingState::External } /// Called in `miner.chain_new_blocks` if the engine wishes to `update_sealing` @@ -449,7 +468,7 @@ pub trait Engine: Sync + Send { } /// Register a component which signs consensus messages. - fn set_signer(&self, _signer: Box) {} + fn set_signer(&self, _signer: Option>) {} /// Sign using the EngineSigner, to be used for consensus tx signing. fn sign(&self, _hash: H256) -> Result { @@ -505,6 +524,24 @@ pub trait Engine: Sync + Send { fn executive_author(&self, header: &Header) -> Result { Ok(*header.author()) } + + /// Returns a list of transactions for a new block if we are the author. + /// + /// This is called when the miner prepares a new block that this node will author and seal. It returns a list of + /// transactions that will be added to the block before any other transactions from the queue. + /// Added for AuRa needs. + fn generate_engine_transactions( + &self, + _block: &ExecutedBlock, + ) -> Result, Error> { + Ok(Vec::new()) + } + + /// Overrides the block gas limit. Whenever this returns `Some` for a header, the next block's gas limit must be + /// exactly that value. used by AuRa engine. + fn gas_limit_override(&self, _header: &Header) -> Option { + None + } } /// t_nb 9.3 Check whether a given block is the best block based on the default total difficulty rule. @@ -610,6 +647,11 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { let schedule = self.schedule(best_block_number); self.machine().decode_transaction(transaction, &schedule) } + + /// The configured minimum gas limit. Used by AuRa Engine. + fn min_gas_limit(&self) -> U256 { + self.params().min_gas_limit + } } // convenience wrappers for existing functions. diff --git a/crates/ethcore/src/engines/signer.rs b/crates/ethcore/src/engines/signer.rs index 74fb61f9c4..373661e889 100644 --- a/crates/ethcore/src/engines/signer.rs +++ b/crates/ethcore/src/engines/signer.rs @@ -16,8 +16,9 @@ //! A signer used by Engines which need to sign messages. -use crypto::publickey::{self, Signature}; +use crypto::publickey::{self, ecies, Error, Public, Signature}; use ethereum_types::{Address, H256}; +//TODO dr /// Everything that an Engine needs to sign messages. pub trait EngineSigner: Send + Sync { @@ -26,6 +27,12 @@ pub trait EngineSigner: Send + Sync { /// Signing address fn address(&self) -> Address; + + /// Decrypt a message that was encrypted to this signer's key. + fn decrypt(&self, auth_data: &[u8], cipher: &[u8]) -> Result, Error>; + + /// The signer's public key, if available. + fn public(&self) -> Option; } /// Creates a new `EngineSigner` from given key pair. @@ -43,6 +50,14 @@ impl EngineSigner for Signer { fn address(&self) -> Address { self.0.address() } + + fn decrypt(&self, auth_data: &[u8], cipher: &[u8]) -> Result, Error> { + ecies::decrypt(self.0.secret(), auth_data, cipher).map_err(From::from) + } + + fn public(&self) -> Option { + Some(*self.0.public()) + } } #[cfg(test)] @@ -78,5 +93,18 @@ mod test_signer { fn address(&self) -> Address { self.1 } + + fn decrypt(&self, auth_data: &[u8], cipher: &[u8]) -> Result, Error> { + self.0 + .decrypt(self.1, None, auth_data, cipher) + .map_err(|e| { + warn!("Unable to decrypt message: {:?}", e); + Error::InvalidMessage + }) + } + + fn public(&self) -> Option { + self.0.account_public(self.1, &self.2).ok() + } } } diff --git a/crates/ethcore/src/engines/validator_set/contract.rs b/crates/ethcore/src/engines/validator_set/contract.rs index 451d8e39ce..a4b781689f 100644 --- a/crates/ethcore/src/engines/validator_set/contract.rs +++ b/crates/ethcore/src/engines/validator_set/contract.rs @@ -19,12 +19,14 @@ use std::sync::Weak; use bytes::Bytes; -use ethereum_types::{Address, H256}; +use ethereum_types::{Address, H256, U256}; use machine::{AuxiliaryData, Call, EthereumMachine}; use parking_lot::RwLock; -use types::{header::Header, BlockNumber}; +use types::{header::Header, ids::BlockId, transaction, BlockNumber}; -use client::EngineClient; +use client::{traits::TransactionRequest, EngineClient}; + +use error::Error as EthcoreError; use super::{safe_contract::ValidatorSafeContract, SimpleList, SystemCall, ValidatorSet}; @@ -35,34 +37,87 @@ pub struct ValidatorContract { contract_address: Address, validators: ValidatorSafeContract, client: RwLock>>, // TODO [keorn]: remove + posdao_transition: Option, } impl ValidatorContract { - pub fn new(contract_address: Address) -> Self { + pub fn new(contract_address: Address, posdao_transition: Option) -> Self { ValidatorContract { contract_address, - validators: ValidatorSafeContract::new(contract_address), + validators: ValidatorSafeContract::new(contract_address, posdao_transition), client: RwLock::new(None), + posdao_transition, } } -} -impl ValidatorContract { - fn transact(&self, data: Bytes) -> Result<(), String> { + fn transact( + &self, + data: Bytes, + gas_price: Option, + client: &dyn EngineClient, + ) -> Result<(), String> { + let full_client = client.as_full_client().ok_or("No full client!")?; + let tx_request = TransactionRequest::call(self.contract_address, data).gas_price(gas_price); + match full_client.transact(tx_request) { + Ok(()) | Err(transaction::Error::AlreadyImported) => Ok(()), + Err(e) => Err(e.to_string())?, + } + } + + fn do_report_malicious( + &self, + address: &Address, + block: BlockNumber, + proof: Bytes, + ) -> Result<(), EthcoreError> { let client = self .client .read() .as_ref() .and_then(Weak::upgrade) - .ok_or_else(|| "No client!")?; - - match client.as_full_client() { - Some(c) => { - c.transact_contract(self.contract_address, data) - .map_err(|e| format!("Transaction import error: {}", e))?; - Ok(()) - } - None => Err("No full client!".into()), + .ok_or("No client!")?; + let latest = client + .block_header(BlockId::Latest) + .ok_or("No latest block!")?; + if !self.contains(&latest.parent_hash(), address) { + warn!(target: "engine", "Not reporting {} on block {}: Not a validator", address, block); + return Ok(()); + } + let data = + validator_report::functions::report_malicious::encode_input(*address, block, proof); + self.validators + .enqueue_report(*address, block, data.clone()); + let gas_price = self.report_gas_price(latest.number()); + self.transact(data, gas_price, &*client)?; + warn!(target: "engine", "Reported malicious validator {} at block {}", address, block); + Ok(()) + } + + fn do_report_benign(&self, address: &Address, block: BlockNumber) -> Result<(), EthcoreError> { + let client = self + .client + .read() + .as_ref() + .and_then(Weak::upgrade) + .ok_or("No client!")?; + let latest = client + .block_header(BlockId::Latest) + .ok_or("No latest block!")?; + let data = validator_report::functions::report_benign::encode_input(*address, block); + let gas_price = self.report_gas_price(latest.number()); + self.transact(data, gas_price, &*client)?; + warn!(target: "engine", "Benign report for validator {} at block {}", address, block); + Ok(()) + } + + /// Returns the gas price for report transactions. + /// + /// After `posdaoTransition`, this is zero. Otherwise it is the default (`None`). + fn report_gas_price(&self, block: BlockNumber) -> Option { + if self.posdao_transition? <= block { + Some(0.into()) + } else { + None } } } @@ -72,6 +127,20 @@ impl ValidatorSet for ValidatorContract { self.validators.default_caller(id) } + fn generate_engine_transactions( + &self, + first: bool, + header: &Header, + call: &mut SystemCall, + ) -> Result, EthcoreError> { + self.validators + .generate_engine_transactions(first, header, call) + } + + fn on_close_block(&self, header: &Header, address: &Address) -> Result<(), EthcoreError> { + self.validators.on_close_block(header, address) + } + fn on_epoch_begin( &self, first: bool, @@ -127,19 +196,14 @@ impl ValidatorSet for ValidatorContract { block: BlockNumber, proof: Bytes, ) { - let data = - validator_report::functions::report_malicious::encode_input(*address, block, proof); - match self.transact(data) { - Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address), - Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), + if let Err(s) = self.do_report_malicious(address, block, proof) { + warn!(target: "engine", "Validator {} could not be reported ({}) on block {}", address, s, block); } } fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) { - let data = validator_report::functions::report_benign::encode_input(*address, block); - match self.transact(data) { - Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), - Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), + if let Err(s) = self.do_report_benign(address, block) { + warn!(target: "engine", "Validator {} could not be reported ({}) on block {}", address, s, block); } } @@ -155,7 +219,8 @@ mod tests { use accounts::AccountProvider; use bytes::ToPretty; use call_contract::CallContract; - use client::{BlockChainClient, BlockInfo, ChainInfo}; + use client::{traits::TransactionRequest, BlockChainClient, BlockInfo, ChainInfo}; + use ethabi::FunctionOutputDecoder; use ethereum_types::{Address, H520}; use hash::keccak; use miner::{self, MinerService}; @@ -169,11 +234,8 @@ mod tests { #[test] fn fetches_validators() { let client = generate_dummy_client_with_spec(Spec::new_validator_contract); - let vc = Arc::new(ValidatorContract::new( - "0000000000000000000000000000000000000005" - .parse::
() - .unwrap(), - )); + let addr: Address = "0000000000000000000000000000000000000005".parse().unwrap(); + let vc = Arc::new(ValidatorContract::new(addr, None)); vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); assert!(vc.contains( @@ -219,6 +281,8 @@ mod tests { assert!(client.engine().verify_block_external(&header).is_err()); client.engine().step(); assert_eq!(client.chain_info().best_block_number, 0); + // `reportBenign` when the designated proposer releases block from the future (bad clock). + assert!(client.engine().verify_block_basic(&header).is_err()); // Now create one that is more in future. That one should be rejected and validator should be reported. let mut header = Header::default(); @@ -232,7 +296,7 @@ mod tests { // Seal a block. client.engine().step(); assert_eq!(client.chain_info().best_block_number, 1); - // Check if the unresponsive validator is `disliked`. + // Check if the unresponsive validator is `disliked`. "d8f2e0bf" accesses the field `disliked`.. assert_eq!( client .call_contract( @@ -254,10 +318,23 @@ mod tests { client.engine().step(); client.engine().step(); assert_eq!(client.chain_info().best_block_number, 2); + let (data, decoder) = + super::validator_report::functions::malice_reported_for_block::call(v1, 1); + let reported_enc = client + .call_contract(BlockId::Latest, validator_contract, data) + .expect("call failed"); + assert_ne!( + Vec::
::new(), + decoder.decode(&reported_enc).expect("decoding failed") + ); // Check if misbehaving validator was removed. + client - .transact_contract(Default::default(), Default::default()) + .transact(TransactionRequest::call( + Default::default(), + Default::default(), + )) .unwrap(); client.engine().step(); client.engine().step(); diff --git a/crates/ethcore/src/engines/validator_set/mod.rs b/crates/ethcore/src/engines/validator_set/mod.rs index e9f2d6b994..c47e747f55 100644 --- a/crates/ethcore/src/engines/validator_set/mod.rs +++ b/crates/ethcore/src/engines/validator_set/mod.rs @@ -33,31 +33,49 @@ use types::{header::Header, ids::BlockId, BlockNumber}; use client::EngineClient; +use error::Error as EthcoreError; + pub use self::simple_list::SimpleList; #[cfg(test)] pub use self::test::TestSet; use self::{contract::ValidatorContract, multi::Multi, safe_contract::ValidatorSafeContract}; use super::SystemCall; -/// Creates a validator set from spec. -pub fn new_validator_set(spec: ValidatorSpec) -> Box { +/// Creates a validator set from the given spec and initializes a transition to POSDAO AuRa consensus. +pub fn new_validator_set_posdao( + spec: ValidatorSpec, + posdao_transition: Option, +) -> Box { match spec { ValidatorSpec::List(list) => { Box::new(SimpleList::new(list.into_iter().map(Into::into).collect())) } - ValidatorSpec::SafeContract(address) => { - Box::new(ValidatorSafeContract::new(address.into())) + ValidatorSpec::SafeContract(address) => Box::new(ValidatorSafeContract::new( + address.into(), + posdao_transition, + )), + ValidatorSpec::Contract(address) => { + Box::new(ValidatorContract::new(address.into(), posdao_transition)) } - ValidatorSpec::Contract(address) => Box::new(ValidatorContract::new(address.into())), ValidatorSpec::Multi(sequence) => Box::new(Multi::new( sequence .into_iter() - .map(|(block, set)| (block.into(), new_validator_set(set))) + .map(|(block, set)| { + ( + block.into(), + new_validator_set_posdao(set, posdao_transition), + ) + }) .collect(), )), } } +/// Creates a validator set from the given spec. +pub fn new_validator_set(spec: ValidatorSpec) -> Box { + new_validator_set_posdao(spec, None) +} + /// A validator set. pub trait ValidatorSet: Send + Sync + 'static { /// Get the default "Call" helper, for use in general operation. @@ -65,6 +83,21 @@ pub trait ValidatorSet: Send + Sync + 'static { // a strict dependency on state always being available. fn default_caller(&self, block_id: BlockId) -> Box; + /// Called for each new block this node is creating. If this block is + /// the first block of an epoch, this is called *after* `on_epoch_begin()`, + /// but with the same parameters. + /// + /// Returns a list of contract calls to be pushed onto the new block. + fn generate_engine_transactions( + &self, + _first: bool, + _header: &Header, + _call: &mut SystemCall, + ) -> Result, EthcoreError>; + + /// Called on the close of every block. + fn on_close_block(&self, _header: &Header, _address: &Address) -> Result<(), EthcoreError>; + /// Checks if a given address is a validator, /// using underlying, default call mechanism. fn contains(&self, parent: &H256, address: &Address) -> bool { diff --git a/crates/ethcore/src/engines/validator_set/multi.rs b/crates/ethcore/src/engines/validator_set/multi.rs index 01618e5af4..358413618e 100644 --- a/crates/ethcore/src/engines/validator_set/multi.rs +++ b/crates/ethcore/src/engines/validator_set/multi.rs @@ -25,6 +25,7 @@ use types::{header::Header, ids::BlockId, BlockNumber}; use super::{SystemCall, ValidatorSet}; use client::EngineClient; +use error::Error as EthcoreError; use machine::{AuxiliaryData, Call, EthereumMachine}; type BlockNumberLookup = @@ -47,6 +48,15 @@ impl Multi { } } + fn map_children(&self, header: &Header, mut func: F) -> Result + where + F: FnMut(&dyn ValidatorSet, bool) -> Result, + { + let (set_block, set) = self.correct_set_by_number(header.number()); + let first = set_block == header.number(); + func(set, first) + } + fn correct_set(&self, id: BlockId) -> Option<&dyn ValidatorSet> { match self.block_number.read()(id) .map(|parent_block| self.correct_set_by_number(parent_block)) @@ -81,16 +91,31 @@ impl ValidatorSet for Multi { .unwrap_or_else(|| Box::new(|_, _| Err("No validator set for given ID.".into()))) } - fn on_epoch_begin( + fn generate_engine_transactions( &self, _first: bool, header: &Header, call: &mut SystemCall, - ) -> Result<(), ::error::Error> { - let (set_block, set) = self.correct_set_by_number(header.number()); - let first = set_block == header.number(); + ) -> Result, EthcoreError> { + self.map_children(header, &mut |set: &dyn ValidatorSet, first| { + set.generate_engine_transactions(first, header, call) + }) + } + fn on_close_block(&self, header: &Header, address: &Address) -> Result<(), EthcoreError> { + self.map_children(header, &mut |set: &dyn ValidatorSet, _first| { + set.on_close_block(header, address) + }) + } - set.on_epoch_begin(first, header, call) + fn on_epoch_begin( + &self, + _first: bool, + header: &Header, + call: &mut SystemCall, + ) -> Result<(), EthcoreError> { + self.map_children(header, &mut |set: &dyn ValidatorSet, first| { + set.on_epoch_begin(first, header, call) + }) } fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result, String> { @@ -182,7 +207,10 @@ impl ValidatorSet for Multi { #[cfg(test)] mod tests { use accounts::AccountProvider; - use client::{traits::ForceUpdateSealing, BlockChainClient, BlockInfo, ChainInfo, ImportBlock}; + use client::{ + traits::{ForceUpdateSealing, TransactionRequest}, + BlockChainClient, BlockInfo, ChainInfo, ImportBlock, + }; use crypto::publickey::Secret; use engines::{validator_set::ValidatorSet, EpochChange}; use ethereum_types::Address; @@ -190,7 +218,7 @@ mod tests { use miner::{self, MinerService}; use spec::Spec; use std::{collections::BTreeMap, sync::Arc}; - use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; + use test_helpers::generate_dummy_client_with_spec; use types::{header::Header, ids::BlockId}; use verification::queue::kind::blocks::Unverified; @@ -216,7 +244,10 @@ mod tests { let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); client - .transact_contract(Default::default(), Default::default()) + .transact(TransactionRequest::call( + Default::default(), + Default::default(), + )) .unwrap(); ::client::EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 0); @@ -227,7 +258,10 @@ mod tests { assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. client - .transact_contract(Default::default(), Default::default()) + .transact(TransactionRequest::call( + Default::default(), + Default::default(), + )) .unwrap(); ::client::EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 1); @@ -237,14 +271,16 @@ mod tests { assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. client - .transact_contract(Default::default(), Default::default()) + .transact(TransactionRequest::call( + Default::default(), + Default::default(), + )) .unwrap(); ::client::EngineClient::update_sealing(&*client, ForceUpdateSealing::No); assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. - let sync_client = - generate_dummy_client_with_spec_and_data(Spec::new_validator_multi, 0, 0, &[]); + let sync_client = generate_dummy_client_with_spec(Spec::new_validator_multi); sync_client .engine() .register_client(Arc::downgrade(&sync_client) as _); diff --git a/crates/ethcore/src/engines/validator_set/safe_contract.rs b/crates/ethcore/src/engines/validator_set/safe_contract.rs index 30e8403f11..451617e2f5 100644 --- a/crates/ethcore/src/engines/validator_set/safe_contract.rs +++ b/crates/ethcore/src/engines/validator_set/safe_contract.rs @@ -15,25 +15,39 @@ // along with OpenEthereum. If not, see . /// Validator set maintained in a contract, updated using `getValidators` method. -use std::sync::{Arc, Weak}; +use std::{ + collections::VecDeque, + sync::{Arc, Weak}, +}; use bytes::Bytes; +use error::{Error as EthcoreError, ErrorKind as EthcoreErrorKind}; use ethabi::FunctionOutputDecoder; use ethereum_types::{Address, Bloom, H256, U256}; use hash::keccak; use kvdb::DBValue; use memory_cache::MemoryLruCache; -use parking_lot::RwLock; +use parking_lot::{Mutex, RwLock}; use rlp::{Rlp, RlpStream}; -use types::{header::Header, ids::BlockId, log_entry::LogEntry, receipt::TypedReceipt}; +use types::{ + header::Header, ids::BlockId, log_entry::LogEntry, receipt::TypedReceipt, transaction, + BlockNumber, +}; use unexpected::Mismatch; use super::{simple_list::SimpleList, SystemCall, ValidatorSet}; -use client::EngineClient; +use client::{traits::TransactionRequest, BlockChainClient, EngineClient}; use machine::{AuxiliaryData, AuxiliaryRequest, Call, EthereumMachine}; use_contract!(validator_set, "res/contracts/validator_set.json"); +/// The maximum number of reports to keep queued. +const MAX_QUEUED_REPORTS: usize = 10; +/// The maximum number of malice reports to include when creating a new block. +const MAX_REPORTS_PER_BLOCK: usize = 10; +/// Don't re-send malice reports every block. Skip this many before retrying. +const REPORTS_SKIP_BLOCKS: u64 = 1; + const MEMOIZE_CAPACITY: usize = 500; // TODO: ethabi should be able to generate this. @@ -71,6 +85,12 @@ pub struct ValidatorSafeContract { contract_address: Address, validators: RwLock>, client: RwLock>>, // TODO [keorn]: remove + report_queue: Mutex, + /// The block number where we resent the queued reports last time. + resent_reports_in_block: Mutex, + /// If set, this is the block number at which the consensus engine switches from AuRa to AuRa + /// with POSDAO modifications. + posdao_transition: Option, } // first proof is just a state proof call of `getValidators` at header's state. @@ -203,14 +223,54 @@ fn prove_initial( } impl ValidatorSafeContract { - pub fn new(contract_address: Address) -> Self { + pub fn new(contract_address: Address, posdao_transition: Option) -> Self { ValidatorSafeContract { contract_address, validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)), client: RwLock::new(None), + report_queue: Mutex::new(ReportQueue::default()), + resent_reports_in_block: Mutex::new(0), + posdao_transition, + } + } + + fn transact(&self, data: Bytes, nonce: U256) -> Result<(), EthcoreError> { + let client = self + .client + .read() + .as_ref() + .and_then(Weak::upgrade) + .ok_or("No client!")?; + let full_client = client.as_full_client().ok_or("No full client!")?; + + let tx_request = TransactionRequest::call(self.contract_address, data) + .gas_price(U256::zero()) + .nonce(nonce); + match full_client.transact(tx_request) { + Ok(()) | Err(transaction::Error::AlreadyImported) => Ok(()), + Err(e) => Err(e)?, } } + /// Puts a malice report into the queue for later resending. + /// + /// # Arguments + /// + /// * `addr` - The address of the misbehaving validator. + /// * `block` - The block number at which the misbehavior occurred. + /// * `data` - The call data for the `reportMalicious` contract call. + pub(crate) fn enqueue_report(&self, addr: Address, block: BlockNumber, data: Vec) { + // Skip the rest of the function unless there has been a transition to POSDAO AuRa. + if self + .posdao_transition + .map_or(true, |block_num| block < block_num) + { + trace!(target: "engine", "Skipping queueing a malicious behavior report"); + return; + } + self.report_queue.lock().push(addr, block, data) + } + /// Queries the state and gets the set of validators. fn get_list(&self, caller: &Call) -> Option { let contract_address = self.contract_address; @@ -314,6 +374,110 @@ impl ValidatorSet for ValidatorSafeContract { }) // generate no proofs in general } + fn generate_engine_transactions( + &self, + _first: bool, + header: &Header, + caller: &mut SystemCall, + ) -> Result, EthcoreError> { + // Skip the rest of the function unless there has been a transition to POSDAO AuRa. + if self + .posdao_transition + .map_or(true, |block_num| header.number() < block_num) + { + trace!(target: "engine", "Skipping a call to emitInitiateChange"); + return Ok(Vec::new()); + } + let mut transactions = Vec::new(); + + // Create the `InitiateChange` event if necessary. + let (data, decoder) = validator_set::functions::emit_initiate_change_callable::call(); + let emit_initiate_change_callable = caller(self.contract_address, data) + .and_then(|x| { + decoder + .decode(&x) + .map_err(|x| format!("chain spec bug: could not decode: {:?}", x)) + }) + .map_err(::engines::EngineError::FailedSystemCall)?; + if !emit_initiate_change_callable { + trace!(target: "engine", "New block #{} issued ― no need to call emitInitiateChange()", header.number()); + } else { + trace!(target: "engine", "New block issued #{} ― calling emitInitiateChange()", header.number()); + let (data, _decoder) = validator_set::functions::emit_initiate_change::call(); + transactions.push((self.contract_address, data)); + } + + let client = self + .client + .read() + .as_ref() + .and_then(Weak::upgrade) + .ok_or("No client!")?; + let client = client.as_full_client().ok_or("No full client!")?; + + // Retry all pending reports. + let mut report_queue = self.report_queue.lock(); + report_queue.filter(client, header.author(), self.contract_address); + for (_address, _block, data) in report_queue.iter().take(MAX_REPORTS_PER_BLOCK) { + transactions.push((self.contract_address, data.clone())) + } + + Ok(transactions) + } + + fn on_close_block(&self, header: &Header, our_address: &Address) -> Result<(), EthcoreError> { + // Skip the rest of the function unless there has been a transition to POSDAO AuRa. + if self + .posdao_transition + .map_or(true, |block_num| header.number() < block_num) + { + trace!(target: "engine", "Skipping resending of queued malicious behavior reports"); + return Ok(()); + } + + let client = self + .client + .read() + .as_ref() + .and_then(Weak::upgrade) + .ok_or("No client!")?; + let client = client.as_full_client().ok_or("No full client!")?; + + let mut report_queue = self.report_queue.lock(); + report_queue.filter(client, our_address, self.contract_address); + report_queue.truncate(); + + let mut resent_reports_in_block = self.resent_reports_in_block.lock(); + + // Skip at least one block after sending malicious reports last time. + if header.number() > *resent_reports_in_block + REPORTS_SKIP_BLOCKS { + *resent_reports_in_block = header.number(); + let mut nonce = client.latest_nonce(our_address); + for (address, block, data) in report_queue.iter() { + debug!(target: "engine", "Retrying to report validator {} for misbehavior on block {} with nonce {}.", + address, block, nonce); + while match self.transact(data.clone(), nonce) { + Ok(()) => false, + Err(EthcoreError( + EthcoreErrorKind::Transaction(transaction::Error::Old), + _, + )) => true, + Err(err) => { + warn!(target: "engine", "Cannot report validator {} for misbehavior on block {}: {}", + address, block, err); + false + } + } { + warn!(target: "engine", "Nonce {} already used. Incrementing.", nonce); + nonce += U256::from(1); + } + nonce += U256::from(1); + } + } + + Ok(()) + } + fn on_epoch_begin( &self, _first: bool, @@ -473,6 +637,68 @@ impl ValidatorSet for ValidatorSafeContract { } } +/// A queue containing pending reports of malicious validators. +#[derive(Debug, Default)] +struct ReportQueue(VecDeque<(Address, BlockNumber, Vec)>); + +impl ReportQueue { + /// Pushes a report to the end of the queue. + fn push(&mut self, addr: Address, block: BlockNumber, data: Vec) { + self.0.push_back((addr, block, data)); + } + + /// Filters reports of validators that have already been reported or are banned. + fn filter( + &mut self, + client: &dyn BlockChainClient, + our_address: &Address, + contract_address: Address, + ) { + self.0.retain(|&(malicious_validator_address, block, ref _data)| { + trace!( + target: "engine", + "Checking if report of malicious validator {} at block {} should be removed from cache", + malicious_validator_address, + block + ); + // Check if the validator should be reported. + let (data, decoder) = validator_set::functions::should_validator_report::call( + *our_address, malicious_validator_address, block + ); + match client.call_contract(BlockId::Latest, contract_address, data) + .and_then(|result| decoder.decode(&result[..]).map_err(|e| e.to_string())) + { + Ok(false) => { + trace!(target: "engine", "Successfully removed report from report cache"); + false + } + Ok(true) => true, + Err(err) => { + warn!(target: "engine", "Failed to query report status {:?}, dropping pending report.", err); + false + } + } + }); + } + + /// Returns an iterator over all transactions in the queue. + fn iter(&self) -> impl Iterator)> { + self.0.iter() + } + + /// Removes reports from the queue if it contains more than `MAX_QUEUED_REPORTS` entries. + fn truncate(&mut self) { + if self.0.len() > MAX_QUEUED_REPORTS { + warn!( + target: "engine", + "Removing {} reports from report cache, even though it has not been finalized", + self.0.len() - MAX_QUEUED_REPORTS + ); + self.0.truncate(MAX_QUEUED_REPORTS); + } + } +} + #[cfg(test)] mod tests { use super::{super::ValidatorSet, ValidatorSafeContract, EVENT_NAME_HASH}; @@ -488,7 +714,7 @@ mod tests { use rustc_hex::FromHex; use spec::Spec; use std::sync::Arc; - use test_helpers::{generate_dummy_client_with_spec, generate_dummy_client_with_spec_and_data}; + use test_helpers::generate_dummy_client_with_spec; use types::{ ids::BlockId, transaction::{Action, Transaction, TypedTransaction}, @@ -498,11 +724,8 @@ mod tests { #[test] fn fetches_validators() { let client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); - let vc = Arc::new(ValidatorSafeContract::new( - "0000000000000000000000000000000000000005" - .parse::
() - .unwrap(), - )); + let addr: Address = "0000000000000000000000000000000000000005".parse().unwrap(); + let vc = Arc::new(ValidatorSafeContract::new(addr, None)); vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); assert!(vc.contains( @@ -600,8 +823,7 @@ mod tests { assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. - let sync_client = - generate_dummy_client_with_spec_and_data(Spec::new_validator_safe_contract, 0, 0, &[]); + let sync_client = generate_dummy_client_with_spec(Spec::new_validator_safe_contract); sync_client .engine() .register_client(Arc::downgrade(&sync_client) as _); diff --git a/crates/ethcore/src/engines/validator_set/simple_list.rs b/crates/ethcore/src/engines/validator_set/simple_list.rs index 8e44204625..c608d68a07 100644 --- a/crates/ethcore/src/engines/validator_set/simple_list.rs +++ b/crates/ethcore/src/engines/validator_set/simple_list.rs @@ -18,7 +18,9 @@ use ethereum_types::{Address, H256}; /// Preconfigured validator list. use parity_util_mem::MallocSizeOf; -use super::ValidatorSet; +use super::{SystemCall, ValidatorSet}; +use bytes::Bytes; +use error::Error as EthcoreError; use machine::{AuxiliaryData, Call, EthereumMachine}; use types::{header::Header, BlockNumber}; @@ -63,6 +65,19 @@ impl ValidatorSet for SimpleList { Box::new(|_, _| Err("Simple list doesn't require calls.".into())) } + fn generate_engine_transactions( + &self, + _first: bool, + _header: &Header, + _call: &mut SystemCall, + ) -> Result, EthcoreError> { + Ok(Vec::new()) + } + + fn on_close_block(&self, _header: &Header, _address: &Address) -> Result<(), EthcoreError> { + Ok(()) + } + fn is_epoch_end(&self, first: bool, _chain_head: &Header) -> Option> { match first { true => Some(Vec::new()), // allow transition to fixed list, and instantly diff --git a/crates/ethcore/src/engines/validator_set/test.rs b/crates/ethcore/src/engines/validator_set/test.rs index ab96a42e69..88db87f75b 100644 --- a/crates/ethcore/src/engines/validator_set/test.rs +++ b/crates/ethcore/src/engines/validator_set/test.rs @@ -26,11 +26,12 @@ use ethereum_types::{Address, H256}; use parity_util_mem::MallocSizeOf; use types::{header::Header, BlockNumber}; -use super::{SimpleList, ValidatorSet}; +use super::{SimpleList, SystemCall, ValidatorSet}; +use error::Error as EthcoreError; use machine::{AuxiliaryData, Call, EthereumMachine}; /// Set used for testing with a single validator. -#[derive(MallocSizeOf)] +#[derive(Clone, MallocSizeOf)] pub struct TestSet { validator: SimpleList, last_malicious: Arc, @@ -54,6 +55,21 @@ impl TestSet { last_benign, } } + + pub fn from_validators(validators: Vec
) -> Self { + let mut ts = TestSet::new(Default::default(), Default::default()); + ts.validator = SimpleList::new(validators); + ts + } + + pub fn last_malicious(&self) -> usize { + self.last_malicious.load(AtomicOrdering::SeqCst) + } + + #[allow(dead_code)] + pub fn last_benign(&self) -> usize { + self.last_benign.load(AtomicOrdering::SeqCst) + } } impl ValidatorSet for TestSet { @@ -61,6 +77,19 @@ impl ValidatorSet for TestSet { Box::new(|_, _| Err("Test set doesn't require calls.".into())) } + fn generate_engine_transactions( + &self, + _first: bool, + _header: &Header, + _call: &mut SystemCall, + ) -> Result, EthcoreError> { + Ok(Vec::new()) + } + + fn on_close_block(&self, _header: &Header, _address: &Address) -> Result<(), EthcoreError> { + Ok(()) + } + fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option> { None } diff --git a/crates/ethcore/src/lib.rs b/crates/ethcore/src/lib.rs index 1b8dcac708..5a0c1b0e33 100644 --- a/crates/ethcore/src/lib.rs +++ b/crates/ethcore/src/lib.rs @@ -21,6 +21,7 @@ extern crate ansi_term; extern crate common_types as types; extern crate crossbeam_utils; +extern crate derive_more; extern crate ethabi; extern crate ethash; extern crate ethcore_blockchain as blockchain; diff --git a/crates/ethcore/src/miner/miner.rs b/crates/ethcore/src/miner/miner.rs index d56127d386..d9336e538c 100644 --- a/crates/ethcore/src/miner/miner.rs +++ b/crates/ethcore/src/miner/miner.rs @@ -60,7 +60,7 @@ use client::{ BlockChain, BlockId, BlockProducer, ChainInfo, ClientIoMessage, Nonce, SealedBlockImporter, TransactionId, TransactionInfo, }; -use engines::{EngineSigner, EthEngine, Seal}; +use engines::{EngineSigner, EthEngine, Seal, SealingState}; use error::{Error, ErrorKind}; use executed::ExecutionError; use executive::contract_address; @@ -288,7 +288,8 @@ impl Miner { Miner { sealing: Mutex::new(SealingWork { queue: UsingQueue::new(options.work_queue_size), - enabled: options.force_sealing || spec.engine.seals_internally().is_some(), + enabled: options.force_sealing + || spec.engine.sealing_state() != SealingState::External, next_allowed_reseal: Instant::now(), next_mandatory_reseal: Instant::now() + options.reseal_max_period, last_request: None, @@ -319,6 +320,17 @@ impl Miner { /// /// NOTE This should be only used for tests. pub fn new_for_tests(spec: &Spec, accounts: Option>) -> Miner { + Miner::new_for_tests_force_sealing(spec, accounts, false) + } + + /// Creates new instance of miner with given spec and accounts. + /// + /// NOTE This should be only used for tests. + pub fn new_for_tests_force_sealing( + spec: &Spec, + accounts: Option>, + force_sealing: bool, + ) -> Miner { let minimal_gas_price = 0.into(); Miner::new( MinerOptions { @@ -329,6 +341,7 @@ impl Miner { no_early_reject: false, }, reseal_min_period: Duration::from_secs(0), + force_sealing, ..Default::default() }, GasPricer::new_fixed(minimal_gas_price), @@ -419,8 +432,8 @@ impl Miner { trace_time!("prepare_block"); let chain_info = chain.chain_info(); - // Open block - let (mut open_block, original_work_hash) = { + // Some engines add transactions to the block for their own purposes, e.g. AuthorityRound RANDAO. + let (mut open_block, original_work_hash, engine_txs) = { let mut sealing = self.sealing.lock(); let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash()); let best_hash = chain_info.best_block_hash; @@ -431,41 +444,50 @@ impl Miner { // if at least one was pushed successfully, close and enqueue new ClosedBlock; // otherwise, leave everything alone. // otherwise, author a fresh block. - let mut open_block = match sealing + match sealing .queue .get_pending_if(|b| b.header.parent_hash() == &best_hash) { Some(old_block) => { trace!(target: "miner", "prepare_block: Already have previous work; updating and returning"); // add transactions to old_block - chain.reopen_block(old_block) + (chain.reopen_block(old_block), last_work_hash, Vec::new()) } None => { // block not found - create it. trace!(target: "miner", "prepare_block: No existing work - making new block"); let params = self.params.read().clone(); - match chain.prepare_open_block( + let block = match chain.prepare_open_block( params.author, params.gas_range_target, params.extra_data, ) { Ok(block) => block, Err(err) => { - warn!(target: "miner", "Open new block failed with error {:?}. This is likely an error in chain specificiations or on-chain consensus smart contracts.", err); + warn!(target: "miner", "Open new block failed with error {:?}. This is likely an error in \ + chain specification or on-chain consensus smart contracts.", err); + return None; + } + }; + // Before adding from the queue to the new block, give the engine a chance to add transactions. + match self.engine.generate_engine_transactions(&block) { + Ok(transactions) => (block, last_work_hash, transactions), + Err(err) => { + error!(target: "miner", "Failed to prepare engine transactions for new block: {:?}. \ + This is likely an error in chain specification or on-chain consensus smart \ + contracts.", err); return None; } } } - }; - - if self.options.infinite_pending_block { - open_block.remove_gas_limit(); } - - (open_block, last_work_hash) }; + if self.options.infinite_pending_block { + open_block.remove_gas_limit(); + } + let mut invalid_transactions = HashSet::new(); let mut not_allowed_transactions = HashSet::new(); let mut senders_to_penalize = HashSet::new(); @@ -501,13 +523,13 @@ impl Miner { ) }; - let pending: Vec> = self.transaction_queue.pending( + let queue_txs: Vec> = self.transaction_queue.pending( client.clone(), pool::PendingSettings { block_number: chain_info.best_block_number, current_timestamp: chain_info.best_block_timestamp, nonce_cap, - max_len: max_transactions, + max_len: max_transactions.saturating_sub(engine_txs.len()), ordering: miner::PendingOrdering::Priority, }, ); @@ -517,12 +539,14 @@ impl Miner { }; let block_start = Instant::now(); - debug!(target: "miner", "Attempting to push {} transactions.", pending.len()); + debug!(target: "miner", "Attempting to push {} transactions.", engine_txs.len() + queue_txs.len()); - for tx in pending { + for transaction in engine_txs + .into_iter() + .chain(queue_txs.into_iter().map(|tx| tx.signed().clone())) + { let start = Instant::now(); - let transaction = tx.signed().clone(); let hash = transaction.hash(); let sender = transaction.sender(); @@ -670,7 +694,7 @@ impl Miner { // keep sealing enabled if any of the conditions is met let sealing_enabled = self.forced_sealing() || self.transaction_queue.has_local_pending_transactions() - || self.engine.seals_internally() == Some(true) + || self.engine.sealing_state() == SealingState::Ready || had_requests; let should_disable_sealing = !sealing_enabled; @@ -679,7 +703,7 @@ impl Miner { should_disable_sealing, self.forced_sealing(), self.transaction_queue.has_local_pending_transactions(), - self.engine.seals_internally(), + self.engine.sealing_state(), had_requests, ); @@ -862,6 +886,11 @@ impl Miner { } }; + if self.engine.sealing_state() != SealingState::External { + trace!(target: "miner", "prepare_pending_block: engine not sealing externally; not preparing"); + return BlockPreparationStatus::NotPrepared; + } + let preparation_status = if prepare_new { // -------------------------------------------------------------------------- // | NOTE Code below requires sealing locks. | @@ -896,7 +925,9 @@ impl Miner { fn prepare_and_update_sealing(&self, chain: &C) { // Make sure to do it after transaction is imported and lock is dropped. // We need to create pending block and enable sealing. - if self.engine.seals_internally().unwrap_or(false) + let sealing_state = self.engine.sealing_state(); + + if sealing_state == SealingState::Ready || self.prepare_pending_block(chain) == BlockPreparationStatus::NotPrepared { // If new block has not been prepared (means we already had one) @@ -924,21 +955,38 @@ impl miner::MinerService for Miner { self.params.write().extra_data = extra_data; } - fn set_author(&self, author: Author) { - self.params.write().author = author.address(); - - if let Author::Sealer(signer) = author { - if self.engine.seals_internally().is_some() { - // Enable sealing - self.sealing.lock().enabled = true; - // -------------------------------------------------------------------------- - // | NOTE Code below may require author and sealing locks | - // | (some `Engine`s call `EngineClient.update_sealing()`) | - // | Make sure to release the locks before calling that method. | - // -------------------------------------------------------------------------- - self.engine.set_signer(signer); - } else { - warn!("Setting an EngineSigner while Engine does not require one."); + fn set_author>>(&self, author: T) { + let author_opt = author.into(); + self.params.write().author = author_opt.as_ref().map(Author::address).unwrap_or_default(); + + match author_opt { + Some(Author::Sealer(signer)) => { + if self.engine.sealing_state() != SealingState::External { + // Enable sealing + self.sealing.lock().enabled = true; + // -------------------------------------------------------------------------- + // | NOTE Code below may require author and sealing locks | + // | (some `Engine`s call `EngineClient.update_sealing()`) | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- + self.engine.set_signer(Some(signer)); + } else { + warn!("Setting an EngineSigner while Engine does not require one."); + } + } + Some(Author::External(_address)) => (), + None => { + // Clear the author. + if self.engine.sealing_state() != SealingState::External { + // Disable sealing. + self.sealing.lock().enabled = false; + // -------------------------------------------------------------------------- + // | NOTE Code below may require author and sealing locks | + // | (some `Engine`s call `EngineClient.update_sealing()`) | + // | Make sure to release the locks before calling that method. | + // -------------------------------------------------------------------------- + self.engine.set_signer(None); + } } } } @@ -1257,6 +1305,11 @@ impl miner::MinerService for Miner { return; } + let sealing_state = self.engine.sealing_state(); + if sealing_state == SealingState::NotReady { + return; + } + // -------------------------------------------------------------------------- // | NOTE Code below requires sealing locks. | // | Make sure to release the locks before calling that method. | @@ -1277,20 +1330,23 @@ impl miner::MinerService for Miner { } } - match self.engine.seals_internally() { - Some(true) => { + match sealing_state { + SealingState::Ready => { trace!(target: "miner", "update_sealing: engine indicates internal sealing"); if self.seal_and_import_block_internally(chain, block) { trace!(target: "miner", "update_sealing: imported internally sealed block"); } return; } - Some(false) => { - trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now"); - // anyway, save the block for later use - self.sealing.lock().queue.set_pending(block); + SealingState::NotReady => { + unreachable!("We returned right after sealing_state was computed. qed.") } - None => { + // => { + // trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now"); + // // anyway, save the block for later use + // self.sealing.lock().queue.set_pending(block); + // } + SealingState::External => { trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work"); self.prepare_work(block, original_work_hash); } @@ -1305,7 +1361,7 @@ impl miner::MinerService for Miner { where C: BlockChain + CallContract + BlockProducer + SealedBlockImporter + Nonce + Sync, { - if self.engine.seals_internally().is_some() { + if self.engine.sealing_state() != SealingState::External { return None; } diff --git a/crates/ethcore/src/miner/mod.rs b/crates/ethcore/src/miner/mod.rs index ddd0f76301..1efb981977 100644 --- a/crates/ethcore/src/miner/mod.rs +++ b/crates/ethcore/src/miner/mod.rs @@ -152,7 +152,7 @@ pub trait MinerService: Send + Sync { /// Set info necessary to sign consensus messages and block authoring. /// /// On chains where sealing is done externally (e.g. PoW) we provide only reward beneficiary. - fn set_author(&self, author: Author); + fn set_author>>(&self, author: T); // Transaction Pool diff --git a/crates/ethcore/src/snapshot/service.rs b/crates/ethcore/src/snapshot/service.rs index c212c3d7f3..3b31d97ffa 100644 --- a/crates/ethcore/src/snapshot/service.rs +++ b/crates/ethcore/src/snapshot/service.rs @@ -1012,7 +1012,8 @@ mod tests { #[test] fn sends_async_messages() { let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()]; - let client = generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices); + let client = + generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices, false); let service = IoService::::start("Test").unwrap(); let spec = Spec::new_test(); diff --git a/crates/ethcore/src/snapshot/tests/service.rs b/crates/ethcore/src/snapshot/tests/service.rs index 801c11a206..7046d4b477 100644 --- a/crates/ethcore/src/snapshot/tests/service.rs +++ b/crates/ethcore/src/snapshot/tests/service.rs @@ -46,8 +46,13 @@ fn restored_is_equivalent() { const TX_PER: usize = 5; let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()]; - let client = - generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, TX_PER, &gas_prices); + let client = generate_dummy_client_with_spec_and_data( + Spec::new_null, + NUM_BLOCKS, + TX_PER, + &gas_prices, + false, + ); let tempdir = TempDir::new("").unwrap(); let client_db = tempdir.path().join("client_db"); @@ -112,7 +117,8 @@ fn restored_is_equivalent() { #[test] fn guards_delete_folders() { let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()]; - let client = generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices); + let client = + generate_dummy_client_with_spec_and_data(Spec::new_null, 400, 5, &gas_prices, false); let spec = Spec::new_null(); let tempdir = TempDir::new("").unwrap(); @@ -178,7 +184,7 @@ fn keep_ancient_blocks() { let spec_f = Spec::new_null; let spec = spec_f(); let client = - generate_dummy_client_with_spec_and_data(spec_f, NUM_BLOCKS as u32, 5, &gas_prices); + generate_dummy_client_with_spec_and_data(spec_f, NUM_BLOCKS as u32, 5, &gas_prices, false); let bc = client.chain(); @@ -298,7 +304,7 @@ fn recover_aborted_recovery() { const NUM_BLOCKS: u32 = 400; let gas_prices = vec![1.into(), 2.into(), 3.into(), 999.into()]; let client = - generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, 5, &gas_prices); + generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, 5, &gas_prices, false); let spec = Spec::new_null(); let tempdir = TempDir::new("oe_snapshot").unwrap(); diff --git a/crates/ethcore/src/spec/spec.rs b/crates/ethcore/src/spec/spec.rs index 2d0bb719d7..395afea39a 100644 --- a/crates/ethcore/src/spec/spec.rs +++ b/crates/ethcore/src/spec/spec.rs @@ -1063,6 +1063,12 @@ impl Spec { load_bundled!("test/constructor") } + /// Create a new Spec with Autority Round randomness contract + #[cfg(any(test, feature = "test-helpers"))] + pub fn new_test_round_randomness_contract() -> Spec { + load_bundled!("test/authority_round_randomness_contract") + } + /// Create a new Spec with AuthorityRound consensus which does internal sealing (not /// requiring work). /// Accounts with secrets keccak("0") and keccak("1") are the validators. diff --git a/crates/ethcore/src/test_helpers.rs b/crates/ethcore/src/test_helpers.rs index 13a1455715..a615862912 100644 --- a/crates/ethcore/src/test_helpers.rs +++ b/crates/ethcore/src/test_helpers.rs @@ -112,7 +112,7 @@ pub fn create_test_block_with_data( /// Generates dummy client (not test client) with corresponding amount of blocks pub fn generate_dummy_client(block_number: u32) -> Arc { - generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &[]) + generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &[], false) } /// Generates dummy client (not test client) with corresponding amount of blocks and txs per every block @@ -126,6 +126,7 @@ pub fn generate_dummy_client_with_data( block_number, txs_per_block, tx_gas_prices, + false, ) } @@ -134,7 +135,7 @@ pub fn generate_dummy_client_with_spec(test_spec: F) -> Arc where F: Fn() -> Spec, { - generate_dummy_client_with_spec_and_data(test_spec, 0, 0, &[]) + generate_dummy_client_with_spec_and_data(test_spec, 0, 0, &[], false) } /// Generates dummy client (not test client) with corresponding amount of blocks, txs per block and spec @@ -143,6 +144,7 @@ pub fn generate_dummy_client_with_spec_and_data( block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256], + force_sealing: bool, ) -> Arc where F: Fn() -> Spec, @@ -150,11 +152,13 @@ where let test_spec = test_spec(); let client_db = new_db(); + let miner = Miner::new_for_tests_force_sealing(&test_spec, None, force_sealing); + let client = Client::new( ClientConfig::default(), &test_spec, client_db, - Arc::new(Miner::new_for_tests(&test_spec, None)), + Arc::new(miner), IoChannel::disconnected(), ) .unwrap(); diff --git a/crates/ethcore/src/trace/types/trace.rs b/crates/ethcore/src/trace/types/trace.rs index 62a1160dd2..02034f5131 100644 --- a/crates/ethcore/src/trace/types/trace.rs +++ b/crates/ethcore/src/trace/types/trace.rs @@ -51,7 +51,7 @@ impl CreateResult { } } -/// Description of a _call_ action, either a `CALL` operation or a message transction. +/// Description of a _call_ action, either a `CALL` operation or a message transaction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] pub struct Call { /// The sending account. @@ -102,7 +102,7 @@ impl Call { } } -/// Description of a _create_ action, either a `CREATE` operation or a create transction. +/// Description of a _create_ action, either a `CREATE` operation or a create transaction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] pub struct Create { /// The address of the creator. diff --git a/crates/ethcore/src/tx_filter.rs b/crates/ethcore/src/tx_filter.rs index 3bcc7df90c..30f0744e72 100644 --- a/crates/ethcore/src/tx_filter.rs +++ b/crates/ethcore/src/tx_filter.rs @@ -35,6 +35,10 @@ use_contract!( "res/contracts/tx_acl_deprecated.json" ); use_contract!(transact_acl, "res/contracts/tx_acl.json"); +use_contract!( + transact_acl_gas_price, + "res/contracts/tx_acl_gas_price.json" +); const MAX_CACHE_SIZE: usize = 4096; @@ -99,6 +103,7 @@ impl TransactionFilter { let sender = transaction.sender(); let value = transaction.tx().value; + let gas_price = transaction.tx().gas_price; let key = (*parent_hash, sender); if let Some(permissions) = permission_cache.get_mut(&key) { @@ -138,6 +143,24 @@ impl TransactionFilter { (tx_permissions::NONE, true) }) } + 3 => { + trace!(target: "tx_filter", "Using filter with gas price and data"); + let (data, decoder) = + transact_acl_gas_price::functions::allowed_tx_types::call( + sender, + to, + value, + gas_price, + transaction.tx().data.clone(), + ); + client.call_contract(BlockId::Hash(*parent_hash), contract_address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) + .map(|(p, f)| (p.low_u32(), f)) + .unwrap_or_else(|e| { + error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); + (tx_permissions::NONE, true) + }) + } _ => { error!(target: "tx_filter", "Unknown version of tx permissions contract is used"); (tx_permissions::NONE, true) @@ -161,10 +184,7 @@ impl TransactionFilter { if filter_only_sender { permission_cache.insert((*parent_hash, sender), permissions); } - trace!(target: "tx_filter", - "Given transaction data: sender: {:?} to: {:?} value: {}. Permissions required: {:X}, got: {:X}", - sender, to, value, tx_type, permissions - ); + trace!(target: "tx_filter", "Given transaction data: sender: {:?} to: {:?} value: {}, gas_price: {}. Permissions required: {:X}, got: {:X}", sender, to, value, gas_price, tx_type, permissions); permissions & tx_type != 0 } } @@ -185,7 +205,7 @@ mod test { /// Contract code: https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f #[test] - fn transaction_filter() { + fn transaction_filter_ver_2() { let spec_data = include_str!("../res/chainspec/test/contract_ver_2_genesis.json"); let db = test_helpers::new_db(); @@ -418,6 +438,74 @@ mod test { )); } + /// Contract code: res/tx_permission_tests/contract_ver_3.sol + #[test] + fn transaction_filter_ver_3() { + let spec_data = include_str!("../res/chainspec/test/contract_ver_3_genesis.json"); + + let db = test_helpers::new_db(); + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap(); + + let client = Client::new( + ClientConfig::default(), + &spec, + db, + Arc::new(Miner::new_for_tests(&spec, None)), + IoChannel::disconnected(), + ) + .unwrap(); + let key1 = KeyPair::from_secret( + Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(), + ) + .unwrap(); + + // The only difference to version 2 is that the contract now knows the transaction's gas price and data. + // So we only test those: The contract allows only transactions with either nonzero gas price or short data. + + let filter = TransactionFilter::from_params(spec.params()).unwrap(); + let mut tx = TypedTransaction::Legacy(Transaction::default()); + tx.tx_mut().action = + Action::Call(Address::from_str("0000000000000000000000000000000000000042").unwrap()); + tx.tx_mut().data = b"01234567".to_vec(); + tx.tx_mut().gas_price = 0.into(); + + let genesis = client.block_hash(BlockId::Latest).unwrap(); + let block_number = 1; + + // Data too long and gas price zero. This transaction is not allowed. + assert!(!filter.transaction_allowed( + &genesis, + block_number, + &tx.clone().sign(key1.secret(), None), + &*client + )); + + // But if we either set a nonzero gas price or short data or both, it is allowed. + tx.tx_mut().gas_price = 1.into(); + assert!(filter.transaction_allowed( + &genesis, + block_number, + &tx.clone().sign(key1.secret(), None), + &*client + )); + tx.tx_mut().data = b"01".to_vec(); + assert!(filter.transaction_allowed( + &genesis, + block_number, + &tx.clone().sign(key1.secret(), None), + &*client + )); + tx.tx_mut().gas_price = 0.into(); + assert!(filter.transaction_allowed( + &genesis, + block_number, + &tx.clone().sign(key1.secret(), None), + &*client + )); + } + /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a #[test] fn transaction_filter_deprecated() { diff --git a/crates/ethcore/src/verification/verification.rs b/crates/ethcore/src/verification/verification.rs index f09cef8d37..6a11b8b189 100644 --- a/crates/ethcore/src/verification/verification.rs +++ b/crates/ethcore/src/verification/verification.rs @@ -83,7 +83,16 @@ pub fn verify_block_basic( } } - // t_nb 4.6 call engine.gas_limit_override (Used only by Aura) TODO added in new version + // t_nb 4.6 call engine.gas_limit_override (Used only by Aura) + if let Some(gas_limit) = engine.gas_limit_override(&block.header) { + if *block.header.gas_limit() != gas_limit { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { + min: Some(gas_limit), + max: Some(gas_limit), + found: *block.header.gas_limit(), + }))); + } + } // t_nb 4.7 for every transaction call engine.verify_transaction_basic for t in &block.transactions { @@ -358,25 +367,26 @@ pub fn verify_header_params( found: *header.gas_used(), }))); } - let min_gas_limit = engine.params().min_gas_limit; - if header.gas_limit() < &min_gas_limit { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { - min: Some(min_gas_limit), - max: None, - found: *header.gas_limit(), - }))); - } - if let Some(limit) = engine.maximum_gas_limit() { - if header.gas_limit() > &limit { - return Err(From::from(::error::BlockError::InvalidGasLimit( - OutOfBounds { + if engine.gas_limit_override(header).is_none() { + let min_gas_limit = engine.min_gas_limit(); + if header.gas_limit() < &min_gas_limit { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { + min: Some(min_gas_limit), + max: None, + found: *header.gas_limit(), + }))); + } + if let Some(limit) = engine.maximum_gas_limit() { + if header.gas_limit() > &limit { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(limit), found: *header.gas_limit(), - }, - ))); + }))); + } } } + let maximum_extra_data_size = engine.maximum_extra_data_size(); if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size { return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { @@ -435,8 +445,6 @@ fn verify_parent(header: &Header, parent: &Header, engine: &dyn EthEngine) -> Re "Parent hash should already have been verified; qed" ); - let gas_limit_divisor = engine.params().gas_limit_bound_divisor; - if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) { let now = SystemTime::now(); let min = CheckedSystemTime::checked_add( @@ -468,15 +476,18 @@ fn verify_parent(header: &Header, parent: &Header, engine: &dyn EthEngine) -> Re .into()); } - let parent_gas_limit = *parent.gas_limit(); - let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor; - let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor; - if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { - min: Some(min_gas), - max: Some(max_gas), - found: *header.gas_limit(), - }))); + if engine.gas_limit_override(header).is_none() { + let gas_limit_divisor = engine.params().gas_limit_bound_divisor; + let parent_gas_limit = *parent.gas_limit(); + let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor; + let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor; + if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { + min: Some(min_gas), + max: Some(max_gas), + found: *header.gas_limit(), + }))); + } } Ok(()) @@ -740,7 +751,7 @@ mod tests { // that's an invalid transaction list rlp let invalid_transactions = vec![vec![0u8]]; header.set_transactions_root(ordered_trie_root(&invalid_transactions)); - header.set_gas_limit(engine.params().min_gas_limit); + header.set_gas_limit(engine.min_gas_limit()); rlp.append(&header); rlp.append_list::, _>(&invalid_transactions); rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); @@ -759,7 +770,7 @@ mod tests { let spec = Spec::new_test(); let engine = &*spec.engine; - let min_gas_limit = engine.params().min_gas_limit; + let min_gas_limit = engine.min_gas_limit(); good.set_gas_limit(min_gas_limit); good.set_timestamp(40); good.set_number(10); diff --git a/crates/ethcore/types/src/transaction/error.rs b/crates/ethcore/types/src/transaction/error.rs index d3351cad85..d90be937f9 100644 --- a/crates/ethcore/types/src/transaction/error.rs +++ b/crates/ethcore/types/src/transaction/error.rs @@ -131,7 +131,7 @@ impl fmt::Display for Error { InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err), NotAllowed => { - "Sender does not have permissions to execute this type of transction".into() + "Sender does not have permissions to execute this type of transaction".into() } TooBig => "Transaction too big".into(), InvalidRlp(ref err) => format!("Transaction has invalid RLP structure: {}.", err), diff --git a/crates/ethjson/src/spec/authority_round.rs b/crates/ethjson/src/spec/authority_round.rs index f84e933a9b..a2893394fb 100644 --- a/crates/ethjson/src/spec/authority_round.rs +++ b/crates/ethjson/src/spec/authority_round.rs @@ -14,10 +14,33 @@ // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . -//! Authority params deserialization. +//! Authority Round parameter deserialization. +//! +//! Here is an example of input parameters where the step duration is constant at 5 seconds, the set +//! of validators is decided by the contract at address `0x10..01` starting from block 0, and where +//! the address of the contract that computes block rewards is set to `0x20..02` for blocks 0 +//! through 41 and to `0x30.03` for all blocks starting from block 42. +//! +//! ```ignore +//! "params": { +//! "stepDuration": "5", +//! "validators": { +//! "multi": { +//! "0": { +//! "contract": "0x1000000000000000000000000000000000000001" +//! } +//! } +//! }, +//! "blockRewardContractTransitions": { +//! "0": "0x2000000000000000000000000000000000000002", +//! "42": "0x3000000000000000000000000000000000000003" +//! } +//! } +//! ``` -use super::{BlockReward, ValidatorSet}; +use super::{BlockReward, StepDuration, ValidatorSet}; use crate::{bytes::Bytes, hash::Address, uint::Uint}; +use std::collections::BTreeMap; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -25,7 +48,7 @@ use crate::{bytes::Bytes, hash::Address, uint::Uint}; #[serde(rename_all = "camelCase")] pub struct AuthorityRoundParams { /// Block duration, in seconds. - pub step_duration: Uint, + pub step_duration: StepDuration, /// Valid authorities pub validators: ValidatorSet, /// Starting step. Determined automatically if not specified. @@ -39,11 +62,24 @@ pub struct AuthorityRoundParams { pub immediate_transitions: Option, /// Reward per block in wei. pub block_reward: Option, - /// Block at which the block reward contract should start being used. + /// Block at which the block reward contract should start being used. This option allows one to + /// add a single block reward contract transition and is compatible with the multiple address + /// option `block_reward_contract_transitions` below. pub block_reward_contract_transition: Option, - /// Block reward contract address (setting the block reward contract - /// overrides the static block reward definition). + /// Block reward contract address which overrides the `block_reward` setting. This option allows + /// one to add a single block reward contract address and is compatible with the multiple + /// address option `block_reward_contract_transitions` below. pub block_reward_contract_address: Option
, + /// Block reward contract addresses with their associated starting block numbers. + /// + /// Setting the block reward contract overrides `block_reward`. If the single block reward + /// contract address is also present then it is added into the map at the block number stored in + /// `block_reward_contract_transition` or 0 if that block number is not provided. Therefore both + /// a single block reward contract transition and a map of reward contract transitions can be + /// used simulataneously in the same configuration. In such a case the code requires that the + /// block number of the single transition is strictly less than any of the block numbers in the + /// map. + pub block_reward_contract_transitions: Option>, /// Block reward code. This overrides the block reward contract address. pub block_reward_contract_code: Option, /// Block at which maximum uncle count should be considered. @@ -56,13 +92,23 @@ pub struct AuthorityRoundParams { pub maximum_empty_steps: Option, /// Strict validation of empty steps transition block. pub strict_empty_steps_transition: Option, + /// First block for which a 2/3 quorum (instead of 1/2) is required. + pub two_thirds_majority_transition: Option, + /// The random number contract's address, or a map of contract transitions. + pub randomness_contract_address: Option>, + /// The addresses of contracts that determine the block gas limit starting from the block number + /// associated with each of those contracts. + pub block_gas_limit_contract_transitions: Option>, + /// The block number at which the consensus engine switches from AuRa to AuRa with POSDAO + /// modifications. + pub posdao_transition: Option, } /// Authority engine deserialization. #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] pub struct AuthorityRound { - /// Ethash params. + /// Authority Round parameters. pub params: AuthorityRoundParams, } @@ -73,7 +119,10 @@ mod tests { use super::BlockReward; use crate::{ hash::Address, - spec::{authority_round::AuthorityRound, validator_set::ValidatorSet}, + spec::{ + authority_round::AuthorityRound, step_duration::StepDuration, + validator_set::ValidatorSet, + }, uint::Uint, }; use ethereum_types::{H160, U256}; @@ -92,12 +141,23 @@ mod tests { "validateStepTransition": 150, "blockReward": 5000000, "maximumUncleCountTransition": 10000000, - "maximumUncleCount": 5 + "maximumUncleCount": 5, + "randomnessContractAddress": { + "10": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "20": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" + }, + "blockGasLimitContractTransitions": { + "10": "0x1000000000000000000000000000000000000001", + "20": "0x2000000000000000000000000000000000000002" + } } }"#; let deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); - assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); + assert_eq!( + deserialized.params.step_duration, + StepDuration::Single(Uint(U256::from(2))) + ); assert_eq!( deserialized.params.validators, ValidatorSet::List(vec![Address( @@ -115,9 +175,34 @@ mod tests { Some(Uint(5.into())) ); assert_eq!( - deserialized.params.block_reward, - Some(BlockReward::Single(Uint(5000000.into()))) - ) + deserialized.params.randomness_contract_address.unwrap(), + vec![ + ( + Uint(10.into()), + Address(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()) + ), + ( + Uint(20.into()), + Address(H160::from_str("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").unwrap()) + ), + ] + .into_iter() + .collect() + ); + let expected_bglc = [ + ( + Uint(10.into()), + Address(H160::from_str("1000000000000000000000000000000000000001").unwrap()), + ), + ( + Uint(20.into()), + Address(H160::from_str("2000000000000000000000000000000000000002").unwrap()), + ), + ]; + assert_eq!( + deserialized.params.block_gas_limit_contract_transitions, + Some(expected_bglc.to_vec().into_iter().collect()) + ); } #[test] @@ -136,7 +221,10 @@ mod tests { }"#; let deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); - assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02))); + assert_eq!( + deserialized.params.step_duration, + StepDuration::Single(Uint(U256::from(0x02))) + ); assert_eq!( deserialized.params.validators, ValidatorSet::Contract(Address( diff --git a/crates/ethjson/src/spec/mod.rs b/crates/ethjson/src/spec/mod.rs index 12955a2d9f..208aa636e9 100644 --- a/crates/ethjson/src/spec/mod.rs +++ b/crates/ethjson/src/spec/mod.rs @@ -30,6 +30,7 @@ pub mod params; pub mod seal; pub mod spec; pub mod state; +pub mod step_duration; pub mod validator_set; pub use self::{ @@ -47,5 +48,6 @@ pub use self::{ seal::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal}, spec::{ForkSpec, Spec}, state::State, + step_duration::StepDuration, validator_set::ValidatorSet, }; diff --git a/crates/ethjson/src/spec/step_duration.rs b/crates/ethjson/src/spec/step_duration.rs new file mode 100644 index 0000000000..8e14b70e87 --- /dev/null +++ b/crates/ethjson/src/spec/step_duration.rs @@ -0,0 +1,36 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Step duration configuration parameter + +use std::collections::BTreeMap; + +use serde::Deserialize; + +use crate::uint::Uint; + +/// Step duration can be specified either as a `Uint` (in seconds), in which case it will be +/// constant, or as a list of pairs consisting of a timestamp of type `Uint` and a duration, in +/// which case the duration of a step will be determined by a mapping arising from that list. +#[derive(Debug, PartialEq, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(untagged)] +pub enum StepDuration { + /// Duration of all steps. + Single(Uint), + /// Step duration transitions: a mapping of timestamp to step durations. + Transitions(BTreeMap), +} diff --git a/crates/rpc/src/v1/helpers/engine_signer.rs b/crates/rpc/src/v1/helpers/engine_signer.rs index 365ddae6ac..f98e8111fc 100644 --- a/crates/rpc/src/v1/helpers/engine_signer.rs +++ b/crates/rpc/src/v1/helpers/engine_signer.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use accounts::AccountProvider; -use crypto::publickey::{self, Address}; +use crypto::publickey::{self, Address, Error, Public}; use ethkey::Password; /// An implementation of EngineSigner using internal account management. @@ -49,7 +49,22 @@ impl ethcore::engines::EngineSigner for EngineSigner { } } + fn decrypt(&self, auth_data: &[u8], cipher: &[u8]) -> Result, Error> { + self.accounts + .decrypt(self.address, None, auth_data, cipher) + .map_err(|e| { + warn!("Unable to decrypt message: {:?}", e); + Error::InvalidMessage + }) + } + fn address(&self) -> Address { self.address } + + fn public(&self) -> Option { + self.accounts + .account_public(self.address, &self.password) + .ok() + } } diff --git a/crates/rpc/src/v1/impls/parity_set.rs b/crates/rpc/src/v1/impls/parity_set.rs index 62c1d801c1..5e2b137ae5 100644 --- a/crates/rpc/src/v1/impls/parity_set.rs +++ b/crates/rpc/src/v1/impls/parity_set.rs @@ -157,6 +157,11 @@ where Ok(true) } + fn clear_engine_signer(&self) -> Result { + self.miner.set_author(None); + Ok(true) + } + fn add_reserved_peer(&self, peer: String) -> Result { match self.net.add_reserved_peer(peer) { Ok(()) => Ok(true), diff --git a/crates/rpc/src/v1/tests/helpers/miner_service.rs b/crates/rpc/src/v1/tests/helpers/miner_service.rs index eb49da6adf..3af4a04aa7 100644 --- a/crates/rpc/src/v1/tests/helpers/miner_service.rs +++ b/crates/rpc/src/v1/tests/helpers/miner_service.rs @@ -134,10 +134,16 @@ impl MinerService for TestMinerService { self.authoring_params.read().clone() } - fn set_author(&self, author: miner::Author) { - self.authoring_params.write().author = author.address(); - if let miner::Author::Sealer(signer) = author { - *self.signer.write() = Some(signer); + fn set_author>>(&self, author: T) { + let author_opt = author.into(); + self.authoring_params.write().author = author_opt + .as_ref() + .map(miner::Author::address) + .unwrap_or_default(); + match author_opt { + Some(miner::Author::Sealer(signer)) => *self.signer.write() = Some(signer), + Some(miner::Author::External(_addr)) => (), + None => *self.signer.write() = None, } } diff --git a/crates/rpc/src/v1/traits/parity_set.rs b/crates/rpc/src/v1/traits/parity_set.rs index 2d64e613d0..fbaacb0ca5 100644 --- a/crates/rpc/src/v1/traits/parity_set.rs +++ b/crates/rpc/src/v1/traits/parity_set.rs @@ -57,6 +57,10 @@ pub trait ParitySet { #[rpc(name = "parity_setEngineSignerSecret")] fn set_engine_signer_secret(&self, _: H256) -> Result; + /// Unsets the engine signer account address. + #[rpc(name = "parity_clearEngineSigner")] + fn clear_engine_signer(&self) -> Result; + /// Sets the limits for transaction queue. #[rpc(name = "parity_setTransactionsLimit")] fn set_transactions_limit(&self, _: usize) -> Result; diff --git a/crates/vm/evm/benches/basic.rs b/crates/vm/evm/benches/basic.rs index 4d2d8e4a60..6199aa910b 100644 --- a/crates/vm/evm/benches/basic.rs +++ b/crates/vm/evm/benches/basic.rs @@ -28,6 +28,7 @@ extern crate parking_lot; extern crate rustc_hex; extern crate vm; +use bytes::Bytes; use criterion::{black_box, Bencher, Criterion}; use ethereum_types::{Address, U256}; use evm::Factory; @@ -37,6 +38,28 @@ use vm::{tests::FakeExt, ActionParams, Ext, GasLeft, Result}; criterion_group!( basic, + mul500, + mul1000, + div500, + div1000, + sdiv500, + sdiv1000, + mod500, + mod1000, + smod500, + smod1000, + addmod500, + addmod1000, + mulmod500, + mulmod1000, + mulmod1_500, + mulmod1_1000, + mulmod5_500, + mulmod5_1000, + mulmod11_500, + mulmod11_1000, + mulmod_big_500, + mulmod_big_1000, simple_loop_log0_usize, simple_loop_log0_u256, mem_gas_calculation_same_usize, @@ -206,3 +229,188 @@ fn result(r: Result) -> U256 { _ => U256::zero(), } } + +/// Runs a given EVM bytecode. +fn run_code(b: &mut Bencher, code: Bytes) { + let factory = Factory::default(); + let mut ext = FakeExt::new(); + b.iter(|| { + let mut params = ActionParams::default(); + params.address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + params.gas = U256::MAX; + params.code = Some(Arc::new(black_box(code.clone()))); + let vm = factory.create(params, ext.schedule(), 0); + result(vm.exec(&mut ext).ok().unwrap()) + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 1) 500 times. +fn mulmod1_500(b: &mut Criterion) { + b.bench_function("mulmod modulo 1, 500 times", |b| { + run_code(b, "6101f45b6001900360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 1) 1000 times. +fn mulmod1_1000(b: &mut Criterion) { + b.bench_function("mulmod modulo 1, 1000 times", |b| { + run_code(b, "6103e85b6001900360017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 5) 500 times. +fn mulmod5_500(b: &mut Criterion) { + b.bench_function("mulmod modulo 5, 500 times", |b| { + run_code(b, "6101f45b6001900360057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 5) 1000 times. +fn mulmod5_1000(b: &mut Criterion) { + b.bench_function("mulmod modulo 5, 1000 times", |b| { + run_code(b, "6103e85b6001900360057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 11) 500 times. +fn mulmod11_500(b: &mut Criterion) { + b.bench_function("mulmod modulo 11, 500 times", |b| { + run_code(b, "6101f45b60019003600b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 11) 1000 times. +fn mulmod11_1000(b: &mut Criterion) { + b.bench_function("mulmod modulo 11, 1000 times", |b| { + run_code(b, "6103e85b60019003600b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 0x58bca9711298bc76cd73f173352c8bc1d1640f977c1ec9a849dfde6fdbfbd591) 500 times. +fn mulmod_big_500(b: &mut Criterion) { + b.bench_function("mulmod modulo random 256-bit number, 500 times", |b| { + run_code(b, "6101f45b600190037f58bca9711298bc76cd73f173352c8bc1d1640f977c1ec9a849dfde6fdbfbd5917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(U256::MAX, U256::MAX, 0x58bca9711298bc76cd73f173352c8bc1d1640f977c1ec9a849dfde6fdbfbd591) 1000 times. +fn mulmod_big_1000(b: &mut Criterion) { + b.bench_function("mulmod modulo random 256-bit number, 1000 times", |b| { + run_code(b, "6103e85b600190037f58bca9711298bc76cd73f173352c8bc1d1640f977c1ec9a849dfde6fdbfbd5917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(a, b, c) for random 256-bit a, b and c. Iterate 500 times. +/// +/// Source: +/// ``` +/// PUSH2 0x01F4 +/// JUMPDEST +/// PUSH1 0x01 +/// SWAP1 +/// SUB +/// PUSH32 0x5ed6db9489224124a1a4110ec8bec8b01369c8b549a4b8c4388a1796dc35a937 +/// PUSH32 0xb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db +/// PUSH32 0xcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca +/// MULMOD +/// POP +/// DUP1 +/// PUSH1 0x03 +/// JUMPI +/// ``` +fn mulmod500(b: &mut Criterion) { + b.bench_function("mulmod randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037f5ed6db9489224124a1a4110ec8bec8b01369c8b549a4b8c4388a1796dc35a9377fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca095080600357".from_hex().unwrap()); + }); +} + +/// Compute mulmod(a, b, c) for random 256-bit a, b and c. Iterate 1000 times. +fn mulmod1000(b: &mut Criterion) { + b.bench_function("mulmod randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037f5ed6db9489224124a1a4110ec8bec8b01369c8b549a4b8c4388a1796dc35a9377fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca095080600357".from_hex().unwrap()); + }); +} + +/// Compute addmod(a, b, c) for random 256-bit a, b and c. Iterate 500 times. +fn addmod500(b: &mut Criterion) { + b.bench_function("addmod randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037f5ed6db9489224124a1a4110ec8bec8b01369c8b549a4b8c4388a1796dc35a9377fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca085080600357".from_hex().unwrap()); + }); +} + +/// Compute addmod(a, b, c) for random 256-bit a, b and c. Iterate 1000 times. +fn addmod1000(b: &mut Criterion) { + b.bench_function("addmod randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037f5ed6db9489224124a1a4110ec8bec8b01369c8b549a4b8c4388a1796dc35a9377fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca085080600357".from_hex().unwrap()); + }); +} + +/// Compute mul(a, b) for random 256-bit a and b. Iterate 500 times. +fn mul500(b: &mut Criterion) { + b.bench_function("mul randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca025080600357".from_hex().unwrap()); + }); +} + +/// Compute mul(a, b) for random 256-bit a and b. Iterate 1000 times. +fn mul1000(b: &mut Criterion) { + b.bench_function("mul randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca025080600357".from_hex().unwrap()); + }); +} + +/// Compute div(a, b) for random 256-bit a and b. Iterate 500 times. +fn div500(b: &mut Criterion) { + b.bench_function("div randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca045080600357".from_hex().unwrap()); + }); +} + +/// Compute div(a, b) for random 256-bit a and b. Iterate 1000 times. +fn div1000(b: &mut Criterion) { + b.bench_function("div randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca045080600357".from_hex().unwrap()); + }); +} + +/// Compute sdiv(a, b) for random 256-bit a and b. Iterate 500 times. +fn sdiv500(b: &mut Criterion) { + b.bench_function("sdiv randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca055080600357".from_hex().unwrap()); + }); +} + +/// Compute sdiv(a, b) for random 256-bit a and b. Iterate 1000 times. +fn sdiv1000(b: &mut Criterion) { + b.bench_function("sdiv randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca055080600357".from_hex().unwrap()); + }); +} + +/// Compute mod(a, b) for random 256-bit a and b. Iterate 500 times. +fn mod500(b: &mut Criterion) { + b.bench_function("mod randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca065080600357".from_hex().unwrap()); + }); +} + +/// Compute mod(a, b) for random 256-bit a and b. Iterate 1000 times. +fn mod1000(b: &mut Criterion) { + b.bench_function("mod randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca065080600357".from_hex().unwrap()); + }); +} + +/// Compute smod(a, b) for random 256-bit a and b. Iterate 500 times. +fn smod500(b: &mut Criterion) { + b.bench_function("smod randomly generated ints, 500 times", |b| { + run_code(b, "6101f45b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca075080600357".from_hex().unwrap()); + }); +} + +/// Compute smod(a, b) for random 256-bit a and b. Iterate 1000 times. +fn smod1000(b: &mut Criterion) { + b.bench_function("smod randomly generated ints, 1000 times", |b| { + run_code(b, "6103e85b600190037fb8e0a2b6b1587398c28bf9e9d34ea24ba34df308eec2acedca363b2fce2c25db7fcc2de1f8ec6cc9a24ed2c48b856637f9e45f0a5feee21a196aa42a290ef454ca075080600357".from_hex().unwrap()); + }); +} From c9190a39edcfec498c3fea8275c17ebbfa13fac6 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 25 Mar 2021 16:04:32 +0100 Subject: [PATCH 102/107] Executable queue for ancient blocks inclusion (#208) * Executable queue for ancient blocks inclusion * Add drop trait for client * Added shutdown to tests * Remove doubled call * Use reth-util from reth repo --- Cargo.lock | 6 + crates/ethcore/Cargo.toml | 1 + crates/ethcore/service/src/service.rs | 1 + crates/ethcore/src/client/client.rs | 128 ++++++++++++------- crates/ethcore/src/client/test_client.rs | 4 + crates/ethcore/src/client/traits.rs | 3 + crates/ethcore/src/json_tests/chain.rs | 1 + crates/ethcore/src/lib.rs | 1 + crates/ethcore/src/snapshot/tests/service.rs | 2 +- crates/ethcore/src/tests/trace.rs | 1 + crates/ethcore/sync/src/chain/mod.rs | 17 ++- 11 files changed, 110 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3611b47a4..9be4fe1441 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1004,6 +1004,7 @@ dependencies = [ "rand_xorshift 0.2.0", "rayon", "regex 1.3.9", + "reth-util", "rlp", "rlp_compress", "rlp_derive", @@ -3916,6 +3917,11 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "reth-util" +version = "0.1.0" +source = "git+https://github.com/gnosis/reth.git?rev=573e128#573e128487d5651f301e21faa97fc8e80f91dee8" + [[package]] name = "ring" version = "0.14.6" diff --git a/crates/ethcore/Cargo.toml b/crates/ethcore/Cargo.toml index e1b83ebc9f..6e77eac699 100644 --- a/crates/ethcore/Cargo.toml +++ b/crates/ethcore/Cargo.toml @@ -72,6 +72,7 @@ time-utils = { path = "../util/time-utils" } trace-time = "0.1" triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" } unexpected = { path = "../util/unexpected" } +reth-util = { git = "https://github.com/gnosis/reth.git", rev = "573e128", package="reth-util" } using_queue = { path = "../concensus/miner/using-queue" } vm = { path = "../vm/vm" } walkdir = "2.3" diff --git a/crates/ethcore/service/src/service.rs b/crates/ethcore/service/src/service.rs index 9969be0efc..7e24113fd7 100644 --- a/crates/ethcore/service/src/service.rs +++ b/crates/ethcore/service/src/service.rs @@ -142,6 +142,7 @@ impl ClientService { pub fn shutdown(&self) { trace!(target: "shutdown", "Shutting down Client Service"); self.snapshot.shutdown(); + self.client.shutdown(); } } diff --git a/crates/ethcore/src/client/client.rs b/crates/ethcore/src/client/client.rs index 7f707a915b..9021c45cae 100644 --- a/crates/ethcore/src/client/client.rs +++ b/crates/ethcore/src/client/client.rs @@ -34,7 +34,6 @@ use blockchain::{ use bytes::{Bytes, ToPretty}; use call_contract::CallContract; use db::{DBTransaction, DBValue, KeyValueDB}; -use error::Error; use ethcore_miner::pool::VerifiedTransaction; use ethereum_types::{Address, H256, H264, U256}; use hash::keccak; @@ -80,8 +79,8 @@ use engines::{ MAX_UNCLE_AGE, }; use error::{ - BlockError, CallError, Error as EthcoreError, ErrorKind as EthcoreErrorKind, EthcoreResult, - ExecutionError, ImportErrorKind, + BlockError, CallError, Error, Error as EthcoreError, ErrorKind as EthcoreErrorKind, + EthcoreResult, ExecutionError, ImportErrorKind, QueueErrorKind, }; use executive::{contract_address, Executed, Executive, TransactOptions}; use factory::{Factories, VmFactory}; @@ -105,14 +104,14 @@ use vm::Schedule; // re-export pub use blockchain::CacheSize as BlockChainCacheSize; use db::{keys::BlockDetails, Readable, Writable}; +pub use reth_util::queue::ExecutionQueue; pub use types::{block_status::BlockStatus, blockchain_info::BlockChainInfo}; pub use verification::QueueInfo as BlockQueueInfo; - use_contract!(registry, "res/contracts/registrar.json"); -const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; +const ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; // Max number of blocks imported at once. -const MAX_ANCIENT_BLOCKS_TO_IMPORT: usize = 4; +const ANCIENT_BLOCKS_BATCH_SIZE: usize = 4; const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2; const MIN_HISTORY_SIZE: u64 = 8; @@ -235,10 +234,9 @@ pub struct Client { /// Queued transactions from IO queue_transactions: IoChannelQueue, /// Ancient blocks import queue - queue_ancient_blocks: IoChannelQueue, /// Queued ancient blocks, make sure they are imported in order. - queued_ancient_blocks: Arc, VecDeque<(Unverified, Bytes)>)>>, - ancient_blocks_import_lock: Arc>, + queued_ancient_blocks: Arc>>, + queued_ancient_blocks_executer: Mutex>>, /// Consensus messages import queue queue_consensus_message: IoChannelQueue, @@ -973,9 +971,8 @@ impl Client { io_channel: RwLock::new(message_channel), notify: RwLock::new(Vec::new()), queue_transactions: IoChannelQueue::new(config.transaction_verification_queue_size), - queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE), queued_ancient_blocks: Default::default(), - ancient_blocks_import_lock: Default::default(), + queued_ancient_blocks_executer: Default::default(), queue_consensus_message: IoChannelQueue::new(usize::max_value()), last_hashes: RwLock::new(VecDeque::new()), factories, @@ -987,6 +984,44 @@ impl Client { config, }); + let exec_client = client.clone(); + + let queued = client.queued_ancient_blocks.clone(); + let queued_ancient_blocks_executer = ExecutionQueue::new( + ANCIENT_BLOCKS_QUEUE_SIZE, + ANCIENT_BLOCKS_BATCH_SIZE, + move |ancient_block: Vec<(Unverified, Bytes)>| { + trace_time!("import_ancient_block"); + for (unverified, receipts_bytes) in ancient_block { + let hash = unverified.hash(); + if !exec_client.chain.read().is_known(&unverified.parent_hash()) { + queued.write().remove(&hash); + continue; + } + let result = exec_client.importer.import_old_block( + unverified, + &receipts_bytes, + &**exec_client.db.read().key_value(), + &*exec_client.chain.read(), + ); + if let Err(e) = result { + error!(target: "client", "Error importing ancient block: {}", e); + + let mut queued = queued.write(); + queued.clear(); + } + // remove from pending + queued.write().remove(&hash); + } + }, + "ancient_block_exec", + ); + + client + .queued_ancient_blocks_executer + .lock() + .replace(queued_ancient_blocks_executer); + // prune old states. { let state_db = client.state_db.read().boxed_clone(); @@ -1034,6 +1069,15 @@ impl Client { Ok(client) } + /// signals shutdown of application. We do cleanup here. + pub fn shutdown(&self) { + let mut abe = self.queued_ancient_blocks_executer.lock(); + if abe.is_some() { + abe.as_mut().unwrap().end() + } + *abe = None; + } + /// Wakes up client if it's a sleep. pub fn keep_alive(&self) { let should_wake = match *self.mode.lock() { @@ -1866,6 +1910,12 @@ impl StateClient for Client { } } +impl Drop for Client { + fn drop(&mut self) { + self.shutdown() + } +} + impl Call for Client { type State = State<::state_db::StateDB>; @@ -2714,7 +2764,7 @@ impl IoClient for Client { let parent_hash = unverified.parent_hash(); // NOTE To prevent race condition with import, make sure to check queued blocks first // (and attempt to acquire lock) - let is_parent_pending = self.queued_ancient_blocks.read().0.contains(&parent_hash); + let is_parent_pending = self.queued_ancient_blocks.read().contains(&parent_hash); if !is_parent_pending && !self.chain.read().is_known(&parent_hash) { bail!(EthcoreErrorKind::Block(BlockError::UnknownParent( parent_hash @@ -2722,49 +2772,33 @@ impl IoClient for Client { } } - // we queue blocks here and trigger an IO message. + // we queue blocks here and trigger an Executer. { let mut queued = self.queued_ancient_blocks.write(); - queued.0.insert(hash); - queued.1.push_back((unverified, receipts_bytes)); + queued.insert(hash); } - let queued = self.queued_ancient_blocks.clone(); - let lock = self.ancient_blocks_import_lock.clone(); - self.queue_ancient_blocks - .queue(&self.io_channel.read(), 1, move |client| { - trace_time!("import_ancient_block"); - // Make sure to hold the lock here to prevent importing out of order. - // We use separate lock, cause we don't want to block queueing. - let _lock = lock.lock(); - for _i in 0..MAX_ANCIENT_BLOCKS_TO_IMPORT { - let first = queued.write().1.pop_front(); - if let Some((unverified, receipts_bytes)) = first { - let hash = unverified.hash(); - let result = client.importer.import_old_block( - unverified, - &receipts_bytes, - &**client.db.read().key_value(), - &*client.chain.read(), - ); - if let Err(e) = result { - error!(target: "client", "Error importing ancient block: {}", e); - - let mut queued = queued.write(); - queued.0.clear(); - queued.1.clear(); - } - // remove from pending - queued.write().0.remove(&hash); - } else { - break; - } + // see content of executer in Client::new() + match self.queued_ancient_blocks_executer.lock().as_ref() { + Some(queue) => { + if !queue.enqueue((unverified, receipts_bytes)) { + bail!(EthcoreErrorKind::Queue(QueueErrorKind::Full( + ANCIENT_BLOCKS_QUEUE_SIZE + ))); } - })?; - + } + None => (), + } Ok(hash) } + fn ancient_block_queue_fullness(&self) -> f32 { + match self.queued_ancient_blocks_executer.lock().as_ref() { + Some(queue) => queue.len() as f32 / ANCIENT_BLOCKS_QUEUE_SIZE as f32, + None => 1.0, //return 1.0 if queue is not set + } + } + fn queue_consensus_message(&self, message: Bytes) { match self .queue_consensus_message diff --git a/crates/ethcore/src/client/test_client.rs b/crates/ethcore/src/client/test_client.rs index 09e8807461..960e959159 100644 --- a/crates/ethcore/src/client/test_client.rs +++ b/crates/ethcore/src/client/test_client.rs @@ -1087,6 +1087,10 @@ impl IoClient for TestBlockChainClient { self.miner.import_external_transactions(self, txs); } + fn ancient_block_queue_fullness(&self) -> f32 { + 0.0 + } + fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> EthcoreResult { self.import_block(unverified) } diff --git a/crates/ethcore/src/client/traits.rs b/crates/ethcore/src/client/traits.rs index f314741e49..6546710b04 100644 --- a/crates/ethcore/src/client/traits.rs +++ b/crates/ethcore/src/client/traits.rs @@ -220,6 +220,9 @@ pub trait IoClient: Sync + Send { receipts_bytes: Bytes, ) -> EthcoreResult; + /// Return percentage of how full is queue that handles ancient blocks. 0 if empty, 1 if full. + fn ancient_block_queue_fullness(&self) -> f32; + /// Queue conensus engine message. fn queue_consensus_message(&self, message: Bytes); } diff --git a/crates/ethcore/src/json_tests/chain.rs b/crates/ethcore/src/json_tests/chain.rs index f923fd2160..b58f4e1fc6 100644 --- a/crates/ethcore/src/json_tests/chain.rs +++ b/crates/ethcore/src/json_tests/chain.rs @@ -232,6 +232,7 @@ pub fn json_chain_test( client.chain_info().best_block_hash == blockchain.best_block.into() && post_state_success, ); + client.shutdown() } } diff --git a/crates/ethcore/src/lib.rs b/crates/ethcore/src/lib.rs index 5a0c1b0e33..b2d9554919 100644 --- a/crates/ethcore/src/lib.rs +++ b/crates/ethcore/src/lib.rs @@ -52,6 +52,7 @@ extern crate parking_lot; extern crate patricia_trie_ethereum as ethtrie; extern crate rand; extern crate rayon; +extern crate reth_util; extern crate rlp; extern crate rustc_hex; extern crate serde; diff --git a/crates/ethcore/src/snapshot/tests/service.rs b/crates/ethcore/src/snapshot/tests/service.rs index 7046d4b477..2c567b232f 100644 --- a/crates/ethcore/src/snapshot/tests/service.rs +++ b/crates/ethcore/src/snapshot/tests/service.rs @@ -369,7 +369,7 @@ fn recover_aborted_recovery() { } e => panic!("Snapshot restoration must be ongoing ; {:?}", e), } - + // abort restoration so that we can delete snapshot root folder service.abort_restore(); // Remove the snapshot directory, and restart the restoration diff --git a/crates/ethcore/src/tests/trace.rs b/crates/ethcore/src/tests/trace.rs index 4cb92a2e35..bb16edac18 100644 --- a/crates/ethcore/src/tests/trace.rs +++ b/crates/ethcore/src/tests/trace.rs @@ -243,5 +243,6 @@ fn can_trace_block_and_uncle_reward() { // Test1. Check block filter let traces = client.block_traces(BlockId::Number(3)); + client.shutdown(); assert_eq!(traces.unwrap().len(), 3); } diff --git a/crates/ethcore/sync/src/chain/mod.rs b/crates/ethcore/sync/src/chain/mod.rs index 1ccbc1f4f8..b5508a39ea 100644 --- a/crates/ethcore/sync/src/chain/mod.rs +++ b/crates/ethcore/sync/src/chain/mod.rs @@ -1131,17 +1131,20 @@ impl ChainSync { } // Only ask for old blocks if the peer has an equal or higher difficulty - let equal_or_higher_difficulty = peer_difficulty.map_or(true, |pd| pd >= syncing_difficulty); - + let equal_or_higher_difficulty = peer_difficulty.map_or(true, |pd| pd >= syncing_difficulty); + // check queue fullness + let ancient_block_fullness = io.chain().ancient_block_queue_fullness(); if force || equal_or_higher_difficulty { let mut is_complete = false; if let Some(old_blocks) = self.old_blocks.as_mut() { - if let Some(request) = old_blocks.request_blocks(peer_id, io, num_active_peers) { - SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); - return; + // check if ancient queue can take more request or not. + if ancient_block_fullness < 0.8 { + if let Some(request) = old_blocks.request_blocks(peer_id, io, num_active_peers) { + SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); + return; + } + is_complete = old_blocks.is_complete(); } - is_complete = old_blocks.is_complete(); - } if is_complete { // if old_blocks is in complete state, set it to None. self.old_blocks = None; From 9037ad0ea782cfbe2fb80713c4f80a0cc4e3e7fd Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Mar 2021 11:04:53 +0200 Subject: [PATCH 103/107] Bump eth/tests to v8.0.2 --- crates/ethcore/res/json_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ethcore/res/json_tests b/crates/ethcore/res/json_tests index e431795bf7..ff68495eb5 160000 --- a/crates/ethcore/res/json_tests +++ b/crates/ethcore/res/json_tests @@ -1 +1 @@ -Subproject commit e431795bf750166671afc3516f5e0332af3318f1 +Subproject commit ff68495eb56c382b2ddcea4020259e106353b874 From 582bca385fedb1af682e989e5bcc6b3b2cf53028 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 31 Mar 2021 15:07:27 +0200 Subject: [PATCH 104/107] Bump to v3.2.2-rc.1. Changelog --- CHANGELOG.md | 25 +++++++++++++++++++++++++ Cargo.lock | 4 ++-- Cargo.toml | 2 +- crates/util/version/Cargo.toml | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 554b8c982d..824ca01b40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +## OpenEthereum v3.2.2-rc.1 + +Bug fixes: +* Backport: Block sync stopped without any errors. #277 (#286) +* Strict memory order (#306) + +Enhancements: +* Executable queue for ancient blocks inclusion (#208) +* Backport AuRa commits for xdai (#330) +* Add Nethermind to clients that accept service transactions (#324) +* Implement the filter argument in parity_pendingTransactions (#295) +* Ethereum-types and various libs upgraded (#315) +* Bump ethereum/tests to v8.0.2 +* [evmbin] Omit storage output, now for std-json (#311) +* Freeze pruning while creating snapshot (#205) +* AuRa multi block reward (#290) +* Improved metrics. DB read/write. prometheus prefix config (#240) +* Send RLPx auth in EIP-8 format (#287) +* rpc module reverted for RPC JSON api (#284) +* Revert "Remove eth/63 protocol version (#252)" + +devops: +* Upgrade docker alpine to `v1.13.2`. for rust `v1.47`. +* Send SIGTERM instead of SIGHUP to OE daemon (#317) + ## OpenEthereum v3.2.1 Hot fix issue, related to initial sync: diff --git a/Cargo.lock b/Cargo.lock index 9be4fe1441..bf43a6f2ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2835,7 +2835,7 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "openethereum" -version = "3.2.1" +version = "3.2.2-rc.1" dependencies = [ "ansi_term 0.10.2", "atty", @@ -3191,7 +3191,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "3.2.1" +version = "3.2.2-rc.1" dependencies = [ "parity-bytes", "rlp", diff --git a/Cargo.toml b/Cargo.toml index 7829a5ef5c..07b8c3e4d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "OpenEthereum" name = "openethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "3.2.1" +version = "3.2.2-rc.1" license = "GPL-3.0" authors = [ "OpenEthereum developers", diff --git a/crates/util/version/Cargo.toml b/crates/util/version/Cargo.toml index 4ff5c3fe53..87e85170b2 100644 --- a/crates/util/version/Cargo.toml +++ b/crates/util/version/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "parity-version" # NOTE: this value is used for OpenEthereum version string (via env CARGO_PKG_VERSION) -version = "3.2.1" +version = "3.2.2-rc.1" authors = ["Parity Technologies "] build = "build.rs" From 9535b96ed227e4d84e5d98756508caca82417416 Mon Sep 17 00:00:00 2001 From: habiana <79815813+habiana@users.noreply.github.com> Date: Thu, 15 Apr 2021 23:34:34 +0800 Subject: [PATCH 105/107] Create SECURITY.md --- habiana/SECURITY.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 habiana/SECURITY.md diff --git a/habiana/SECURITY.md b/habiana/SECURITY.md new file mode 100644 index 0000000000..034e848032 --- /dev/null +++ b/habiana/SECURITY.md @@ -0,0 +1,21 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +Use this section to tell people how to report a vulnerability. + +Tell them where to go, how often they can expect to get an update on a +reported vulnerability, what to expect if the vulnerability is accepted or +declined, etc. From 6ab2e32a4f1204cde86654fc98dba7e43821bcc6 Mon Sep 17 00:00:00 2001 From: habiana <79815813+habiana@users.noreply.github.com> Date: Thu, 15 Apr 2021 23:39:04 +0800 Subject: [PATCH 106/107] Create crunch42-analysis.yml --- .github/workflows/crunch42-analysis.yml | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/crunch42-analysis.yml diff --git a/.github/workflows/crunch42-analysis.yml b/.github/workflows/crunch42-analysis.yml new file mode 100644 index 0000000000..2c71f6f35e --- /dev/null +++ b/.github/workflows/crunch42-analysis.yml @@ -0,0 +1,49 @@ +'pollyramos' +# This workflow locates REST API file contracts +# (Swagger or OpenAPI format, v2 and v3, JSON and YAML) +# and runs 200+ security checks on them using 42Crunch Security Audit technology. +# +# Documentation is located here: https://docs.42crunch.com/latest/content/tasks/integrate_github_actions.htm +# +# To use this workflow, you will need to complete the following setup steps. +# +# 1. Create a free 42Crunch account at https://platform.42crunch.com/register +# +# 2. Follow steps at https://docs.42crunch.com/latest/content/tasks/integrate_github_actions.htm +# to create an API Token on the 42Crunch platform +# +# 3. Add a secret in GitHub as explained in https://docs.42crunch.com/latest/content/tasks/integrate_github_actions.htm, +# store the 42Crunch API Token in that secret, and supply the secret's name as api-token parameter in this workflow +# +# If you have any questions or need help contact https://support.42crunch.com + +name: "42Crunch REST API Static Security Testing" + +# follow standard Code Scanning triggers +on: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + schedule: + - cron: '22 14 * * 1' + +jobs: + rest-api-static-security-testing: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: 42Crunch REST API Static Security Testing + uses: 42Crunch/api-security-audit-action@v1 + with: + # Please create free account at https://platform.42crunch.com/register + # Follow these steps to configure API_TOKEN https://docs.42crunch.com/latest/content/tasks/integrate_github_actions.htm + api-token: ${{ secrets.API_TOKEN }} + # Fail if any OpenAPI file scores lower than 75 + min-score: 75 + # Upload results to Github code scanning + upload-to-code-scanning: true + # Github token for uploading the results + github-token: ${{ github.token }} From ee3c0e14713f209e2a648db5cc9c7d3d403c09de Mon Sep 17 00:00:00 2001 From: Lars Gohr Date: Tue, 28 Mar 2023 03:03:26 +0200 Subject: [PATCH 107/107] Updated elgohr/Publish-Docker-Github-Action to a supported version (v5) --- .github/workflows/deploy-docker-nightly.yml | 2 +- .github/workflows/deploy-docker-tag.yml | 2 +- .github/workflows/deploy-docker.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-docker-nightly.yml b/.github/workflows/deploy-docker-nightly.yml index b80691b155..5edea37968 100644 --- a/.github/workflows/deploy-docker-nightly.yml +++ b/.github/workflows/deploy-docker-nightly.yml @@ -20,7 +20,7 @@ jobs: profile: minimal override: true - name: Deploy to docker hub - uses: elgohr/Publish-Docker-Github-Action@master + uses: elgohr/Publish-Docker-Github-Action@v5 with: name: openethereum/openethereum username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/deploy-docker-tag.yml b/.github/workflows/deploy-docker-tag.yml index 84beb5decc..2407be60a9 100644 --- a/.github/workflows/deploy-docker-tag.yml +++ b/.github/workflows/deploy-docker-tag.yml @@ -21,7 +21,7 @@ jobs: profile: minimal override: true - name: Deploy to docker hub - uses: elgohr/Publish-Docker-Github-Action@master + uses: elgohr/Publish-Docker-Github-Action@v5 with: name: openethereum/openethereum username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml index 44c70a8042..e645b9822e 100644 --- a/.github/workflows/deploy-docker.yml +++ b/.github/workflows/deploy-docker.yml @@ -21,7 +21,7 @@ jobs: profile: minimal override: true - name: Deploy to docker hub - uses: elgohr/Publish-Docker-Github-Action@master + uses: elgohr/Publish-Docker-Github-Action@v5 with: name: openethereum/openethereum username: ${{ secrets.DOCKER_USERNAME }}