Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
987390fb7d | ||
|
|
797f23f30b | ||
|
|
c1da49bbc4 | ||
|
|
1164193019 | ||
|
|
1c217cbf2b | ||
|
|
d24f71f150 | ||
|
|
4c66a021ec | ||
|
|
ccc57328e2 | ||
|
|
77240b6e5a | ||
|
|
2e428ddd58 | ||
|
|
cd4081c149 | ||
|
|
428342d69d | ||
|
|
8ee9b262f9 |
@@ -26,14 +26,14 @@ linux-stable:
|
||||
- cargo build -j $(nproc) --release -p ethstore
|
||||
- cargo build -j $(nproc) --release -p ethkey
|
||||
- strip target/release/parity
|
||||
- strip target/release/evm
|
||||
- strip target/release/parity-evm
|
||||
- strip target/release/ethstore
|
||||
- strip target/release/ethkey
|
||||
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||
- md5sum target/release/parity > parity.md5
|
||||
- sh scripts/deb-build.sh amd64
|
||||
- cp target/release/parity deb/usr/bin/parity
|
||||
- cp target/release/evm deb/usr/bin/evm
|
||||
- cp target/release/parity-evm deb/usr/bin/parity-evm
|
||||
- cp target/release/ethstore deb/usr/bin/ethstore
|
||||
- cp target/release/ethkey deb/usr/bin/ethkey
|
||||
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
||||
@@ -55,9 +55,9 @@ linux-stable:
|
||||
artifacts:
|
||||
paths:
|
||||
- target/release/parity
|
||||
- target/release/parity/evmbin
|
||||
- target/release/parity/ethstore
|
||||
- target/release/parity/ethkey
|
||||
- target/release/parity-evm
|
||||
- target/release/ethstore
|
||||
- target/release/ethkey
|
||||
name: "stable-x86_64-unknown-linux-gnu_parity"
|
||||
linux-stable-debian:
|
||||
stage: build
|
||||
@@ -73,14 +73,14 @@ linux-stable-debian:
|
||||
- cargo build -j $(nproc) --release -p ethstore
|
||||
- cargo build -j $(nproc) --release -p ethkey
|
||||
- strip target/release/parity
|
||||
- strip target/release/evm
|
||||
- strip target/release/parity-evm
|
||||
- strip target/release/ethstore
|
||||
- strip target/release/ethkey
|
||||
- export SHA3=$(target/release/parity tools hash target/release/parity)
|
||||
- md5sum target/release/parity > parity.md5
|
||||
- sh scripts/deb-build.sh amd64
|
||||
- cp target/release/parity deb/usr/bin/parity
|
||||
- cp target/release/evm deb/usr/bin/evm
|
||||
- cp target/release/parity-evm deb/usr/bin/parity-evm
|
||||
- cp target/release/ethstore deb/usr/bin/ethstore
|
||||
- cp target/release/ethkey deb/usr/bin/ethkey
|
||||
- export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
|
||||
|
||||
180
Cargo.lock
generated
180
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
||||
[root]
|
||||
name = "parity"
|
||||
version = "1.6.2"
|
||||
version = "1.6.5"
|
||||
dependencies = [
|
||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -23,7 +23,7 @@ dependencies = [
|
||||
"ethcore-secretstore 1.0.0",
|
||||
"ethcore-signer 1.6.0",
|
||||
"ethcore-stratum 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethsync 1.6.0",
|
||||
"evmbin 0.1.0",
|
||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -204,7 +204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multihash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -253,7 +253,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -261,7 +261,7 @@ name = "core-foundation-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -284,7 +284,7 @@ version = "1.1.1"
|
||||
source = "git+https://github.com/ethcore/rust-ctrlc.git#f4927770f89eca80ec250911eea3adcbf579ac48"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -293,7 +293,7 @@ name = "daemonize"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -348,7 +348,7 @@ source = "git+https://github.com/ethcore/rust-secp256k1#98ad9b9ecae44a563efdd642
|
||||
dependencies = [
|
||||
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -394,13 +394,14 @@ dependencies = [
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"ethcore-stratum 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethjson 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"ethstore 0.1.0",
|
||||
"evmjit 1.6.0",
|
||||
"hardware-wallet 1.6.0",
|
||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -422,7 +423,7 @@ version = "0.1.2"
|
||||
dependencies = [
|
||||
"bigint 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -443,7 +444,7 @@ dependencies = [
|
||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-devtools 1.6.0",
|
||||
"ethcore-rpc 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"fetch 0.1.0",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||
@@ -491,8 +492,8 @@ name = "ethcore-ipc"
|
||||
version = "1.6.0"
|
||||
dependencies = [
|
||||
"ethcore-devtools 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
"ethcore-util 1.6.5",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -515,7 +516,7 @@ dependencies = [
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -527,7 +528,7 @@ dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -538,9 +539,9 @@ dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -553,7 +554,7 @@ dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-network 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -569,7 +570,7 @@ name = "ethcore-logger"
|
||||
version = "1.6.0"
|
||||
dependencies = [
|
||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -585,11 +586,11 @@ dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-devtools 1.6.0",
|
||||
"ethcore-io 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.1 (git+https://github.com/ethcore/mio)",
|
||||
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -613,7 +614,7 @@ dependencies = [
|
||||
"ethcore-io 1.6.0",
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-light 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethjson 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
@@ -648,7 +649,7 @@ dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -666,7 +667,7 @@ dependencies = [
|
||||
"ethcore-devtools 1.6.0",
|
||||
"ethcore-io 1.6.0",
|
||||
"ethcore-rpc 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -685,7 +686,7 @@ dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"jsonrpc-macros 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
@@ -699,7 +700,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethcore-util"
|
||||
version = "1.6.2"
|
||||
version = "1.6.5"
|
||||
dependencies = [
|
||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -713,7 +714,7 @@ dependencies = [
|
||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -748,7 +749,7 @@ dependencies = [
|
||||
name = "ethjson"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -776,12 +777,12 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-devtools 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethcrypto 0.1.0",
|
||||
"ethkey 0.2.0",
|
||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -809,7 +810,7 @@ dependencies = [
|
||||
"ethcore-ipc-nano 1.6.0",
|
||||
"ethcore-light 1.6.0",
|
||||
"ethcore-network 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethkey 0.2.0",
|
||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -826,7 +827,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -842,7 +843,7 @@ name = "fdlimit"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -862,7 +863,7 @@ name = "flate2"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -937,7 +938,7 @@ version = "0.3.1"
|
||||
source = "git+https://github.com/ethcore/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1054,7 +1055,7 @@ version = "1.6.0"
|
||||
dependencies = [
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1064,7 +1065,7 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1173,7 +1174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.16"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@@ -1182,7 +1183,7 @@ version = "0.3.0"
|
||||
source = "git+https://github.com/ethcore/libusb-rs#32bacf61abd981d5cbd4a8fecca5a2dc0b762a96"
|
||||
dependencies = [
|
||||
"bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libusb-sys 0.2.3 (git+https://github.com/ethcore/libusb-sys)",
|
||||
]
|
||||
|
||||
@@ -1192,7 +1193,7 @@ version = "0.2.3"
|
||||
source = "git+https://github.com/ethcore/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1228,7 +1229,7 @@ name = "memchr"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1256,7 +1257,7 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1265,7 +1266,7 @@ version = "0.5.1"
|
||||
source = "git+https://github.com/ethcore/mio?branch=v0.5.x#3842d3b250ffd7bd9b16f9586b875ddcbac2b0dd"
|
||||
dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1281,7 +1282,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1297,7 +1298,7 @@ version = "0.6.0-dev"
|
||||
source = "git+https://github.com/ethcore/mio?branch=timer-fix#31eccc40ece3d47abaefaf23bb2114033175b972"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1313,7 +1314,7 @@ source = "git+https://github.com/ethcore/mio#ef182bae193a9c7457cd2cf661fcaffb226
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1329,7 +1330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1369,29 +1370,29 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "multihash"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ring 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanomsg"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7#673b79beef6e149273899850d7692335a481a920"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanomsg-sys"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00"
|
||||
source = "git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7#673b79beef6e149273899850d7692335a481a920"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1413,7 +1414,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1424,7 +1425,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1434,7 +1435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1447,7 +1448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1537,7 +1538,7 @@ name = "num_cpus"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1545,7 +1546,7 @@ name = "num_cpus"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1577,7 +1578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1587,7 +1588,7 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1621,7 +1622,7 @@ name = "parity-hash-fetch"
|
||||
version = "1.6.0"
|
||||
dependencies = [
|
||||
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"fetch 0.1.0",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1638,11 +1639,11 @@ version = "1.6.0"
|
||||
dependencies = [
|
||||
"cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||
"jsonrpc-http-server 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multihash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.1.0",
|
||||
]
|
||||
|
||||
@@ -1652,7 +1653,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethcore 1.6.0",
|
||||
"ethcore-io 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethkey 0.2.0",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.1.0",
|
||||
@@ -1675,7 +1676,7 @@ version = "1.4.0"
|
||||
dependencies = [
|
||||
"ethcore-rpc 1.6.0",
|
||||
"ethcore-signer 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1706,7 +1707,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "parity-ui-precompiled"
|
||||
version = "1.4.0"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git?branch=beta#2a7fc4e6c5f958e8716b028b6ded010a9e238f9b"
|
||||
source = "git+https://github.com/ethcore/js-precompiled.git?branch=beta#ad0cbde4b11d76174c7dbfdbb8dc94ae7ae525e4"
|
||||
dependencies = [
|
||||
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1719,7 +1720,7 @@ dependencies = [
|
||||
"ethcore 1.6.0",
|
||||
"ethcore-ipc 1.6.0",
|
||||
"ethcore-ipc-codegen 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"ethsync 1.6.0",
|
||||
"ipc-common-types 1.6.0",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1743,7 +1744,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -1872,7 +1873,7 @@ name = "rand"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1918,10 +1919,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.6.2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1940,7 +1942,7 @@ name = "rocksdb"
|
||||
version = "0.4.5"
|
||||
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
|
||||
]
|
||||
|
||||
@@ -1950,7 +1952,7 @@ version = "0.3.0"
|
||||
source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1971,7 +1973,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1982,7 +1984,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1993,7 +1995,7 @@ version = "1.4.0"
|
||||
dependencies = [
|
||||
"ethcore-bigint 0.1.2",
|
||||
"ethcore-rpc 1.6.0",
|
||||
"ethcore-util 1.6.2",
|
||||
"ethcore-util 1.6.5",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-rpc-client 1.4.0",
|
||||
"rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2005,7 +2007,7 @@ version = "0.2.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2059,7 +2061,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"security-framework-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -2069,7 +2071,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2262,7 +2264,7 @@ version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -2305,7 +2307,7 @@ name = "termios"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2314,7 +2316,7 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2331,7 +2333,7 @@ version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -2635,7 +2637,7 @@ dependencies = [
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f"
|
||||
"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
|
||||
"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d"
|
||||
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
|
||||
"checksum libusb 0.3.0 (git+https://github.com/ethcore/libusb-rs)" = "<none>"
|
||||
"checksum libusb-sys 0.2.3 (git+https://github.com/ethcore/libusb-sys)" = "<none>"
|
||||
"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48"
|
||||
@@ -2655,9 +2657,9 @@ dependencies = [
|
||||
"checksum miow 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d5bfc6782530ac8ace97af10a540054a37126b63b0702ddaaa243b73b5745b9a"
|
||||
"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8"
|
||||
"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6"
|
||||
"checksum multihash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "755d5a39bee3faaf649437e873beab334990221b2faf1f2e56ca10a9e4600235"
|
||||
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
||||
"checksum nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)" = "<none>"
|
||||
"checksum multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c9f70f2402fa07c16c40be8fd0a748a39257c5dc3ff5c857cbbde2f39135c505"
|
||||
"checksum nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)" = "<none>"
|
||||
"checksum nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)" = "<none>"
|
||||
"checksum native-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4e52995154bb6f0b41e4379a279482c9387c1632e3798ba4e511ef8c54ee09"
|
||||
"checksum net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a816012ca11cb47009693c1e0c6130e26d39e4d97ee2a13c50e868ec83e3204"
|
||||
"checksum nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f05c2fc965fc1cd6b73fa57fa7b89f288178737f2f3ce9e63e4a6a141189000e"
|
||||
@@ -2706,7 +2708,7 @@ dependencies = [
|
||||
"checksum regex 0.1.68 (registry+https://github.com/rust-lang/crates.io-index)" = "b4329b8928a284580a1c63ec9d846b12f6d3472317243ff7077aff11f23f2b29"
|
||||
"checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9"
|
||||
"checksum reqwest 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bef9ed8fdfcc30947d6b774938dc0c3f369a474efe440df2c7f278180b2d2e6"
|
||||
"checksum ring 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "87ac4fce2ee4bb10dd106788e90fdfa4c5a7f3f9f6aae29824db77dc57e2767d"
|
||||
"checksum ring 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "595afba2db7545b940ec900dc59b5281f719d327fc0674eeadc9953617e55357"
|
||||
"checksum rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)" = "<none>"
|
||||
"checksum rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)" = "<none>"
|
||||
"checksum rotor 0.6.3 (git+https://github.com/ethcore/rotor)" = "<none>"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity"
|
||||
version = "1.6.2"
|
||||
version = "1.6.5"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ byteorder = "1.0"
|
||||
transient-hashmap = "0.1"
|
||||
linked-hash-map = "0.3.0"
|
||||
lru-cache = "0.1.0"
|
||||
itertools = "0.5"
|
||||
ethabi = "1.0.0"
|
||||
evmjit = { path = "../evmjit", optional = true }
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
"gasLimit": "0x222222"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"params": {
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x2A"
|
||||
"networkID" : "0x2A",
|
||||
"validateReceipts" : false
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x3",
|
||||
"forkBlock": 333922,
|
||||
"forkCanonHash": "0x8737eb141d4f05db57af63fc8d3b4d4d8f9cddb0c4e1ab855de8c288fdc1924f",
|
||||
"forkBlock": 641350,
|
||||
"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
|
||||
"eip98Transition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
@@ -44,11 +44,8 @@
|
||||
"gasLimit": "0x1000000"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://a22f0977ce02653bf95e38730106356342df48b5222e2c2a1a6f9ef34769bf593bae9ca0a888cf60839edd52efc1b6e393c63a57d76f4c4fe14e641f1f9e637e@128.199.55.137:30303",
|
||||
"enode://012239fccf3ff1d92b036983a430cb6705c6528c96c0354413f8854802138e5135c084ab36e7c54efb621c46728df8c3a6f4c1db9bb48a1330efe3f82f2dd7a6@52.169.94.142:30303",
|
||||
"enode://1462682e4b7ba2258346d55e25e5b9d264b0db40cee12bdfba4e72b1d7050350ea954c006e9106dd96a128e6e0bd6dffb17eed51f9f99bf7f9cdadfeaf8da4ff@51.15.61.253:30303",
|
||||
"enode://98fbb020c799ae39a828bd75dc2bd5d4721539faf317076b275f91182a5c8900b592e8abfdddceae674a7c3bb40ea00a6ca9ccb7805ab58c4b7b29c61c8f7239@51.15.62.44:30303",
|
||||
"enode://d801dd4e3d15a8bf785931add164bd9c313e3f6b5749d9302b311f2b48064cba5c86c32b1302c27cd983fc89ae07d4d306dd1197610835b8782e95dfb1b3f9ea@51.15.43.255:30303"
|
||||
"enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303",
|
||||
"enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"eip98Transition": "0x7fffffffffffffff",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
"gasLimit": "0x222222"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
"gasLimit": "0x222222"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
42
ethcore/res/validator_multi.json
Normal file
42
ethcore/res/validator_multi.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "TestMutiValidator",
|
||||
"engine": {
|
||||
"basicAuthority": {
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"durationLimit": "0x0d",
|
||||
"validators": {
|
||||
"multi": {
|
||||
"0": { "list": ["0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1"] },
|
||||
"2": { "list": ["0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"accountStartNonce": "0x0",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x69"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"generic": "0xc180"
|
||||
},
|
||||
"difficulty": "0x20000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x2fefd8"
|
||||
},
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "99999999999999999999999" },
|
||||
"0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "99999999999999999999999" }
|
||||
}
|
||||
}
|
||||
@@ -553,7 +553,6 @@ pub fn enact(
|
||||
b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
|
||||
b.set_uncles_hash(header.uncles_hash().clone());
|
||||
b.set_transactions_root(header.transactions_root().clone());
|
||||
b.set_receipts_root(header.receipts_root().clone());
|
||||
|
||||
push_transactions(&mut b, transactions)?;
|
||||
for u in uncles {
|
||||
|
||||
@@ -253,7 +253,7 @@ impl Client {
|
||||
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
||||
trace!(target: "client", "Found registrar at {}", reg_addr);
|
||||
let weak = Arc::downgrade(&client);
|
||||
let registrar = Registry::new(reg_addr, move |a, d| weak.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d)));
|
||||
let registrar = Registry::new(reg_addr, move |a, d| weak.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(BlockId::Latest, a, d)));
|
||||
*client.registrar.lock() = Some(registrar);
|
||||
}
|
||||
Ok(client)
|
||||
@@ -380,7 +380,7 @@ impl Client {
|
||||
})?;
|
||||
|
||||
// Final Verification
|
||||
if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) {
|
||||
if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) {
|
||||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||
return Err(());
|
||||
}
|
||||
@@ -1445,7 +1445,7 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
}
|
||||
|
||||
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||
fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||
let from = Address::default();
|
||||
let transaction = Transaction {
|
||||
nonce: self.latest_nonce(&from),
|
||||
@@ -1456,7 +1456,7 @@ impl BlockChainClient for Client {
|
||||
data: data,
|
||||
}.fake_sign(from);
|
||||
|
||||
self.call(&transaction, BlockId::Latest, Default::default())
|
||||
self.call(&transaction, block_id, Default::default())
|
||||
.map_err(|e| format!("{:?}", e))
|
||||
.map(|executed| {
|
||||
executed.output
|
||||
|
||||
@@ -731,7 +731,7 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn call_contract(&self, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
||||
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
||||
|
||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError> {
|
||||
let transaction = Transaction {
|
||||
|
||||
@@ -254,7 +254,7 @@ pub trait BlockChainClient : Sync + Send {
|
||||
fn pruning_info(&self) -> PruningInfo;
|
||||
|
||||
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||
fn call_contract(&self, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
|
||||
/// Import a transaction: used for misbehaviour reporting.
|
||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError>;
|
||||
|
||||
@@ -82,7 +82,7 @@ pub struct AuthorityRound {
|
||||
proposed: AtomicBool,
|
||||
client: RwLock<Option<Weak<EngineClient>>>,
|
||||
signer: EngineSigner,
|
||||
validators: Box<ValidatorSet + Send + Sync>,
|
||||
validators: Box<ValidatorSet>,
|
||||
/// Is this Engine just for testing (prevents step calibration).
|
||||
calibrate_step: bool,
|
||||
}
|
||||
@@ -150,12 +150,12 @@ impl AuthorityRound {
|
||||
}
|
||||
}
|
||||
|
||||
fn step_proposer(&self, step: usize) -> Address {
|
||||
self.validators.get(step)
|
||||
fn step_proposer(&self, bh: &H256, step: usize) -> Address {
|
||||
self.validators.get(bh, step)
|
||||
}
|
||||
|
||||
fn is_step_proposer(&self, step: usize, address: &Address) -> bool {
|
||||
self.step_proposer(step) == *address
|
||||
fn is_step_proposer(&self, bh: &H256, step: usize, address: &Address) -> bool {
|
||||
self.step_proposer(bh, step) == *address
|
||||
}
|
||||
|
||||
fn is_future_step(&self, step: usize) -> bool {
|
||||
@@ -249,7 +249,7 @@ impl Engine for AuthorityRound {
|
||||
}
|
||||
|
||||
fn seals_internally(&self) -> Option<bool> {
|
||||
Some(self.validators.contains(&self.signer.address()))
|
||||
Some(self.signer.address() != Address::default())
|
||||
}
|
||||
|
||||
/// Attempt to seal the block internally.
|
||||
@@ -260,7 +260,7 @@ impl Engine for AuthorityRound {
|
||||
if self.proposed.load(AtomicOrdering::SeqCst) { return Seal::None; }
|
||||
let header = block.header();
|
||||
let step = self.step.load(AtomicOrdering::SeqCst);
|
||||
if self.is_step_proposer(step, header.author()) {
|
||||
if self.is_step_proposer(header.parent_hash(), step, header.author()) {
|
||||
if let Ok(signature) = self.signer.sign(header.bare_hash()) {
|
||||
trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step);
|
||||
self.proposed.store(true, AtomicOrdering::SeqCst);
|
||||
@@ -299,32 +299,33 @@ impl Engine for AuthorityRound {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the signature belongs to the correct proposer.
|
||||
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
let header_step = header_step(header)?;
|
||||
fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Do the validator and gas limit validation.
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
let step = header_step(header)?;
|
||||
// Give one step slack if step is lagging, double vote is still not possible.
|
||||
if self.is_future_step(header_step) {
|
||||
if self.is_future_step(step) {
|
||||
trace!(target: "engine", "verify_block_unordered: block from the future");
|
||||
self.validators.report_benign(header.author());
|
||||
Err(BlockError::InvalidSeal)?
|
||||
} else {
|
||||
// Check if the signature belongs to a validator, can depend on parent state.
|
||||
let proposer_signature = header_signature(header)?;
|
||||
let correct_proposer = self.step_proposer(header_step);
|
||||
if verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())? {
|
||||
Ok(())
|
||||
} else {
|
||||
trace!(target: "engine", "verify_block_unordered: bad proposer for step: {}", header_step);
|
||||
let correct_proposer = self.step_proposer(header.parent_hash(), step);
|
||||
if !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())? {
|
||||
trace!(target: "engine", "verify_block_unordered: bad proposer for step: {}", step);
|
||||
Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
// Do not calculate difficulty for genesis blocks.
|
||||
if header.number() == 0 {
|
||||
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
|
||||
}
|
||||
|
||||
let step = header_step(header)?;
|
||||
// Check if parent is from a previous step.
|
||||
if step == header_step(parent)? {
|
||||
trace!(target: "engine", "Multiple blocks proposed for step {}.", step);
|
||||
@@ -412,7 +413,7 @@ mod tests {
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![encode(&H520::default()).to_vec()]);
|
||||
|
||||
let verify_result = engine.verify_block_unordered(&header, None);
|
||||
let verify_result = engine.verify_block_family(&header, &Default::default(), None);
|
||||
assert!(verify_result.is_err());
|
||||
}
|
||||
|
||||
@@ -450,10 +451,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn proposer_switching() {
|
||||
let mut header: Header = Header::default();
|
||||
let tap = AccountProvider::transient_provider();
|
||||
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
|
||||
|
||||
let mut parent_header: Header = Header::default();
|
||||
parent_header.set_seal(vec![encode(&0usize).to_vec()]);
|
||||
parent_header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
let mut header: Header = Header::default();
|
||||
header.set_number(1);
|
||||
header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
header.set_author(addr);
|
||||
|
||||
let engine = Spec::new_test_round().engine;
|
||||
@@ -462,17 +467,22 @@ mod tests {
|
||||
// Two validators.
|
||||
// Spec starts with step 2.
|
||||
header.set_seal(vec![encode(&2usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
assert!(engine.verify_block_seal(&header).is_err());
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_err());
|
||||
header.set_seal(vec![encode(&1usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
assert!(engine.verify_block_seal(&header).is_ok());
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_future_block() {
|
||||
let mut header: Header = Header::default();
|
||||
let tap = AccountProvider::transient_provider();
|
||||
let addr = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "0").unwrap();
|
||||
|
||||
let mut parent_header: Header = Header::default();
|
||||
parent_header.set_seal(vec![encode(&0usize).to_vec()]);
|
||||
parent_header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
let mut header: Header = Header::default();
|
||||
header.set_number(1);
|
||||
header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
header.set_author(addr);
|
||||
|
||||
let engine = Spec::new_test_round().engine;
|
||||
@@ -481,8 +491,8 @@ mod tests {
|
||||
// Two validators.
|
||||
// Spec starts with step 2.
|
||||
header.set_seal(vec![encode(&1usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
assert!(engine.verify_block_seal(&header).is_ok());
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
header.set_seal(vec![encode(&5usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
|
||||
assert!(engine.verify_block_seal(&header).is_err());
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ pub struct BasicAuthority {
|
||||
gas_limit_bound_divisor: U256,
|
||||
builtins: BTreeMap<Address, Builtin>,
|
||||
signer: EngineSigner,
|
||||
validators: Box<ValidatorSet + Send + Sync>,
|
||||
validators: Box<ValidatorSet>,
|
||||
}
|
||||
|
||||
impl BasicAuthority {
|
||||
@@ -104,14 +104,14 @@ impl Engine for BasicAuthority {
|
||||
}
|
||||
|
||||
fn seals_internally(&self) -> Option<bool> {
|
||||
Some(self.validators.contains(&self.signer.address()))
|
||||
Some(self.signer.address() != Address::default())
|
||||
}
|
||||
|
||||
/// Attempt to seal the block internally.
|
||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||
let header = block.header();
|
||||
let author = header.author();
|
||||
if self.validators.contains(author) {
|
||||
if self.validators.contains(header.parent_hash(), author) {
|
||||
// account should be pernamently unlocked, otherwise sealing will fail
|
||||
if let Ok(signature) = self.signer.sign(header.bare_hash()) {
|
||||
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).to_vec()]);
|
||||
@@ -133,20 +133,20 @@ impl Engine for BasicAuthority {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||
use rlp::{UntrustedRlp, View};
|
||||
|
||||
// check the signature is legit.
|
||||
let sig = UntrustedRlp::new(&header.seal()[0]).as_val::<H520>()?;
|
||||
let signer = public_to_address(&recover(&sig.into(), &header.bare_hash())?);
|
||||
if !self.validators.contains(&signer) {
|
||||
return Err(BlockError::InvalidSeal)?;
|
||||
}
|
||||
fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
|
||||
// we should not calculate difficulty for genesis blocks
|
||||
use rlp::{UntrustedRlp, View};
|
||||
// Check if the signature belongs to a validator, can depend on parent state.
|
||||
let sig = UntrustedRlp::new(&header.seal()[0]).as_val::<H520>()?;
|
||||
let signer = public_to_address(&recover(&sig.into(), &header.bare_hash())?);
|
||||
if !self.validators.contains(header.parent_hash(), &signer) {
|
||||
return Err(BlockError::InvalidSeal)?;
|
||||
}
|
||||
|
||||
// Do not calculate difficulty for genesis blocks.
|
||||
if header.number() == 0 {
|
||||
return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() })));
|
||||
}
|
||||
@@ -239,7 +239,7 @@ mod tests {
|
||||
let mut header: Header = Header::default();
|
||||
header.set_seal(vec![::rlp::encode(&H520::default()).to_vec()]);
|
||||
|
||||
let verify_result = engine.verify_block_unordered(&header, None);
|
||||
let verify_result = engine.verify_block_family(&header, &Default::default(), None);
|
||||
assert!(verify_result.is_err());
|
||||
}
|
||||
|
||||
|
||||
@@ -95,8 +95,10 @@ pub struct Tendermint {
|
||||
last_lock: AtomicUsize,
|
||||
/// Bare hash of the proposed block, used for seal submission.
|
||||
proposal: RwLock<Option<H256>>,
|
||||
/// Hash of the proposal parent block.
|
||||
proposal_parent: RwLock<H256>,
|
||||
/// Set used to determine the current validators.
|
||||
validators: Box<ValidatorSet + Send + Sync>,
|
||||
validators: Box<ValidatorSet>,
|
||||
}
|
||||
|
||||
impl Tendermint {
|
||||
@@ -114,11 +116,12 @@ impl Tendermint {
|
||||
height: AtomicUsize::new(1),
|
||||
view: AtomicUsize::new(0),
|
||||
step: RwLock::new(Step::Propose),
|
||||
votes: VoteCollector::default(),
|
||||
votes: Default::default(),
|
||||
signer: Default::default(),
|
||||
lock_change: RwLock::new(None),
|
||||
last_lock: AtomicUsize::new(0),
|
||||
proposal: RwLock::new(None),
|
||||
proposal_parent: Default::default(),
|
||||
validators: new_validator_set(our_params.validators),
|
||||
});
|
||||
let handler = TransitionHandler::new(Arc::downgrade(&engine) as Weak<Engine>, Box::new(our_params.timeouts));
|
||||
@@ -232,7 +235,7 @@ impl Tendermint {
|
||||
let height = self.height.load(AtomicOrdering::SeqCst);
|
||||
if let Some(block_hash) = *self.proposal.read() {
|
||||
// Generate seal and remove old votes.
|
||||
if self.is_signer_proposer() {
|
||||
if self.is_signer_proposer(&*self.proposal_parent.read()) {
|
||||
let proposal_step = VoteStep::new(height, view, Step::Propose);
|
||||
let precommit_step = VoteStep::new(proposal_step.height, proposal_step.view, Step::Precommit);
|
||||
if let Some(seal) = self.votes.seal_signatures(proposal_step, precommit_step, &block_hash) {
|
||||
@@ -254,23 +257,23 @@ impl Tendermint {
|
||||
}
|
||||
|
||||
fn is_authority(&self, address: &Address) -> bool {
|
||||
self.validators.contains(address)
|
||||
self.validators.contains(&*self.proposal_parent.read(), address)
|
||||
}
|
||||
|
||||
fn is_above_threshold(&self, n: usize) -> bool {
|
||||
n > self.validators.count() * 2/3
|
||||
n > self.validators.count(&*self.proposal_parent.read()) * 2/3
|
||||
}
|
||||
|
||||
/// Find the designated for the given view.
|
||||
fn view_proposer(&self, height: Height, view: View) -> Address {
|
||||
fn view_proposer(&self, bh: &H256, height: Height, view: View) -> Address {
|
||||
let proposer_nonce = height + view;
|
||||
trace!(target: "engine", "Proposer nonce: {}", proposer_nonce);
|
||||
self.validators.get(proposer_nonce)
|
||||
self.validators.get(bh, proposer_nonce)
|
||||
}
|
||||
|
||||
/// Check if address is a proposer for given view.
|
||||
fn is_view_proposer(&self, height: Height, view: View, address: &Address) -> Result<(), EngineError> {
|
||||
let proposer = self.view_proposer(height, view);
|
||||
fn is_view_proposer(&self, bh: &H256, height: Height, view: View, address: &Address) -> Result<(), EngineError> {
|
||||
let proposer = self.view_proposer(bh, height, view);
|
||||
if proposer == *address {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -279,8 +282,8 @@ impl Tendermint {
|
||||
}
|
||||
|
||||
/// Check if current signer is the current proposer.
|
||||
fn is_signer_proposer(&self) -> bool {
|
||||
let proposer = self.view_proposer(self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst));
|
||||
fn is_signer_proposer(&self, bh: &H256) -> bool {
|
||||
let proposer = self.view_proposer(bh, self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst));
|
||||
self.signer.is_address(&proposer)
|
||||
}
|
||||
|
||||
@@ -419,7 +422,7 @@ impl Engine for Tendermint {
|
||||
|
||||
/// Should this node participate.
|
||||
fn seals_internally(&self) -> Option<bool> {
|
||||
Some(self.is_authority(&self.signer.address()))
|
||||
Some(self.signer.address() != Address::default())
|
||||
}
|
||||
|
||||
/// Attempt to seal generate a proposal seal.
|
||||
@@ -427,7 +430,7 @@ impl Engine for Tendermint {
|
||||
let header = block.header();
|
||||
let author = header.author();
|
||||
// Only proposer can generate seal if None was generated.
|
||||
if !self.is_signer_proposer() || self.proposal.read().is_some() {
|
||||
if !self.is_signer_proposer(header.parent_hash()) || self.proposal.read().is_some() {
|
||||
return Seal::None;
|
||||
}
|
||||
|
||||
@@ -441,6 +444,7 @@ impl Engine for Tendermint {
|
||||
self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), author);
|
||||
// Remember proposal for later seal submission.
|
||||
*self.proposal.write() = bh;
|
||||
*self.proposal_parent.write() = header.parent_hash().clone();
|
||||
Seal::Proposal(vec![
|
||||
::rlp::encode(&view).to_vec(),
|
||||
::rlp::encode(&signature).to_vec(),
|
||||
@@ -505,7 +509,12 @@ impl Engine for Tendermint {
|
||||
|
||||
}
|
||||
|
||||
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Verify validators and gas limit.
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
let proposal = ConsensusMessage::new_proposal(header)?;
|
||||
let proposer = proposal.verify()?;
|
||||
if !self.is_authority(&proposer) {
|
||||
@@ -522,7 +531,7 @@ impl Engine for Tendermint {
|
||||
Some(a) => a,
|
||||
None => public_to_address(&recover(&precommit.signature.into(), &precommit_hash)?),
|
||||
};
|
||||
if !self.validators.contains(&address) {
|
||||
if !self.validators.contains(header.parent_hash(), &address) {
|
||||
Err(EngineError::NotAuthorized(address.to_owned()))?
|
||||
}
|
||||
|
||||
@@ -545,12 +554,9 @@ impl Engine for Tendermint {
|
||||
found: signatures_len
|
||||
}))?;
|
||||
}
|
||||
self.is_view_proposer(proposal.vote_step.height, proposal.vote_step.view, &proposer)?;
|
||||
self.is_view_proposer(header.parent_hash(), proposal.vote_step.height, proposal.vote_step.view, &proposer)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
|
||||
if header.number() == 0 {
|
||||
Err(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))?;
|
||||
}
|
||||
@@ -595,6 +601,7 @@ impl Engine for Tendermint {
|
||||
debug!(target: "engine", "Received a new proposal {:?} from {}.", proposal.vote_step, proposer);
|
||||
if self.is_view(&proposal) {
|
||||
*self.proposal.write() = proposal.block_hash.clone();
|
||||
*self.proposal_parent.write() = header.parent_hash().clone();
|
||||
}
|
||||
self.votes.vote(proposal, &proposer);
|
||||
true
|
||||
@@ -607,7 +614,7 @@ impl Engine for Tendermint {
|
||||
trace!(target: "engine", "Propose timeout.");
|
||||
if self.proposal.read().is_none() {
|
||||
// Report the proposer if no proposal was received.
|
||||
let current_proposer = self.view_proposer(self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst));
|
||||
let current_proposer = self.view_proposer(&*self.proposal_parent.read(), self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst));
|
||||
self.validators.report_benign(¤t_proposer);
|
||||
}
|
||||
Step::Prevote
|
||||
@@ -765,20 +772,25 @@ mod tests {
|
||||
let (spec, tap) = setup();
|
||||
let engine = spec.engine;
|
||||
|
||||
let mut header = Header::default();
|
||||
let validator = insert_and_unlock(&tap, "0");
|
||||
header.set_author(validator);
|
||||
let seal = proposal_seal(&tap, &header, 0);
|
||||
header.set_seal(seal);
|
||||
// Good proposer.
|
||||
assert!(engine.verify_block_unordered(&header.clone(), None).is_ok());
|
||||
let mut parent_header: Header = Header::default();
|
||||
parent_header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
|
||||
let mut header = Header::default();
|
||||
header.set_number(1);
|
||||
header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
let validator = insert_and_unlock(&tap, "1");
|
||||
header.set_author(validator);
|
||||
let seal = proposal_seal(&tap, &header, 0);
|
||||
header.set_seal(seal);
|
||||
// Good proposer.
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
|
||||
let validator = insert_and_unlock(&tap, "0");
|
||||
header.set_author(validator);
|
||||
let seal = proposal_seal(&tap, &header, 0);
|
||||
header.set_seal(seal);
|
||||
// Bad proposer.
|
||||
match engine.verify_block_unordered(&header, None) {
|
||||
match engine.verify_block_family(&header, &parent_header, None) {
|
||||
Err(Error::Engine(EngineError::NotProposer(_))) => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
@@ -788,7 +800,7 @@ mod tests {
|
||||
let seal = proposal_seal(&tap, &header, 0);
|
||||
header.set_seal(seal);
|
||||
// Not authority.
|
||||
match engine.verify_block_unordered(&header, None) {
|
||||
match engine.verify_block_family(&header, &parent_header, None) {
|
||||
Err(Error::Engine(EngineError::NotAuthorized(_))) => {},
|
||||
_ => panic!(),
|
||||
};
|
||||
@@ -800,19 +812,24 @@ mod tests {
|
||||
let (spec, tap) = setup();
|
||||
let engine = spec.engine;
|
||||
|
||||
let mut parent_header: Header = Header::default();
|
||||
parent_header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
|
||||
let mut header = Header::default();
|
||||
header.set_number(2);
|
||||
header.set_gas_limit(U256::from_str("222222").unwrap());
|
||||
let proposer = insert_and_unlock(&tap, "1");
|
||||
header.set_author(proposer);
|
||||
let mut seal = proposal_seal(&tap, &header, 0);
|
||||
|
||||
let vote_info = message_info_rlp(&VoteStep::new(0, 0, Step::Precommit), Some(header.bare_hash()));
|
||||
let vote_info = message_info_rlp(&VoteStep::new(2, 0, Step::Precommit), Some(header.bare_hash()));
|
||||
let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap();
|
||||
|
||||
seal[2] = ::rlp::encode(&vec![H520::from(signature1.clone())]).to_vec();
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
// One good signature is not enough.
|
||||
match engine.verify_block_unordered(&header, None) {
|
||||
match engine.verify_block_family(&header, &parent_header, None) {
|
||||
Err(Error::Engine(EngineError::BadSealFieldSize(_))) => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
@@ -823,7 +840,7 @@ mod tests {
|
||||
seal[2] = ::rlp::encode(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).to_vec();
|
||||
header.set_seal(seal.clone());
|
||||
|
||||
assert!(engine.verify_block_unordered(&header, None).is_ok());
|
||||
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
|
||||
let bad_voter = insert_and_unlock(&tap, "101");
|
||||
let bad_signature = tap.sign(bad_voter, None, vote_info.sha3()).unwrap();
|
||||
@@ -832,7 +849,7 @@ mod tests {
|
||||
header.set_seal(seal);
|
||||
|
||||
// One good and one bad signature.
|
||||
match engine.verify_block_unordered(&header, None) {
|
||||
match engine.verify_block_family(&header, &parent_header, None) {
|
||||
Err(Error::Engine(EngineError::NotAuthorized(_))) => {},
|
||||
_ => panic!(),
|
||||
};
|
||||
|
||||
@@ -26,30 +26,30 @@ use super::safe_contract::ValidatorSafeContract;
|
||||
/// The validator contract should have the following interface:
|
||||
/// [{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}]
|
||||
pub struct ValidatorContract {
|
||||
validators: Arc<ValidatorSafeContract>,
|
||||
validators: ValidatorSafeContract,
|
||||
provider: RwLock<Option<provider::Contract>>,
|
||||
}
|
||||
|
||||
impl ValidatorContract {
|
||||
pub fn new(contract_address: Address) -> Self {
|
||||
ValidatorContract {
|
||||
validators: Arc::new(ValidatorSafeContract::new(contract_address)),
|
||||
validators: ValidatorSafeContract::new(contract_address),
|
||||
provider: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidatorSet for Arc<ValidatorContract> {
|
||||
fn contains(&self, address: &Address) -> bool {
|
||||
self.validators.contains(address)
|
||||
impl ValidatorSet for ValidatorContract {
|
||||
fn contains(&self, bh: &H256, address: &Address) -> bool {
|
||||
self.validators.contains(bh, address)
|
||||
}
|
||||
|
||||
fn get(&self, nonce: usize) -> Address {
|
||||
self.validators.get(nonce)
|
||||
fn get(&self, bh: &H256, nonce: usize) -> Address {
|
||||
self.validators.get(bh, nonce)
|
||||
}
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.validators.count()
|
||||
fn count(&self, bh: &H256) -> usize {
|
||||
self.validators.count(bh)
|
||||
}
|
||||
|
||||
fn report_malicious(&self, address: &Address) {
|
||||
@@ -144,6 +144,7 @@ mod tests {
|
||||
use header::Header;
|
||||
use account_provider::AccountProvider;
|
||||
use miner::MinerService;
|
||||
use types::ids::BlockId;
|
||||
use client::BlockChainClient;
|
||||
use tests::helpers::generate_dummy_client_with_spec_and_accounts;
|
||||
use super::super::ValidatorSet;
|
||||
@@ -154,8 +155,9 @@ mod tests {
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None);
|
||||
let vc = Arc::new(ValidatorContract::new(Address::from_str("0000000000000000000000000000000000000005").unwrap()));
|
||||
vc.register_contract(Arc::downgrade(&client));
|
||||
assert!(vc.contains(&Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()));
|
||||
assert!(vc.contains(&Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap()));
|
||||
let last_hash = client.best_block_header().hash();
|
||||
assert!(vc.contains(&last_hash, &Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()));
|
||||
assert!(vc.contains(&last_hash, &Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -171,18 +173,21 @@ mod tests {
|
||||
|
||||
client.miner().set_engine_signer(v1, "".into()).unwrap();
|
||||
let mut header = Header::default();
|
||||
let seal = encode(&vec!(5u8)).to_vec();
|
||||
header.set_seal(vec!(seal));
|
||||
let seal = vec![encode(&5u8).to_vec(), encode(&(&H520::default() as &[u8])).to_vec()];
|
||||
header.set_seal(seal);
|
||||
header.set_author(v1);
|
||||
header.set_number(1);
|
||||
header.set_number(2);
|
||||
header.set_parent_hash(client.chain_info().best_block_hash);
|
||||
|
||||
// `reportBenign` when the designated proposer releases block from the future (bad clock).
|
||||
assert!(client.engine().verify_block_unordered(&header, None).is_err());
|
||||
assert!(client.engine().verify_block_family(&header, &header, None).is_err());
|
||||
// Seal a block.
|
||||
client.engine().step();
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
// Check if the unresponsive validator is `disliked`.
|
||||
assert_eq!(client.call_contract(validator_contract, "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), "0000000000000000000000007d577a597b2742b498cb5cf0c26cdcd726d39e6e");
|
||||
assert_eq!(client.call_contract(BlockId::Latest, validator_contract, "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), "0000000000000000000000007d577a597b2742b498cb5cf0c26cdcd726d39e6e");
|
||||
// Simulate a misbehaving validator by handling a double proposal.
|
||||
let header = client.best_block_header().decode();
|
||||
assert!(client.engine().verify_block_family(&header, &header, None).is_err());
|
||||
// Seal a block.
|
||||
client.engine().step();
|
||||
|
||||
@@ -19,31 +19,36 @@
|
||||
mod simple_list;
|
||||
mod safe_contract;
|
||||
mod contract;
|
||||
mod multi;
|
||||
|
||||
use std::sync::Weak;
|
||||
use util::{Address, Arc};
|
||||
use util::{Address, H256};
|
||||
use ethjson::spec::ValidatorSet as ValidatorSpec;
|
||||
use client::Client;
|
||||
use self::simple_list::SimpleList;
|
||||
use self::contract::ValidatorContract;
|
||||
use self::safe_contract::ValidatorSafeContract;
|
||||
use self::multi::Multi;
|
||||
|
||||
/// Creates a validator set from spec.
|
||||
pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet + Send + Sync> {
|
||||
pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> {
|
||||
match spec {
|
||||
ValidatorSpec::List(list) => Box::new(SimpleList::new(list.into_iter().map(Into::into).collect())),
|
||||
ValidatorSpec::SafeContract(address) => Box::new(Arc::new(ValidatorSafeContract::new(address.into()))),
|
||||
ValidatorSpec::Contract(address) => Box::new(Arc::new(ValidatorContract::new(address.into()))),
|
||||
ValidatorSpec::SafeContract(address) => Box::new(ValidatorSafeContract::new(address.into())),
|
||||
ValidatorSpec::Contract(address) => Box::new(ValidatorContract::new(address.into())),
|
||||
ValidatorSpec::Multi(sequence) => Box::new(
|
||||
Multi::new(sequence.into_iter().map(|(block, set)| (block.into(), new_validator_set(set))).collect())
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ValidatorSet {
|
||||
pub trait ValidatorSet: Send + Sync {
|
||||
/// Checks if a given address is a validator.
|
||||
fn contains(&self, address: &Address) -> bool;
|
||||
fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool;
|
||||
/// Draws an validator nonce modulo number of validators.
|
||||
fn get(&self, nonce: usize) -> Address;
|
||||
fn get(&self, parent_block_hash: &H256, nonce: usize) -> Address;
|
||||
/// Returns the current number of validators.
|
||||
fn count(&self) -> usize;
|
||||
fn count(&self, parent_block_hash: &H256) -> usize;
|
||||
/// Notifies about malicious behaviour.
|
||||
fn report_malicious(&self, _validator: &Address) {}
|
||||
/// Notifies about benign misbehaviour.
|
||||
|
||||
158
ethcore/src/engines/validator_set/multi.rs
Normal file
158
ethcore/src/engines/validator_set/multi.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright 2015-2017 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/// Validator set changing at fork blocks.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Weak;
|
||||
use util::{H256, Address, RwLock};
|
||||
use ids::BlockId;
|
||||
use header::BlockNumber;
|
||||
use client::{Client, BlockChainClient};
|
||||
use super::ValidatorSet;
|
||||
|
||||
type BlockNumberLookup = Box<Fn(&H256) -> Result<BlockNumber, String> + Send + Sync + 'static>;
|
||||
|
||||
pub struct Multi {
|
||||
sets: BTreeMap<BlockNumber, Box<ValidatorSet>>,
|
||||
block_number: RwLock<BlockNumberLookup>,
|
||||
}
|
||||
|
||||
impl Multi {
|
||||
pub fn new(set_map: BTreeMap<BlockNumber, Box<ValidatorSet>>) -> Self {
|
||||
assert!(set_map.get(&0u64).is_some(), "ValidatorSet has to be specified from block 0.");
|
||||
Multi {
|
||||
sets: set_map,
|
||||
block_number: RwLock::new(Box::new(move |_| Err("No client!".into()))),
|
||||
}
|
||||
}
|
||||
|
||||
fn correct_set(&self, bh: &H256) -> Option<&Box<ValidatorSet>> {
|
||||
match self
|
||||
.block_number
|
||||
.read()(bh)
|
||||
.map(|parent_block| self
|
||||
.sets
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|&(block, _)| *block <= parent_block + 1)
|
||||
.expect("constructor validation ensures that there is at least one validator set for block 0;
|
||||
block 0 is less than any uint;
|
||||
qed")
|
||||
) {
|
||||
Ok((block, set)) => {
|
||||
trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block);
|
||||
Some(set)
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target: "engine", "ValidatorSet could not be recovered: {}", e);
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidatorSet for Multi {
|
||||
fn contains(&self, bh: &H256, address: &Address) -> bool {
|
||||
self.correct_set(bh).map_or(false, |set| set.contains(bh, address))
|
||||
}
|
||||
|
||||
fn get(&self, bh: &H256, nonce: usize) -> Address {
|
||||
self.correct_set(bh).map_or_else(Default::default, |set| set.get(bh, nonce))
|
||||
}
|
||||
|
||||
fn count(&self, bh: &H256) -> usize {
|
||||
self.correct_set(bh).map_or_else(usize::max_value, |set| set.count(bh))
|
||||
}
|
||||
|
||||
fn report_malicious(&self, validator: &Address) {
|
||||
for set in self.sets.values() {
|
||||
set.report_malicious(validator);
|
||||
}
|
||||
}
|
||||
|
||||
fn report_benign(&self, validator: &Address) {
|
||||
for set in self.sets.values() {
|
||||
set.report_benign(validator);
|
||||
}
|
||||
}
|
||||
|
||||
fn register_contract(&self, client: Weak<Client>) {
|
||||
for set in self.sets.values() {
|
||||
set.register_contract(client.clone());
|
||||
}
|
||||
*self.block_number.write() = Box::new(move |hash| client
|
||||
.upgrade()
|
||||
.ok_or("No client!".into())
|
||||
.and_then(|c| c.block_number(BlockId::Hash(*hash)).ok_or("Unknown block".into())));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use types::ids::BlockId;
|
||||
use spec::Spec;
|
||||
use account_provider::AccountProvider;
|
||||
use client::{BlockChainClient, EngineClient};
|
||||
use ethkey::Secret;
|
||||
use miner::MinerService;
|
||||
use tests::helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
|
||||
|
||||
#[test]
|
||||
fn uses_current_set() {
|
||||
::env_logger::init().unwrap();
|
||||
let tap = Arc::new(AccountProvider::transient_provider());
|
||||
let s0 = Secret::from_slice(&"0".sha3()).unwrap();
|
||||
let v0 = tap.insert_account(s0.clone(), "").unwrap();
|
||||
let v1 = tap.insert_account(Secret::from_slice(&"1".sha3()).unwrap(), "").unwrap();
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap));
|
||||
client.engine().register_client(Arc::downgrade(&client));
|
||||
|
||||
// Make sure txs go through.
|
||||
client.miner().set_gas_floor_target(1_000_000.into());
|
||||
|
||||
// Wrong signer for the first block.
|
||||
client.miner().set_engine_signer(v1, "".into()).unwrap();
|
||||
client.transact_contract(Default::default(), Default::default()).unwrap();
|
||||
client.update_sealing();
|
||||
assert_eq!(client.chain_info().best_block_number, 0);
|
||||
// Right signer for the first block.
|
||||
client.miner().set_engine_signer(v0, "".into()).unwrap();
|
||||
client.update_sealing();
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
// This time v0 is wrong.
|
||||
client.transact_contract(Default::default(), Default::default()).unwrap();
|
||||
client.update_sealing();
|
||||
assert_eq!(client.chain_info().best_block_number, 1);
|
||||
client.miner().set_engine_signer(v1, "".into()).unwrap();
|
||||
client.update_sealing();
|
||||
assert_eq!(client.chain_info().best_block_number, 2);
|
||||
// v1 is still good.
|
||||
client.transact_contract(Default::default(), Default::default()).unwrap();
|
||||
client.update_sealing();
|
||||
assert_eq!(client.chain_info().best_block_number, 3);
|
||||
|
||||
// Check syncing.
|
||||
let sync_client = generate_dummy_client_with_spec_and_data(Spec::new_validator_multi, 0, 0, &[]);
|
||||
sync_client.engine().register_client(Arc::downgrade(&sync_client));
|
||||
for i in 1..4 {
|
||||
sync_client.import_block(client.block(BlockId::Number(i)).unwrap().into_inner()).unwrap();
|
||||
}
|
||||
sync_client.flush_queue();
|
||||
assert_eq!(sync_client.chain_info().best_block_number, 3);
|
||||
}
|
||||
}
|
||||
@@ -17,17 +17,23 @@
|
||||
/// Validator set maintained in a contract, updated using `getValidators` method.
|
||||
|
||||
use std::sync::Weak;
|
||||
use ethabi;
|
||||
use util::*;
|
||||
use util::cache::MemoryLruCache;
|
||||
use types::ids::BlockId;
|
||||
use client::{Client, BlockChainClient};
|
||||
use client::chain_notify::ChainNotify;
|
||||
use super::ValidatorSet;
|
||||
use super::simple_list::SimpleList;
|
||||
|
||||
const MEMOIZE_CAPACITY: usize = 500;
|
||||
const CONTRACT_INTERFACE: &'static [u8] = b"[{\"constant\":true,\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"type\":\"function\"}]";
|
||||
const GET_VALIDATORS: &'static str = "getValidators";
|
||||
|
||||
/// The validator contract should have the following interface:
|
||||
/// [{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}]
|
||||
pub struct ValidatorSafeContract {
|
||||
pub address: Address,
|
||||
validators: RwLock<SimpleList>,
|
||||
validators: RwLock<MemoryLruCache<H256, SimpleList>>,
|
||||
provider: RwLock<Option<provider::Contract>>,
|
||||
}
|
||||
|
||||
@@ -35,102 +41,127 @@ impl ValidatorSafeContract {
|
||||
pub fn new(contract_address: Address) -> Self {
|
||||
ValidatorSafeContract {
|
||||
address: contract_address,
|
||||
validators: Default::default(),
|
||||
validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)),
|
||||
provider: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries the state and updates the set of validators.
|
||||
pub fn update(&self) {
|
||||
/// Queries the state and gets the set of validators.
|
||||
fn get_list(&self, block_hash: H256) -> Option<SimpleList> {
|
||||
if let Some(ref provider) = *self.provider.read() {
|
||||
match provider.get_validators() {
|
||||
match provider.get_validators(BlockId::Hash(block_hash)) {
|
||||
Ok(new) => {
|
||||
debug!(target: "engine", "Set of validators obtained: {:?}", new);
|
||||
*self.validators.write() = SimpleList::new(new);
|
||||
Some(SimpleList::new(new))
|
||||
},
|
||||
Err(s) => {
|
||||
debug!(target: "engine", "Set of validators could not be updated: {}", s);
|
||||
None
|
||||
},
|
||||
Err(s) => warn!(target: "engine", "Set of validators could not be updated: {}", s),
|
||||
}
|
||||
} else {
|
||||
warn!(target: "engine", "Set of validators could not be updated: no provider contract.")
|
||||
warn!(target: "engine", "Set of validators could not be updated: no provider contract.");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks validators on every block.
|
||||
impl ChainNotify for ValidatorSafeContract {
|
||||
fn new_blocks(
|
||||
&self,
|
||||
_: Vec<H256>,
|
||||
_: Vec<H256>,
|
||||
enacted: Vec<H256>,
|
||||
_: Vec<H256>,
|
||||
_: Vec<H256>,
|
||||
_: Vec<Bytes>,
|
||||
_duration: u64) {
|
||||
if !enacted.is_empty() {
|
||||
self.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidatorSet for Arc<ValidatorSafeContract> {
|
||||
fn contains(&self, address: &Address) -> bool {
|
||||
self.validators.read().contains(address)
|
||||
impl ValidatorSet for ValidatorSafeContract {
|
||||
fn contains(&self, block_hash: &H256, address: &Address) -> bool {
|
||||
let mut guard = self.validators.write();
|
||||
let maybe_existing = guard
|
||||
.get_mut(block_hash)
|
||||
.map(|list| list.contains(block_hash, address));
|
||||
maybe_existing
|
||||
.unwrap_or_else(|| self
|
||||
.get_list(block_hash.clone())
|
||||
.map_or(false, |list| {
|
||||
let contains = list.contains(block_hash, address);
|
||||
guard.insert(block_hash.clone(), list);
|
||||
contains
|
||||
}))
|
||||
}
|
||||
|
||||
fn get(&self, nonce: usize) -> Address {
|
||||
self.validators.read().get(nonce)
|
||||
fn get(&self, block_hash: &H256, nonce: usize) -> Address {
|
||||
let mut guard = self.validators.write();
|
||||
let maybe_existing = guard
|
||||
.get_mut(block_hash)
|
||||
.map(|list| list.get(block_hash, nonce));
|
||||
maybe_existing
|
||||
.unwrap_or_else(|| self
|
||||
.get_list(block_hash.clone())
|
||||
.map_or_else(Default::default, |list| {
|
||||
let address = list.get(block_hash, nonce);
|
||||
guard.insert(block_hash.clone(), list);
|
||||
address
|
||||
}))
|
||||
}
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.validators.read().count()
|
||||
fn count(&self, block_hash: &H256) -> usize {
|
||||
let mut guard = self.validators.write();
|
||||
let maybe_existing = guard
|
||||
.get_mut(block_hash)
|
||||
.map(|list| list.count(block_hash));
|
||||
maybe_existing
|
||||
.unwrap_or_else(|| self
|
||||
.get_list(block_hash.clone())
|
||||
.map_or_else(usize::max_value, |list| {
|
||||
let address = list.count(block_hash);
|
||||
guard.insert(block_hash.clone(), list);
|
||||
address
|
||||
}))
|
||||
}
|
||||
|
||||
fn register_contract(&self, client: Weak<Client>) {
|
||||
if let Some(c) = client.upgrade() {
|
||||
c.add_notify(self.clone());
|
||||
}
|
||||
{
|
||||
*self.provider.write() = Some(provider::Contract::new(self.address, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d))));
|
||||
}
|
||||
self.update();
|
||||
trace!(target: "engine", "Setting up contract caller.");
|
||||
let contract = ethabi::Contract::new(ethabi::Interface::load(CONTRACT_INTERFACE).expect("JSON interface is valid; qed"));
|
||||
let call = contract.function(GET_VALIDATORS.into()).expect("Method name is valid; qed");
|
||||
let data = call.encode_call(vec![]).expect("get_validators does not take any arguments; qed");
|
||||
let contract_address = self.address.clone();
|
||||
let do_call = move |id| client
|
||||
.upgrade()
|
||||
.ok_or("No client!".into())
|
||||
.and_then(|c| c.call_contract(id, contract_address.clone(), data.clone()))
|
||||
.map(|raw_output| call.decode_output(raw_output).expect("ethabi is correct; qed"));
|
||||
*self.provider.write() = Some(provider::Contract::new(do_call));
|
||||
}
|
||||
}
|
||||
|
||||
mod provider {
|
||||
// Autogenerated from JSON contract definition using Rust contract convertor.
|
||||
#![allow(unused_imports)]
|
||||
use std::string::String;
|
||||
use std::result::Result;
|
||||
use std::fmt;
|
||||
use {util, ethabi};
|
||||
use util::{FixedHash, Uint};
|
||||
use types::ids::BlockId;
|
||||
|
||||
pub struct Contract {
|
||||
contract: ethabi::Contract,
|
||||
address: util::Address,
|
||||
do_call: Box<Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send + Sync + 'static>,
|
||||
do_call: Box<Fn(BlockId) -> Result<Vec<ethabi::Token>, String> + Send + Sync + 'static>,
|
||||
}
|
||||
|
||||
impl Contract {
|
||||
pub fn new<F>(address: util::Address, do_call: F) -> Self where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send + Sync + 'static {
|
||||
pub fn new<F>(do_call: F) -> Self where F: Fn(BlockId) -> Result<Vec<ethabi::Token>, String> + Send + Sync + 'static {
|
||||
Contract {
|
||||
contract: ethabi::Contract::new(ethabi::Interface::load(b"[{\"constant\":true,\"inputs\":[],\"name\":\"getValidators\",\"outputs\":[{\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"type\":\"function\"}]").expect("JSON is autogenerated; qed")),
|
||||
address: address,
|
||||
do_call: Box::new(do_call),
|
||||
}
|
||||
}
|
||||
fn as_string<T: fmt::Debug>(e: T) -> String { format!("{:?}", e) }
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_validators(&self) -> Result<Vec<util::Address>, String> {
|
||||
let call = self.contract.function("getValidators".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_array().and_then(|v| v.into_iter().map(|a| a.to_address()).collect::<Option<Vec<[u8; 20]>>>()).ok_or("Invalid type returned")?; r.into_iter().map(|a| util::Address::from(a)).collect::<Vec<_>>() }))
|
||||
|
||||
/// Gets validators from contract with interface: `{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"}`
|
||||
pub fn get_validators(&self, id: BlockId) -> Result<Vec<util::Address>, String> {
|
||||
Ok((self.do_call)(id)?
|
||||
.into_iter()
|
||||
.rev()
|
||||
.collect::<Vec<_>>()
|
||||
.pop()
|
||||
.expect("get_validators returns one argument; qed")
|
||||
.to_array()
|
||||
.and_then(|v| v
|
||||
.into_iter()
|
||||
.map(|a| a.to_address())
|
||||
.collect::<Option<Vec<[u8; 20]>>>())
|
||||
.expect("get_validators returns a list of addresses; qed")
|
||||
.into_iter()
|
||||
.map(util::Address::from)
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,13 +169,14 @@ mod provider {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use util::*;
|
||||
use types::ids::BlockId;
|
||||
use spec::Spec;
|
||||
use account_provider::AccountProvider;
|
||||
use transaction::{Transaction, Action};
|
||||
use client::{BlockChainClient, EngineClient};
|
||||
use ethkey::Secret;
|
||||
use miner::MinerService;
|
||||
use tests::helpers::generate_dummy_client_with_spec_and_accounts;
|
||||
use tests::helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data};
|
||||
use super::super::ValidatorSet;
|
||||
use super::ValidatorSafeContract;
|
||||
|
||||
@@ -153,12 +185,13 @@ mod tests {
|
||||
let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None);
|
||||
let vc = Arc::new(ValidatorSafeContract::new(Address::from_str("0000000000000000000000000000000000000005").unwrap()));
|
||||
vc.register_contract(Arc::downgrade(&client));
|
||||
assert!(vc.contains(&Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()));
|
||||
assert!(vc.contains(&Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap()));
|
||||
let last_hash = client.best_block_header().hash();
|
||||
assert!(vc.contains(&last_hash, &Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()));
|
||||
assert!(vc.contains(&last_hash, &Address::from_str("82a978b3f5962a5b0957d9ee9eef472ee55b42f1").unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn updates_validators() {
|
||||
fn knows_validators() {
|
||||
let tap = Arc::new(AccountProvider::transient_provider());
|
||||
let s0 = Secret::from_slice(&"1".sha3()).unwrap();
|
||||
let v0 = tap.insert_account(s0.clone(), "").unwrap();
|
||||
@@ -212,5 +245,14 @@ mod tests {
|
||||
client.update_sealing();
|
||||
// Able to seal again.
|
||||
assert_eq!(client.chain_info().best_block_number, 3);
|
||||
|
||||
// Check syncing.
|
||||
let sync_client = generate_dummy_client_with_spec_and_data(Spec::new_validator_safe_contract, 0, 0, &[]);
|
||||
sync_client.engine().register_client(Arc::downgrade(&sync_client));
|
||||
for i in 1..4 {
|
||||
sync_client.import_block(client.block(BlockId::Number(i)).unwrap().into_inner()).unwrap();
|
||||
}
|
||||
sync_client.flush_queue();
|
||||
assert_eq!(sync_client.chain_info().best_block_number, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/// Preconfigured validator list.
|
||||
|
||||
use util::Address;
|
||||
use util::{H256, Address, HeapSizeOf};
|
||||
use super::ValidatorSet;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
@@ -34,16 +34,22 @@ impl SimpleList {
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapSizeOf for SimpleList {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.validators.heap_size_of_children() + self.validator_n.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidatorSet for SimpleList {
|
||||
fn contains(&self, address: &Address) -> bool {
|
||||
fn contains(&self, _bh: &H256, address: &Address) -> bool {
|
||||
self.validators.contains(address)
|
||||
}
|
||||
|
||||
fn get(&self, nonce: usize) -> Address {
|
||||
fn get(&self, _bh: &H256, nonce: usize) -> Address {
|
||||
self.validators.get(nonce % self.validator_n).expect("There are validator_n authorities; taking number modulo validator_n gives number in validator_n range; qed").clone()
|
||||
}
|
||||
|
||||
fn count(&self) -> usize {
|
||||
fn count(&self, _bh: &H256) -> usize {
|
||||
self.validator_n
|
||||
}
|
||||
}
|
||||
@@ -60,9 +66,9 @@ mod tests {
|
||||
let a1 = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
||||
let a2 = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||
let list = SimpleList::new(vec![a1.clone(), a2.clone()]);
|
||||
assert!(list.contains(&a1));
|
||||
assert_eq!(list.get(0), a1);
|
||||
assert_eq!(list.get(1), a2);
|
||||
assert_eq!(list.get(2), a1);
|
||||
assert!(list.contains(&Default::default(), &a1));
|
||||
assert_eq!(list.get(&Default::default(), 0), a1);
|
||||
assert_eq!(list.get(&Default::default(), 1), a2);
|
||||
assert_eq!(list.get(&Default::default(), 2), a1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ extern crate ethcore_stratum;
|
||||
extern crate ethabi;
|
||||
extern crate hardware_wallet;
|
||||
extern crate stats;
|
||||
extern crate itertools;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -230,7 +230,8 @@ pub struct Miner {
|
||||
impl Miner {
|
||||
/// Push notifier that will handle new jobs
|
||||
pub fn push_notifier(&self, notifier: Box<NotifyWork>) {
|
||||
self.notifiers.write().push(notifier)
|
||||
self.notifiers.write().push(notifier);
|
||||
self.sealing_work.lock().enabled = true;
|
||||
}
|
||||
|
||||
/// Creates new instance of miner Arc.
|
||||
@@ -298,7 +299,7 @@ impl Miner {
|
||||
}
|
||||
|
||||
fn forced_sealing(&self) -> bool {
|
||||
self.options.force_sealing || !self.options.new_work_notify.is_empty()
|
||||
self.options.force_sealing || !self.notifiers.read().is_empty()
|
||||
}
|
||||
|
||||
/// Clear all pending block states
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use types::ids::BlockId;
|
||||
use client::MiningBlockChainClient;
|
||||
use transaction::SignedTransaction;
|
||||
use util::{U256, Uint, Mutex};
|
||||
@@ -45,7 +46,7 @@ impl ServiceTransactionChecker {
|
||||
debug_assert_eq!(tx.gas_price, U256::zero());
|
||||
|
||||
if let Some(ref contract) = *self.contract.lock() {
|
||||
let do_call = |a, d| client.call_contract(a, d);
|
||||
let do_call = |a, d| client.call_contract(BlockId::Latest, a, d);
|
||||
contract.certified(&do_call, &tx.sender())
|
||||
} else {
|
||||
Err("contract is not configured".to_owned())
|
||||
|
||||
@@ -211,6 +211,8 @@ impl From<AddrParseError> for Error {
|
||||
|
||||
impl super::work_notify::NotifyWork for Stratum {
|
||||
fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) {
|
||||
trace!(target: "stratum", "Notify work");
|
||||
|
||||
self.service.push_work_all(
|
||||
self.dispatcher.payload(pow_hash, difficulty, number)
|
||||
).unwrap_or_else(
|
||||
|
||||
@@ -23,6 +23,7 @@ use snapshot::Error;
|
||||
use util::{U256, FixedHash, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP};
|
||||
use util::trie::{TrieDB, Trie};
|
||||
use rlp::{RlpStream, Stream, UntrustedRlp, View};
|
||||
use itertools::Itertools;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -60,55 +61,53 @@ impl CodeState {
|
||||
}
|
||||
}
|
||||
|
||||
// walk the account's storage trie, returning an RLP item containing the
|
||||
// account properties and the storage.
|
||||
pub fn to_fat_rlp(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet<H256>) -> Result<Bytes, Error> {
|
||||
// walk the account's storage trie, returning a vector of RLP items containing the
|
||||
// account properties and the storage. Each item contains at most `max_storage_items`
|
||||
// storage records split according to snapshot format definition.
|
||||
pub fn to_fat_rlps(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet<H256>, max_storage_items: usize) -> Result<Vec<Bytes>, Error> {
|
||||
if acc == &ACC_EMPTY {
|
||||
return Ok(::rlp::NULL_RLP.to_vec());
|
||||
return Ok(vec![::rlp::NULL_RLP.to_vec()]);
|
||||
}
|
||||
|
||||
let db = TrieDB::new(acct_db, &acc.storage_root)?;
|
||||
|
||||
let mut pairs = Vec::new();
|
||||
let chunks = db.iter()?.chunks(max_storage_items);
|
||||
let pair_chunks = chunks.into_iter().map(|chunk| chunk.collect());
|
||||
pair_chunks.pad_using(1, |_| Vec::new(), ).map(|pairs| {
|
||||
let mut stream = RlpStream::new_list(pairs.len());
|
||||
|
||||
for item in db.iter()? {
|
||||
let (k, v) = item?;
|
||||
pairs.push((k, v));
|
||||
}
|
||||
for r in pairs {
|
||||
let (k, v) = r?;
|
||||
stream.begin_list(2).append(&k).append(&&*v);
|
||||
}
|
||||
|
||||
let mut stream = RlpStream::new_list(pairs.len());
|
||||
let pairs_rlp = stream.out();
|
||||
|
||||
for (k, v) in pairs {
|
||||
stream.begin_list(2).append(&k).append(&&*v);
|
||||
}
|
||||
let mut account_stream = RlpStream::new_list(5);
|
||||
account_stream.append(&acc.nonce)
|
||||
.append(&acc.balance);
|
||||
|
||||
let pairs_rlp = stream.out();
|
||||
|
||||
let mut account_stream = RlpStream::new_list(5);
|
||||
account_stream.append(&acc.nonce)
|
||||
.append(&acc.balance);
|
||||
|
||||
// [has_code, code_hash].
|
||||
if acc.code_hash == SHA3_EMPTY {
|
||||
account_stream.append(&CodeState::Empty.raw()).append_empty_data();
|
||||
} else if used_code.contains(&acc.code_hash) {
|
||||
account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash);
|
||||
} else {
|
||||
match acct_db.get(&acc.code_hash) {
|
||||
Some(c) => {
|
||||
used_code.insert(acc.code_hash.clone());
|
||||
account_stream.append(&CodeState::Inline.raw()).append(&&*c);
|
||||
}
|
||||
None => {
|
||||
warn!("code lookup failed during snapshot");
|
||||
account_stream.append(&false).append_empty_data();
|
||||
// [has_code, code_hash].
|
||||
if acc.code_hash == SHA3_EMPTY {
|
||||
account_stream.append(&CodeState::Empty.raw()).append_empty_data();
|
||||
} else if used_code.contains(&acc.code_hash) {
|
||||
account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash);
|
||||
} else {
|
||||
match acct_db.get(&acc.code_hash) {
|
||||
Some(c) => {
|
||||
used_code.insert(acc.code_hash.clone());
|
||||
account_stream.append(&CodeState::Inline.raw()).append(&&*c);
|
||||
}
|
||||
None => {
|
||||
warn!("code lookup failed during snapshot");
|
||||
account_stream.append(&false).append_empty_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
account_stream.append_raw(&pairs_rlp, 1);
|
||||
|
||||
Ok(account_stream.out())
|
||||
account_stream.append_raw(&pairs_rlp, 1);
|
||||
Ok(account_stream.out())
|
||||
}).collect()
|
||||
}
|
||||
|
||||
// decode a fat rlp, and rebuild the storage trie as we go.
|
||||
@@ -117,6 +116,7 @@ pub fn to_fat_rlp(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashS
|
||||
pub fn from_fat_rlp(
|
||||
acct_db: &mut AccountDBMut,
|
||||
rlp: UntrustedRlp,
|
||||
mut storage_root: H256,
|
||||
) -> Result<(BasicAccount, Option<Bytes>), Error> {
|
||||
use util::{TrieDBMut, TrieMut};
|
||||
|
||||
@@ -148,10 +148,12 @@ pub fn from_fat_rlp(
|
||||
}
|
||||
};
|
||||
|
||||
let mut storage_root = H256::zero();
|
||||
|
||||
{
|
||||
let mut storage_trie = TrieDBMut::new(acct_db, &mut storage_root);
|
||||
let mut storage_trie = if storage_root.is_zero() {
|
||||
TrieDBMut::new(acct_db, &mut storage_root)
|
||||
} else {
|
||||
TrieDBMut::from_existing(acct_db, &mut storage_root)?
|
||||
};
|
||||
let pairs = rlp.at(4)?;
|
||||
for pair_rlp in pairs.iter() {
|
||||
let k: Bytes = pair_rlp.val_at(0)?;
|
||||
@@ -184,7 +186,7 @@ mod tests {
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use super::{ACC_EMPTY, to_fat_rlp, from_fat_rlp};
|
||||
use super::{ACC_EMPTY, to_fat_rlps, from_fat_rlp};
|
||||
|
||||
#[test]
|
||||
fn encoding_basic() {
|
||||
@@ -201,9 +203,9 @@ mod tests {
|
||||
let thin_rlp = ::rlp::encode(&account);
|
||||
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account);
|
||||
|
||||
let fat_rlp = to_fat_rlp(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default()).unwrap();
|
||||
let fat_rlp = UntrustedRlp::new(&fat_rlp);
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account);
|
||||
let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap();
|
||||
let fat_rlp = UntrustedRlp::new(&fat_rlps[0]);
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -226,9 +228,40 @@ mod tests {
|
||||
let thin_rlp = ::rlp::encode(&account);
|
||||
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account);
|
||||
|
||||
let fat_rlp = to_fat_rlp(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default()).unwrap();
|
||||
let fat_rlp = UntrustedRlp::new(&fat_rlp);
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account);
|
||||
let fat_rlp = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap();
|
||||
let fat_rlp = UntrustedRlp::new(&fat_rlp[0]);
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encoding_storage_split() {
|
||||
let mut db = get_temp_state_db();
|
||||
let addr = Address::random();
|
||||
|
||||
let account = {
|
||||
let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr);
|
||||
let mut root = SHA3_NULL_RLP;
|
||||
fill_storage(acct_db, &mut root, &mut H256::zero());
|
||||
BasicAccount {
|
||||
nonce: 25.into(),
|
||||
balance: 987654321.into(),
|
||||
storage_root: root,
|
||||
code_hash: SHA3_EMPTY,
|
||||
}
|
||||
};
|
||||
|
||||
let thin_rlp = ::rlp::encode(&account);
|
||||
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), account);
|
||||
|
||||
let fat_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 100).unwrap();
|
||||
let mut root = SHA3_NULL_RLP;
|
||||
let mut restored_account = None;
|
||||
for rlp in fat_rlps {
|
||||
let fat_rlp = UntrustedRlp::new(&rlp);
|
||||
restored_account = Some(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, root).unwrap().0);
|
||||
root = restored_account.as_ref().unwrap().storage_root.clone();
|
||||
}
|
||||
assert_eq!(restored_account, Some(account));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -264,18 +297,18 @@ mod tests {
|
||||
|
||||
let mut used_code = HashSet::new();
|
||||
|
||||
let fat_rlp1 = to_fat_rlp(&account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code).unwrap();
|
||||
let fat_rlp2 = to_fat_rlp(&account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code).unwrap();
|
||||
let fat_rlp1 = to_fat_rlps(&account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value()).unwrap();
|
||||
let fat_rlp2 = to_fat_rlps(&account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value()).unwrap();
|
||||
assert_eq!(used_code.len(), 1);
|
||||
|
||||
let fat_rlp1 = UntrustedRlp::new(&fat_rlp1);
|
||||
let fat_rlp2 = UntrustedRlp::new(&fat_rlp2);
|
||||
let fat_rlp1 = UntrustedRlp::new(&fat_rlp1[0]);
|
||||
let fat_rlp2 = UntrustedRlp::new(&fat_rlp2[0]);
|
||||
|
||||
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2).unwrap();
|
||||
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr2), fat_rlp2, H256::zero()).unwrap();
|
||||
assert!(maybe_code.is_none());
|
||||
assert_eq!(acc, account2);
|
||||
|
||||
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1).unwrap();
|
||||
let (acc, maybe_code) = from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr1), fat_rlp1, H256::zero()).unwrap();
|
||||
assert_eq!(maybe_code, Some(b"this is definitely code".to_vec()));
|
||||
assert_eq!(acc, account1);
|
||||
}
|
||||
@@ -285,7 +318,7 @@ mod tests {
|
||||
let mut db = get_temp_state_db();
|
||||
let mut used_code = HashSet::new();
|
||||
|
||||
assert_eq!(to_fat_rlp(&ACC_EMPTY, &AccountDB::new(db.as_hashdb(), &Address::default()), &mut used_code).unwrap(), ::rlp::NULL_RLP.to_vec());
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), UntrustedRlp::new(&::rlp::NULL_RLP)).unwrap(), (ACC_EMPTY, None));
|
||||
assert_eq!(to_fat_rlps(&ACC_EMPTY, &AccountDB::new(db.as_hashdb(), &Address::default()), &mut used_code, usize::max_value()).unwrap(), vec![::rlp::NULL_RLP.to_vec()]);
|
||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), UntrustedRlp::new(&::rlp::NULL_RLP), H256::zero()).unwrap(), (ACC_EMPTY, None));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ pub enum Error {
|
||||
Decoder(DecoderError),
|
||||
/// Io error.
|
||||
Io(::std::io::Error),
|
||||
/// Snapshot version is not supported.
|
||||
VersionNotSupported(u64),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@@ -73,6 +75,7 @@ impl fmt::Display for Error {
|
||||
Error::Io(ref err) => err.fmt(f),
|
||||
Error::Decoder(ref err) => err.fmt(f),
|
||||
Error::Trie(ref err) => err.fmt(f),
|
||||
Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ use rlp::{self, Encodable, RlpStream, UntrustedRlp, Stream, View};
|
||||
|
||||
use super::ManifestData;
|
||||
|
||||
const SNAPSHOT_VERSION: u64 = 2;
|
||||
|
||||
/// Something which can write snapshots.
|
||||
/// Writing the same chunk multiple times will lead to implementation-defined
|
||||
/// behavior, and is not advised.
|
||||
@@ -120,8 +122,9 @@ impl SnapshotWriter for PackedWriter {
|
||||
fn finish(mut self, manifest: ManifestData) -> io::Result<()> {
|
||||
// we ignore the hashes fields of the manifest under the assumption that
|
||||
// they are consistent with ours.
|
||||
let mut stream = RlpStream::new_list(5);
|
||||
let mut stream = RlpStream::new_list(6);
|
||||
stream
|
||||
.append(&SNAPSHOT_VERSION)
|
||||
.append(&self.state_hashes)
|
||||
.append(&self.block_hashes)
|
||||
.append(&manifest.state_root)
|
||||
@@ -223,7 +226,7 @@ impl PackedReader {
|
||||
/// Create a new `PackedReader` for the file at the given path.
|
||||
/// This will fail if any io errors are encountered or the file
|
||||
/// is not a valid packed snapshot.
|
||||
pub fn new(path: &Path) -> Result<Option<Self>, ::error::Error> {
|
||||
pub fn new(path: &Path) -> Result<Option<Self>, ::snapshot::error::Error> {
|
||||
let mut file = File::open(path)?;
|
||||
let file_len = file.metadata()?.len();
|
||||
if file_len < 8 {
|
||||
@@ -257,15 +260,26 @@ impl PackedReader {
|
||||
|
||||
let rlp = UntrustedRlp::new(&manifest_buf);
|
||||
|
||||
let state: Vec<ChunkInfo> = rlp.val_at(0)?;
|
||||
let blocks: Vec<ChunkInfo> = rlp.val_at(1)?;
|
||||
let (start, version) = if rlp.item_count() == 5 {
|
||||
(0, 1)
|
||||
} else {
|
||||
(1, rlp.val_at(0)?)
|
||||
};
|
||||
|
||||
if version > SNAPSHOT_VERSION {
|
||||
return Err(::snapshot::error::Error::VersionNotSupported(version));
|
||||
}
|
||||
|
||||
let state: Vec<ChunkInfo> = rlp.val_at(0 + start)?;
|
||||
let blocks: Vec<ChunkInfo> = rlp.val_at(1 + start)?;
|
||||
|
||||
let manifest = ManifestData {
|
||||
version: version,
|
||||
state_hashes: state.iter().map(|c| c.0).collect(),
|
||||
block_hashes: blocks.iter().map(|c| c.0).collect(),
|
||||
state_root: rlp.val_at(2)?,
|
||||
block_number: rlp.val_at(3)?,
|
||||
block_hash: rlp.val_at(4)?,
|
||||
state_root: rlp.val_at(2 + start)?,
|
||||
block_number: rlp.val_at(3 + start)?,
|
||||
block_hash: rlp.val_at(4 + start)?,
|
||||
};
|
||||
|
||||
Ok(Some(PackedReader {
|
||||
@@ -348,7 +362,7 @@ mod tests {
|
||||
use util::sha3::Hashable;
|
||||
|
||||
use snapshot::ManifestData;
|
||||
use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader};
|
||||
use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader, SNAPSHOT_VERSION};
|
||||
|
||||
const STATE_CHUNKS: &'static [&'static [u8]] = &[b"dog", b"cat", b"hello world", b"hi", b"notarealchunk"];
|
||||
const BLOCK_CHUNKS: &'static [&'static [u8]] = &[b"hello!", b"goodbye!", b"abcdefg", b"hijklmnop", b"qrstuvwxy", b"and", b"z"];
|
||||
@@ -374,6 +388,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let manifest = ManifestData {
|
||||
version: SNAPSHOT_VERSION,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: block_hashes,
|
||||
state_root: b"notarealroot".sha3(),
|
||||
@@ -412,6 +427,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let manifest = ManifestData {
|
||||
version: SNAPSHOT_VERSION,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: block_hashes,
|
||||
state_root: b"notarealroot".sha3(),
|
||||
@@ -428,4 +444,4 @@ mod tests {
|
||||
reader.chunk(hash.clone()).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ pub use self::traits::SnapshotService;
|
||||
pub use self::watcher::Watcher;
|
||||
pub use types::snapshot_manifest::ManifestData;
|
||||
pub use types::restoration_status::RestorationStatus;
|
||||
pub use types::basic_account::BasicAccount;
|
||||
|
||||
pub mod io;
|
||||
pub mod service;
|
||||
@@ -82,6 +83,9 @@ mod traits {
|
||||
// Try to have chunks be around 4MB (before compression)
|
||||
const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
|
||||
|
||||
// Try to have chunks be around 4MB (before compression)
|
||||
const MAX_STORAGE_ENTRIES_PER_ACCOUNT_RECORD: usize = 80_000;
|
||||
|
||||
// How many blocks to include in a snapshot, starting from the head of the chain.
|
||||
const SNAPSHOT_BLOCKS: u64 = 30000;
|
||||
|
||||
@@ -147,6 +151,7 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
|
||||
info!("produced {} state chunks and {} block chunks.", state_hashes.len(), block_hashes.len());
|
||||
|
||||
let manifest_data = ManifestData {
|
||||
version: 2,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: block_hashes,
|
||||
state_root: *state_root,
|
||||
@@ -300,14 +305,14 @@ impl<'a> StateChunker<'a> {
|
||||
//
|
||||
// If the buffer is greater than the desired chunk size,
|
||||
// this will write out the data to disk.
|
||||
fn push(&mut self, account_hash: Bytes, data: Bytes) -> Result<(), Error> {
|
||||
fn push(&mut self, account_hash: Bytes, data: Bytes, force_chunk: bool) -> Result<(), Error> {
|
||||
let pair = {
|
||||
let mut stream = RlpStream::new_list(2);
|
||||
stream.append(&account_hash).append_raw(&data, 1);
|
||||
stream.out()
|
||||
};
|
||||
|
||||
if self.cur_size + pair.len() >= PREFERRED_CHUNK_SIZE {
|
||||
if force_chunk || self.cur_size + pair.len() >= PREFERRED_CHUNK_SIZE {
|
||||
self.write_chunk()?;
|
||||
}
|
||||
|
||||
@@ -372,8 +377,10 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex<SnapshotWriter +
|
||||
|
||||
let account_db = AccountDB::from_hash(db, account_key_hash);
|
||||
|
||||
let fat_rlp = account::to_fat_rlp(&account, &account_db, &mut used_code)?;
|
||||
chunker.push(account_key, fat_rlp)?;
|
||||
let fat_rlps = account::to_fat_rlps(&account, &account_db, &mut used_code, MAX_STORAGE_ENTRIES_PER_ACCOUNT_RECORD)?;
|
||||
for (i, fat_rlp) in fat_rlps.into_iter().enumerate() {
|
||||
chunker.push(account_key.clone(), fat_rlp, i > 0)?;
|
||||
}
|
||||
}
|
||||
|
||||
if chunker.cur_size != 0 {
|
||||
@@ -390,6 +397,7 @@ pub struct StateRebuilder {
|
||||
known_code: HashMap<H256, H256>, // code hashes mapped to first account with this code.
|
||||
missing_code: HashMap<H256, Vec<H256>>, // maps code hashes to lists of accounts missing that code.
|
||||
bloom: Bloom,
|
||||
known_storage_roots: HashMap<H256, H256>, // maps account hashes to last known storage root. Only filled for last account per chunk.
|
||||
}
|
||||
|
||||
impl StateRebuilder {
|
||||
@@ -401,6 +409,7 @@ impl StateRebuilder {
|
||||
known_code: HashMap::new(),
|
||||
missing_code: HashMap::new(),
|
||||
bloom: StateDB::load_bloom(&*db),
|
||||
known_storage_roots: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,6 +427,7 @@ impl StateRebuilder {
|
||||
rlp,
|
||||
&mut pairs,
|
||||
&self.known_code,
|
||||
&mut self.known_storage_roots,
|
||||
flag
|
||||
)?;
|
||||
|
||||
@@ -464,14 +474,18 @@ impl StateRebuilder {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for accounts missing code. Once all chunks have been fed, there should
|
||||
/// be none.
|
||||
pub fn check_missing(self) -> Result<(), Error> {
|
||||
/// Finalize the restoration. Check for accounts missing code and make a dummy
|
||||
/// journal entry.
|
||||
/// Once all chunks have been fed, there should be nothing missing.
|
||||
pub fn finalize(mut self, era: u64, id: H256) -> Result<(), ::error::Error> {
|
||||
let missing = self.missing_code.keys().cloned().collect::<Vec<_>>();
|
||||
match missing.is_empty() {
|
||||
true => Ok(()),
|
||||
false => Err(Error::MissingCode(missing)),
|
||||
}
|
||||
if !missing.is_empty() { return Err(Error::MissingCode(missing).into()) }
|
||||
|
||||
let mut batch = self.db.backing().transaction();
|
||||
self.db.journal_under(&mut batch, era, &id)?;
|
||||
self.db.backing().write_buffered(batch);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get the state root of the rebuilder.
|
||||
@@ -492,10 +506,11 @@ fn rebuild_accounts(
|
||||
account_fat_rlps: UntrustedRlp,
|
||||
out_chunk: &mut [(H256, Bytes)],
|
||||
known_code: &HashMap<H256, H256>,
|
||||
known_storage_roots: &mut HashMap<H256, H256>,
|
||||
abort_flag: &AtomicBool,
|
||||
) -> Result<RebuiltStatus, ::error::Error> {
|
||||
let mut status = RebuiltStatus::default();
|
||||
for (account_rlp, out) in account_fat_rlps.into_iter().zip(out_chunk) {
|
||||
for (account_rlp, out) in account_fat_rlps.into_iter().zip(out_chunk.iter_mut()) {
|
||||
if !abort_flag.load(Ordering::SeqCst) { return Err(Error::RestorationAborted.into()) }
|
||||
|
||||
let hash: H256 = account_rlp.val_at(0)?;
|
||||
@@ -506,7 +521,8 @@ fn rebuild_accounts(
|
||||
// fill out the storage trie and code while decoding.
|
||||
let (acc, maybe_code) = {
|
||||
let mut acct_db = AccountDBMut::from_hash(db, hash);
|
||||
account::from_fat_rlp(&mut acct_db, fat_rlp)?
|
||||
let storage_root = known_storage_roots.get(&hash).cloned().unwrap_or(H256::zero());
|
||||
account::from_fat_rlp(&mut acct_db, fat_rlp, storage_root)?
|
||||
};
|
||||
|
||||
let code_hash = acc.code_hash.clone();
|
||||
@@ -538,6 +554,12 @@ fn rebuild_accounts(
|
||||
|
||||
*out = (hash, thin_rlp);
|
||||
}
|
||||
if let Some(&(ref hash, ref rlp)) = out_chunk.iter().last() {
|
||||
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp).storage_root);
|
||||
}
|
||||
if let Some(&(ref hash, ref rlp)) = out_chunk.iter().next() {
|
||||
known_storage_roots.insert(*hash, ::rlp::decode::<BasicAccount>(rlp).storage_root);
|
||||
}
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ impl Restoration {
|
||||
}
|
||||
|
||||
// check for missing code.
|
||||
self.state.check_missing()?;
|
||||
self.state.finalize(self.manifest.block_number, self.manifest.block_hash)?;
|
||||
|
||||
// connect out-of-order chunks and verify chain integrity.
|
||||
self.blocks.finalize(self.canonical_hashes)?;
|
||||
@@ -656,6 +656,7 @@ mod tests {
|
||||
assert_eq!(service.status(), RestorationStatus::Inactive);
|
||||
|
||||
let manifest = ManifestData {
|
||||
version: 2,
|
||||
state_hashes: vec![],
|
||||
block_hashes: vec![],
|
||||
state_root: Default::default(),
|
||||
|
||||
@@ -63,6 +63,7 @@ fn chunk_and_restore(amount: u64) {
|
||||
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
|
||||
let block_hashes = chunk_blocks(&bc, best_hash, &writer, &Progress::default()).unwrap();
|
||||
let manifest = ::snapshot::ManifestData {
|
||||
version: 2,
|
||||
state_hashes: Vec::new(),
|
||||
block_hashes: block_hashes,
|
||||
state_root: ::util::sha3::SHA3_NULL_RLP,
|
||||
@@ -125,6 +126,7 @@ fn checks_flag() {
|
||||
let chain = BlockChain::new(Default::default(), &genesis, db.clone());
|
||||
|
||||
let manifest = ::snapshot::ManifestData {
|
||||
version: 2,
|
||||
state_hashes: Vec::new(),
|
||||
block_hashes: Vec::new(),
|
||||
state_root: ::util::sha3::SHA3_NULL_RLP,
|
||||
|
||||
@@ -27,6 +27,7 @@ use super::ManifestData;
|
||||
#[test]
|
||||
fn manifest_rlp() {
|
||||
let manifest = ManifestData {
|
||||
version: 2,
|
||||
block_hashes: Vec::new(),
|
||||
state_hashes: Vec::new(),
|
||||
block_number: 1234567,
|
||||
@@ -35,4 +36,4 @@ fn manifest_rlp() {
|
||||
};
|
||||
let raw = manifest.clone().into_rlp();
|
||||
assert_eq!(ManifestData::from_rlp(&raw).unwrap(), manifest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,7 @@ fn guards_delete_folders() {
|
||||
path.push("restoration");
|
||||
|
||||
let manifest = ManifestData {
|
||||
version: 2,
|
||||
state_hashes: vec![],
|
||||
block_hashes: vec![],
|
||||
block_number: 0,
|
||||
|
||||
@@ -58,10 +58,11 @@ fn snap_and_restore() {
|
||||
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
||||
|
||||
writer.into_inner().finish(::snapshot::ManifestData {
|
||||
version: 2,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: Vec::new(),
|
||||
state_root: state_root,
|
||||
block_number: 0,
|
||||
block_number: 1000,
|
||||
block_hash: H256::default(),
|
||||
}).unwrap();
|
||||
|
||||
@@ -69,7 +70,7 @@ fn snap_and_restore() {
|
||||
db_path.push("db");
|
||||
let db = {
|
||||
let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap());
|
||||
let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive);
|
||||
let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent);
|
||||
let reader = PackedReader::new(&snap_file).unwrap().unwrap();
|
||||
|
||||
let flag = AtomicBool::new(true);
|
||||
@@ -82,12 +83,13 @@ fn snap_and_restore() {
|
||||
}
|
||||
|
||||
assert_eq!(rebuilder.state_root(), state_root);
|
||||
rebuilder.check_missing().unwrap();
|
||||
rebuilder.finalize(1000, H256::default()).unwrap();
|
||||
|
||||
new_db
|
||||
};
|
||||
|
||||
let new_db = journaldb::new(db, Algorithm::Archive, ::db::COL_STATE);
|
||||
let new_db = journaldb::new(db, Algorithm::OverlayRecent, ::db::COL_STATE);
|
||||
assert_eq!(new_db.earliest_era(), Some(1000));
|
||||
|
||||
compare_dbs(&old_db, new_db.as_hashdb());
|
||||
}
|
||||
@@ -120,10 +122,10 @@ fn get_code_from_prev_chunk() {
|
||||
let mut db = MemoryDB::new();
|
||||
AccountDBMut::from_hash(&mut db, hash).insert(&code[..]);
|
||||
|
||||
let fat_rlp = account::to_fat_rlp(&acc, &AccountDB::from_hash(&db, hash), &mut used_code).unwrap();
|
||||
let fat_rlp = account::to_fat_rlps(&acc, &AccountDB::from_hash(&db, hash), &mut used_code, usize::max_value()).unwrap();
|
||||
|
||||
let mut stream = RlpStream::new_list(1);
|
||||
stream.begin_list(2).append(&hash).append_raw(&fat_rlp, 1);
|
||||
stream.begin_list(2).append(&hash).append_raw(&fat_rlp[0], 1);
|
||||
stream.out()
|
||||
};
|
||||
|
||||
@@ -134,13 +136,18 @@ fn get_code_from_prev_chunk() {
|
||||
let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
|
||||
let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap());
|
||||
|
||||
let mut rebuilder = StateRebuilder::new(new_db, Algorithm::Archive);
|
||||
let flag = AtomicBool::new(true);
|
||||
{
|
||||
let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent);
|
||||
let flag = AtomicBool::new(true);
|
||||
|
||||
rebuilder.feed(&chunk1, &flag).unwrap();
|
||||
rebuilder.feed(&chunk2, &flag).unwrap();
|
||||
rebuilder.feed(&chunk1, &flag).unwrap();
|
||||
rebuilder.feed(&chunk2, &flag).unwrap();
|
||||
|
||||
rebuilder.check_missing().unwrap();
|
||||
rebuilder.finalize(1000, H256::random()).unwrap();
|
||||
}
|
||||
|
||||
let state_db = journaldb::new(new_db, Algorithm::OverlayRecent, ::db::COL_STATE);
|
||||
assert_eq!(state_db.earliest_era(), Some(1000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -164,6 +171,7 @@ fn checks_flag() {
|
||||
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
||||
|
||||
writer.into_inner().finish(::snapshot::ManifestData {
|
||||
version: 2,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: Vec::new(),
|
||||
state_root: state_root,
|
||||
@@ -175,7 +183,7 @@ fn checks_flag() {
|
||||
db_path.push("db");
|
||||
{
|
||||
let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap());
|
||||
let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::Archive);
|
||||
let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent);
|
||||
let reader = PackedReader::new(&snap_file).unwrap().unwrap();
|
||||
|
||||
let flag = AtomicBool::new(false);
|
||||
|
||||
@@ -55,6 +55,8 @@ pub struct CommonParams {
|
||||
pub fork_block: Option<(BlockNumber, H256)>,
|
||||
/// Number of first block where EIP-98 rules begin.
|
||||
pub eip98_transition: BlockNumber,
|
||||
/// Validate block receipts root.
|
||||
pub validate_receipts: bool,
|
||||
}
|
||||
|
||||
impl From<ethjson::spec::Params> for CommonParams {
|
||||
@@ -68,6 +70,7 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
min_gas_limit: p.min_gas_limit.into(),
|
||||
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
|
||||
eip98_transition: p.eip98_transition.map_or(0, Into::into),
|
||||
validate_receipts: p.validate_receipts.unwrap_or(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,6 +360,10 @@ impl Spec {
|
||||
/// Account is marked with `reportBenign` it can be checked as disliked with "0xd8f2e0bf".
|
||||
/// Validator can be removed with `reportMalicious`.
|
||||
pub fn new_validator_contract() -> Self { load_bundled!("validator_contract") }
|
||||
|
||||
/// Create a new Spec with BasicAuthority which uses multiple validator sets changing with height.
|
||||
/// Account with secrets "0".sha3() is the validator for block 1 and with "1".sha3() onwards.
|
||||
pub fn new_validator_multi() -> Self { load_bundled!("validator_multi") }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -24,6 +24,8 @@ use util::Bytes;
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "ipc", binary)]
|
||||
pub struct ManifestData {
|
||||
/// Snapshot format version.
|
||||
pub version: u64,
|
||||
/// List of state chunk hashes.
|
||||
pub state_hashes: Vec<H256>,
|
||||
/// List of block chunk hashes.
|
||||
@@ -39,7 +41,8 @@ pub struct ManifestData {
|
||||
impl ManifestData {
|
||||
/// Encode the manifest data to rlp.
|
||||
pub fn into_rlp(self) -> Bytes {
|
||||
let mut stream = RlpStream::new_list(5);
|
||||
let mut stream = RlpStream::new_list(6);
|
||||
stream.append(&self.version);
|
||||
stream.append(&self.state_hashes);
|
||||
stream.append(&self.block_hashes);
|
||||
stream.append(&self.state_root);
|
||||
@@ -52,14 +55,20 @@ impl ManifestData {
|
||||
/// Try to restore manifest data from raw bytes, interpreted as RLP.
|
||||
pub fn from_rlp(raw: &[u8]) -> Result<Self, DecoderError> {
|
||||
let decoder = UntrustedRlp::new(raw);
|
||||
let (start, version) = if decoder.item_count() == 5 {
|
||||
(0, 1)
|
||||
} else {
|
||||
(1, decoder.val_at(0)?)
|
||||
};
|
||||
|
||||
let state_hashes: Vec<H256> = decoder.val_at(0)?;
|
||||
let block_hashes: Vec<H256> = decoder.val_at(1)?;
|
||||
let state_root: H256 = decoder.val_at(2)?;
|
||||
let block_number: u64 = decoder.val_at(3)?;
|
||||
let block_hash: H256 = decoder.val_at(4)?;
|
||||
let state_hashes: Vec<H256> = decoder.val_at(start + 0)?;
|
||||
let block_hashes: Vec<H256> = decoder.val_at(start + 1)?;
|
||||
let state_root: H256 = decoder.val_at(start + 2)?;
|
||||
let block_number: u64 = decoder.val_at(start + 3)?;
|
||||
let block_hash: H256 = decoder.val_at(start + 4)?;
|
||||
|
||||
Ok(ManifestData {
|
||||
version: version,
|
||||
state_hashes: state_hashes,
|
||||
block_hashes: block_hashes,
|
||||
state_root: state_root,
|
||||
|
||||
@@ -31,7 +31,7 @@ impl Verifier for CanonVerifier {
|
||||
verification::verify_block_family(header, bytes, engine, bc)
|
||||
}
|
||||
|
||||
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> {
|
||||
verification::verify_block_final(expected, got)
|
||||
fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error> {
|
||||
verification::verify_block_final(expected, got, receipts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ impl Verifier for NoopVerifier {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> {
|
||||
fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
|
||||
}
|
||||
|
||||
/// Phase 4 verification. Check block information against transaction enactment results,
|
||||
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
|
||||
pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool) -> Result<(), Error> {
|
||||
if expected.gas_used() != got.gas_used() {
|
||||
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() })))
|
||||
}
|
||||
@@ -188,7 +188,7 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>
|
||||
if expected.state_root() != got.state_root() {
|
||||
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
|
||||
}
|
||||
if expected.receipts_root() != got.receipts_root() {
|
||||
if check_receipts && expected.receipts_root() != got.receipts_root() {
|
||||
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -26,5 +26,5 @@ pub trait Verifier: Send + Sync {
|
||||
/// Verify a block relative to its parent and uncles.
|
||||
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
|
||||
/// Do a final verification check for an enacted header vs its expected counterpart.
|
||||
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
|
||||
fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[lib]
|
||||
name = "evm"
|
||||
name = "evmbin"
|
||||
path = "./src/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "evm"
|
||||
name = "parity-evm"
|
||||
path = "./src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -271,7 +271,7 @@ impl Manager {
|
||||
chunk_size += size;
|
||||
}
|
||||
trace!("writing {:?}", &hid_chunk[..]);
|
||||
let n = handle.write(&hid_chunk[0..chunk_size])?;
|
||||
let n = handle.write(&hid_chunk[..])?;
|
||||
if n < chunk_size {
|
||||
return Err(Error::Protocol("Write data size mismatch"));
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
ethcore-ipc = { path = "../rpc" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git", branch = "parity-1.7" }
|
||||
ethcore-ipc-nano = { path = "../nano" }
|
||||
semver = "0.5"
|
||||
log = "0.3"
|
||||
|
||||
@@ -8,6 +8,6 @@ license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
ethcore-ipc = { path = "../rpc" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git", branch = "parity-1.7" }
|
||||
log = "0.3"
|
||||
lazy_static = "0.2"
|
||||
|
||||
@@ -8,6 +8,6 @@ license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
ethcore-devtools = { path = "../../devtools" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git", branch = "parity-1.7" }
|
||||
ethcore-util = { path = "../../util" }
|
||||
semver = "0.5"
|
||||
|
||||
@@ -11,7 +11,7 @@ path = "run.rs"
|
||||
ethcore-ipc = { path = "../rpc" }
|
||||
ethcore-devtools = { path = "../../devtools" }
|
||||
semver = "0.5"
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git" }
|
||||
nanomsg = { git = "https://github.com/ethcore/nanomsg.rs.git", branch = "parity-1.7" }
|
||||
ethcore-ipc-nano = { path = "../nano" }
|
||||
ethcore-util = { path = "../../util" }
|
||||
log = "0.3"
|
||||
|
||||
@@ -120,20 +120,22 @@ export default class HardwareStore {
|
||||
});
|
||||
}
|
||||
|
||||
createAccountInfo (entry) {
|
||||
createAccountInfo (entry, original = {}) {
|
||||
const { address, manufacturer, name } = entry;
|
||||
|
||||
return Promise
|
||||
.all([
|
||||
this._api.parity.setAccountName(address, name),
|
||||
this._api.parity.setAccountMeta(address, {
|
||||
original.name
|
||||
? Promise.resolve(true)
|
||||
: this._api.parity.setAccountName(address, name),
|
||||
this._api.parity.setAccountMeta(address, Object.assign({
|
||||
description: `${manufacturer} ${name}`,
|
||||
hardware: {
|
||||
manufacturer
|
||||
},
|
||||
tags: ['hardware'],
|
||||
timestamp: Date.now()
|
||||
})
|
||||
}, original.meta || {}))
|
||||
])
|
||||
.catch((error) => {
|
||||
console.warn('HardwareStore::createEntry', error);
|
||||
|
||||
@@ -130,25 +130,58 @@ describe('mobx/HardwareStore', () => {
|
||||
|
||||
describe('operations', () => {
|
||||
describe('createAccountInfo', () => {
|
||||
beforeEach(() => {
|
||||
return store.createAccountInfo({
|
||||
address: 'testAddr',
|
||||
manufacturer: 'testMfg',
|
||||
name: 'testName'
|
||||
describe('when not existing', () => {
|
||||
beforeEach(() => {
|
||||
return store.createAccountInfo({
|
||||
address: 'testAddr',
|
||||
manufacturer: 'testMfg',
|
||||
name: 'testName'
|
||||
});
|
||||
});
|
||||
|
||||
it('calls into parity_setAccountName', () => {
|
||||
expect(api.parity.setAccountName).to.have.been.calledWith('testAddr', 'testName');
|
||||
});
|
||||
|
||||
it('calls into parity_setAccountMeta', () => {
|
||||
expect(api.parity.setAccountMeta).to.have.been.calledWith('testAddr', sinon.match({
|
||||
description: 'testMfg testName',
|
||||
hardware: {
|
||||
manufacturer: 'testMfg'
|
||||
},
|
||||
tags: ['hardware']
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it('calls into parity_setAccountName', () => {
|
||||
expect(api.parity.setAccountName).to.have.been.calledWith('testAddr', 'testName');
|
||||
});
|
||||
describe('when already exists', () => {
|
||||
beforeEach(() => {
|
||||
return store.createAccountInfo({
|
||||
address: 'testAddr',
|
||||
manufacturer: 'testMfg',
|
||||
name: 'testName'
|
||||
}, {
|
||||
name: 'originalName',
|
||||
meta: {
|
||||
description: 'originalDescription',
|
||||
tags: ['tagA', 'tagB']
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('calls into parity_setAccountMeta', () => {
|
||||
expect(api.parity.setAccountMeta).to.have.been.calledWith('testAddr', sinon.match({
|
||||
description: 'testMfg testName',
|
||||
hardware: {
|
||||
manufacturer: 'testMfg'
|
||||
}
|
||||
}));
|
||||
it('does not call into parity_setAccountName', () => {
|
||||
expect(api.parity.setAccountName).not.to.have.been.called;
|
||||
});
|
||||
|
||||
it('calls into parity_setAccountMeta', () => {
|
||||
expect(api.parity.setAccountMeta).to.have.been.calledWith('testAddr', sinon.match({
|
||||
description: 'originalDescription',
|
||||
hardware: {
|
||||
manufacturer: 'testMfg'
|
||||
},
|
||||
tags: ['tagA', 'tagB']
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ export default class FirstRun extends Component {
|
||||
defaultMessage='As part of a new installation, the next few steps will guide you through the process of setting up you Parity instance and your associated accounts. Our aim is to make it as simple as possible and to get you up and running in record-time, so please bear with us. Once completed you will have -'
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
<FormattedMessage
|
||||
@@ -70,7 +70,7 @@ export default class FirstRun extends Component {
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id='firstRun.welcome.next'
|
||||
|
||||
@@ -77,7 +77,8 @@
|
||||
}
|
||||
|
||||
.form {
|
||||
box-sizing: border-box;
|
||||
margin-top: 0;
|
||||
padding: 0.75rem 1.5rem 1.5rem 1.5rem;
|
||||
padding: 0.75rem 1.5rem 1.5rem;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
@@ -92,6 +92,26 @@ export default class SecureApi extends Api {
|
||||
return this._transport.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the current API with the given values
|
||||
* (`signerPort`, `dappsInterface`, `dappsPort`, ...)
|
||||
*/
|
||||
configure (configuration) {
|
||||
const { dappsInterface, dappsPort, signerPort } = configuration;
|
||||
|
||||
if (dappsInterface) {
|
||||
this._dappsInterface = dappsInterface;
|
||||
}
|
||||
|
||||
if (dappsPort) {
|
||||
this._dappsPort = dappsPort;
|
||||
}
|
||||
|
||||
if (signerPort) {
|
||||
this._signerPort = signerPort;
|
||||
}
|
||||
}
|
||||
|
||||
connect () {
|
||||
if (this._isConnecting) {
|
||||
return;
|
||||
|
||||
@@ -24,6 +24,7 @@ $transitionAll: all 0.75s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
padding: 0em;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
/*transform: translateZ(0);
|
||||
transition: $transitionAll;*/
|
||||
|
||||
@@ -51,7 +51,7 @@ $popoverZ: 3600;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0.25;
|
||||
z-index: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
@@ -68,12 +68,13 @@ $popoverZ: 3600;
|
||||
}
|
||||
|
||||
&.modal {
|
||||
z-index: $modalZ;
|
||||
|
||||
&:not(.small) {
|
||||
bottom: $modalBottom;
|
||||
left: $modalLeft;
|
||||
right: $modalRight;
|
||||
top: $modalTop;
|
||||
z-index: $modalZ;
|
||||
}
|
||||
|
||||
/* TODO: Small Portals don't adjust their overall height like we have with the
|
||||
|
||||
@@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ReactPortal from 'react-portal';
|
||||
import keycode from 'keycode';
|
||||
import { noop } from 'lodash';
|
||||
|
||||
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||
import { CloseIcon } from '~/ui/Icons';
|
||||
@@ -29,7 +30,6 @@ import styles from './portal.css';
|
||||
|
||||
export default class Portal extends Component {
|
||||
static propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
open: PropTypes.bool.isRequired,
|
||||
activeStep: PropTypes.number,
|
||||
busy: PropTypes.bool,
|
||||
@@ -45,11 +45,16 @@ export default class Portal extends Component {
|
||||
isChildModal: PropTypes.bool,
|
||||
isSmallModal: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
steps: PropTypes.array,
|
||||
title: nodeOrStringProptype()
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onClose: noop
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
this.setBodyOverflow(this.props.open);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
$transition: all 0.25s;
|
||||
$widthNormal: 33.33%;
|
||||
$widthExpanded: 42%;
|
||||
$widthContracted: 29%;
|
||||
|
||||
.section {
|
||||
position: relative;
|
||||
@@ -44,6 +45,8 @@ $widthExpanded: 42%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 0 1 $widthNormal;
|
||||
max-width: $widthNormal;
|
||||
min-width: $widthContracted;
|
||||
opacity: 0.85;
|
||||
padding: 0.25em;
|
||||
|
||||
|
||||
@@ -394,8 +394,12 @@ class Accounts extends Component {
|
||||
|
||||
Object
|
||||
.keys(wallets)
|
||||
.filter((address) => !accountsInfo[address])
|
||||
.forEach((address) => this.hwstore.createAccountInfo(wallets[address]));
|
||||
.filter((address) => {
|
||||
const account = accountsInfo[address];
|
||||
|
||||
return !account || !account.meta || !account.meta.hardware;
|
||||
})
|
||||
.forEach((address) => this.hwstore.createAccountInfo(wallets[address], accountsInfo[address]));
|
||||
|
||||
this.setVisibleAccounts();
|
||||
}
|
||||
|
||||
122
js/src/views/Accounts/accounts.spec.js
Normal file
122
js/src/views/Accounts/accounts.spec.js
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright 2015-2017 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import Accounts from './';
|
||||
|
||||
let api;
|
||||
let component;
|
||||
let hwstore;
|
||||
let instance;
|
||||
let redux;
|
||||
|
||||
function createApi () {
|
||||
api = {};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
function createHwStore (walletAddress = '0x456') {
|
||||
hwstore = {
|
||||
wallets: {
|
||||
[walletAddress]: {
|
||||
address: walletAddress
|
||||
}
|
||||
},
|
||||
createAccountInfo: sinon.stub()
|
||||
};
|
||||
|
||||
return hwstore;
|
||||
}
|
||||
|
||||
function createRedux () {
|
||||
redux = {
|
||||
dispatch: sinon.stub(),
|
||||
subscribe: sinon.stub(),
|
||||
getState: () => {
|
||||
return {
|
||||
personal: {
|
||||
accounts: {},
|
||||
accountsInfo: {
|
||||
'0x123': { meta: '1' },
|
||||
'0x999': { meta: { hardware: {} } }
|
||||
}
|
||||
},
|
||||
balances: {
|
||||
balances: {}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return redux;
|
||||
}
|
||||
|
||||
function render (props = {}) {
|
||||
component = shallow(
|
||||
<Accounts { ...props } />,
|
||||
{
|
||||
context: {
|
||||
store: createRedux()
|
||||
}
|
||||
}
|
||||
).find('Accounts').shallow({
|
||||
context: {
|
||||
api: createApi()
|
||||
}
|
||||
});
|
||||
instance = component.instance();
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
describe('views/Accounts', () => {
|
||||
beforeEach(() => {
|
||||
render();
|
||||
});
|
||||
|
||||
it('renders defaults', () => {
|
||||
expect(component).to.be.ok;
|
||||
});
|
||||
|
||||
describe('instance event methods', () => {
|
||||
describe('onHardwareChange', () => {
|
||||
it('detects completely new entries', () => {
|
||||
instance.hwstore = createHwStore();
|
||||
instance.onHardwareChange();
|
||||
|
||||
expect(hwstore.createAccountInfo).to.have.been.calledWith({ address: '0x456' });
|
||||
});
|
||||
|
||||
it('detects addressbook entries', () => {
|
||||
instance.hwstore = createHwStore('0x123');
|
||||
instance.onHardwareChange();
|
||||
|
||||
expect(hwstore.createAccountInfo).to.have.been.calledWith({ address: '0x123' }, { meta: '1' });
|
||||
});
|
||||
|
||||
it('ignores existing hardware entries', () => {
|
||||
instance.hwstore = createHwStore('0x999');
|
||||
instance.onHardwareChange();
|
||||
|
||||
expect(hwstore.createAccountInfo).not.to.have.been.called;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -17,12 +17,20 @@
|
||||
import { action, observable } from 'mobx';
|
||||
import store from 'store';
|
||||
|
||||
const OLD_LS_FIRST_RUN_KEY = 'showFirstRun';
|
||||
const LS_FIRST_RUN_KEY = '_parity::showFirstRun';
|
||||
|
||||
export default class Store {
|
||||
@observable firstrunVisible = false;
|
||||
|
||||
constructor (api) {
|
||||
// Migrate the old key to the new one
|
||||
this._migrateStore();
|
||||
|
||||
this._api = api;
|
||||
this.firstrunVisible = store.get('showFirstRun');
|
||||
// Show the first run if it hasn't been shown before
|
||||
// (thus an undefined value)
|
||||
this.firstrunVisible = store.get(LS_FIRST_RUN_KEY) === undefined;
|
||||
|
||||
this._checkAccounts();
|
||||
}
|
||||
@@ -33,16 +41,41 @@ export default class Store {
|
||||
|
||||
@action toggleFirstrun = (visible = false) => {
|
||||
this.firstrunVisible = visible;
|
||||
store.set('showFirstRun', !!visible);
|
||||
|
||||
// There's no need to write to storage that the
|
||||
// First Run should be visible
|
||||
if (!visible) {
|
||||
store.set(LS_FIRST_RUN_KEY, !!visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate the old LocalStorage ket format
|
||||
* to the new one
|
||||
*/
|
||||
_migrateStore () {
|
||||
const oldValue = store.get(OLD_LS_FIRST_RUN_KEY);
|
||||
const newValue = store.get(LS_FIRST_RUN_KEY);
|
||||
|
||||
if (newValue === undefined && oldValue !== undefined) {
|
||||
store.set(LS_FIRST_RUN_KEY, oldValue);
|
||||
store.remove(OLD_LS_FIRST_RUN_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
_checkAccounts () {
|
||||
this._api.parity
|
||||
.allAccountsInfo()
|
||||
.then((info) => {
|
||||
return Promise
|
||||
.all([
|
||||
this._api.parity.listVaults(),
|
||||
this._api.parity.allAccountsInfo()
|
||||
])
|
||||
.then(([ vaults, info ]) => {
|
||||
const accounts = Object.keys(info).filter((address) => info[address].uuid);
|
||||
// Has accounts if any vaults or accounts
|
||||
const hasAccounts = (accounts && accounts.length > 0) || (vaults && vaults.length > 0);
|
||||
|
||||
this.toggleFirstrun(this.firstrunVisible || !accounts || !accounts.length);
|
||||
// Show First Run if no accounts and no vaults
|
||||
this.toggleFirstrun(this.firstrunVisible || !hasAccounts);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('checkAccounts', error);
|
||||
|
||||
@@ -27,7 +27,7 @@ import styles from './transactionPendingFormConfirm.css';
|
||||
|
||||
export default class TransactionPendingFormConfirm extends Component {
|
||||
static propTypes = {
|
||||
account: PropTypes.object.isRequired,
|
||||
account: PropTypes.object,
|
||||
address: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
isSending: PropTypes.bool.isRequired,
|
||||
@@ -36,6 +36,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
account: {},
|
||||
focus: false
|
||||
};
|
||||
|
||||
@@ -80,7 +81,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
||||
|
||||
getPasswordHint () {
|
||||
const { account } = this.props;
|
||||
const accountHint = account && account.meta && account.meta.passwordHint;
|
||||
const accountHint = account.meta && account.meta.passwordHint;
|
||||
|
||||
if (accountHint) {
|
||||
return accountHint;
|
||||
@@ -149,14 +150,16 @@ export default class TransactionPendingFormConfirm extends Component {
|
||||
const { account } = this.props;
|
||||
const { password } = this.state;
|
||||
|
||||
if (account && account.hardware) {
|
||||
if (account.hardware) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isAccount = account.uuid;
|
||||
|
||||
return (
|
||||
<Input
|
||||
hint={
|
||||
account.uuid
|
||||
isAccount
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='signer.txPendingConfirm.password.unlock.hint'
|
||||
@@ -171,7 +174,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
||||
)
|
||||
}
|
||||
label={
|
||||
account.uuid
|
||||
isAccount
|
||||
? (
|
||||
<FormattedMessage
|
||||
id='signer.txPendingConfirm.password.unlock.label'
|
||||
|
||||
@@ -48,7 +48,7 @@ function render (address) {
|
||||
|
||||
component = shallow(
|
||||
<TransactionPendingFormConfirm
|
||||
account={ ACCOUNTS[address] || {} }
|
||||
account={ ACCOUNTS[address] }
|
||||
address={ address }
|
||||
onConfirm={ onConfirm }
|
||||
isSending={ false }
|
||||
@@ -130,5 +130,9 @@ describe('views/Signer/TransactionPendingFormConfirm', () => {
|
||||
it('renders the password', () => {
|
||||
expect(instance.renderPassword()).not.to.be.null;
|
||||
});
|
||||
|
||||
it('renders the hint', () => {
|
||||
expect(instance.renderHint()).to.be.null;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,6 +53,9 @@ pub struct Params {
|
||||
/// See `CommonParams` docs.
|
||||
#[serde(rename="eip98Transition")]
|
||||
pub eip98_transition: Option<Uint>,
|
||||
/// See `CommonParams` docs.
|
||||
#[serde(rename="validateReceipts")]
|
||||
pub validate_receipts: Option<bool>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
//! Validator set deserialization.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use uint::Uint;
|
||||
use hash::Address;
|
||||
|
||||
/// Different ways of specifying validators.
|
||||
@@ -30,6 +32,9 @@ pub enum ValidatorSet {
|
||||
/// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions.
|
||||
#[serde(rename="contract")]
|
||||
Contract(Address),
|
||||
/// A map of starting blocks for each validator set.
|
||||
#[serde(rename="multi")]
|
||||
Multi(BTreeMap<Uint, ValidatorSet>),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -40,11 +45,17 @@ mod tests {
|
||||
#[test]
|
||||
fn validator_set_deserialization() {
|
||||
let s = r#"[{
|
||||
"list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
|
||||
"list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
|
||||
}, {
|
||||
"safeContract" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
"safeContract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
}, {
|
||||
"contract" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
"contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
}, {
|
||||
"multi": {
|
||||
"0": { "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] },
|
||||
"10": { "list": ["0xd6d9d2cd449a754c494264e1809c50e34d64562b"] },
|
||||
"20": { "contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" }
|
||||
}
|
||||
}]"#;
|
||||
|
||||
let _deserialized: Vec<ValidatorSet> = serde_json::from_str(s).unwrap();
|
||||
|
||||
@@ -462,7 +462,7 @@
|
||||
<key>OVERWRITE_PERMISSIONS</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.6.2</string>
|
||||
<string>1.6.5</string>
|
||||
</dict>
|
||||
<key>UUID</key>
|
||||
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.6</string>
|
||||
<string>1.6.5</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
||||
!define VERSIONMAJOR 1
|
||||
!define VERSIONMINOR 6
|
||||
!define VERSIONBUILD 2
|
||||
!define VERSIONBUILD 5
|
||||
!define ARGS "--warp"
|
||||
!define FIRST_START_ARGS "ui --warp --mode=passive"
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#!/bin/bash
|
||||
cd docker/hub
|
||||
docker build --build-arg BUILD_TAG=$1 --no-cache=true --tag ethcore/parity:$1 .
|
||||
if [ "$1" == "latest" ]; then DOCKER_BUILD_TAG="beta-release"; fi
|
||||
docker build --build-arg BUILD_TAG=$DOCKER_BUILD_TAG --no-cache=true --tag ethcore/parity:$1 .
|
||||
docker push ethcore/parity:$1
|
||||
|
||||
|
||||
@@ -158,6 +158,8 @@ pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x16;
|
||||
|
||||
const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3;
|
||||
|
||||
const MIN_SUPPORTED_SNAPSHOT_MANIFEST_VERSION: u64 = 1;
|
||||
|
||||
const WAIT_PEERS_TIMEOUT_SEC: u64 = 5;
|
||||
const STATUS_TIMEOUT_SEC: u64 = 5;
|
||||
const HEADERS_TIMEOUT_SEC: u64 = 15;
|
||||
@@ -1023,12 +1025,18 @@ impl ChainSync {
|
||||
let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) {
|
||||
Err(e) => {
|
||||
trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e);
|
||||
io.disconnect_peer(peer_id);
|
||||
io.disable_peer(peer_id);
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
Ok(manifest) => manifest,
|
||||
};
|
||||
if manifest.version < MIN_SUPPORTED_SNAPSHOT_MANIFEST_VERSION {
|
||||
trace!(target: "sync", "{}: Snapshot manifest version too low: {}", peer_id, manifest.version);
|
||||
io.disable_peer(peer_id);
|
||||
self.continue_sync(io);
|
||||
return Ok(());
|
||||
}
|
||||
self.snapshot.reset_to(&manifest, &manifest_rlp.as_raw().sha3());
|
||||
io.snapshot_service().begin_restore(manifest);
|
||||
self.state = SyncState::SnapshotData;
|
||||
|
||||
@@ -139,6 +139,7 @@ mod test {
|
||||
let state_chunks: Vec<Bytes> = (0..20).map(|_| H256::random().to_vec()).collect();
|
||||
let block_chunks: Vec<Bytes> = (0..20).map(|_| H256::random().to_vec()).collect();
|
||||
let manifest = ManifestData {
|
||||
version: 2,
|
||||
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
||||
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
||||
state_root: H256::new(),
|
||||
|
||||
@@ -49,6 +49,7 @@ impl TestSnapshotService {
|
||||
let state_chunks: Vec<Bytes> = (0..num_state_chunks).map(|_| H256::random().to_vec()).collect();
|
||||
let block_chunks: Vec<Bytes> = (0..num_block_chunks).map(|_| H256::random().to_vec()).collect();
|
||||
let manifest = ManifestData {
|
||||
version: 2,
|
||||
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
||||
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
||||
state_root: H256::new(),
|
||||
|
||||
@@ -247,7 +247,7 @@ impl Updater {
|
||||
if let Some(ops_addr) = self.client.upgrade().and_then(|c| c.registry_address("operations".into())) {
|
||||
trace!(target: "updater", "Found operations at {}", ops_addr);
|
||||
let client = self.client.clone();
|
||||
*self.operations.lock() = Some(Operations::new(ops_addr, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(a, d))));
|
||||
*self.operations.lock() = Some(Operations::new(ops_addr, move |a, d| client.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(BlockId::Latest, a, d))));
|
||||
} else {
|
||||
// No Operations contract - bail.
|
||||
return;
|
||||
@@ -274,7 +274,7 @@ impl Updater {
|
||||
let running_latest = latest.track.version.hash == self.version_info().hash;
|
||||
let already_have_latest = s.installed.as_ref().or(s.ready.as_ref()).map_or(false, |t| *t == latest.track);
|
||||
|
||||
if self.update_policy.enable_downloading && !running_later && !running_latest && !already_have_latest {
|
||||
if !s.disabled && self.update_policy.enable_downloading && !running_later && !running_latest && !already_have_latest {
|
||||
if let Some(b) = latest.track.binary {
|
||||
if s.fetching.is_none() {
|
||||
if self.updates_path(&Self::update_file_name(&latest.track.version)).exists() {
|
||||
@@ -340,7 +340,7 @@ impl fetch::urlhint::ContractClient for Updater {
|
||||
|
||||
fn call(&self, address: Address, data: Bytes) -> Result<Bytes, String> {
|
||||
self.client.upgrade().ok_or_else(|| "Client not available".to_owned())?
|
||||
.call_contract(address, data)
|
||||
.call_contract(BlockId::Latest, address, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description = "Ethcore utility library"
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "ethcore-util"
|
||||
version = "1.6.2"
|
||||
version = "1.6.5"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@@ -380,10 +380,7 @@ impl JournalDB for OverlayRecentDB {
|
||||
|
||||
match rc {
|
||||
0 => {}
|
||||
1 => {
|
||||
if cfg!(debug_assertions) && self.backing.get(self.column, &key)?.is_some() {
|
||||
return Err(BaseDataError::AlreadyExists(key).into());
|
||||
}
|
||||
_ if rc > 0 => {
|
||||
batch.put(self.column, &key, &value)
|
||||
}
|
||||
-1 => {
|
||||
@@ -392,7 +389,7 @@ impl JournalDB for OverlayRecentDB {
|
||||
}
|
||||
batch.delete(self.column, &key)
|
||||
}
|
||||
_ => panic!("Attempted to inject invalid state."),
|
||||
_ => panic!("Attempted to inject invalid state ({})", rc),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user