From 5c56fc50237b6fe9976d752decbbd6672cf789fa Mon Sep 17 00:00:00 2001 From: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com> Date: Wed, 14 Nov 2018 15:23:44 +0100 Subject: [PATCH] Backport Beta 2.2.1 (#9905) * Bump beta to version 2.2.1 * fix: Intermittent failing CI due to addr in use (#9885) Allow OS to set port at runtime * Use Weak reference in PubSubClient (#9886) * Fix json tracer overflow (#9873) * Fix json tracer overflow * Replace trace_executed with a direct trace push * Remove unused variable * Add test for 5a51 * Remove duplicate json! * Fix docker script (#9854) * Dockerfile: change source path of the newly added check_sync.sh (#9869) * Allow to seal work on latest block (#9876) * Allow to seal work on latest block. * Test from @todr to check sealing conditions. * gitlab-ci: make android release build succeed (#9743) * use docker cargo config file for android builds * make android build succeed * ethcore: use Machine::verify_transaction on parent block (#9900) * ethcore: use Machine::verify_transaction on parent block also fixes off-by-one activation of transaction permission contract * ethcore: clarify call to verify_transaction * foundation: #6692865, ropsten: #4417537, kovan: #9363457 * Remove rust-toolchain file (#9906) * EIP-712 implementation (#9631) * EIP-712 impl * added more tests * removed size parsing unwrap * corrected TYPE_REGEX to disallow zero sized fixed length arrays, replaced LinkedHashSet with IndexSet, added API spec to docs, fixed Type::Byte encoding branch * use Option instead of u64 for Type::Array::Length * replace `.iter()` with `.values()` Co-Authored-By: seunlanlege * tabify eip712.rs * use proper comments for docs * Cargo.lock: revert unrelated changes * tabify encode.rs * EIP 191 (#9701) * added sign_191 rpc method * fixed hash_structured_data return type * added ConfirmationPayload::SignMessage for non-prefixed signatures, added tests for sign191 * renamed WithValidator -> PresignedTransaction * rename applicationData to data in test * adds docs for EIP191Version, renamed SignRequest to EIP191SignRequest * light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure (#9824) * fix start_gas, handle OOG exceptions & NotEnoughGas * Change START_GAS: 50_000 -> 60_000 * When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached * When `NotEnoughBasGas error` is received then use the required gas provided in the response * fix(light-fetch): ensure block_gas_limit is tried Try the `block_gas_limit` before regard the execution as an error * Update rpc/src/v1/helpers/light_fetch.rs Co-Authored-By: niklasad1 * simplify cargo audit * Use block header for building finality (#9914) * ci: nuke the gitlab caches (#9855) --- .gitlab-ci.yml | 8 - Cargo.lock | 148 +++++++- Cargo.toml | 4 +- ethcore/res/ethereum/foundation.json | 107 +++++- ethcore/res/ethereum/kovan.json | 172 ++++++++- ethcore/res/ethereum/ropsten.json | 111 +++++- ethcore/src/client/client.rs | 2 +- ethcore/src/engines/authority_round/mod.rs | 12 +- ethcore/src/engines/mod.rs | 2 +- ethcore/src/machine.rs | 4 +- ethcore/src/miner/miner.rs | 34 +- ethcore/src/verification/verification.rs | 4 +- evmbin/src/display/json.rs | 57 ++- rpc/Cargo.toml | 1 + rpc/src/lib.rs | 1 + rpc/src/tests/ws.rs | 4 +- rpc/src/v1/helpers/dispatch.rs | 21 +- rpc/src/v1/helpers/eip191.rs | 61 +++ rpc/src/v1/helpers/errors.rs | 8 + rpc/src/v1/helpers/light_fetch.rs | 40 +- rpc/src/v1/helpers/mod.rs | 1 + rpc/src/v1/helpers/requests.rs | 4 + rpc/src/v1/impls/personal.rs | 48 ++- rpc/src/v1/impls/pubsub.rs | 12 +- rpc/src/v1/impls/signer.rs | 8 + rpc/src/v1/tests/mocked/personal.rs | 94 ++++- rpc/src/v1/traits/personal.rs | 14 +- rpc/src/v1/types/confirmations.rs | 55 ++- rpc/src/v1/types/eip191.rs | 57 +++ rpc/src/v1/types/mod.rs | 5 +- rust-toolchain | 1 - scripts/docker/hub/Dockerfile | 2 +- scripts/gitlab/build-unix.sh | 49 ++- scripts/gitlab/build-windows.sh | 2 - scripts/gitlab/cargo-audit.sh | 4 +- util/EIP-712/Cargo.toml | 23 ++ util/EIP-712/src/eip712.rs | 177 +++++++++ util/EIP-712/src/encode.rs | 415 +++++++++++++++++++++ util/EIP-712/src/error.rs | 125 +++++++ util/EIP-712/src/lib.rs | 192 ++++++++++ util/EIP-712/src/parser.rs | 172 +++++++++ util/version/Cargo.toml | 2 +- 42 files changed, 2146 insertions(+), 117 deletions(-) create mode 100644 rpc/src/v1/helpers/eip191.rs create mode 100644 rpc/src/v1/types/eip191.rs delete mode 100644 rust-toolchain create mode 100644 util/EIP-712/Cargo.toml create mode 100644 util/EIP-712/src/eip712.rs create mode 100644 util/EIP-712/src/encode.rs create mode 100644 util/EIP-712/src/error.rs create mode 100644 util/EIP-712/src/lib.rs create mode 100644 util/EIP-712/src/parser.rs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fc2adcc31..bf11cad67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,16 +9,8 @@ image: parity/rust:gitlab-ci variables: CI_SERVER_NAME: "GitLab CI" CARGO_HOME: "${CI_PROJECT_DIR}/.cargo" - BUILD_TARGET: ubuntu - BUILD_ARCH: amd64 CARGO_TARGET: x86_64-unknown-linux-gnu -cache: - key: "${CI_JOB_NAME}" - paths: - - ./target - - ./.cargo - .releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries") only: &releaseable_branches - stable diff --git a/Cargo.lock b/Cargo.lock index 8b7dc4883..eaa74650e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,6 +424,29 @@ name = "edit-distance" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "eip712" +version = "0.1.0" +dependencies = [ + "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lunarity-lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "validator_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.5.0" @@ -1061,6 +1084,26 @@ dependencies = [ "vm 0.1.0", ] +[[package]] +name = "failure" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fake-fetch" version = "0.0.1" @@ -1173,6 +1216,14 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gcc" version = "0.3.55" @@ -1216,7 +1267,7 @@ dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1389,6 +1440,11 @@ dependencies = [ "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "if_chain" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "igd" version = "0.7.0" @@ -1407,7 +1463,7 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1442,6 +1498,14 @@ dependencies = [ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -1751,6 +1815,14 @@ dependencies = [ "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lunarity-lexer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "macros" version = "0.1.0" @@ -2080,7 +2152,7 @@ version = "1.12.0" dependencies = [ "jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-ethereum 2.2.0", + "parity-ethereum 2.2.1", ] [[package]] @@ -2096,7 +2168,7 @@ dependencies = [ [[package]] name = "parity-ethereum" -version = "2.2.0" +version = "2.2.1" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2145,7 +2217,7 @@ dependencies = [ "parity-rpc-client 1.4.0", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.2.0", + "parity-version 2.2.1", "parity-whisper 0.1.0", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2261,6 +2333,7 @@ version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "eip712 0.1.0", "ethash 1.12.0", "ethcore 1.12.0", "ethcore-devtools 1.12.0", @@ -2299,7 +2372,7 @@ dependencies = [ "parity-crypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parity-updater 1.12.0", - "parity-version 2.2.0", + "parity-version 2.2.1", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2396,7 +2469,7 @@ dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.12.0", "parity-path 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-version 2.2.0", + "parity-version 2.2.1", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2406,7 +2479,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "2.2.0" +version = "2.2.1" dependencies = [ "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3176,6 +3249,17 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "target_info" version = "0.1.0" @@ -3515,6 +3599,14 @@ dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toolshed" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "trace-time" version = "0.1.1" @@ -3687,6 +3779,34 @@ name = "utf8-ranges" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "validator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "validator_derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)", + "validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vec_map" version = "0.8.1" @@ -3972,6 +4092,8 @@ dependencies = [ "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b3c5a18bc5e73a32a110ac743ec04b02bbbcd3b71d3118d40a6113d509378a" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" +"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" +"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum fixed-hash 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d5ec8112f00ea8a483e04748a85522184418fd1cf02890b626d8fc28683f7de" @@ -3982,6 +4104,7 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" @@ -4001,13 +4124,15 @@ dependencies = [ "checksum hyper 0.12.11 (registry+https://github.com/rust-lang/crates.io-index)" = "78d50abbd1790e0f4c74cb1d4a2211b439bac661d54107ad5564c55e77906762" "checksum hyper-rustls 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68f2aa6b1681795bf4da8063f718cd23145aa0c9a5143d9787b345aa60d38ee4" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec" "checksum igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a254e265e8810deb357a9de757f784787ec415d056ededf410c0aa460afee9e" -"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5" "checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)" = "70783119ac90828aaba91eae39db32c6c1b8838deea3637e5238efa0130801ab" "checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" +"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1ecfa3b81afc64d9a6539c4eece96ac9a93c551c713a313800dade8e33d7b5c1" "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" @@ -4038,6 +4163,7 @@ dependencies = [ "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f" "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum lunarity-lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1670671f305792567116d4660e6e5bd785d6fa973e817c3445c0a7a54cecb6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4b3629fe9fdbff6daa6c33b90f7c08355c1aca05a3d01fa8063b822fcf185f3b" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" @@ -4157,6 +4283,7 @@ dependencies = [ "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b036b7b35e846707c0e55c2c9441fa47867c0f87fca416921db3261b1d8c741a" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" @@ -4189,6 +4316,7 @@ dependencies = [ "checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" "checksum tokio-uds 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22e3aa6d1fcc19e635418dc0a30ab5bd65d347973d6f43f1a37bf8d9d1335fc9" "checksum toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4a2ecc31b0351ea18b3fe11274b8db6e4d82bce861bbb22e6dbed40417902c65" +"checksum toolshed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "450441e131c7663af72e63a33c02a6a1fbaaa8601dc652ed6757813bb55aeec7" "checksum trace-time 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe82f2f0bf1991e163e757baf044282823155dd326e70f44ce2186c3c320cc9" "checksum transaction-pool 1.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e5866e5126b14358f1d7af4bf51a0be677a363799b90e655edcec8254edef1d2" "checksum transient-hashmap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aeb4b191d033a35edfce392a38cdcf9790b6cebcb30fa690c312c29da4dc433e" @@ -4211,6 +4339,8 @@ dependencies = [ "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum validator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "236a5eda3df2c877872e98dbc55d497d943792e6405d8fc65bd4f8a5e3b53c99" +"checksum validator_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d360d6f5754972c0c1da14fb3d5580daa31aee566e1e45e2f8d3bf5950ecd3e9" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" diff --git a/Cargo.toml b/Cargo.toml index d5283e8ae..e0f197ecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "Parity Ethereum client" name = "parity-ethereum" # NOTE Make sure to update util/version/Cargo.toml as well -version = "2.2.0" +version = "2.2.1" license = "GPL-3.0" authors = ["Parity Technologies "] @@ -136,4 +136,4 @@ members = [ "util/keccak-hasher", "util/patricia-trie-ethereum", "util/fastmap", -] \ No newline at end of file +] diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 98d988165..e14d7e086 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -177,8 +177,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053", - "totalDifficulty": "7128515864594819065361", + "header": "f90210a0b5950d9087e0e1d3dfc18cae9388fc798d9b3932a6efb4fc073081f5561adc8da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794829bd824b016326a401d083b33d092293333a830a00caa3307575bbbe59bb8f8a89f115ccb864866c2591d8d3ec3bffa6231532e52a024278597d4fddf58a4b55fe6a8bb7bf0e6cf1c6e75158b3d0d0b1bb9bb16647da01ba199a450390854e88ea5504144be61dd681e805aed7a1cc8bea61d5b61194bb901001902100820000000020110010418b02612064240040a4051001001a0024400e2484001141a422e56073887504031028220080010040501800000080080268040050018400100cc4710800419088000005a840a201c09011040086001260040000021004842021800024204400204a8a1180a8a0002164400202000115420602005512a20410088002248c000020e801803c051202030000420810912000401010604000801543084004414c051048082100000221684005c8015a40100040170025040132500014054900482500403088004000821194124a0b20000200229b9601c230180400802020800000408e49314200190121404002080218814a08085870ac84878814c3083662001837a2147837a050f845be9e82d8fe4b883e5bda9e7a59ee4bb99e9b1bca05714f772f5e2fa3a41a8c7435407b579b7c16397cf08eca605eadd9e63db7f6a88315d0b500d2cb0a8", + "totalDifficulty": "7772265011609637471285", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -3346,7 +3346,108 @@ "0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf", "0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447", "0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20", - "0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4" + "0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4", + "0x7ba213077278bd01ff874e760c3a0bfd4e5cf65bb18eed8b0f8076d81e16d05b", + "0x92eace1cff535745aae658d9ad90c372d41ce318a20716ae3b2c0958bdb48b33", + "0x76b2607fae8dbe532d8516c4c33e309f2c0a963bb68035f4361a2859d62d2daf", + "0xfb0c46a588438f4f217e183ef7772b649b5a45a318253496b01676253dedb568", + "0xd6dba12c700a0c5ca59b9d17f628066405de8e4399f92472cccce2e25e70ba4d", + "0x2390984444cbc9de301adaf0853f4f6ed2fb56fefeabce717306cf1e40da9618", + "0xa6992b0db82c50ce623febc7f16c8a316ce262255de11ad1914316b3d986fe66", + "0x96787cf8e0a70ffe5b84151ae8219362ba6d9465223c23c135590fe4cb9ab592", + "0x0b4e7fba24f6bed3790b8fc289e2715d9a3f4235c9316dd9d4f889f710a65ae4", + "0x49585a7af98ad032371df01c458fab933ac399ff4d2d35731a2d86fc136b5eb8", + "0x517947f22d8d56466dbb496f3e98fcd01864176af19be2112f2260e55bddbd58", + "0xbc0aa38cbc79c3557fa81e446071e6d531989d088c6311060bff971e430fa36b", + "0x5a0a88750db7ad3190dcaaf5bde2649e6fd99cc5b05979fff84ae689ed47b51b", + "0x9ad902d6abe59faabfa5fde485c2fe16f6f3e2c41aa8bdaba021e94a3c292dc8", + "0xbd6e7bf8b466940b9f619e3f433fb68c68d344974798996e454c925e2628b1b2", + "0x112b5e9d438eb79aa9d7b4488b6aa9f7edf7599dce805d8781510302da45e9a2", + "0x881255ae2cab543ee6b429e1b201c197cb35051d53f881cb51fc58f9c760e51d", + "0xcf56a4ed6b771e4905e6ba888390526eba8ba3483ead7585dee00c0eaea58cbc", + "0x12705d1609ee34bce0c82bab9da730452db57863371f5b84de84c4c135537237", + "0xa9abc081a75bfcde86ea830483be240cb3bcfa72ae34a16dfc35cb964dd7a457", + "0x65cf0c91f8567d8567ac3f00ddc19da0b916179266c7e42768fd5d7271e91092", + "0x07f15ccc91a47edfe9b67a79d05ed1da1410e3ac16e4a4c2147c3ef0de26ae62", + "0xb44eb7db9e4dbe8901bfac43ad54ef27576a3ac0c78218138715e03b3f9a782e", + "0x9ef66d20aeccdea66ade0fe8ccc0a85dbe9498305509c8919b670ae8e854a450", + "0xb10a7dbd4857f910ae8cca5d1b7a85923adaad65c4b00d1255813efef00c646f", + "0x20410bc64b58a1c221f7b38f293700591692c73a785d94a5548b336bd5db10da", + "0xed7176f398eb75ae6c1d4348d3882aade99573f8369ef00e809b1ff91b5a9191", + "0x35f06785e1f7e362682e969586322b1588624f6025692ca87db21cb199c382f4", + "0x9a6b06141660e2bd106f6d46afd2f3e64d72711ffe6a9c495887bc3932f7934e", + "0xd64e602a976e86d3948d0f4cf0b8f13a63558d5bdea5affb36eeb91007a653b3", + "0x71050553ca1da7234764a5486e4647fdad00652560eb47102c1d0fc039b4b63e", + "0x53ba43f79de58a957e8ac0d998ecb4999c68f423b1769d9e8df2405259dcdaa6", + "0x17b33d269609bd90fac57eaeb298bf489a3b8a985cfd9998d297c7e0628bc84c", + "0x9b47bba7ff6b283e76100e36246c0dcad836ff29a674fbb1c6d2f58e38e29f92", + "0x262f8387628500fa26e2cdca6b5938262c8fa81888daed41a09d880df136167f", + "0xb6c6d0ed2824a9818fa9476c99a810cf33a0c1fd3f2fb6b7a44603f2442525e7", + "0x6f3437e677dcc60cb587f6100eaa2e7ef5c76b57023b63ae61a6a8ed2750512d", + "0x4bb5aad759b0c6390cf4dbc6c32e78f2721c2be3f40ca3d11de880fbe90e456a", + "0xfbeced3e048769a07bfd50010de59cd24f2c534234abc1ee7f3fe9d7e3d9f482", + "0xbe871fdd431974370e8156fb9347377d1bb07990ff60296abbaaf2c38b4059d0", + "0xcbdf566fceb5adc33608a847c77b6f3501cdc4182ba98e04e1f7e8b8ae66ba5b", + "0xa06a5de4aeafdb5981ae02004a38c524116ebe557dda83abdf03141e4dfbd4cd", + "0x73660bb361b94287b85b6c41394bea5447e8e3ccffaba1772a765a8fc0fa9b27", + "0xf80439908d6173fe4fea42aeb07ddea2c644e581373dbe9dbb9d092f12fd2125", + "0x32d935f078bdbb9ae693bef4ab8316e7da701edf42f156568b639193b0ea24bf", + "0x8ef0b9f247b5b9d9e5a813877d03a518d1f06900e2fdf5743feda3537ab3777d", + "0x59f92f14340a77b94839b6ea61389691a6fa5bb2ddc5b2241e873b066d37fc61", + "0x0288bdae302901b701df46263f4b12bdd6bd76436c3ae1626936e1b4bb631ca7", + "0x2fcfd5a54d6bbe07d4063ef64fe4b164bd8cb89a8e03cb5fabee98bfef280e43", + "0xd8d1169b3a9aca48f167cd43e9617d3ecc74658ea61ace251beb370d3c05f86c", + "0xdb2c3ef7b8a8a18ad3a8ce7cb8a6be2e1ef2cd694fb3f1b2e0732f2e27c758cb", + "0xfbffbf26f4756bcf1cd217686597ffe9c1282a70b279c8b01ee5076ec31b1c2c", + "0x2cf1404cc8482698eccde40185740753c47319b1aa30d9204fe53922feaae9b8", + "0x553a9e079d09d3f8251947ab37891027fc3d041246f2e43f01321fc3523b508f", + "0x35954f131f276933c7ef3938f35c6011806c7dd637fa249451379003d740cbaa", + "0x1ee7a658e8a2368391810667c35b8b0e321d381907e2312e7789a3cc7b0341aa", + "0x4cb3c908526bc6ccbdd39d855b3b3649e59eec4322bf48f07598d98240101d0c", + "0x996eb99b0cb27fb5ec07873af17933f377ed2c131f02926bab74341c475a95a9", + "0x68a90de2c8ea439db0417b77a23eb66e7421268335be7e4f593a52b1093681fa", + "0x4325afa26bf545951a73c016d866f1c71a5855ef52202b7ad0c54dc23906936d", + "0xaf5111b606b0e6d699bb4fb61c8a0592af7eb45dd7357b3e896ebc3e798919ad", + "0x4de03498b2d532a8eb01a12edea2a15b8a907d6d23ccfc380507a5d294abce99", + "0x5d642ba55dc046ef1b84fe594ae2e46b844cc6590d580e2591ba9c0c1c942c24", + "0x8477bb69d6d23ae4f45e56c372d66f42ba7417cf5107136081b5ccdd208b1545", + "0x924f641a7cea7cf76ad8920b9ee7c39e74304169571b028fbe40e6ed255a90f4", + "0x4b39dbfae8635f286284009a0213c6d267d5f48485a25f2df855c5cac5e7d6ca", + "0x61827bf3a120a079111665f78ba2e5ad15943492e4ffdfc708e235f44ce92842", + "0xdc0c0dafc340277058a6f8e03bf4e5e733e05fa638e2a8c4ebe4521960bbdc20", + "0x7038c52c4e92d6ed20b19481ed63d432325f94ee2a3ad4c0d5e25fafe5b32bd6", + "0xe1f5a1123679ce45005d53672018e16648fd44c4a2251802f295d29ed876a0db", + "0x173a332438a181f6cf1773b2603556d229254861534f34ad65b2170b0cf47fb5", + "0x22a19ab1d828b5d05057f40f5cf798e27ec068fc584968987b7bbe440f52ac84", + "0x15b3e3b6e1de6b8a407ad7e325c53c4bfa9e73f23c6f3acedcdf68d759f73860", + "0x0347a8e310cbc921daf829002ba0c44399c4dd7c930ac1fca203272949e09dc9", + "0x9babeec2d3003ddb15fdcb89ec7b61c0d7f795145b58f55a17810447d5afe5be", + "0x62c14ff2ed414ede1e3fa7fc2fccbab0b8f284b9f38127823c3dc9eb55a08b44", + "0xb301a7c865abe0f42d9444b5c3b775dc6ab4c99effbe8d54cec29745ff4af01d", + "0x3fabed16363d78f34a13ca6b99cfc592671668d4281c5eb3ab07f4b9017a4ebc", + "0xb14af7c7331f7b5518e04bc31c8c2b63d9d497acac405bc22e1ab2431105b867", + "0xb7b90e8852ae132f858cb98635fd6e1267b141de7da6773ec4092d5c83def42b", + "0x1a5c8bed811fc72de8146516cc4d668fc4557baf48082503a2a5cc0e473b6e08", + "0x0060158b427095081a18fc57c4f56290873188960dc0e4d2b16cdd57b5761100", + "0x2f0dd546f4982d47b6e04ce282b19be8e165b5c89b5f03c1ac8c6d8be2af2b4f", + "0x229d31a50f46afeda23a2535c8b011a827383c981e7e59f67622359e4b307a10", + "0x10da7b2e78954845b506b9672ff93d3a617f187521116d442b364a1178f10f08", + "0x511325c034c772ff3a61b1c8d94e3c13f19cf1e93523a8924666833bc1e5b0ba", + "0x3a8b0251b2f7c99774d0a7863388422723b5405fd1db035ec5e30df90306e251", + "0x885c3b0507dcdd6e1cec187cf3d97ee12ce101ccf63d99c1c7fc77dd57ee0439", + "0xa76f1fdcf546ccb62f86ec7b85bd8eb662f696d7aed2f2ed2b3c769af90897b2", + "0xbec073b15a35de54487b60f92615cd44dbcb5a5fa9d1bcca2ea31437b2e45756", + "0x662013eba4201630ccc4a9b6fb1dac36f439cc6cd2b6f295c0260713d075108e", + "0x81b0148f7e690088330650b01c52831d50f3d30ba2fd2074bca5513c179ad30a", + "0x01614cb8f2f2bd6794a20513fffe99a36eee526b7145405db15f9c2ede980093", + "0xd3d8664a5464c8f681e37265948c4046e373843e602bee66c8583277397db258", + "0xdaf61a9e7157100cce6ea5bc405926fd4190fda7354edaafad9b6e468bb24422", + "0xeb05144e032621f7b1792dacbdc79c044a268442a9a9284ef1b2d1d60cadb29f", + "0xb1916e802e8e3eca2570d1a190d317cf38cf9f6b58119b65ed0d60b9749461ad", + "0x17e103cb26e7c5c7678a523f99f90387490bcca00916190e7e1b38274c52a375", + "0x105b8126ef037364f46a44fdca4fea1ec4c099de5a05918688249fb8844dfea0", + "0x7ca09f536bb9f0d7b3809c086918ba4750722edfd47153a8412fc761eb4783c8", + "0xc988cc2d92dcb85eaff8cf2f70ca49646cc5aff6c8e10b43a0581193137d3b92" ] }, "nodes": [ diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 336d32bae..1935e4174 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -62,8 +62,8 @@ "gasLimit": "0x5B8D80" }, "hardcodedSync": { - "header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01", - "totalDifficulty": "3020091077015059097853315484608800838133866777", + "header": "f90247a0434ba1ebe3bc9d9d12886f616afee0eb785dd00d78aa64502045b249c8a3cc33a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940010f94b296a852aaac52ea6c5ac72e03afd032da0d1c1137be913218840c44bdb8f5709a59d8608b05be0dc2401402e11ff1bf2ada0eb50a864e57e19bd4c8499725a6a3841f706ff5d743e64f1d06db903aca62eaba0d4d77727f7253c109e6f048fa5b1583b6c2911ad77f7d59d8947d38a96a67729b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffe838ee001837a120083013502845bea4f689fde830200088f5061726974792d457468657265756d86312e32392e30826c698416fa93dab841c80b3e34bacdc91e01f6a76c64a920a65edfea86b84e0fd59c6d8dbd7758f2dc4e3cb446de8dc07f3d8cb71375a6315f401cd1ce54c56694e4e01f7e774555e701", + "totalDifficulty": "3135776192732436705400032023148164213445066062", "CHTs": [ "0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac", "0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02", @@ -4470,7 +4470,173 @@ "0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4", "0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00", "0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2", - "0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12" + "0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12", + "0x2c711e8eec1be3caef6e16a03dcca83dac3a565c93327c67f4e8ea9f2697d9e9", + "0x21d7a9a3f22a163767075aa693d82a962e4458b074bd8f3485c4ded1e47c1172", + "0x1509cac83867db4b888107974d5c8547dc4aa1db3b8e886291f0f9eb6bd7af58", + "0xa555eb6001982080479c9bdd3da9e8668bf90ca9538f16f27a45ae698ec85fb7", + "0x1d1f4019fa3ea7ec85ee0a411560738791f2d45fe5fe6242d07267183a852b96", + "0x2a8994caa5a27eb3081cc749cda5694da7ed3fbb8a1b4c67d7e92306cbd3c6ab", + "0x8389736ba114022ea97a6b3e755d75e74c3c370e9eb916c0f2d73a46a6f6c396", + "0x6a2e5d08ea64195a4153fc7bf26b7a99dcc9d31d8f58faa07510a1e87fb1ade4", + "0x78b66b38fd9b9cd3a5bc9c91c6f816153c2c28c1055f7ac9ad12ab61f9464850", + "0xb2f77834f7a88c4354763a28080d95be44dcb380d01f09292e679a6ed274b179", + "0x2070456b2bff0c30ae26b2435af82e153094aeea8102a75541e02a39e9ebe717", + "0x4e3bb2fbdc71602a62f0c423aa45398af09cf3ad24f0437027b4590e7056b882", + "0xe877208750e7569ce78215659ef78c1656e98b63ab6cc3e1381d7581afbea99f", + "0x8c9d8132d01b83cffd1a1fd9d19a3d2fb3a58a0a28602018db44f8b6dd5fe1aa", + "0xcece8a371b72873a660f4077f98b04d6a3cde1a150852db3a194a293e6a08b72", + "0xe72c8c7211acf2d67bf904cb3428c6fd69c8bd679d52deb3b2e749d5a3124b86", + "0x504f53693e747fbba7475dff1aad887ad0124d48cc7892ec488fda56e31e0de5", + "0xddb3ce7ac0c7e2d141df857e9e5c083d66f4a62ead742bf6631756a72fb643e3", + "0xdc1c6a45dd8308ea319671732de7578a65a025852a3cbe88aa9c5d770d662990", + "0xb6a9df772bdb5e7cdff569bb9d3078c081ed53e870f9171a5b0369d84fe6ce50", + "0x1b436a7d8c9af357c8175430e1d0d3057096c92bd8bd24fe285fa55673c68b72", + "0xa57ce7fed7521e26a908ead89253bc57939459b4c34fba583eececd0f9104e2a", + "0xb16c4f6bdce8de6657d049e2e41f91a1cef8623671eacb9ab02fff45cee7c0c3", + "0x8d23f3ea29767da41a2090cfceb56a65236a405031b69e614c78fb79c1847651", + "0x33149d4876fa24dea4e872ad1da120e01b14e8f9f8270611fced328a36df25ca", + "0x266c558486a85de2536e8849d49443e7d39797a6ed817ad7217633c28166bf06", + "0x2073a22a1f157025228f8fc82bdaff48d3cb1c9b004ac2cb867c2cbbe7cafd95", + "0xcf643d70f96101c99cedcc2d169b0196c564e7a8b235ae093ad25b1ba8981d01", + "0x1489101bebc1b60e4c0fa37a94bb946f1b51ba284c667e4b2f3270ef9d264d41", + "0xd2eceef739e2601390d872bdbb58f8d67864b000f7fbab07b0354c44279379e8", + "0xf67a02d7e7e6da127015e5137f90e30ab43c2e828e62c3f8fe68ad5a0a3011fb", + "0x01fe94220a07efc2bde2404c584f67e9b06e47eba05e50e71ad59710d9d6a9fd", + "0x509bc80d1a464116b4f234001c3f2d7aac7772cd6ec5fa6ef9606ab8ab273127", + "0xea497db1233691b3b86d8fc80ebffe28e6863f445a0b352a1286412a94ad2f6f", + "0x80074f0e2cb668b6a8e5b454db4ae5cf2482894f3ccb7648cfa26b3365a0a54b", + "0x56c8cd15e5e1a21c6f32f7211d18e1e56c89da688cf11b80c9e55718514eab24", + "0x6705989758f03a8c4ee93d44f53b4114a10337694197186b62ac2220188a6879", + "0x7581fbe2b0ae6e0a61d073fd1700c3111d2e3e8d9342d50800ba05d026c9edd6", + "0x254548091369ad8e0abbd2eb4e31e2c08c8e9dc0256fd0097e50e75831946924", + "0xac3119a5ba40f303a9a70ecdef9b6d4722c6adb6592a0cf52e5a312a1a0819c2", + "0xbdf30bc3cd852b882c5d410e6d4419e0f36ed17b761b58fe58ded980829d1cf8", + "0xebaeb5965563f6fa71006d8c2d285e093a167630c319cee2dfa961c4a583b60b", + "0x6cd6717885bd50263a97574e8a56a3ccbca88229bce595b38a454c1184ea94d5", + "0xc9bba3a4a72f0f08663e3af36e2bac2d4c8422b2e3c3bd29705e5b86e7c42a20", + "0xcc442230a4b6aed5a1eb2b8744a09aefe3cfb9e477816edfa829dfbd3f7c2bc7", + "0x4ee48471e3326144c7a48b15fa5f39691ad9f24b82430ca281eb961b18019e02", + "0x35016779dd877530f99b1d3372a0a77eff7ae831208d2bdfcd0979b838190acd", + "0xe3e9b2a4adc4b4e167376b33b8bf2a00bd64d52f66f4e7b291ade123e8c04402", + "0x5a7d1466e2538b62ceada9577079248788e912e23c4cbc52d7b82a1afbf28ec7", + "0xb8529c5a2b2dbfb72e70165b9c9291e7c02b43f157092a9b59f3b4cad85fb587", + "0x55e90fb666a950f38ae41732269cb69afca8643b75a99bce508a16e06685fc03", + "0x651f45996ed080d8a8dcb78550089331ad67c2df33330d1871dff956463aed3e", + "0x9c6b4a961663c59dde3a4f0fdf7b68b0b5f049719ba0d10d841855cffc7ee166", + "0x15c4d98e0ee4fa1535f83625a20bf1a491852884f8fe608eae6b9bde45986779", + "0xc7891cf34fcc61935a43f37bd7f23b674c785ef3b2718358fb627364f3d8b09b", + "0x8105fb76c9e1281f0f0d7c520dc6cd1d546d1b4b29cfa398eecd7965af57f408", + "0x2a141f1c4e1f1e7be5d10c444dde3d1b5fe1a69f23506d5ed1842957375a1208", + "0x9d2313d34a5a6873f2ae1e2684db00e3b693ba962796fe7e78d26a2c49104471", + "0x84d0245b1537ec1fae89fd39741d3b6427ceda3933f750befe4e2d8ec022fc1b", + "0x93d281ff6bfefc7f94058a0d87cb826b97728c9593ef4876b88c35d26b2163bf", + "0x9018a352b09cb36311d0b54bd83a33dcd5dca5ae7032f1d399fec3a0e5a9cb7a", + "0xf01486ea17dca0bb45c245c9ba76d20d1a2f4eb718b7d07fb5183736e5cd08c5", + "0xf797fec0a8cddb31ace66223e1355211e41211c4bfd33a416c8a1a86e497f630", + "0xf24aef69daf4e2b90b4f3bdedddbabbae86a7fd1182947da7306c8145f82cc88", + "0xdd14e34cd000ddb6ae6426dcd78cabbf6bfbe5b3ecd7553c4989b3891e506257", + "0xc01ece645c7430801ee26b20ad215e221f7de0e060fe004b450b372a6c4438a9", + "0x64c836653383bcb165207b80ee8f9377ad25ef1bcd6cf7ba166cca78419898ed", + "0x6b1cdfa195df272d7e35ccd843191d5725919c0d8b71f1abf4b950a954770503", + "0xebe51f94a9f445d83180c4f075d944fa2f05b5b784b7e3cb4bc1544020bd35cf", + "0x7007f6b2c04420d390fbdb6a9fc21edd3249c1a098f8a9383131b8be50c6f975", + "0x6b7e93d96f74fc2b068104a017fa5fa74836e8be5599865309361ad9305d9bb9", + "0xcccf2dc238c68464f3b0446e06fc48fedf202e366ace5734cdac5a7fe7c43342", + "0xfec77750c277cd6bb0937d25d7f598d07cbffb1117b6232e932a296f32b45ce5", + "0xb04e6883c11ba3f2b7f0301936c3dcb622f6f78b3d3d57e48c6dcba063038d6e", + "0x23fe83ea2f197cb97a3ce5f2afd75652cae993f30bc627e8b9572a0069ae088b", + "0x44cc6bf2cee513c826ecc0c130a32b61b0153129721ad2a70d4503b71c128247", + "0xb1a11be5f9b37faf1901b1405494af32084641dc02685ec33be7f6e82e360a42", + "0x284bdf9a6aa0ac964b0f5e72d0d47c713c919d72fa9e24f42b65d749efb6e2c3", + "0x96a0a0e92ed87946a322c9bca6c0ebf70e51e0e825e2ede85b975349f9bb2caa", + "0xd73becb6a3d9a155d46a96d17412cf015724a79b166d2961d24125d92e355947", + "0xd87f142746611ce081945999f42b8da49cbda03a10bf953ba043417861e27c77", + "0x4af010485b5385579a534693bd21ef3768c8920c5b5dc6f9ddf722cc68fd6550", + "0x65a2f4ec5cf3b37530fe0672418214618393db47ad1185f285b445cf5f53cf26", + "0x1d208df2a2785599565a40d934eb2c0cc1673c1dd43d11685d698122ecf24d6f", + "0x046b7211427f0027ed4b69b06cb43986d3cd53d1579a2e078f6904a06ee6587d", + "0x053fb3ccc35edc1a1623f8652dd8c239045b02b58ffe7d51337950ae43365990", + "0x0721f82b52ff87272e1b0af5f4dc16b90dfaaaf3ba56b91bef555d283c98a8ae", + "0x26e93e4e2d0df49a857bfcede7e6ac234d75b71617b561ce39c3db130449e4fb", + "0x5ed6d53c35a0aa52d9dd0a244f31be00426292c11676737c7283f567ba485dbc", + "0x047add17bd1601a06a32b721165ecb2afb55290e025a828696f234b95c52eae3", + "0x6f9e6884745cad7091646f7767a6b17ebffb6482ee4726f5c1f3b9e02d26b77f", + "0xab29ed5be2938fb19614da621ea9828eb338514309b3d56efc6f19b57b8f4f6a", + "0xd5f14043479e8e37c6545527b2e93a76763a654661af9a25adae2b37dac40672", + "0xc43635c1489c3cf3aa231419bfcf7bcb2455a812e4781e5947bb76cf0219d1e4", + "0x72117c92f8bab83ccc7fbe5fc6cd931c765238ebd67ad8c4fcf1353eb78c8df2", + "0x5deed7df3559ed75d7c2388a6e583067222684741143350f85d236bc5fb4075f", + "0x655bbc0590587c030902e32d88cc9113fcbdd5c3371820868768abaeacecb79c", + "0x1641c875e8e44b1fa71badcbb4f724a71e2f916d9cd212f09e9039ef41b1242f", + "0x40bacdc3f0b53522cdf2aefafa2bbd9c8e9f8fd25b4b33bc19a87d72a5de293d", + "0xc35c6cffaf93170662a6f3d4a0152c988b0f4916a33d037801f6f589a6140d08", + "0xd4e37125c0ca7844e048bac4e4c6069ec24b0493e4547f53679fc8df2a1e0d66", + "0x34c6bcf0e01dd55a1d3a82df0a2edcb2caccbc4be93fdfde32c7718276e59bbd", + "0x78e50d394d9d42ca8aae3f4dfccfb32fc3923073a6643c010fd49ec3897c4fe5", + "0xeba75c237fb213e893083c5ed0e28dde3ec1f5f1b60edfdddc17a54de9cdfaf3", + "0x4f35b9a67fc66492fea331378c479eba921fe0a6f0589b5ac07a44b1ea9b4995", + "0xbb4d09d98b27d672259b608f5075575cca49f87cce0519813c1ba4a614d369ee", + "0x805550ff80be2d3a543d5076961442f70dcd86e82762149c125d2ce371a32f69", + "0x7d81d766cc2d6c66c7bf07be0a416f2a4c0dd2bd94026270a410ea6a051dd4aa", + "0x30edcef101041c0e0acecb8d6c15a28c70b8894e56196cddefb5fb6b39658ceb", + "0xe5e8d21a00ccabb5cb50b4d04ee1dcc217fb9908e72bf0efab69d4ce7a0b7eab", + "0x3793f78e2e582b56fb3d24e3bd4aa69db4741e768795f9681285b0fd34ebd602", + "0x4a9378b4ad76df084739b2a63459ac67abf8eff7499210936fb9e6644265054a", + "0x2e47b62375a267e104ad2f8bfaf5c985fa7c6f4c438739810517e41141a825bd", + "0x73dd638affe08c104b37d53e6cb7884b8a9b4cd4afa4bbec6ef608bab4559dd9", + "0xc566dce73da1cc0d069a032045c44ac4ac86b145efd2cb1c363a2d403fd8d7cd", + "0xa1a04d193c5408d0edf85e771c6976c5dc8de08c87d906b6c9de1efa4b4fcbca", + "0x3245d987f205b01c54448d9a9d76bc7e4174c1021726a68f5feb6748ac373f8d", + "0x1f963274b936dde92281f2acd47d3685261b03845efc7d10ab8b02500c239af0", + "0xa1e6d69b28aea5d24c3dc301dfb0d6df8ee8fe693d1d0f419cde3b4d20d22a89", + "0x31b0711795c77cae9e1b62b87244a5eafa4b1764aa1620d53be7e779db060984", + "0xea141234dd00c54ec7912c80baca591b53a058b81fed1673317fa4ec37c2c715", + "0xc5902f3941d647da304e94062951b09f4d6da5bcff71517c7a35e8b49c6ac569", + "0x54c5677af7e31b84010f8b2941ffed5080e9b4d18b608fcbd230f163a5e04ba5", + "0x1a12c56542a01bc58288a58e8e526f2b2c81a5238c83bbfe4808d206b3b9d0e4", + "0xa398984bab81b7640674893496b2346eaa8257aad4cc8bb52474f7162fb6fa2d", + "0xf454a592314f1b7459d21eeb6ffe54c96ae2e25a7051dab1f8129518d3788cd2", + "0x12964f85bcc410fb40e89f518d749c7dc2be7546a960849dcf560eea2ec3d333", + "0xb176775c2ff94aedef2c099b936468986874d17eb563086215525acbee2fdbd1", + "0x250de6e94d60125bb680e862fcb70823d06e4f27308ea1ecea8a465d5febc860", + "0x731cc6817fec665290d7637c67fdbc72bbebae70a13f9346f47f3b368eb1e4a5", + "0x489e955cc77f16d8aa16bada320127380315eac978f0fd1033baa04911123332", + "0xa88623d9f89221dce46b55ca7248581b4e3ace94a7cccc9fd44a3b03412fa729", + "0x4a65c1808d79577b36dfb5fa74d0deb96e90d0105ee373d552685cc4f73d35d8", + "0x7aa8228e6f8fb98a23e1599e12ecd84c879475a23f10660e763e338a347c9002", + "0xa825d02023ab76478b83a2a61dcc5cf6c05ca741b960043adba3f13d1c99612a", + "0xd3c90e414048510d9594ae7a593e25641b6baf93f9625cc4a3caade094f02e07", + "0x4d631d9024a4e75111189835b4ec0007a6951d710512dd7b91a8d56da95e57b2", + "0x0158c7f49affa675f04aa4ebdf11e88bab8c6dc0abfecc0100d32489b0d59f1a", + "0x4ec96496694ef53e17b11b3122cc45cce3a4fe1a252fe9c0d379b302db1318ac", + "0xeec44b94d9f6c7359047d257ffd5f1f5cee87b3ebd6845dc1fe48be686a9ba69", + "0xe24c7b667382186196e5da605ce75a5cd9c7e4803fb2e268b4de5848737db026", + "0x14a551850f945f02fa2ab84c6ffe3d17930c81f5b15e94ce92342c3646b8cd9a", + "0x7e9a72469a52662bbcacd449dc7df8fa75e5cd1480dac3b635148a34e0f9e375", + "0x2dd4fd0394574c5d8c9272c42175e3a88d8501753bb25a77fa937123d0c2538d", + "0x6f044eb54fd2b8e51d89f6db2ee6e654b144d9e69cddf79b7899e06af5bf39f5", + "0x091d894513fca5d2239f6b5ce73737aa2657c90c2af196b2b893ba0b0205859c", + "0x78b9ca580e3eca0808e60420ead000365eeafa60c6394e055a653a7f536c8b6d", + "0x595cfe325aa600ef0d7de6b2eb717b33c92dfbb1e3ecb9487fe332c878e9f121", + "0xe1dcc22aa44a0243f67dcb0aef7e0eb1ceee269b0faa67633698f8ee29155115", + "0xddd3354d4167161c6b18173ae24fffac2cff12a8bcb3ddf1d964907716685cb3", + "0x55c02c02eb758f8c9aab60a2432d29e73b567e3e3d0148611ce4569fa074c5d9", + "0x5d07d5a7d45fe16a0521c55b3dd898b922c619e5b938535e2f974f11b4edfdc7", + "0xf75100a1a2f8d6daf0dc36569cbf579ed6e52838b163fe50b5deaad8fe7bd07d", + "0xb6391d028fbc88825eabf1dc4566e58112e6d3b7cfe6d387d0fa58df387df78f", + "0x8a58fab34ada4d30eecbad64a001015c91e446cf14e95c9d7a3d894530787b03", + "0xac13b36d0eb0483ab8cf21f49c78f9e32092c74c878ff520ed3a3c0080fdf5fd", + "0x358c1021fbdf028ec82b811cdeb504adc2611a1ab477e8a191f780592d598361", + "0x6a7af25eb6d089ad63712187d1414e8bd04fb6bfbac26e6086b1a3e2d66f6f7e", + "0x6bebf617fe66129dc8c9dadef1a74df05567ed2fc89f4e5c4dd36327d6b0a5e5", + "0xc658d76eb9f3fb91327c64668b08d3e9bfbbb2099bf5d9aeb6a61b8e4f893c39", + "0xfe68ecc66eaa625842068f8b5ad4bdf5cbce0c82ecfafa4bf48b08de49c58595", + "0x26eba0a168f2e5f3ffcb37955839d37432b39f2f447497854d42d802826fb1ee", + "0x8b4f8964062d0f00e40a41d21852a2e22abba1f4cf75f594797e368e4df21f7d", + "0x916993123d91b181d145e2668efed6eae3845fd76d4765df3a04d8adde8c7142", + "0x21b91051b5c5fbd22164a655de8485cfc2a9eff58ed09d6fbbb454560898daed", + "0xb52ca76065bcf43f06335977ab87d6c809dcf4e6cdfc452ac2018b77c64089a5" ] }, "accounts": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 264e6ee97..86926a7c0 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -62,8 +62,8 @@ "gasLimit": "0x1000000" }, "hardcodedSync":{ - "header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67", - "totalDifficulty": "12027449412394243", + "header": "f90205a0cd611d63e443c91cba1dc259c71fdb96bb70a1b78639166f7aa2a09b36843f7da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940d85c541489b4c67df516b86898e1ed59c8d639aa039cdbfba9ee1e91d15fead004292a7df0865204ee878daab2375683cc527df2ca0ebf5b5fe0ef82be8bda42e6767ad7881269cefe650c3a899f38f5ed1c05cad8da0578f443c4b0d0bd89e42a855436258f1b19d1a018f6769c5be7aca0679ce6008b90100000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000008000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000800000000000000008501856ef4de83436801837a121d830e1038845bea0191864b564f544845a08dcfeee7d79d54276d8bc35765ade21a51d277540a3d7a8e17fc26b6324487e488d70f2a90307e2ae3", + "totalDifficulty": "14549054591321060", "CHTs": [ "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", @@ -2116,7 +2116,112 @@ "0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85", "0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b", "0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c", - "0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9" + "0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9", + "0xa1157fb181aaa945793b029d3915b37103d050f1f695862d9cda90df4755c189", + "0x449c9daae1c38b3d3f6861b63dc611f147b8a29029927f85c32b5e549df8ee9d", + "0x5739fcf908f960416e5227ff6f95aeb00696f8eb7192968239458a0aebf42533", + "0xfaa6017362d6e64f9ae1b6d11764ddba77cd980261acb5bdbb17b7cdee2d3024", + "0x97fee586909cf8b3cfb2f2dd4e251cb642eb551f1e5d9fa557a21dcb66f430c0", + "0x9934d90e0b4ec5900107784116323b0f76d1d71491cf9c619520478b6eb97ded", + "0x8f5afe4fefb0de810442e27b2bce63e3a424f9e339a0e1f46f6ed26617a4a404", + "0xcd12ed1b75e624f93d9e4fe7dc65407b6d7963196e4082fb459ce354977355a1", + "0x6858ff0c07de87aa2a88498ae948efe6cffade00f3f21086f0a71b8364090846", + "0xaca944e99122e4fe41c62b88e67940332483c8aae2a3a615508f848ceb1c044e", + "0xa8bd3a6b9197bec8849737e6771f563d14d7415707776ce4bed9460588c55c9a", + "0x20e5f18e795844cfcf2326f52ab1e56f4a53a1ce405fd355e0d37de5f6d552ee", + "0x038821cd156d2d9e2aff1ce3525726c42f581ca3e9e2cc75df524a3dbdfe0feb", + "0xb79bd23e10d1e6c7ae749cecaa732966ce3c2e2ea8b640d43638f14d7b78a21c", + "0x2c4d3bcae4a76ffe6924555b320847211367ee37899b187d8fd4358d91264c2e", + "0x0896db7657d2aa8d02166bd4ceba7515b24147fcf0aa34223590fb80db64f848", + "0x95f3b077d9cff92709d46185a7dc5d723f257fb77641e436b0f1bf07947844a1", + "0x6fdd931a93229698b92e6419074bc308a372e0923b35321b725916c1c151cae0", + "0x8c337c36c2027d0f2fb96405f76d3190cdd01237f6a602e07976e09c4a2339e4", + "0x8091a859cf86c1e2c22c870ebc10334f50e05bac2a41153102bf3f698bf5156b", + "0x382435cc836bf1873e489cb4d42d1c1673c5d1b452ba2d16dbd1ca77b7b87a8c", + "0xac5a288b16ed708b00cbe956a14e2a64b321f40851ea25ab1aded7b096822ec6", + "0xee95229b736827a21e0b7154873da3da59e38a1ba3e3b1770de2ed973495ce23", + "0x5168b6e3b5274054fec17b94a82931bc229d0270e5e4c9aeb61539fe8ba4f4a3", + "0x588c6144dfbb33922873946a44f03092bd65d2f89a01b3973002ed38f48917bc", + "0x6c51a964953dc036043b6e8c7fba4a3f6e83295306767bcc3562d9a8cdb04497", + "0x2cfdde11cc2669c5b504c4a82c31ff03e3f0b3aff044519b44bc39405bbf3c9b", + "0xd93200e550400a7179ac7afc394b22b7c710192eadbf429389450e7167191fdb", + "0x5e32f497c606c01c9be8ce1cca5f3cf475f62cf38b2195244a7c93df7d064dde", + "0xb0b74e34fd3983aef31a0584b6a7483ee936622b5fffbdce1411a9db6171c685", + "0x69d0a96a2eca8d6a5c32e700d3f910330930a3348e98e5b276013fcf70c0fe5f", + "0xf49cbb26f2463d38fde553e483de2d4bc6dd85efe2d0e56a2a79810df6af6db9", + "0xe58aa167a26eadf11257f1fcb5da7eef50f9985b590320cc6c015176965ea58e", + "0x582f08d14023a661a9d9dfd1db8324be88fc631cb9136e92f379ad7703584414", + "0xb9c5e584f5e231c2c41b41799a945d60b7ec22487e587ef55e2d9710489c3c00", + "0xd8b70c6657a5bf1fa4b67c4fc046c1eda284d677c610dbacaf0d2d84e4d782dd", + "0x1e29fb536e468abf66b59dd6f48d177a5100a192f1807afc12bb5c97368b8c95", + "0x595ac042acdb51370bf6bfd2b2058dda4781dd7ec330474defb2d5dd00e7f50e", + "0x3d00887c6509b148c5fadde21014aae94924fef363fd5723d80d6a2028df1de5", + "0x9632d419c9fdc7e676b130806cb9c86631aade0adc6a129d3769908ff97e7ef3", + "0x2f91c7ce1158228c8264a6147c6ca396b0d536cdde997a922cde2772b786743f", + "0xf4c731ac2e2612b7e7afcf3ba5911a58a03ef075133923218f54a736b25acb81", + "0x6748a5143ad25f0a461257a47eeab8f057782a438274ced580ca2bd3725d6be3", + "0x05a113b04baf81b6396dd32d59a53908d07a374ebdf17314ec334b3330a16697", + "0xb1bafaef874da14b8a9f883f89a896ec37d9af1b0958f5a3867780278bfe940d", + "0xd93c67d29befe531330c37dfa8b64db7339c8ac35b8cb674d741a414d90d77ef", + "0xb4319281a05f00968367a349e626ec63227412193c30aaface14ac6f7a480024", + "0xf6dce891724a49024535047bee44f889d5228066a931a8f40c18c7efed60f31b", + "0xccdeb308e3402c7dc72588871c23fb4f6fdc60e2a63230f628c5a2951878535b", + "0x90958033b917eea42ffb8bf077ccab8b19c2448113e8a128815ab3441846404b", + "0xed3436553039948094f33cffaff91a7e2b1eab86b638de5c8eb09538c8df0a8e", + "0x0910ba3093e37abaf70ffc0ef6a3b9b82e8c5f7ae497eec14b753f23d0a25343", + "0xdc78d9fceec3add33b92e1a0ee402b80cd87946e0def46f284d26eac46be6bcd", + "0x1d71a82b8d4b89f73747d8073a36acf8496757d35bb452e9cfd74d758774f492", + "0x5399612937722b6fbcb90c1768a92bb35acd4da6168814c1d9deb6156cf35134", + "0xc7156ee3591ab91824b2d4868d28baf11855a63a801b3793f99fdde7867eac7f", + "0xd25b288f3333ea8e33b33f42edf7b64976281e4840599aa49b07da39f895073a", + "0xc6596a87c544e84cfaa2baaa4fb0a93f3fa9d1e6938426ea05a418568a1589b0", + "0xdbf30aa7f1cb3a6d7661934d7ea2ec0665843ea1ec9b05fddd77fdb33fa7d834", + "0xfac2628cb5d70c177e8defbf62b0448297ecb13962638b9a26c5d05203cb2937", + "0xe8c5a65edee74d59e7b9e2fb4779485958d95303fff95bfebc0c1f4bf24ef9bf", + "0x67d21b95f40ca7c991f37981393dcec3218e70d5402d82ecbfcb21ae532872bb", + "0xba19c10601ed47bffb755f791325c50af9229d5c25294f315116fdb3640ca35a", + "0xf4c026f65e31d4606541c4e679d30d7336cfeeb81e9893465eb08c310792c061", + "0x5425ff602e06947bda22cfb687ace85c10896b5d48de144149cba26bac9a35ae", + "0xe11f82e350c209213da7d977e2de5199559ad3793a24a226cb4be367c0aa3c4a", + "0x13fb0194f473a4af296184d3293005dffcd28f1cf4b986bdaacede4a0a096fa6", + "0x3dab80c9fc23caf409e38791f07e107da3b5d0d9d4a64f87164e6d455660591b", + "0x5901803b234ef0445acfcd884baf0777970d3b600b80ab137dc1015a5b790885", + "0x3735e2d0ac017cd2c0570830615ed9eb642183fee5b2c2155e5fefc1d4de2561", + "0xea9030afc249a1e4f6c86f4b19660ea63783824e8d1c3de30e38802f1aea9d12", + "0x9def3e76927de026a1a76f39c242263ffbf94b3ef42fb6e98626b67ec3d8a308", + "0x504886149f29d5eb02412202f04b45f23cc97a82206bdf237c433e83c52e386b", + "0xc84d3b9e84727c2d9279dfebcdf8104762e3b101dd9f39c9482a456f87bcf976", + "0xf4737cd864b198c8049ece5a4f18eea18b48a649997c42504b560188adfb6f2b", + "0x410894a208ff99bd3ec5f925aa7ff6932c4404390df9e337601fa7b7251d09ff", + "0xe6e7e7e2b54bcbe37eb7066b9a3c9b01b632d228c8ed5ef8f1871d9b7235a55b", + "0x8af02fe4657f956a9ede1a9b0a83d67367b43a8f5efdf6bd753d09f428b58960", + "0xdd056794fcb6f5b694934b17ef35577dbec8d04159fe447e0eba02e4ff4e9d96", + "0xef94a3289e9e197b04c17886373adbe66a451efe052fb419846006b5f659b91a", + "0x5558e5612dc3c222d76e7190409fc5d38479e08f6fdf4b7df299e6da968c2811", + "0x5f38cc5046a503d424c4b63cb060956babe0c1de050517d0067eccfa23cb664d", + "0x4c6a04827f46e51378e9ff3b811c878dead62da3ae20ef7d392c57512a09a719", + "0x68fd9806bea1d937063778b245a6788cd992e4fc614d5bce1ffe06e125f67701", + "0x0751a79f86c4220e81bbf6b4692976ed4c315f9b62937b23083f4db2370f04eb", + "0x5651840a2065a3468d97bf824e78455eb5e22b82b45fde7bb69b297c4c40e853", + "0x959d277feeb492ed3393fcd5774f1dde27c6018b07cc4fc93b937ee266ae12ea", + "0xa145f2ed353350a89de97e83433188adbd14107c16c654c131203442c34f2899", + "0xf888fc918eab6f88a5f6c6545d47a32dd558f10d00e86a9949cb3f144b7264e2", + "0x2fef7f5f1c149c87602cbe38766631abc992efaee26dd5b59e5bc361f6901cf4", + "0x5e0735a9be3eb97e790a93502a6f138a8863b0f0c20905bee0ac14d5aff4206a", + "0x9c40cbdab8e769c2c6f9de57c23621c5d8a25adaedd1ba9df17fa1680cd4e63f", + "0x995e6a00f5bc63f0a5d837a6671260771f12995b82da19c72a9546ae7b93f38f", + "0x10f647c754615b475543fca5ed9a4491503867fae619513dad966af63cb7ed2b", + "0x7e45b18bd06e946d20bc3807aa926aa5c0a10555b9dc18f9574136969b8f48d5", + "0x8a419fcb515eef5a139a37241872c095818fd276f77e6388c74b82ae49e6386f", + "0x2cb2d82e278d8ba47830ed3dbd6edf69d2e49721182488ffe0a01698071e7d40", + "0x1e9e5cb7a68e7a2decef900bd250bd31c1f024ddd240799327263c72940c7e59", + "0x3904821c4388b16e9851e3a7318f4177102da38525cd3e5e5708430a243470a1", + "0x7785b9d9ff6dfa45d945aaa393270bf8b62bbde46e941aa068606c173963e518", + "0xbff782fbbadfc752f5c2a239e49ab13200fc35cfba29a5332fe936a0367d336c", + "0x294a3fd73f102c7017c9208857dfb91ec7c323916dd1bb3c9f1fac2c7d952b4b", + "0x3a9fe3685814b6cff7a918e514a9d5375a1fc8268a48d5b78da93dfda115332f", + "0xc033a1836983d485e28e5a0825c953a76d4c7f4a8ec5f7eb0b11baf5ae2beb79", + "0xb088df91127cad5d72f8db96d7ea86dfdef55374bf982222a45df7d2b631ceb6" ] }, "nodes": [ diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 348911424..ff09f7c72 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -481,7 +481,7 @@ impl Importer { let mut batch = DBTransaction::new(); - let ancestry_actions = self.engine.ancestry_actions(&block, &mut chain.ancestry_with_metadata_iter(*parent)); + let ancestry_actions = self.engine.ancestry_actions(&header, &mut chain.ancestry_with_metadata_iter(*parent)); let receipts = block.receipts; let traces = block.traces.drain(); diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index c6195d0b2..1a54ccec1 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -798,6 +798,7 @@ impl AuthorityRound { } }; + let epoch_transition_hash = epoch_manager.epoch_transition_hash; let ancestry_iter = ancestry.map(|header| { let mut signers = vec![*header.author()]; signers.extend(parent_empty_steps_signers.drain(..)); @@ -815,10 +816,11 @@ impl AuthorityRound { None } }) - .while_some(); + .while_some() + .take_while(|&(h, _)| h != epoch_transition_hash); - if let Err(_) = epoch_manager.finality_checker.build_ancestry_subchain(ancestry_iter) { - debug!(target: "engine", "inconsistent validator set within epoch"); + if let Err(e) = epoch_manager.finality_checker.build_ancestry_subchain(ancestry_iter) { + debug!(target: "engine", "inconsistent validator set within epoch: {:?}", e); return Vec::new(); } } @@ -1448,9 +1450,9 @@ impl Engine for AuthorityRound { super::total_difficulty_fork_choice(new, current) } - fn ancestry_actions(&self, block: &ExecutedBlock, ancestry: &mut Iterator) -> Vec { + fn ancestry_actions(&self, header: &Header, ancestry: &mut Iterator) -> Vec { let finalized = self.build_finality( - block.header(), + header, &mut ancestry.take_while(|e| !e.is_finalized).map(|e| e.header), ); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 9bf7fa92b..39f3ac204 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -429,7 +429,7 @@ pub trait Engine: Sync + Send { /// 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, _block: &M::LiveBlock, _ancestry: &mut Iterator) -> Vec { + fn ancestry_actions(&self, _header: &M::Header, _ancestry: &mut Iterator) -> Vec { Vec::new() } diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index c74cc6bf4..47cea8505 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -371,11 +371,11 @@ impl EthereumMachine { } /// Does verification of the transaction against the parent state. - pub fn verify_transaction(&self, t: &SignedTransaction, header: &Header, client: &C) + pub fn verify_transaction(&self, t: &SignedTransaction, parent: &Header, client: &C) -> Result<(), transaction::Error> { if let Some(ref filter) = self.tx_filter.as_ref() { - if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) { + if !filter.transaction_allowed(&parent.hash(), parent.number() + 1, t, client) { return Err(transaction::Error::NotAllowed.into()) } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ca5d5f7b5..39dac1f2b 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -576,10 +576,9 @@ impl Miner { trace!(target: "miner", "requires_reseal: sealing enabled"); // Disable sealing if there were no requests for SEALING_TIMEOUT_IN_BLOCKS - let had_requests = sealing.last_request.map(|last_request| { - best_block > last_request - && best_block - last_request <= SEALING_TIMEOUT_IN_BLOCKS - }).unwrap_or(false); + let had_requests = sealing.last_request.map(|last_request| + best_block.saturating_sub(last_request) <= SEALING_TIMEOUT_IN_BLOCKS + ).unwrap_or(false); // keep sealing enabled if any of the conditions is met let sealing_enabled = self.forced_sealing() @@ -1394,6 +1393,33 @@ mod tests { assert_eq!(miner.prepare_pending_block(&client), BlockPreparationStatus::NotPrepared); } + #[test] + fn should_not_return_stale_work_packages() { + // given + let client = TestBlockChainClient::default(); + let miner = miner(); + + // initial work package should create the pending block + let res = miner.work_package(&client); + assert_eq!(res.unwrap().1, 1); + // This should be true, since there were some requests. + assert_eq!(miner.requires_reseal(0), true); + + // when new block is imported + let client = generate_dummy_client(2); + let imported = [0.into()]; + let empty = &[]; + miner.chain_new_blocks(&*client, &imported, empty, &imported, empty, false); + + // then + // This should be false, because it's too early. + assert_eq!(miner.requires_reseal(2), false); + // but still work package should be ready + let res = miner.work_package(&*client); + assert_eq!(res.unwrap().1, 3); + assert_eq!(miner.prepare_pending_block(&*client), BlockPreparationStatus::NotPrepared); + } + #[test] fn should_not_use_pending_block_if_best_block_is_higher() { // given diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 2d8c17a67..3bfe30a44 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -147,7 +147,9 @@ pub fn verify_block_family(header: &Header, parent: verify_uncles(params.block, params.block_provider, engine)?; for tx in ¶ms.block.transactions { - engine.machine().verify_transaction(tx, header, params.client)?; + // transactions are verified against the parent header since the current + // state wasn't available when the tx was created + engine.machine().verify_transaction(tx, parent, params.client)?; } Ok(()) diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 8159b07e9..9b1b7b10e 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -55,6 +55,22 @@ impl Informant { Self::with_informant_in_depth(informant.subinfos.last_mut().expect("prepare/done_trace are not balanced"), depth - 1, f); } } + + fn informant_trace(informant: &Informant, gas_used: U256) -> String { + 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()), + "stack": informant.stack, + "storage": informant.storage, + "depth": informant.depth, + }).to_string() + } } impl vm::Informant for Informant { @@ -125,22 +141,11 @@ impl trace::VMTracer for Informant { fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) { let subdepth = self.subdepth; Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| { - let mem_diff = informant.mem_written.clone().map(|(o, s)| (o, &(mem[o..o+s]))); let store_diff = informant.store_written.clone(); let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info()); - let trace = 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()), - "stack": informant.stack, - "storage": informant.storage, - "depth": informant.depth, - }); - informant.traces.push(trace.to_string()); + let trace = Self::informant_trace(informant, gas_used); + informant.traces.push(trace); informant.unmatched = false; informant.gas_used = gas_used; @@ -151,11 +156,11 @@ impl trace::VMTracer for Informant { informant.stack.extend_from_slice(stack_push); // TODO [ToDr] Align memory? - if let Some((pos, data)) = mem_diff { - if informant.memory.len() < (pos + data.len()) { - informant.memory.resize(pos + data.len(), 0); + if let Some((pos, size)) = informant.mem_written.clone() { + if informant.memory.len() < (pos + size) { + informant.memory.resize(pos + size, 0); } - informant.memory[pos..pos + data.len()].copy_from_slice(data); + informant.memory[pos..(pos + size)].copy_from_slice(&mem[pos..(pos + size)]); } if let Some((pos, val)) = store_diff { @@ -195,7 +200,12 @@ impl trace::VMTracer for Informant { // print last line with final state: self.gas_cost = 0.into(); let gas_used = self.gas_used; - self.trace_executed(gas_used, &[], &[]); + let subdepth = self.subdepth; + + Self::with_informant_in_depth(&mut self, subdepth, |informant: &mut Informant| { + let trace = Self::informant_trace(informant, gas_used); + informant.traces.push(trace); + }); } else if !self.subtraces.is_empty() { self.traces.extend(mem::replace(&mut self.subtraces, vec![])); } @@ -280,6 +290,17 @@ mod tests { {"pc":0,"op":248,"opName":"","gas":"0xffff","gasCost":"0x0","memory":"0x","stack":[],"storage":{},"depth":1} "#, ); + + run_test( + Informant::default(), + &compare_json, + "5A51", + 0xfffff, + r#" +{"depth":1,"gas":"0xfffff","gasCost":"0x2","memory":"0x","op":90,"opName":"GAS","pc":0,"stack":[],"storage":{}} +{"depth":1,"gas":"0xffffd","gasCost":"0x0","memory":"0x","op":81,"opName":"MLOAD","pc":1,"stack":["0xffffd"],"storage":{}} + "#, + ); } #[test] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index fa48e7495..dd1dbed07 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -59,6 +59,7 @@ parity-updater = { path = "../updater" } parity-version = { path = "../util/version" } patricia-trie = "0.3.0" rlp = { version = "0.3.0", features = ["ethereum"] } +eip712 = { path = "../util/EIP-712" } stats = { path = "../util/stats" } vm = { path = "../ethcore/vm" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index cb14c42c4..e1f5423ca 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -63,6 +63,7 @@ extern crate parity_runtime; extern crate parity_updater as updater; extern crate parity_version as version; extern crate patricia_trie as trie; +extern crate eip712; extern crate rlp; extern crate stats; extern crate vm; diff --git a/rpc/src/tests/ws.rs b/rpc/src/tests/ws.rs index 6fd93fef7..794eff3ed 100644 --- a/rpc/src/tests/ws.rs +++ b/rpc/src/tests/ws.rs @@ -28,8 +28,7 @@ use tests::helpers::{GuardedAuthCodes, Server}; /// Setup a mock signer for tests pub fn serve() -> (Server, usize, GuardedAuthCodes) { - let port = 35000 + rand::random::() % 10000; - let address = format!("127.0.0.1:{}", port).parse().unwrap(); + let address = "127.0.0.1:0".parse().unwrap(); let io = MetaIoHandler::default(); let authcodes = GuardedAuthCodes::new(); let stats = Arc::new(informant::RpcStats::default()); @@ -44,6 +43,7 @@ pub fn serve() -> (Server, usize, GuardedAuthCodes) { extractors::WsExtractor::new(Some(&authcodes.path)), extractors::WsStats::new(stats), ).unwrap()); + let port = res.addr().port() as usize; (res, port, authcodes) } diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 3b0d007a2..67f3c9fd4 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -49,7 +49,8 @@ use v1::types::{ RichRawTransaction as RpcRichRawTransaction, ConfirmationPayload as RpcConfirmationPayload, ConfirmationResponse, - SignRequest as RpcSignRequest, + EthSignRequest as RpcEthSignRequest, + EIP191SignRequest as RpcSignRequest, DecryptRequest as RpcDecryptRequest, }; use rlp; @@ -693,6 +694,19 @@ pub fn execute( ); Box::new(future::done(res)) }, + ConfirmationPayload::SignMessage(address, data) => { + if accounts.is_hardware_address(&address) { + return Box::new(future::err(errors::account("Error signing message with hardware_wallet", + "Message signing is unsupported"))); + } + let res = signature(&accounts, address, data, pass) + .map(|result| result + .map(|rsv| H520(rsv.into_electrum())) + .map(RpcH520::from) + .map(ConfirmationResponse::Signature) + ); + Box::new(future::done(res)) + }, ConfirmationPayload::Decrypt(address, data) => { if accounts.is_hardware_address(&address) { return Box::new(future::err(errors::unsupported("Decrypting via hardware wallets is not supported.", None))); @@ -775,8 +789,11 @@ pub fn from_rpc(payload: RpcConfirmationPayload, default_account: Address, di RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => { Box::new(future::ok(ConfirmationPayload::Decrypt(address.into(), msg.into()))) }, - RpcConfirmationPayload::EthSignMessage(RpcSignRequest { address, data }) => { + RpcConfirmationPayload::EthSignMessage(RpcEthSignRequest { address, data }) => { Box::new(future::ok(ConfirmationPayload::EthSignMessage(address.into(), data.into()))) }, + RpcConfirmationPayload::EIP191SignMessage(RpcSignRequest { address, data }) => { + Box::new(future::ok(ConfirmationPayload::SignMessage(address.into(), data.into()))) + }, } } diff --git a/rpc/src/v1/helpers/eip191.rs b/rpc/src/v1/helpers/eip191.rs new file mode 100644 index 000000000..56ceba5f2 --- /dev/null +++ b/rpc/src/v1/helpers/eip191.rs @@ -0,0 +1,61 @@ +// Copyright 2015-2018 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 . + +//! EIP-191 compliant decoding + hashing +use v1::types::{EIP191Version, Bytes, PresignedTransaction}; +use eip712::{hash_structured_data, EIP712}; +use serde_json::{Value, from_value}; +use v1::helpers::errors; +use jsonrpc_core::Error; +use v1::helpers::dispatch::eth_data_hash; +use hash::keccak; +use std::fmt::Display; +use ethereum_types::H256; + +/// deserializes and hashes the message depending on the version specifier +pub fn hash_message(version: EIP191Version, message: Value) -> Result { + let data = match version { + EIP191Version::StructuredData => { + let typed_data = from_value::(message) + .map_err(map_serde_err("StructuredData"))?; + + hash_structured_data(typed_data) + .map_err(|err| errors::invalid_call_data(err.kind()))? + } + + EIP191Version::PresignedTransaction => { + let data = from_value::(message) + .map_err(map_serde_err("WithValidator"))?; + let prefix = b"\x19\x00"; + let data = [&prefix[..], &data.validator.0[..], &data.data.0[..]].concat(); + keccak(data) + } + + EIP191Version::PersonalMessage => { + let bytes = from_value::(message) + .map_err(map_serde_err("Bytes"))?; + eth_data_hash(bytes.0) + } + }; + + Ok(data) +} + +fn map_serde_err(struct_name: &'static str) -> impl Fn(T) -> Error { + move |error: T| { + errors::invalid_call_data(format!("Error deserializing '{}': {}", struct_name, error)) + } +} diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index e7526e8cd..f177e2515 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -286,6 +286,14 @@ pub fn signing(error: AccountError) -> Error { } } +pub fn invalid_call_data(error: T) -> Error { + Error { + code: ErrorCode::ServerError(codes::ENCODING_ERROR), + message: format!("{}", error), + data: None + } +} + pub fn password(error: AccountError) -> Error { Error { code: ErrorCode::ServerError(codes::PASSWORD_INVALID), diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 50f4e1df6..b77d3b9cc 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -19,12 +19,12 @@ use std::cmp; use std::sync::Arc; -use light::on_demand::error::Error as OnDemandError; use ethcore::basic_account::BasicAccount; use ethcore::encoded; use ethcore::filter::Filter as EthcoreFilter; use ethcore::ids::BlockId; use ethcore::receipt::Receipt; +use ethcore::executed::ExecutionError; use jsonrpc_core::{Result, Error}; use jsonrpc_core::futures::{future, Future}; @@ -38,6 +38,7 @@ use light::on_demand::{ request, OnDemand, HeaderRef, Request as OnDemandRequest, Response as OnDemandResponse, ExecutionResult, }; +use light::on_demand::error::Error as OnDemandError; use light::request::Field; use sync::LightSync; @@ -202,8 +203,8 @@ impl LightFetch { /// Helper for getting proved execution. pub fn proved_read_only_execution(&self, req: CallRequest, num: Trailing) -> impl Future + Send { const DEFAULT_GAS_PRICE: u64 = 21_000; - // starting gas when gas not provided. - const START_GAS: u64 = 50_000; + // (21000 G_transaction + 32000 G_create + some marginal to allow a few operations) + const START_GAS: u64 = 60_000; let (sync, on_demand, client) = (self.sync.clone(), self.on_demand.clone(), self.client.clone()); let req: CallRequestHelper = req.into(); @@ -615,28 +616,41 @@ struct ExecuteParams { sync: Arc, } -// has a peer execute the transaction with given params. If `gas_known` is false, -// this will double the gas on each `OutOfGas` error. +// Has a peer execute the transaction with given params. If `gas_known` is false, this will set the `gas value` to the +// `required gas value` unless it exceeds the block gas limit fn execute_read_only_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send { if !gas_known { Box::new(future::loop_fn(params, |mut params| { execute_read_only_tx(true, params.clone()).and_then(move |res| { match res { Ok(executed) => { - // TODO: how to distinguish between actual OOG and - // exception? - if executed.exception.is_some() { - let old_gas = params.tx.gas; - params.tx.gas = params.tx.gas * 2u32; - if params.tx.gas > params.hdr.gas_limit() { - params.tx.gas = old_gas; + // `OutOfGas` exception, try double the gas + if let Some(vm::Error::OutOfGas) = executed.exception { + // block gas limit already tried, regard as an error and don't retry + if params.tx.gas >= params.hdr.gas_limit() { + trace!(target: "light_fetch", "OutOutGas exception received, gas increase: failed"); } else { + params.tx.gas = cmp::min(params.tx.gas * 2_u32, params.hdr.gas_limit()); + trace!(target: "light_fetch", "OutOutGas exception received, gas increased to {}", + params.tx.gas); return Ok(future::Loop::Continue(params)) } } - Ok(future::Loop::Break(Ok(executed))) } + Err(ExecutionError::NotEnoughBaseGas { required, got }) => { + trace!(target: "light_fetch", "Not enough start gas provided required: {}, got: {}", + required, got); + if required <= params.hdr.gas_limit() { + params.tx.gas = required; + return Ok(future::Loop::Continue(params)) + } else { + warn!(target: "light_fetch", + "Required gas is bigger than block header's gas dropping the request"); + Ok(future::Loop::Break(Err(ExecutionError::NotEnoughBaseGas { required, got }))) + } + } + // Non-recoverable execution error failed => Ok(future::Loop::Break(failed)), } }) diff --git a/rpc/src/v1/helpers/mod.rs b/rpc/src/v1/helpers/mod.rs index 5098eca89..0259818af 100644 --- a/rpc/src/v1/helpers/mod.rs +++ b/rpc/src/v1/helpers/mod.rs @@ -25,6 +25,7 @@ pub mod light_fetch; pub mod nonce; pub mod oneshot; pub mod secretstore; +pub mod eip191; mod network_settings; mod poll_filter; diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs index 478f6785b..90fb42f50 100644 --- a/rpc/src/v1/helpers/requests.rs +++ b/rpc/src/v1/helpers/requests.rs @@ -18,6 +18,7 @@ use ethereum_types::{U256, Address}; use bytes::Bytes; use v1::types::{Origin, TransactionCondition}; +use ethereum_types::H256; /// Transaction request coming from RPC #[derive(Debug, Clone, Default, Eq, PartialEq, Hash)] @@ -117,6 +118,8 @@ pub enum ConfirmationPayload { SignTransaction(FilledTransactionRequest), /// Sign a message with an Ethereum specific security prefix. EthSignMessage(Address, Bytes), + /// Sign a message + SignMessage(Address, H256), /// Decrypt request Decrypt(Address, Bytes), } @@ -127,6 +130,7 @@ impl ConfirmationPayload { ConfirmationPayload::SendTransaction(ref request) => request.from, ConfirmationPayload::SignTransaction(ref request) => request.from, ConfirmationPayload::EthSignMessage(ref address, _) => *address, + ConfirmationPayload::SignMessage(ref address, _) => *address, ConfirmationPayload::Decrypt(ref address, _) => *address, } } diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index a83fff926..4da0c1023 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -26,7 +26,7 @@ use ethkey::{public_to_address, recover, Signature}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; -use v1::helpers::errors; +use v1::helpers::{errors, eip191}; use v1::helpers::dispatch::{self, eth_data_hash, Dispatcher, SignWith}; use v1::traits::Personal; use v1::types::{ @@ -36,8 +36,11 @@ use v1::types::{ ConfirmationResponse as RpcConfirmationResponse, TransactionRequest, RichRawTransaction as RpcRichRawTransaction, + EIP191Version, }; use v1::metadata::Metadata; +use eip712::{EIP712, hash_structured_data}; +use jsonrpc_core::types::Value; /// Account management (personal) rpc implementation. pub struct PersonalClient { @@ -150,6 +153,49 @@ impl Personal for PersonalClient { })) } + fn sign_191(&self, version: EIP191Version, data: Value, account: RpcH160, password: String) -> BoxFuture { + let data = try_bf!(eip191::hash_message(version, data)); + let dispatcher = self.dispatcher.clone(); + let accounts = self.accounts.clone(); + + let payload = RpcConfirmationPayload::EIP191SignMessage((account.clone(), data.into()).into()); + + Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) + .and_then(|payload| { + dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) + }) + .map(|v| v.into_value()) + .then(|res| match res { + Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), + Err(e) => Err(e), + e => Err(errors::internal("Unexpected result", e)), + }) + ) + } + + fn sign_typed_data(&self, typed_data: EIP712, account: RpcH160, password: String) -> BoxFuture { + let data = match hash_structured_data(typed_data) { + Ok(d) => d, + Err(err) => return Box::new(future::err(errors::invalid_call_data(err.kind()))), + }; + let dispatcher = self.dispatcher.clone(); + let accounts = self.accounts.clone(); + + let payload = RpcConfirmationPayload::EIP191SignMessage((account.clone(), data.into()).into()); + + Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) + .and_then(|payload| { + dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) + }) + .map(|v| v.into_value()) + .then(|res| match res { + Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), + Err(e) => Err(e), + e => Err(errors::internal("Unexpected result", e)), + }) + ) + } + fn ec_recover(&self, data: RpcBytes, signature: RpcH520) -> BoxFuture { let signature: H520 = signature.into(); let signature = Signature::from_electrum(&signature); diff --git a/rpc/src/v1/impls/pubsub.rs b/rpc/src/v1/impls/pubsub.rs index 98ac5707e..193fec72b 100644 --- a/rpc/src/v1/impls/pubsub.rs +++ b/rpc/src/v1/impls/pubsub.rs @@ -21,7 +21,7 @@ use std::time::Duration; use parking_lot::RwLock; use jsonrpc_core::{self as core, Result, MetaIoHandler}; -use jsonrpc_core::futures::{Future, Stream, Sink}; +use jsonrpc_core::futures::{future, Future, Stream, Sink}; use jsonrpc_macros::Trailing; use jsonrpc_macros::pubsub::Subscriber; use jsonrpc_pubsub::SubscriptionId; @@ -42,7 +42,7 @@ impl> PubSubClient { /// Creates new `PubSubClient`. pub fn new(rpc: MetaIoHandler, executor: Executor) -> Self { let poll_manager = Arc::new(RwLock::new(GenericPollManager::new(rpc))); - let pm2 = poll_manager.clone(); + let pm2 = Arc::downgrade(&poll_manager); let timer = tokio_timer::wheel() .tick_duration(Duration::from_millis(500)) @@ -52,7 +52,13 @@ impl> PubSubClient { let interval = timer.interval(Duration::from_millis(1000)); executor.spawn(interval .map_err(|e| warn!("Polling timer error: {:?}", e)) - .for_each(move |_| pm2.read().tick()) + .for_each(move |_| { + if let Some(pm2) = pm2.upgrade() { + pm2.read().tick() + } else { + Box::new(future::err(())) + } + }) ); PubSubClient { diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index a6197433f..15cd21d20 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -215,6 +215,14 @@ impl Signer for SignerClient { Err(err) => Err(errors::invalid_params("Invalid signature received.", err)), } }, + 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())), + Ok(false) => Err(errors::invalid_params("Sender address does not match the signature.", ())), + Err(err) => Err(errors::invalid_params("Invalid signature received.", err)), + } + }, ConfirmationPayload::Decrypt(_address, _data) => { // TODO [ToDr]: Decrypt can we verify if the answer is correct? Ok(ConfirmationResponse::Decrypt(bytes)) diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 344998a92..5098d807d 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -25,12 +25,16 @@ use jsonrpc_core::IoHandler; use parking_lot::Mutex; use transaction::{Action, Transaction}; use parity_runtime::Runtime; +use hash::keccak; use v1::{PersonalClient, Personal, Metadata}; -use v1::helpers::nonce; +use v1::helpers::{nonce, eip191}; use v1::helpers::dispatch::{eth_data_hash, FullDispatcher}; use v1::tests::helpers::TestMinerService; -use v1::types::H520; +use v1::types::{EIP191Version, PresignedTransaction, H520}; +use rustc_hex::ToHex; +use serde_json::to_value; +use ethkey::Secret; struct PersonalTester { _runtime: Runtime, @@ -328,3 +332,89 @@ fn should_unlock_account_permanently() { assert_eq!(tester.io.handle_request_sync(&request), Some(response.into())); assert!(tester.accounts.sign(address, None, Default::default()).is_ok(), "Should unlock account."); } + +#[test] +fn sign_eip191_with_validator() { + let tester = setup(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "personal_sign191", + "params": [ + "0x00", + { + "validator": ""#.to_owned() + &format!("0x{:x}", address) + r#"", + "data": ""# + &format!("0x{:x}", keccak("hello world")) + r#"" + }, + ""# + &format!("0x{:x}", address) + r#"", + "password123" + ], + "id": 1 + }"#; + let with_validator = to_value(PresignedTransaction { + validator: address.into(), + data: keccak("hello world").to_vec().into() + }).unwrap(); + let result = eip191::hash_message(EIP191Version::PresignedTransaction, with_validator).unwrap(); + let result = tester.accounts.sign(address, Some("password123".into()), result).unwrap().into_electrum(); + let expected = r#"{"jsonrpc":"2.0","result":""#.to_owned() + &format!("0x{}", result.to_hex()) + r#"","id":1}"#; + let response = tester.io.handle_request_sync(&request).unwrap(); + assert_eq!(response, expected) +} + +#[test] +fn sign_eip191_structured_data() { + let tester = setup(); + let secret: Secret = keccak("cow").into(); + let address = tester.accounts.insert_account(secret, &"lol".into()).unwrap(); + let request = r#"{ + "jsonrpc": "2.0", + "method": "personal_sign191", + "params": [ + "0x01", + { + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "0x1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + }, + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + } + }, + ""#.to_owned() + &format!("0x{:x}", address) + r#"", + "lol" + ], + "id": 1 + }"#; + let expected = r#"{"jsonrpc":"2.0","result":"0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c","id":1}"#; + let response = tester.io.handle_request_sync(&request).unwrap(); + assert_eq!(response, expected) +} diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index 718721910..cda33f4cf 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -15,9 +15,10 @@ // along with Parity. If not, see . //! Personal rpc interface. +use eip712::EIP712; +use jsonrpc_core::types::Value; use jsonrpc_core::{BoxFuture, Result}; - -use v1::types::{Bytes, U128, H160, H256, H520, TransactionRequest, RichRawTransaction as RpcRichRawTransaction}; +use v1::types::{Bytes, U128, H160, H256, H520, TransactionRequest, RichRawTransaction as RpcRichRawTransaction, EIP191Version}; build_rpc_trait! { /// Personal rpc interface. Safe (read-only) functions. @@ -42,6 +43,15 @@ build_rpc_trait! { #[rpc(name = "personal_sign")] fn sign(&self, Bytes, H160, String) -> BoxFuture; + /// Produces an EIP-712 compliant signature with given account using the given password to unlock the + /// account during the request. + #[rpc(name = "personal_signTypedData")] + fn sign_typed_data(&self, EIP712, H160, String) -> BoxFuture; + + /// Signs an arbitrary message based on the version specified + #[rpc(name = "personal_sign191")] + fn sign_191(&self, EIP191Version, Value, H160, String) -> BoxFuture; + /// Returns the account associated with the private key that was used to calculate the signature in /// `personal_sign`. #[rpc(name = "personal_ecRecover")] diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index e5da13298..62b6c3f9f 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -59,31 +59,62 @@ impl fmt::Display for ConfirmationPayload { ConfirmationPayload::SendTransaction(ref transaction) => write!(f, "{}", transaction), ConfirmationPayload::SignTransaction(ref transaction) => write!(f, "(Sign only) {}", transaction), ConfirmationPayload::EthSignMessage(ref sign) => write!(f, "{}", sign), + ConfirmationPayload::EIP191SignMessage(ref sign) => write!(f, "{}", sign), ConfirmationPayload::Decrypt(ref decrypt) => write!(f, "{}", decrypt), } } } -/// Sign request +/// Ethereum-prefixed Sign request #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -pub struct SignRequest { +pub struct EthSignRequest { /// Address pub address: H160, /// Hash to sign pub data: Bytes, } -impl From<(H160, Bytes)> for SignRequest { - fn from(tuple: (H160, Bytes)) -> Self { - SignRequest { +/// EIP191 Sign request +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct EIP191SignRequest { + /// Address + pub address: H160, + /// Hash to sign + pub data: H256, +} + +impl From<(H160, H256)> for EIP191SignRequest { + fn from(tuple: (H160, H256)) -> Self { + EIP191SignRequest { address: tuple.0, data: tuple.1, } } } -impl fmt::Display for SignRequest { +impl fmt::Display for EIP191SignRequest { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "sign 0x{} with {}", + self.data.0.pretty(), + Colour::White.bold().paint(format!("0x{:?}", self.address)), + ) + } +} + +impl From<(H160, Bytes)> for EthSignRequest { + fn from(tuple: (H160, Bytes)) -> Self { + EthSignRequest { + address: tuple.0, + data: tuple.1, + } + } +} + +impl fmt::Display for EthSignRequest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, @@ -169,8 +200,10 @@ pub enum ConfirmationPayload { #[serde(rename="signTransaction")] SignTransaction(TransactionRequest), /// Signature - #[serde(rename="sign")] - EthSignMessage(SignRequest), + #[serde(rename = "sign")] + EthSignMessage(EthSignRequest), + /// signature without prefix + EIP191SignMessage(EIP191SignRequest), /// Decryption #[serde(rename="decrypt")] Decrypt(DecryptRequest), @@ -181,7 +214,11 @@ impl From for ConfirmationPayload { match c { helpers::ConfirmationPayload::SendTransaction(t) => ConfirmationPayload::SendTransaction(t.into()), helpers::ConfirmationPayload::SignTransaction(t) => ConfirmationPayload::SignTransaction(t.into()), - helpers::ConfirmationPayload::EthSignMessage(address, data) => ConfirmationPayload::EthSignMessage(SignRequest { + helpers::ConfirmationPayload::EthSignMessage(address, data) => ConfirmationPayload::EthSignMessage(EthSignRequest { + address: address.into(), + data: data.into(), + }), + helpers::ConfirmationPayload::SignMessage(address, data) => ConfirmationPayload::EIP191SignMessage(EIP191SignRequest { address: address.into(), data: data.into(), }), diff --git a/rpc/src/v1/types/eip191.rs b/rpc/src/v1/types/eip191.rs new file mode 100644 index 000000000..d5dce3255 --- /dev/null +++ b/rpc/src/v1/types/eip191.rs @@ -0,0 +1,57 @@ +// Copyright 2015-2018 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 . + +//! EIP-191 specific types +use serde::{Deserialize, Deserializer}; +use serde::de; +use v1::types::{H160, Bytes}; + +/// EIP-191 version specifier +#[derive(Debug)] +pub enum EIP191Version { + /// byte specifier for structured data (0x01) + StructuredData, + /// byte specifier for personal message (0x45) + PersonalMessage, + /// byte specifier for presignedtransaction (0x00) + PresignedTransaction +} + +/// EIP-191 version 0x0 struct +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct PresignedTransaction { + // address of intended validator + pub validator: H160, + // application specific data + pub data: Bytes +} + +impl<'de> Deserialize<'de> for EIP191Version { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + let byte_version = match s.as_str() { + "0x00" => EIP191Version::PresignedTransaction, + "0x01" => EIP191Version::StructuredData, + "0x45" => EIP191Version::PersonalMessage, + other => return Err(de::Error::custom(format!("Invalid byte version '{}'", other))), + }; + Ok(byte_version) + } +} diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index eb8c0dc22..b2e7c074b 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -43,9 +43,10 @@ mod transaction_condition; mod uint; mod work; mod private_receipt; +mod eip191; pub mod pubsub; - +pub use self::eip191::{EIP191Version, PresignedTransaction}; pub use self::account_info::{AccountInfo, ExtAccountInfo, HwAccountInfo}; pub use self::bytes::Bytes; pub use self::block::{RichBlock, Block, BlockTransactions, Header, RichHeader, Rich}; @@ -53,7 +54,7 @@ pub use self::block_number::{BlockNumber, LightBlockNumber, block_number_to_id}; pub use self::call_request::CallRequest; pub use self::confirmations::{ ConfirmationPayload, ConfirmationRequest, ConfirmationResponse, ConfirmationResponseWithToken, - TransactionModification, SignRequest, DecryptRequest, Either + TransactionModification, EIP191SignRequest, EthSignRequest, DecryptRequest, Either }; pub use self::consensus_status::*; pub use self::derivation::{DeriveHash, DeriveHierarchical, Derive}; diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 2bf5ad044..000000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -stable diff --git a/scripts/docker/hub/Dockerfile b/scripts/docker/hub/Dockerfile index 35d1b0570..1ac92e71b 100644 --- a/scripts/docker/hub/Dockerfile +++ b/scripts/docker/hub/Dockerfile @@ -31,7 +31,7 @@ COPY artifacts/x86_64-unknown-linux-gnu/$TARGET ./bin/$TARGET RUN echo "#!/bin/bash \n ${TARGET} \$@" > ./entrypoint.sh RUN chmod +x ./entrypoint.sh -ADD check_sync.sh /check_sync.sh +COPY scripts/docker/hub/check_sync.sh /check_sync.sh # setup ENTRYPOINT EXPOSE 5001 8080 8082 8083 8545 8546 8180 30303/tcp 30303/udp diff --git a/scripts/gitlab/build-unix.sh b/scripts/gitlab/build-unix.sh index 00933f1ee..cf6bfe147 100755 --- a/scripts/gitlab/build-unix.sh +++ b/scripts/gitlab/build-unix.sh @@ -6,18 +6,23 @@ set -u # treat unset variables as error echo "__________Show ENVIROMENT__________" echo "CI_SERVER_NAME: " $CI_SERVER_NAME echo "CARGO_HOME: " $CARGO_HOME -echo "BUILD_TARGET: " $BUILD_TARGET -echo "BUILD_ARCH: " $BUILD_ARCH echo "CARGO_TARGET: " $CARGO_TARGET echo "CC: " $CC echo "CXX: " $CXX echo "__________CARGO CONFIG__________" -mkdir -p .cargo -rm -f .cargo/config -echo "[target.$CARGO_TARGET]" >> .cargo/config -echo "linker= \"$CC\"" >> .cargo/config -cat .cargo/config +if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ] +then + # use build container's cargo config + cat /.cargo/config +else + mkdir -p .cargo + rm -f .cargo/config + echo "[target.$CARGO_TARGET]" >> .cargo/config + echo "linker= \"$CC\"" >> .cargo/config + cat .cargo/config +fi + echo "_____ Building target: "$CARGO_TARGET" _____" time cargo build --target $CARGO_TARGET --release --features final @@ -32,15 +37,31 @@ mkdir -p artifacts cd artifacts mkdir -p $CARGO_TARGET cd $CARGO_TARGET -cp ../../target/$CARGO_TARGET/release/parity ./parity -cp ../../target/$CARGO_TARGET/release/parity-evm ./parity-evm -cp ../../target/$CARGO_TARGET/release/ethstore ./ethstore -cp ../../target/$CARGO_TARGET/release/ethkey ./ethkey -cp ../../target/$CARGO_TARGET/release/whisper ./whisper -strip -v ./* +cp -v ../../target/$CARGO_TARGET/release/parity ./parity +cp -v ../../target/$CARGO_TARGET/release/parity-evm ./parity-evm +cp -v ../../target/$CARGO_TARGET/release/ethstore ./ethstore +cp -v ../../target/$CARGO_TARGET/release/ethkey ./ethkey +cp -v ../../target/$CARGO_TARGET/release/whisper ./whisper + + +# stripping can also be done on release build time +# export RUSTFLAGS="${RUSTFLAGS} -C link-arg=-s" +if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ] +then + arm-linux-androideabi-strip -v ./* +else + strip -v ./* +fi + echo "_____ Calculating checksums _____" for binary in $(ls) do rhash --sha256 $binary -o $binary.sha256 - ./parity tools hash $binary > $binary.sha3 + if [ "${CARGO_TARGET}" = "armv7-linux-androideabi" ] + then + echo "> ${binary} cannot be hashed with cross-compiled binary" + else + ./parity tools hash $binary > $binary.sha3 + fi done + diff --git a/scripts/gitlab/build-windows.sh b/scripts/gitlab/build-windows.sh index afd4c64a6..d4176c758 100755 --- a/scripts/gitlab/build-windows.sh +++ b/scripts/gitlab/build-windows.sh @@ -8,8 +8,6 @@ set LIB="C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240. echo "__________Show ENVIROMENT__________" echo "CI_SERVER_NAME: " $CI_SERVER_NAME echo "CARGO_HOME: " $CARGO_HOME -echo "BUILD_TARGET: " $BUILD_TARGET -echo "BUILD_ARCH: " $BUILD_ARCH echo "CARGO_TARGET: " $CARGO_TARGET echo "_____ Building target: "$CARGO_TARGET" _____" diff --git a/scripts/gitlab/cargo-audit.sh b/scripts/gitlab/cargo-audit.sh index 1e53f77cd..16f0dc934 100755 --- a/scripts/gitlab/cargo-audit.sh +++ b/scripts/gitlab/cargo-audit.sh @@ -3,5 +3,5 @@ set -e # fail on any error set -u # treat unset variables as error -CARGO_TARGET_DIR=./target cargo +stable install cargo-audit --force -cargo +stable audit +cargo install cargo-audit +cargo audit diff --git a/util/EIP-712/Cargo.toml b/util/EIP-712/Cargo.toml new file mode 100644 index 000000000..308df98d8 --- /dev/null +++ b/util/EIP-712/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "eip712" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +serde_derive = "1.0" +serde = "1.0" +serde_json = "1.0" +ethabi = "6.0" +keccak-hash = "0.1" +ethereum-types = "0.4" +failure = "0.1" +itertools = "0.7" +failure_derive = "0.1" +lazy_static = "1.1" +toolshed = "0.4" +regex = "1.0" +validator = "0.8" +validator_derive = "0.8" +lunarity-lexer = "0.1" +rustc-hex = "2.0" +indexmap = "1.0.2" diff --git a/util/EIP-712/src/eip712.rs b/util/EIP-712/src/eip712.rs new file mode 100644 index 000000000..fea97a988 --- /dev/null +++ b/util/EIP-712/src/eip712.rs @@ -0,0 +1,177 @@ +// Copyright 2015-2018 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 . + +//! EIP712 structs +use serde_json::{Value}; +use std::collections::HashMap; +use ethereum_types::{U256, H256, Address}; +use regex::Regex; +use validator::Validate; +use validator::ValidationErrors; + +pub(crate) type MessageTypes = HashMap>; + +lazy_static! { + // match solidity identifier with the addition of '[(\d)*]*' + static ref TYPE_REGEX: Regex = Regex::new(r"^[a-zA-Z_$][a-zA-Z_$0-9]*(\[([1-9]\d*)*\])*$").unwrap(); + static ref IDENT_REGEX: Regex = Regex::new(r"^[a-zA-Z_$][a-zA-Z_$0-9]*$").unwrap(); +} + +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +#[derive(Deserialize, Serialize, Validate, Debug, Clone)] +pub(crate) struct EIP712Domain { + pub(crate) name: String, + pub(crate) version: String, + pub(crate) chain_id: U256, + pub(crate) verifying_contract: Address, + #[serde(skip_serializing_if="Option::is_none")] + pub(crate) salt: Option, +} +/// EIP-712 struct +#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields)] +#[derive(Deserialize, Debug, Clone)] +pub struct EIP712 { + pub(crate) types: MessageTypes, + pub(crate) primary_type: String, + pub(crate) message: Value, + pub(crate) domain: EIP712Domain, +} + +impl Validate for EIP712 { + fn validate(&self) -> Result<(), ValidationErrors> { + for field_types in self.types.values() { + for field_type in field_types { + field_type.validate()?; + } + } + Ok(()) + } +} + +#[derive(Serialize, Deserialize, Validate, Debug, Clone)] +pub(crate) struct FieldType { + #[validate(regex = "IDENT_REGEX")] + pub name: String, + #[serde(rename = "type")] + #[validate(regex = "TYPE_REGEX")] + pub type_: String, +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::from_str; + + #[test] + fn test_regex() { + let test_cases = vec!["unint bytes32", "Seun\\[]", "byte[]uint", "byte[7[]uint][]", "Person[0]"]; + for case in test_cases { + assert_eq!(TYPE_REGEX.is_match(case), false) + } + + let test_cases = vec!["bytes32", "Foo[]", "bytes1", "bytes32[][]", "byte[9]", "contents"]; + for case in test_cases { + assert_eq!(TYPE_REGEX.is_match(case), true) + } + } + + #[test] + fn test_deserialization() { + let string = r#"{ + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "0x1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + }, + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + } + }"#; + let _ = from_str::(string).unwrap(); + } + + #[test] + fn test_failing_deserialization() { + let string = r#"{ + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "0x1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + }, + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "7uint256[x] Seun" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet amen", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + } + }"#; + let data = from_str::(string).unwrap(); + assert_eq!(data.validate().is_err(), true); + } +} diff --git a/util/EIP-712/src/encode.rs b/util/EIP-712/src/encode.rs new file mode 100644 index 000000000..2add93db5 --- /dev/null +++ b/util/EIP-712/src/encode.rs @@ -0,0 +1,415 @@ +// Copyright 2015-2018 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 . + +//! EIP712 Encoder +use ethabi::{encode, Token as EthAbiToken}; +use ethereum_types::{Address as EthAddress, U256, H256}; +use keccak_hash::keccak; +use serde_json::Value; +use std::str::FromStr; +use itertools::Itertools; +use indexmap::IndexSet; +use serde_json::to_value; +use parser::{Parser, Type}; +use error::{Result, ErrorKind, serde_error}; +use eip712::{EIP712, MessageTypes}; +use rustc_hex::FromHex; +use validator::Validate; +use std::collections::HashSet; + + +fn check_hex(string: &str) -> Result<()> { + if string.len() >= 2 && &string[..2] == "0x" { + return Ok(()) + } + + return Err(ErrorKind::HexParseError( + format!("Expected a 0x-prefixed string of even length, found {} length string", string.len())) + )? +} +/// given a type and HashMap> +/// returns a HashSet of dependent types of the given type +fn build_dependencies<'a>(message_type: &'a str, message_types: &'a MessageTypes) -> Option<(HashSet<&'a str>)> +{ + if message_types.get(message_type).is_none() { + return None; + } + + let mut types = IndexSet::new(); + types.insert(message_type); + let mut deps = HashSet::new(); + + while let Some(item) = types.pop() { + if let Some(fields) = message_types.get(item) { + deps.insert(item); + + for field in fields { + // seen this type before? or not a custom type skip + if deps.contains(&*field.type_) || !message_types.contains_key(&*field.type_) { + continue; + } + types.insert(&*field.type_); + } + } + }; + + return Some(deps) +} + +fn encode_type(message_type: &str, message_types: &MessageTypes) -> Result { + let deps = { + let mut temp = build_dependencies(message_type, message_types).ok_or_else(|| ErrorKind::NonExistentType)?; + temp.remove(message_type); + let mut temp = temp.into_iter().collect::>(); + (&mut temp[..]).sort_unstable(); + temp.insert(0, message_type); + temp + }; + + let encoded = deps + .into_iter() + .filter_map(|dep| { + message_types.get(dep).map(|field_types| { + let types = field_types + .iter() + .map(|value| format!("{} {}", value.type_, value.name)) + .join(","); + return format!("{}({})", dep, types); + }) + }) + .collect::>() + .concat(); + Ok(encoded) +} + +fn type_hash(message_type: &str, typed_data: &MessageTypes) -> Result { + Ok(keccak(encode_type(message_type, typed_data)?)) +} + +fn encode_data( + parser: &Parser, + message_type: &Type, + message_types: &MessageTypes, + value: &Value, + field_name: Option<&str> +) -> Result> +{ + let encoded = match message_type { + Type::Array { + inner, + length + } => { + let mut items = vec![]; + let values = value.as_array().ok_or_else(|| serde_error("array", field_name))?; + + // check if the type definition actually matches + // the length of items to be encoded + if length.is_some() && Some(values.len() as u64) != *length { + let array_type = format!("{}[{}]", *inner, length.unwrap()); + return Err(ErrorKind::UnequalArrayItems(length.unwrap(), array_type, values.len() as u64))? + } + + for item in values { + let mut encoded = encode_data(parser, &*inner, &message_types, item, field_name)?; + items.append(&mut encoded); + } + + keccak(items).to_vec() + } + + Type::Custom(ref ident) if message_types.get(&*ident).is_some() => { + let type_hash = (&type_hash(ident, &message_types)?).to_vec(); + let mut tokens = encode(&[EthAbiToken::FixedBytes(type_hash)]); + + for field in message_types.get(ident).expect("Already checked in match guard; qed") { + let value = &value[&field.name]; + let type_ = parser.parse_type(&*field.type_)?; + let mut encoded = encode_data(parser, &type_, &message_types, &value, Some(&*field.name))?; + tokens.append(&mut encoded); + } + + keccak(tokens).to_vec() + } + + Type::Bytes => { + let string = value.as_str().ok_or_else(|| serde_error("string", field_name))?; + + check_hex(&string)?; + + let bytes = (&string[2..]) + .from_hex::>() + .map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; + let bytes = keccak(&bytes).to_vec(); + + encode(&[EthAbiToken::FixedBytes(bytes)]) + } + + Type::Byte(_) => { + let string = value.as_str().ok_or_else(|| serde_error("string", field_name))?; + + check_hex(&string)?; + + let mut bytes = (&string[2..]) + .from_hex::>() + .map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; + + encode(&[EthAbiToken::FixedBytes(bytes)]) + } + + Type::String => { + let value = value.as_str().ok_or_else(|| serde_error("string", field_name))?; + let hash = keccak(value).to_vec(); + encode(&[EthAbiToken::FixedBytes(hash)]) + } + + Type::Bool => encode(&[EthAbiToken::Bool(value.as_bool().ok_or_else(|| serde_error("bool", field_name))?)]), + + Type::Address => { + let addr = value.as_str().ok_or_else(|| serde_error("string", field_name))?; + if addr.len() != 42 { + return Err(ErrorKind::InvalidAddressLength(addr.len()))?; + } + let address = EthAddress::from_str(&addr[2..]).map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; + encode(&[EthAbiToken::Address(address)]) + } + + Type::Uint | Type::Int => { + let string = value.as_str().ok_or_else(|| serde_error("int/uint", field_name))?; + + check_hex(&string)?; + + let uint = U256::from_str(&string[2..]).map_err(|err| ErrorKind::HexParseError(format!("{}", err)))?; + + let token = if *message_type == Type::Uint { + EthAbiToken::Uint(uint) + } else { + EthAbiToken::Int(uint) + }; + encode(&[token]) + } + + _ => return Err(ErrorKind::UnknownType(format!("{}", field_name.unwrap_or("")), format!("{}", *message_type)))? + }; + + Ok(encoded) +} + +/// encodes and hashes the given EIP712 struct +pub fn hash_structured_data(typed_data: EIP712) -> Result { + // validate input + typed_data.validate()?; + // EIP-191 compliant + let prefix = (b"\x19\x01").to_vec(); + let domain = to_value(&typed_data.domain).unwrap(); + let parser = Parser::new(); + let (domain_hash, data_hash) = ( + encode_data(&parser, &Type::Custom("EIP712Domain".into()), &typed_data.types, &domain, None)?, + encode_data(&parser, &Type::Custom(typed_data.primary_type), &typed_data.types, &typed_data.message, None)? + ); + let concat = [&prefix[..], &domain_hash[..], &data_hash[..]].concat(); + Ok(keccak(concat)) +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::from_str; + use rustc_hex::ToHex; + + const JSON: &'static str = r#"{ + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "0x1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + }, + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + } + }"#; + + #[test] + fn test_build_dependencies() { + let string = r#"{ + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + }"#; + + let value = from_str::(string).expect("alas error!"); + let mail = "Mail"; + let person = "Person"; + + let hashset = { + let mut temp = HashSet::new(); + temp.insert(mail); + temp.insert(person); + temp + }; + assert_eq!(build_dependencies(mail, &value), Some(hashset)); + } + + #[test] + fn test_encode_type() { + let string = r#"{ + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + }"#; + + let value = from_str::(string).expect("alas error!"); + let mail = &String::from("Mail"); + assert_eq!( + "Mail(Person from,Person to,string contents)Person(string name,address wallet)", + encode_type(&mail, &value).expect("alas error!") + ) + } + + #[test] + fn test_encode_type_hash() { + let string = r#"{ + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person" }, + { "name": "contents", "type": "string" } + ] + }"#; + + let value = from_str::(string).expect("alas error!"); + let mail = &String::from("Mail"); + let hash = (type_hash(&mail, &value).expect("alas error!").0).to_hex::(); + assert_eq!( + hash, + "a0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2" + ); + } + + #[test] + fn test_hash_data() { + let typed_data = from_str::(JSON).expect("alas error!"); + assert_eq!( + hash_structured_data(typed_data).expect("alas error!").to_hex::(), + "be609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2" + ) + } + + #[test] + fn test_unequal_array_lengths() { + const TEST: &'static str = r#"{ + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "0x1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": [{ + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }], + "contents": "Hello, Bob!" + }, + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "chainId", "type": "uint256" }, + { "name": "verifyingContract", "type": "address" } + ], + "Person": [ + { "name": "name", "type": "string" }, + { "name": "wallet", "type": "address" } + ], + "Mail": [ + { "name": "from", "type": "Person" }, + { "name": "to", "type": "Person[2]" }, + { "name": "contents", "type": "string" } + ] + } + }"#; + + let typed_data = from_str::(TEST).expect("alas error!"); + assert_eq!( + hash_structured_data(typed_data).unwrap_err().kind(), + ErrorKind::UnequalArrayItems(2, "Person[2]".into(), 1) + ) + } +} diff --git a/util/EIP-712/src/error.rs b/util/EIP-712/src/error.rs new file mode 100644 index 000000000..e6b5634e5 --- /dev/null +++ b/util/EIP-712/src/error.rs @@ -0,0 +1,125 @@ +// Copyright 2015-2018 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 . + +use std::fmt::{self, Display}; +use failure::{Fail, Context, Backtrace}; +use validator::ValidationErrors; +use validator::ValidationErrorsKind; + +pub(crate) type Result = ::std::result::Result; +/// Error type +#[derive(Debug)] +pub struct Error { + inner: Context, +} +/// Possible errors encountered while hashing/encoding an EIP-712 compliant data structure +#[derive(Clone, Fail, Debug, PartialEq)] +pub enum ErrorKind { + /// if we fail to deserialize from a serde::Value as a type specified in message types + /// fail with this error. + #[fail(display = "Expected type '{}' for field '{}'", _0, _1)] + UnexpectedType(String, String), + /// the primary type supplied doesn't exist in the MessageTypes + #[fail(display = "The given primaryType wasn't found in the types field")] + NonExistentType, + /// an invalid address was encountered during encoding + #[fail(display = "Address string should be a 0x-prefixed 40 character string, got '{}'", _0)] + InvalidAddressLength(usize), + /// a hex parse error occured + #[fail(display = "Failed to parse hex '{}'", _0)] + HexParseError(String), + /// the field was declared with a unknown type + #[fail(display = "The field '{}' has an unknown type '{}'", _0, _1)] + UnknownType(String, String), + /// Unexpected token + #[fail(display = "Unexpected token '{}' while parsing typename '{}'", _0, _1)] + UnexpectedToken(String, String), + /// the user has attempted to define a typed array with a depth > 10 + #[fail(display = "Maximum depth for nested arrays is 10")] + UnsupportedArrayDepth, + /// FieldType validation error + #[fail(display = "{}", _0)] + ValidationError(String), + /// the typed array defined in message types was declared with a fixed length + /// that is of unequal length with the items to be encoded + #[fail(display = "Expected {} items for array type {}, got {} items", _0, _1, _2)] + UnequalArrayItems(u64, String, u64), + /// Typed array length doesn't fit into a u64 + #[fail(display = "Attempted to declare fixed size with length {}", _0)] + InvalidArraySize(String) +} + +pub(crate) fn serde_error(expected: &str, field: Option<&str>) -> ErrorKind { + ErrorKind::UnexpectedType(expected.to_owned(), field.unwrap_or("").to_owned()) +} + +impl Fail for Error { + fn cause(&self) -> Option<&Fail> { + self.inner.cause() + } + + fn backtrace(&self) -> Option<&Backtrace> { + self.inner.backtrace() + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.inner, f) + } +} + +impl Error { + /// extract the error kind + pub fn kind(&self) -> ErrorKind { + self.inner.get_context().clone() + } +} + +impl From for Error { + fn from(kind: ErrorKind) -> Error { + Error { inner: Context::new(kind) } + } +} + +impl From> for Error { + fn from(inner: Context) -> Error { + Error { inner } + } +} + +impl From for Error { + fn from(error: ValidationErrors) -> Self { + let mut string: String = "".into(); + for (field_name, error_kind) in error.errors() { + match error_kind { + ValidationErrorsKind::Field(validation_errors) => { + for error in validation_errors { + let str_error = format!( + "the field '{}', has an invalid value {}", + field_name, + error.params["value"] + ); + string.push_str(&str_error); + } + }, + _ => unreachable!("#[validate] is only used on fields for regex;\ + its impossible to get any other ErrorKind; qed") + } + } + ErrorKind::ValidationError(string).into() + } +} diff --git a/util/EIP-712/src/lib.rs b/util/EIP-712/src/lib.rs new file mode 100644 index 000000000..206b68510 --- /dev/null +++ b/util/EIP-712/src/lib.rs @@ -0,0 +1,192 @@ +// Copyright 2015-2018 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 . + +//! EIP-712 encoding utilities +//! +//! # Specification +//! +//! `encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = "\x19\x01" ‖ domainSeparator ‖ hashStruct(message)` +//! - data adheres to 𝕊, a structure defined in the rigorous eip-712 +//! - `\x01` is needed to comply with EIP-191 +//! - `domainSeparator` and `hashStruct` are defined below +//! +//! ## A) domainSeparator +//! +//! `domainSeparator = hashStruct(eip712Domain)` +//!
+//!
+//! Struct named `EIP712Domain` with the following fields +//! +//! - `name: String` +//! - `version: String` +//! - `chain_id: U256`, +//! - `verifying_contract: H160` +//! - `salt: Option` +//! +//! ## C) hashStruct +//! +//! `hashStruct(s : 𝕊) = keccak256(typeHash ‖ encodeData(s))` +//!
+//! `typeHash = keccak256(encodeType(typeOf(s)))` +//! +//! ### i) encodeType +//! +//! - `name ‖ "(" ‖ member₁ ‖ "," ‖ member₂ ‖ "," ‖ … ‖ memberₙ ")"` +//! - each member is written as `type ‖ " " ‖ name` +//! - encodings cascade down and are sorted by name +//! +//! ### ii) encodeData +//! +//! - `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)` +//! - each encoded member is 32-byte long +//! +//! #### a) atomic +//! +//! - `boolean` => `U256` +//! - `address` => `H160` +//! - `uint` => sign-extended `U256` in big endian order +//! - `bytes1:31` => `H@256` +//! +//! #### b) dynamic +//! +//! - `bytes` => `keccak256(bytes)` +//! - `string` => `keccak256(string)` +//! +//! #### c) referenced +//! +//! - `array` => `keccak256(encodeData(array))` +//! - `struct` => `rec(keccak256(hashStruct(struct)))` +//! +//! ## D) Example +//! ### Query +//! ```json +//! { +//! "jsonrpc": "2.0", +//! "method": "eth_signTypedData", +//! "params": [ +//! "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", +//! { +//! "types": { +//! "EIP712Domain": [ +//! { +//! "name": "name", +//! "type": "string" +//! }, +//! { +//! "name": "version", +//! "type": "string" +//! }, +//! { +//! "name": "chainId", +//! "type": "uint256" +//! }, +//! { +//! "name": "verifyingContract", +//! "type": "address" +//! } +//! ], +//! "Person": [ +//! { +//! "name": "name", +//! "type": "string" +//! }, +//! { +//! "name": "wallet", +//! "type": "address" +//! } +//! ], +//! "Mail": [ +//! { +//! "name": "from", +//! "type": "Person" +//! }, +//! { +//! "name": "to", +//! "type": "Person" +//! }, +//! { +//! "name": "contents", +//! "type": "string" +//! } +//! ] +//! }, +//! "primaryType": "Mail", +//! "domain": { +//! "name": "Ether Mail", +//! "version": "1", +//! "chainId": 1, +//! "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" +//! }, +//! "message": { +//! "from": { +//! "name": "Cow", +//! "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" +//! }, +//! "to": { +//! "name": "Bob", +//! "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" +//! }, +//! "contents": "Hello, Bob!" +//! } +//! } +//! ], +//! "id": 1 +//! } +//! ``` +// +//! ### Response +//! ```json +//! { +//! "id":1, +//! "jsonrpc": "2.0", +//! "result": "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c" +//! } +//! ``` + +#![warn(missing_docs, unused_extern_crates)] + +extern crate serde_json; +extern crate ethabi; +extern crate ethereum_types; +extern crate keccak_hash; +extern crate itertools; +extern crate failure; +extern crate indexmap; +extern crate lunarity_lexer; +extern crate toolshed; +extern crate regex; +extern crate validator; +#[macro_use] +extern crate validator_derive; +#[macro_use] +extern crate failure_derive; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate lazy_static; +extern crate rustc_hex; + +mod eip712; +mod error; +mod parser; +mod encode; + +/// the EIP-712 encoding function +pub use encode::hash_structured_data; +/// encoding Error types +pub use error::{ErrorKind, Error}; +/// EIP712 struct +pub use eip712::EIP712; diff --git a/util/EIP-712/src/parser.rs b/util/EIP-712/src/parser.rs new file mode 100644 index 000000000..7f515f7c9 --- /dev/null +++ b/util/EIP-712/src/parser.rs @@ -0,0 +1,172 @@ +// Copyright 2015-2018 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 . + +//! Solidity type-name parsing +use lunarity_lexer::{Lexer, Token}; +use error::*; +use toolshed::Arena; +use std::{fmt, result}; + +#[derive(Debug, Clone, PartialEq)] +pub enum Type { + Address, + Uint, + Int, + String, + Bool, + Bytes, + Byte(u8), + Custom(String), + Array { + length: Option, + inner: Box + } +} + +impl From for String { + fn from(field_type: Type) -> String { + match field_type { + Type::Address => "address".into(), + Type::Uint => "uint".into(), + Type::Int => "int".into(), + Type::String => "string".into(), + Type::Bool => "bool".into(), + Type::Bytes => "bytes".into(), + Type::Byte(len) => format!("bytes{}", len), + Type::Custom(custom) => custom, + Type::Array { + inner, + length + } => { + let inner: String = (*inner).into(); + match length { + None => format!("{}[]", inner), + Some(length) => format!("{}[{}]", inner, length) + } + } + } + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { + let item: String = self.clone().into(); + write!(f, "{}", item) + } +} + +pub struct Parser { + arena: Arena, +} + +impl Parser { + pub fn new() -> Self { + Parser { + arena: Arena::new() + } + } + + /// the type string is being validated before it's parsed. + pub fn parse_type(&self, field_type: &str) -> Result { + #[derive(PartialEq)] + enum State { Open, Close } + + let mut lexer = Lexer::new(&self.arena, field_type); + let mut token = None; + let mut state = State::Close; + let mut array_depth = 0; + let mut current_array_length: Option = None; + + while lexer.token != Token::EndOfProgram { + let type_ = match lexer.token { + Token::Identifier => Type::Custom(lexer.token_as_str().to_owned()), + Token::TypeByte => Type::Byte(lexer.type_size.0), + Token::TypeBytes => Type::Bytes, + Token::TypeBool => Type::Bool, + Token::TypeUint => Type::Uint, + Token::TypeInt => Type::Int, + Token::TypeString => Type::String, + Token::TypeAddress => Type::Address, + Token::LiteralInteger => { + let length = lexer.token_as_str(); + current_array_length = Some(length + .parse() + .map_err(|_| + ErrorKind::InvalidArraySize(length.into()) + )? + ); + lexer.consume(); + continue; + }, + Token::BracketOpen if token.is_some() && state == State::Close => { + state = State::Open; + lexer.consume(); + continue + } + Token::BracketClose if array_depth < 10 => { + if state == State::Open && token.is_some() { + let length = current_array_length.take(); + state = State::Close; + token = Some(Type::Array { + inner: Box::new(token.expect("if statement checks for some; qed")), + length + }); + lexer.consume(); + array_depth += 1; + continue + } else { + return Err(ErrorKind::UnexpectedToken(lexer.token_as_str().to_owned(), field_type.to_owned()))? + } + } + Token::BracketClose if array_depth == 10 => { + return Err(ErrorKind::UnsupportedArrayDepth)? + } + _ => return Err(ErrorKind::UnexpectedToken(lexer.token_as_str().to_owned(), field_type.to_owned()))? + }; + + token = Some(type_); + lexer.consume(); + } + + Ok(token.ok_or_else(|| ErrorKind::NonExistentType)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parser() { + let parser = Parser::new(); + let source = "byte[][][7][][][][][][][]"; + parser.parse_type(source).unwrap(); + } + + #[test] + fn test_nested_array() { + let parser = Parser::new(); + let source = "byte[][][7][][][][][][][][]"; + assert_eq!(parser.parse_type(source).is_err(), true); + } + + #[test] + fn test_malformed_array_type() { + let parser = Parser::new(); + let source = "byte[7[]uint][]"; + assert_eq!(parser.parse_type(source).is_err(), true) + } +} diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index f8d5193f0..854d04c85 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "parity-version" # NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION) -version = "2.2.0" +version = "2.2.1" authors = ["Parity Technologies "] build = "build.rs"