[beta] Backports (#5299)
* Fix FireFox overflows (#5000) * Max width for container * Set min-width * Switching ValidatorSet (#4961) * add multi validator set * nicer comment * validate in constructor * reporting * Avoid clogging up tmp when updater dir has bad permissions. (#5024) * force earliest era set in snapshot restore (#5021) * v1.6.5 * Fine grained snapshot chunking * Ropsten revival
This commit is contained in:
parent
c1da49bbc4
commit
797f23f30b
51
Cargo.lock
generated
51
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
[root]
|
[root]
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.6.4"
|
version = "1.6.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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-secretstore 1.0.0",
|
||||||
"ethcore-signer 1.6.0",
|
"ethcore-signer 1.6.0",
|
||||||
"ethcore-stratum 1.6.0",
|
"ethcore-stratum 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethsync 1.6.0",
|
"ethsync 1.6.0",
|
||||||
"evmbin 0.1.0",
|
"evmbin 0.1.0",
|
||||||
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -394,13 +394,14 @@ dependencies = [
|
|||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-stratum 1.6.0",
|
"ethcore-stratum 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"ethstore 0.1.0",
|
"ethstore 0.1.0",
|
||||||
"evmjit 1.6.0",
|
"evmjit 1.6.0",
|
||||||
"hardware-wallet 1.6.0",
|
"hardware-wallet 1.6.0",
|
||||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
"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)",
|
"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)",
|
"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)",
|
"log 0.3.6 (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)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-devtools 1.6.0",
|
"ethcore-devtools 1.6.0",
|
||||||
"ethcore-rpc 1.6.0",
|
"ethcore-rpc 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
||||||
@ -491,7 +492,7 @@ name = "ethcore-ipc"
|
|||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-devtools 1.6.0",
|
"ethcore-devtools 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
"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)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -538,7 +539,7 @@ dependencies = [
|
|||||||
"ethcore-ipc 1.6.0",
|
"ethcore-ipc 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"log 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)",
|
||||||
"nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git?branch=parity-1.7)",
|
"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)",
|
"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 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-network 1.6.0",
|
"ethcore-network 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -569,7 +570,7 @@ name = "ethcore-logger"
|
|||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -585,7 +586,7 @@ dependencies = [
|
|||||||
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-devtools 1.6.0",
|
"ethcore-devtools 1.6.0",
|
||||||
"ethcore-io 1.6.0",
|
"ethcore-io 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -613,7 +614,7 @@ dependencies = [
|
|||||||
"ethcore-io 1.6.0",
|
"ethcore-io 1.6.0",
|
||||||
"ethcore-ipc 1.6.0",
|
"ethcore-ipc 1.6.0",
|
||||||
"ethcore-light 1.6.0",
|
"ethcore-light 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
@ -648,7 +649,7 @@ dependencies = [
|
|||||||
"ethcore-ipc 1.6.0",
|
"ethcore-ipc 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -666,7 +667,7 @@ dependencies = [
|
|||||||
"ethcore-devtools 1.6.0",
|
"ethcore-devtools 1.6.0",
|
||||||
"ethcore-io 1.6.0",
|
"ethcore-io 1.6.0",
|
||||||
"ethcore-rpc 1.6.0",
|
"ethcore-rpc 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"jsonrpc-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
"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)",
|
"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)",
|
"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 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"jsonrpc-macros 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]]
|
[[package]]
|
||||||
name = "ethcore-util"
|
name = "ethcore-util"
|
||||||
version = "1.6.4"
|
version = "1.6.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -748,7 +749,7 @@ dependencies = [
|
|||||||
name = "ethjson"
|
name = "ethjson"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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 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)",
|
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -776,7 +777,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-devtools 1.6.0",
|
"ethcore-devtools 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethcrypto 0.1.0",
|
"ethcrypto 0.1.0",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -809,7 +810,7 @@ dependencies = [
|
|||||||
"ethcore-ipc-nano 1.6.0",
|
"ethcore-ipc-nano 1.6.0",
|
||||||
"ethcore-light 1.6.0",
|
"ethcore-light 1.6.0",
|
||||||
"ethcore-network 1.6.0",
|
"ethcore-network 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -826,7 +827,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore 1.6.0",
|
"ethcore 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1054,7 +1055,7 @@ version = "1.6.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-ipc 1.6.0",
|
"ethcore-ipc 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1621,7 +1622,7 @@ name = "parity-hash-fetch"
|
|||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1638,7 +1639,7 @@ version = "1.6.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethcore 1.6.0",
|
"ethcore 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"hyper 0.10.0-a.0 (git+https://github.com/ethcore/hyper)",
|
"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)",
|
"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)",
|
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1652,7 +1653,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore 1.6.0",
|
"ethcore 1.6.0",
|
||||||
"ethcore-io 1.6.0",
|
"ethcore-io 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethkey 0.2.0",
|
"ethkey 0.2.0",
|
||||||
"log 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)",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
@ -1675,7 +1676,7 @@ version = "1.4.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-rpc 1.6.0",
|
"ethcore-rpc 1.6.0",
|
||||||
"ethcore-signer 1.6.0",
|
"ethcore-signer 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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-core 6.0.0 (git+https://github.com/ethcore/jsonrpc.git)",
|
||||||
"log 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)",
|
||||||
@ -1719,7 +1720,7 @@ dependencies = [
|
|||||||
"ethcore 1.6.0",
|
"ethcore 1.6.0",
|
||||||
"ethcore-ipc 1.6.0",
|
"ethcore-ipc 1.6.0",
|
||||||
"ethcore-ipc-codegen 1.6.0",
|
"ethcore-ipc-codegen 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"ethsync 1.6.0",
|
"ethsync 1.6.0",
|
||||||
"ipc-common-types 1.6.0",
|
"ipc-common-types 1.6.0",
|
||||||
"log 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)",
|
||||||
@ -1994,7 +1995,7 @@ version = "1.4.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-bigint 0.1.2",
|
"ethcore-bigint 0.1.2",
|
||||||
"ethcore-rpc 1.6.0",
|
"ethcore-rpc 1.6.0",
|
||||||
"ethcore-util 1.6.4",
|
"ethcore-util 1.6.5",
|
||||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-rpc-client 1.4.0",
|
"parity-rpc-client 1.4.0",
|
||||||
"rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
description = "Parity Ethereum client"
|
description = "Parity Ethereum client"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.6.4"
|
version = "1.6.5"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ byteorder = "1.0"
|
|||||||
transient-hashmap = "0.1"
|
transient-hashmap = "0.1"
|
||||||
linked-hash-map = "0.3.0"
|
linked-hash-map = "0.3.0"
|
||||||
lru-cache = "0.1.0"
|
lru-cache = "0.1.0"
|
||||||
|
itertools = "0.5"
|
||||||
ethabi = "1.0.0"
|
ethabi = "1.0.0"
|
||||||
evmjit = { path = "../evmjit", optional = true }
|
evmjit = { path = "../evmjit", optional = true }
|
||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
"maximumExtraDataSize": "0x20",
|
"maximumExtraDataSize": "0x20",
|
||||||
"minGasLimit": "0x1388",
|
"minGasLimit": "0x1388",
|
||||||
"networkID" : "0x3",
|
"networkID" : "0x3",
|
||||||
"forkBlock": 333922,
|
"forkBlock": 641350,
|
||||||
"forkCanonHash": "0x8737eb141d4f05db57af63fc8d3b4d4d8f9cddb0c4e1ab855de8c288fdc1924f",
|
"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
|
||||||
"eip98Transition": "0x7fffffffffffff"
|
"eip98Transition": "0x7fffffffffffff"
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
@ -44,11 +44,8 @@
|
|||||||
"gasLimit": "0x1000000"
|
"gasLimit": "0x1000000"
|
||||||
},
|
},
|
||||||
"nodes": [
|
"nodes": [
|
||||||
"enode://a22f0977ce02653bf95e38730106356342df48b5222e2c2a1a6f9ef34769bf593bae9ca0a888cf60839edd52efc1b6e393c63a57d76f4c4fe14e641f1f9e637e@128.199.55.137:30303",
|
"enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303",
|
||||||
"enode://012239fccf3ff1d92b036983a430cb6705c6528c96c0354413f8854802138e5135c084ab36e7c54efb621c46728df8c3a6f4c1db9bb48a1330efe3f82f2dd7a6@52.169.94.142:30303",
|
"enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303"
|
||||||
"enode://1462682e4b7ba2258346d55e25e5b9d264b0db40cee12bdfba4e72b1d7050350ea954c006e9106dd96a128e6e0bd6dffb17eed51f9f99bf7f9cdadfeaf8da4ff@51.15.61.253:30303",
|
|
||||||
"enode://98fbb020c799ae39a828bd75dc2bd5d4721539faf317076b275f91182a5c8900b592e8abfdddceae674a7c3bb40ea00a6ca9ccb7805ab58c4b7b29c61c8f7239@51.15.62.44:30303",
|
|
||||||
"enode://d801dd4e3d15a8bf785931add164bd9c313e3f6b5749d9302b311f2b48064cba5c86c32b1302c27cd983fc89ae07d4d306dd1197610835b8782e95dfb1b3f9ea@51.15.43.255:30303"
|
|
||||||
],
|
],
|
||||||
"accounts": {
|
"accounts": {
|
||||||
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "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" }
|
||||||
|
}
|
||||||
|
}
|
@ -82,7 +82,7 @@ pub struct AuthorityRound {
|
|||||||
proposed: AtomicBool,
|
proposed: AtomicBool,
|
||||||
client: RwLock<Option<Weak<EngineClient>>>,
|
client: RwLock<Option<Weak<EngineClient>>>,
|
||||||
signer: EngineSigner,
|
signer: EngineSigner,
|
||||||
validators: Box<ValidatorSet + Send + Sync>,
|
validators: Box<ValidatorSet>,
|
||||||
/// Is this Engine just for testing (prevents step calibration).
|
/// Is this Engine just for testing (prevents step calibration).
|
||||||
calibrate_step: bool,
|
calibrate_step: bool,
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ pub struct BasicAuthority {
|
|||||||
gas_limit_bound_divisor: U256,
|
gas_limit_bound_divisor: U256,
|
||||||
builtins: BTreeMap<Address, Builtin>,
|
builtins: BTreeMap<Address, Builtin>,
|
||||||
signer: EngineSigner,
|
signer: EngineSigner,
|
||||||
validators: Box<ValidatorSet + Send + Sync>,
|
validators: Box<ValidatorSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BasicAuthority {
|
impl BasicAuthority {
|
||||||
|
@ -98,7 +98,7 @@ pub struct Tendermint {
|
|||||||
/// Hash of the proposal parent block.
|
/// Hash of the proposal parent block.
|
||||||
proposal_parent: RwLock<H256>,
|
proposal_parent: RwLock<H256>,
|
||||||
/// Set used to determine the current validators.
|
/// Set used to determine the current validators.
|
||||||
validators: Box<ValidatorSet + Send + Sync>,
|
validators: Box<ValidatorSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tendermint {
|
impl Tendermint {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
mod simple_list;
|
mod simple_list;
|
||||||
mod safe_contract;
|
mod safe_contract;
|
||||||
mod contract;
|
mod contract;
|
||||||
|
mod multi;
|
||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
use util::{Address, H256};
|
use util::{Address, H256};
|
||||||
@ -27,23 +28,27 @@ use client::Client;
|
|||||||
use self::simple_list::SimpleList;
|
use self::simple_list::SimpleList;
|
||||||
use self::contract::ValidatorContract;
|
use self::contract::ValidatorContract;
|
||||||
use self::safe_contract::ValidatorSafeContract;
|
use self::safe_contract::ValidatorSafeContract;
|
||||||
|
use self::multi::Multi;
|
||||||
|
|
||||||
/// Creates a validator set from spec.
|
/// 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 {
|
match spec {
|
||||||
ValidatorSpec::List(list) => Box::new(SimpleList::new(list.into_iter().map(Into::into).collect())),
|
ValidatorSpec::List(list) => Box::new(SimpleList::new(list.into_iter().map(Into::into).collect())),
|
||||||
ValidatorSpec::SafeContract(address) => Box::new(ValidatorSafeContract::new(address.into())),
|
ValidatorSpec::SafeContract(address) => Box::new(ValidatorSafeContract::new(address.into())),
|
||||||
ValidatorSpec::Contract(address) => Box::new(ValidatorContract::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.
|
/// Checks if a given address is a validator.
|
||||||
fn contains(&self, bh: &H256, address: &Address) -> bool;
|
fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool;
|
||||||
/// Draws an validator nonce modulo number of validators.
|
/// Draws an validator nonce modulo number of validators.
|
||||||
fn get(&self, bh: &H256, nonce: usize) -> Address;
|
fn get(&self, parent_block_hash: &H256, nonce: usize) -> Address;
|
||||||
/// Returns the current number of validators.
|
/// Returns the current number of validators.
|
||||||
fn count(&self, bh: &H256) -> usize;
|
fn count(&self, parent_block_hash: &H256) -> usize;
|
||||||
/// Notifies about malicious behaviour.
|
/// Notifies about malicious behaviour.
|
||||||
fn report_malicious(&self, _validator: &Address) {}
|
fn report_malicious(&self, _validator: &Address) {}
|
||||||
/// Notifies about benign misbehaviour.
|
/// 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);
|
||||||
|
}
|
||||||
|
}
|
@ -107,6 +107,7 @@ extern crate ethcore_stratum;
|
|||||||
extern crate ethabi;
|
extern crate ethabi;
|
||||||
extern crate hardware_wallet;
|
extern crate hardware_wallet;
|
||||||
extern crate stats;
|
extern crate stats;
|
||||||
|
extern crate itertools;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
@ -23,6 +23,7 @@ use snapshot::Error;
|
|||||||
use util::{U256, FixedHash, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP};
|
use util::{U256, FixedHash, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP};
|
||||||
use util::trie::{TrieDB, Trie};
|
use util::trie::{TrieDB, Trie};
|
||||||
use rlp::{RlpStream, Stream, UntrustedRlp, View};
|
use rlp::{RlpStream, Stream, UntrustedRlp, View};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
@ -60,55 +61,53 @@ impl CodeState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk the account's storage trie, returning an RLP item containing the
|
// walk the account's storage trie, returning a vector of RLP items containing the
|
||||||
// account properties and the storage.
|
// account properties and the storage. Each item contains at most `max_storage_items`
|
||||||
pub fn to_fat_rlp(acc: &BasicAccount, acct_db: &AccountDB, used_code: &mut HashSet<H256>) -> Result<Bytes, Error> {
|
// 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 {
|
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 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()? {
|
for r in pairs {
|
||||||
let (k, v) = item?;
|
let (k, v) = r?;
|
||||||
pairs.push((k, v));
|
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 {
|
let mut account_stream = RlpStream::new_list(5);
|
||||||
stream.begin_list(2).append(&k).append(&&*v);
|
account_stream.append(&acc.nonce)
|
||||||
}
|
.append(&acc.balance);
|
||||||
|
|
||||||
let pairs_rlp = stream.out();
|
// [has_code, code_hash].
|
||||||
|
if acc.code_hash == SHA3_EMPTY {
|
||||||
let mut account_stream = RlpStream::new_list(5);
|
account_stream.append(&CodeState::Empty.raw()).append_empty_data();
|
||||||
account_stream.append(&acc.nonce)
|
} else if used_code.contains(&acc.code_hash) {
|
||||||
.append(&acc.balance);
|
account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash);
|
||||||
|
} else {
|
||||||
// [has_code, code_hash].
|
match acct_db.get(&acc.code_hash) {
|
||||||
if acc.code_hash == SHA3_EMPTY {
|
Some(c) => {
|
||||||
account_stream.append(&CodeState::Empty.raw()).append_empty_data();
|
used_code.insert(acc.code_hash.clone());
|
||||||
} else if used_code.contains(&acc.code_hash) {
|
account_stream.append(&CodeState::Inline.raw()).append(&&*c);
|
||||||
account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash);
|
}
|
||||||
} else {
|
None => {
|
||||||
match acct_db.get(&acc.code_hash) {
|
warn!("code lookup failed during snapshot");
|
||||||
Some(c) => {
|
account_stream.append(&false).append_empty_data();
|
||||||
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);
|
account_stream.append_raw(&pairs_rlp, 1);
|
||||||
|
Ok(account_stream.out())
|
||||||
Ok(account_stream.out())
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode a fat rlp, and rebuild the storage trie as we go.
|
// 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(
|
pub fn from_fat_rlp(
|
||||||
acct_db: &mut AccountDBMut,
|
acct_db: &mut AccountDBMut,
|
||||||
rlp: UntrustedRlp,
|
rlp: UntrustedRlp,
|
||||||
|
mut storage_root: H256,
|
||||||
) -> Result<(BasicAccount, Option<Bytes>), Error> {
|
) -> Result<(BasicAccount, Option<Bytes>), Error> {
|
||||||
use util::{TrieDBMut, TrieMut};
|
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)?;
|
let pairs = rlp.at(4)?;
|
||||||
for pair_rlp in pairs.iter() {
|
for pair_rlp in pairs.iter() {
|
||||||
let k: Bytes = pair_rlp.val_at(0)?;
|
let k: Bytes = pair_rlp.val_at(0)?;
|
||||||
@ -184,7 +186,7 @@ mod tests {
|
|||||||
|
|
||||||
use std::collections::HashSet;
|
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]
|
#[test]
|
||||||
fn encoding_basic() {
|
fn encoding_basic() {
|
||||||
@ -201,9 +203,9 @@ mod tests {
|
|||||||
let thin_rlp = ::rlp::encode(&account);
|
let thin_rlp = ::rlp::encode(&account);
|
||||||
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), 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_rlps = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap();
|
||||||
let fat_rlp = UntrustedRlp::new(&fat_rlp);
|
let fat_rlp = UntrustedRlp::new(&fat_rlps[0]);
|
||||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account);
|
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -226,9 +228,40 @@ mod tests {
|
|||||||
let thin_rlp = ::rlp::encode(&account);
|
let thin_rlp = ::rlp::encode(&account);
|
||||||
assert_eq!(::rlp::decode::<BasicAccount>(&thin_rlp), 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 = to_fat_rlps(&account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value()).unwrap();
|
||||||
let fat_rlp = UntrustedRlp::new(&fat_rlp);
|
let fat_rlp = UntrustedRlp::new(&fat_rlp[0]);
|
||||||
assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp).unwrap().0, account);
|
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]
|
#[test]
|
||||||
@ -264,18 +297,18 @@ mod tests {
|
|||||||
|
|
||||||
let mut used_code = HashSet::new();
|
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_rlp1 = to_fat_rlps(&account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value()).unwrap();
|
||||||
let fat_rlp2 = to_fat_rlp(&account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code).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);
|
assert_eq!(used_code.len(), 1);
|
||||||
|
|
||||||
let fat_rlp1 = UntrustedRlp::new(&fat_rlp1);
|
let fat_rlp1 = UntrustedRlp::new(&fat_rlp1[0]);
|
||||||
let fat_rlp2 = UntrustedRlp::new(&fat_rlp2);
|
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!(maybe_code.is_none());
|
||||||
assert_eq!(acc, account2);
|
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!(maybe_code, Some(b"this is definitely code".to_vec()));
|
||||||
assert_eq!(acc, account1);
|
assert_eq!(acc, account1);
|
||||||
}
|
}
|
||||||
@ -285,7 +318,7 @@ mod tests {
|
|||||||
let mut db = get_temp_state_db();
|
let mut db = get_temp_state_db();
|
||||||
let mut used_code = HashSet::new();
|
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!(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)).unwrap(), (ACC_EMPTY, None));
|
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),
|
Decoder(DecoderError),
|
||||||
/// Io error.
|
/// Io error.
|
||||||
Io(::std::io::Error),
|
Io(::std::io::Error),
|
||||||
|
/// Snapshot version is not supported.
|
||||||
|
VersionNotSupported(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -73,6 +75,7 @@ impl fmt::Display for Error {
|
|||||||
Error::Io(ref err) => err.fmt(f),
|
Error::Io(ref err) => err.fmt(f),
|
||||||
Error::Decoder(ref err) => err.fmt(f),
|
Error::Decoder(ref err) => err.fmt(f),
|
||||||
Error::Trie(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;
|
use super::ManifestData;
|
||||||
|
|
||||||
|
const SNAPSHOT_VERSION: u64 = 2;
|
||||||
|
|
||||||
/// Something which can write snapshots.
|
/// Something which can write snapshots.
|
||||||
/// Writing the same chunk multiple times will lead to implementation-defined
|
/// Writing the same chunk multiple times will lead to implementation-defined
|
||||||
/// behavior, and is not advised.
|
/// behavior, and is not advised.
|
||||||
@ -120,8 +122,9 @@ impl SnapshotWriter for PackedWriter {
|
|||||||
fn finish(mut self, manifest: ManifestData) -> io::Result<()> {
|
fn finish(mut self, manifest: ManifestData) -> io::Result<()> {
|
||||||
// we ignore the hashes fields of the manifest under the assumption that
|
// we ignore the hashes fields of the manifest under the assumption that
|
||||||
// they are consistent with ours.
|
// they are consistent with ours.
|
||||||
let mut stream = RlpStream::new_list(5);
|
let mut stream = RlpStream::new_list(6);
|
||||||
stream
|
stream
|
||||||
|
.append(&SNAPSHOT_VERSION)
|
||||||
.append(&self.state_hashes)
|
.append(&self.state_hashes)
|
||||||
.append(&self.block_hashes)
|
.append(&self.block_hashes)
|
||||||
.append(&manifest.state_root)
|
.append(&manifest.state_root)
|
||||||
@ -223,7 +226,7 @@ impl PackedReader {
|
|||||||
/// Create a new `PackedReader` for the file at the given path.
|
/// Create a new `PackedReader` for the file at the given path.
|
||||||
/// This will fail if any io errors are encountered or the file
|
/// This will fail if any io errors are encountered or the file
|
||||||
/// is not a valid packed snapshot.
|
/// 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 mut file = File::open(path)?;
|
||||||
let file_len = file.metadata()?.len();
|
let file_len = file.metadata()?.len();
|
||||||
if file_len < 8 {
|
if file_len < 8 {
|
||||||
@ -257,15 +260,26 @@ impl PackedReader {
|
|||||||
|
|
||||||
let rlp = UntrustedRlp::new(&manifest_buf);
|
let rlp = UntrustedRlp::new(&manifest_buf);
|
||||||
|
|
||||||
let state: Vec<ChunkInfo> = rlp.val_at(0)?;
|
let (start, version) = if rlp.item_count() == 5 {
|
||||||
let blocks: Vec<ChunkInfo> = rlp.val_at(1)?;
|
(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 {
|
let manifest = ManifestData {
|
||||||
|
version: version,
|
||||||
state_hashes: state.iter().map(|c| c.0).collect(),
|
state_hashes: state.iter().map(|c| c.0).collect(),
|
||||||
block_hashes: blocks.iter().map(|c| c.0).collect(),
|
block_hashes: blocks.iter().map(|c| c.0).collect(),
|
||||||
state_root: rlp.val_at(2)?,
|
state_root: rlp.val_at(2 + start)?,
|
||||||
block_number: rlp.val_at(3)?,
|
block_number: rlp.val_at(3 + start)?,
|
||||||
block_hash: rlp.val_at(4)?,
|
block_hash: rlp.val_at(4 + start)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(PackedReader {
|
Ok(Some(PackedReader {
|
||||||
@ -348,7 +362,7 @@ mod tests {
|
|||||||
use util::sha3::Hashable;
|
use util::sha3::Hashable;
|
||||||
|
|
||||||
use snapshot::ManifestData;
|
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 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"];
|
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 {
|
let manifest = ManifestData {
|
||||||
|
version: SNAPSHOT_VERSION,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: b"notarealroot".sha3(),
|
state_root: b"notarealroot".sha3(),
|
||||||
@ -412,6 +427,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: SNAPSHOT_VERSION,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: b"notarealroot".sha3(),
|
state_root: b"notarealroot".sha3(),
|
||||||
@ -428,4 +444,4 @@ mod tests {
|
|||||||
reader.chunk(hash.clone()).unwrap();
|
reader.chunk(hash.clone()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ pub use self::traits::SnapshotService;
|
|||||||
pub use self::watcher::Watcher;
|
pub use self::watcher::Watcher;
|
||||||
pub use types::snapshot_manifest::ManifestData;
|
pub use types::snapshot_manifest::ManifestData;
|
||||||
pub use types::restoration_status::RestorationStatus;
|
pub use types::restoration_status::RestorationStatus;
|
||||||
|
pub use types::basic_account::BasicAccount;
|
||||||
|
|
||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
@ -82,6 +83,9 @@ mod traits {
|
|||||||
// Try to have chunks be around 4MB (before compression)
|
// Try to have chunks be around 4MB (before compression)
|
||||||
const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024;
|
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.
|
// How many blocks to include in a snapshot, starting from the head of the chain.
|
||||||
const SNAPSHOT_BLOCKS: u64 = 30000;
|
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());
|
info!("produced {} state chunks and {} block chunks.", state_hashes.len(), block_hashes.len());
|
||||||
|
|
||||||
let manifest_data = ManifestData {
|
let manifest_data = ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: *state_root,
|
state_root: *state_root,
|
||||||
@ -300,14 +305,14 @@ impl<'a> StateChunker<'a> {
|
|||||||
//
|
//
|
||||||
// If the buffer is greater than the desired chunk size,
|
// If the buffer is greater than the desired chunk size,
|
||||||
// this will write out the data to disk.
|
// 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 pair = {
|
||||||
let mut stream = RlpStream::new_list(2);
|
let mut stream = RlpStream::new_list(2);
|
||||||
stream.append(&account_hash).append_raw(&data, 1);
|
stream.append(&account_hash).append_raw(&data, 1);
|
||||||
stream.out()
|
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()?;
|
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 account_db = AccountDB::from_hash(db, account_key_hash);
|
||||||
|
|
||||||
let fat_rlp = account::to_fat_rlp(&account, &account_db, &mut used_code)?;
|
let fat_rlps = account::to_fat_rlps(&account, &account_db, &mut used_code, MAX_STORAGE_ENTRIES_PER_ACCOUNT_RECORD)?;
|
||||||
chunker.push(account_key, fat_rlp)?;
|
for (i, fat_rlp) in fat_rlps.into_iter().enumerate() {
|
||||||
|
chunker.push(account_key.clone(), fat_rlp, i > 0)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if chunker.cur_size != 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.
|
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.
|
missing_code: HashMap<H256, Vec<H256>>, // maps code hashes to lists of accounts missing that code.
|
||||||
bloom: Bloom,
|
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 {
|
impl StateRebuilder {
|
||||||
@ -401,6 +409,7 @@ impl StateRebuilder {
|
|||||||
known_code: HashMap::new(),
|
known_code: HashMap::new(),
|
||||||
missing_code: HashMap::new(),
|
missing_code: HashMap::new(),
|
||||||
bloom: StateDB::load_bloom(&*db),
|
bloom: StateDB::load_bloom(&*db),
|
||||||
|
known_storage_roots: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,6 +427,7 @@ impl StateRebuilder {
|
|||||||
rlp,
|
rlp,
|
||||||
&mut pairs,
|
&mut pairs,
|
||||||
&self.known_code,
|
&self.known_code,
|
||||||
|
&mut self.known_storage_roots,
|
||||||
flag
|
flag
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -464,14 +474,18 @@ impl StateRebuilder {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check for accounts missing code. Once all chunks have been fed, there should
|
/// Finalize the restoration. Check for accounts missing code and make a dummy
|
||||||
/// be none.
|
/// journal entry.
|
||||||
pub fn check_missing(self) -> Result<(), Error> {
|
/// 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<_>>();
|
let missing = self.missing_code.keys().cloned().collect::<Vec<_>>();
|
||||||
match missing.is_empty() {
|
if !missing.is_empty() { return Err(Error::MissingCode(missing).into()) }
|
||||||
true => Ok(()),
|
|
||||||
false => Err(Error::MissingCode(missing)),
|
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.
|
/// Get the state root of the rebuilder.
|
||||||
@ -492,10 +506,11 @@ fn rebuild_accounts(
|
|||||||
account_fat_rlps: UntrustedRlp,
|
account_fat_rlps: UntrustedRlp,
|
||||||
out_chunk: &mut [(H256, Bytes)],
|
out_chunk: &mut [(H256, Bytes)],
|
||||||
known_code: &HashMap<H256, H256>,
|
known_code: &HashMap<H256, H256>,
|
||||||
|
known_storage_roots: &mut HashMap<H256, H256>,
|
||||||
abort_flag: &AtomicBool,
|
abort_flag: &AtomicBool,
|
||||||
) -> Result<RebuiltStatus, ::error::Error> {
|
) -> Result<RebuiltStatus, ::error::Error> {
|
||||||
let mut status = RebuiltStatus::default();
|
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()) }
|
if !abort_flag.load(Ordering::SeqCst) { return Err(Error::RestorationAborted.into()) }
|
||||||
|
|
||||||
let hash: H256 = account_rlp.val_at(0)?;
|
let hash: H256 = account_rlp.val_at(0)?;
|
||||||
@ -506,7 +521,8 @@ fn rebuild_accounts(
|
|||||||
// fill out the storage trie and code while decoding.
|
// fill out the storage trie and code while decoding.
|
||||||
let (acc, maybe_code) = {
|
let (acc, maybe_code) = {
|
||||||
let mut acct_db = AccountDBMut::from_hash(db, hash);
|
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();
|
let code_hash = acc.code_hash.clone();
|
||||||
@ -538,6 +554,12 @@ fn rebuild_accounts(
|
|||||||
|
|
||||||
*out = (hash, thin_rlp);
|
*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)
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ impl Restoration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for missing code.
|
// 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.
|
// connect out-of-order chunks and verify chain integrity.
|
||||||
self.blocks.finalize(self.canonical_hashes)?;
|
self.blocks.finalize(self.canonical_hashes)?;
|
||||||
@ -656,6 +656,7 @@ mod tests {
|
|||||||
assert_eq!(service.status(), RestorationStatus::Inactive);
|
assert_eq!(service.status(), RestorationStatus::Inactive);
|
||||||
|
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: vec![],
|
state_hashes: vec![],
|
||||||
block_hashes: vec![],
|
block_hashes: vec![],
|
||||||
state_root: Default::default(),
|
state_root: Default::default(),
|
||||||
|
@ -63,6 +63,7 @@ fn chunk_and_restore(amount: u64) {
|
|||||||
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
|
let writer = Mutex::new(PackedWriter::new(&snapshot_path).unwrap());
|
||||||
let block_hashes = chunk_blocks(&bc, best_hash, &writer, &Progress::default()).unwrap();
|
let block_hashes = chunk_blocks(&bc, best_hash, &writer, &Progress::default()).unwrap();
|
||||||
let manifest = ::snapshot::ManifestData {
|
let manifest = ::snapshot::ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: Vec::new(),
|
state_hashes: Vec::new(),
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: ::util::sha3::SHA3_NULL_RLP,
|
state_root: ::util::sha3::SHA3_NULL_RLP,
|
||||||
@ -125,6 +126,7 @@ fn checks_flag() {
|
|||||||
let chain = BlockChain::new(Default::default(), &genesis, db.clone());
|
let chain = BlockChain::new(Default::default(), &genesis, db.clone());
|
||||||
|
|
||||||
let manifest = ::snapshot::ManifestData {
|
let manifest = ::snapshot::ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: Vec::new(),
|
state_hashes: Vec::new(),
|
||||||
block_hashes: Vec::new(),
|
block_hashes: Vec::new(),
|
||||||
state_root: ::util::sha3::SHA3_NULL_RLP,
|
state_root: ::util::sha3::SHA3_NULL_RLP,
|
||||||
|
@ -27,6 +27,7 @@ use super::ManifestData;
|
|||||||
#[test]
|
#[test]
|
||||||
fn manifest_rlp() {
|
fn manifest_rlp() {
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: 2,
|
||||||
block_hashes: Vec::new(),
|
block_hashes: Vec::new(),
|
||||||
state_hashes: Vec::new(),
|
state_hashes: Vec::new(),
|
||||||
block_number: 1234567,
|
block_number: 1234567,
|
||||||
@ -35,4 +36,4 @@ fn manifest_rlp() {
|
|||||||
};
|
};
|
||||||
let raw = manifest.clone().into_rlp();
|
let raw = manifest.clone().into_rlp();
|
||||||
assert_eq!(ManifestData::from_rlp(&raw).unwrap(), manifest);
|
assert_eq!(ManifestData::from_rlp(&raw).unwrap(), manifest);
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,7 @@ fn guards_delete_folders() {
|
|||||||
path.push("restoration");
|
path.push("restoration");
|
||||||
|
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: vec![],
|
state_hashes: vec![],
|
||||||
block_hashes: vec![],
|
block_hashes: vec![],
|
||||||
block_number: 0,
|
block_number: 0,
|
||||||
|
@ -58,10 +58,11 @@ fn snap_and_restore() {
|
|||||||
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
||||||
|
|
||||||
writer.into_inner().finish(::snapshot::ManifestData {
|
writer.into_inner().finish(::snapshot::ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: Vec::new(),
|
block_hashes: Vec::new(),
|
||||||
state_root: state_root,
|
state_root: state_root,
|
||||||
block_number: 0,
|
block_number: 1000,
|
||||||
block_hash: H256::default(),
|
block_hash: H256::default(),
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ fn snap_and_restore() {
|
|||||||
db_path.push("db");
|
db_path.push("db");
|
||||||
let db = {
|
let db = {
|
||||||
let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap());
|
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 reader = PackedReader::new(&snap_file).unwrap().unwrap();
|
||||||
|
|
||||||
let flag = AtomicBool::new(true);
|
let flag = AtomicBool::new(true);
|
||||||
@ -82,12 +83,13 @@ fn snap_and_restore() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(rebuilder.state_root(), state_root);
|
assert_eq!(rebuilder.state_root(), state_root);
|
||||||
rebuilder.check_missing().unwrap();
|
rebuilder.finalize(1000, H256::default()).unwrap();
|
||||||
|
|
||||||
new_db
|
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());
|
compare_dbs(&old_db, new_db.as_hashdb());
|
||||||
}
|
}
|
||||||
@ -120,10 +122,10 @@ fn get_code_from_prev_chunk() {
|
|||||||
let mut db = MemoryDB::new();
|
let mut db = MemoryDB::new();
|
||||||
AccountDBMut::from_hash(&mut db, hash).insert(&code[..]);
|
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);
|
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()
|
stream.out()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,13 +136,18 @@ fn get_code_from_prev_chunk() {
|
|||||||
let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
|
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 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(&chunk1, &flag).unwrap();
|
||||||
rebuilder.feed(&chunk2, &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]
|
#[test]
|
||||||
@ -164,6 +171,7 @@ fn checks_flag() {
|
|||||||
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
let state_hashes = chunk_state(&old_db, &state_root, &writer, &Progress::default()).unwrap();
|
||||||
|
|
||||||
writer.into_inner().finish(::snapshot::ManifestData {
|
writer.into_inner().finish(::snapshot::ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: Vec::new(),
|
block_hashes: Vec::new(),
|
||||||
state_root: state_root,
|
state_root: state_root,
|
||||||
@ -175,7 +183,7 @@ fn checks_flag() {
|
|||||||
db_path.push("db");
|
db_path.push("db");
|
||||||
{
|
{
|
||||||
let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap());
|
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 reader = PackedReader::new(&snap_file).unwrap().unwrap();
|
||||||
|
|
||||||
let flag = AtomicBool::new(false);
|
let flag = AtomicBool::new(false);
|
||||||
|
@ -360,6 +360,10 @@ impl Spec {
|
|||||||
/// Account is marked with `reportBenign` it can be checked as disliked with "0xd8f2e0bf".
|
/// Account is marked with `reportBenign` it can be checked as disliked with "0xd8f2e0bf".
|
||||||
/// Validator can be removed with `reportMalicious`.
|
/// Validator can be removed with `reportMalicious`.
|
||||||
pub fn new_validator_contract() -> Self { load_bundled!("validator_contract") }
|
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)]
|
#[cfg(test)]
|
||||||
|
@ -24,6 +24,8 @@ use util::Bytes;
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "ipc", binary)]
|
#[cfg_attr(feature = "ipc", binary)]
|
||||||
pub struct ManifestData {
|
pub struct ManifestData {
|
||||||
|
/// Snapshot format version.
|
||||||
|
pub version: u64,
|
||||||
/// List of state chunk hashes.
|
/// List of state chunk hashes.
|
||||||
pub state_hashes: Vec<H256>,
|
pub state_hashes: Vec<H256>,
|
||||||
/// List of block chunk hashes.
|
/// List of block chunk hashes.
|
||||||
@ -39,7 +41,8 @@ pub struct ManifestData {
|
|||||||
impl ManifestData {
|
impl ManifestData {
|
||||||
/// Encode the manifest data to rlp.
|
/// Encode the manifest data to rlp.
|
||||||
pub fn into_rlp(self) -> Bytes {
|
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.state_hashes);
|
||||||
stream.append(&self.block_hashes);
|
stream.append(&self.block_hashes);
|
||||||
stream.append(&self.state_root);
|
stream.append(&self.state_root);
|
||||||
@ -52,14 +55,20 @@ impl ManifestData {
|
|||||||
/// Try to restore manifest data from raw bytes, interpreted as RLP.
|
/// Try to restore manifest data from raw bytes, interpreted as RLP.
|
||||||
pub fn from_rlp(raw: &[u8]) -> Result<Self, DecoderError> {
|
pub fn from_rlp(raw: &[u8]) -> Result<Self, DecoderError> {
|
||||||
let decoder = UntrustedRlp::new(raw);
|
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 state_hashes: Vec<H256> = decoder.val_at(start + 0)?;
|
||||||
let block_hashes: Vec<H256> = decoder.val_at(1)?;
|
let block_hashes: Vec<H256> = decoder.val_at(start + 1)?;
|
||||||
let state_root: H256 = decoder.val_at(2)?;
|
let state_root: H256 = decoder.val_at(start + 2)?;
|
||||||
let block_number: u64 = decoder.val_at(3)?;
|
let block_number: u64 = decoder.val_at(start + 3)?;
|
||||||
let block_hash: H256 = decoder.val_at(4)?;
|
let block_hash: H256 = decoder.val_at(start + 4)?;
|
||||||
|
|
||||||
Ok(ManifestData {
|
Ok(ManifestData {
|
||||||
|
version: version,
|
||||||
state_hashes: state_hashes,
|
state_hashes: state_hashes,
|
||||||
block_hashes: block_hashes,
|
block_hashes: block_hashes,
|
||||||
state_root: state_root,
|
state_root: state_root,
|
||||||
|
@ -24,6 +24,7 @@ $transitionAll: all 0.75s cubic-bezier(0.23, 1, 0.32, 1);
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0em;
|
padding: 0em;
|
||||||
|
max-width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
/*transform: translateZ(0);
|
/*transform: translateZ(0);
|
||||||
transition: $transitionAll;*/
|
transition: $transitionAll;*/
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
$transition: all 0.25s;
|
$transition: all 0.25s;
|
||||||
$widthNormal: 33.33%;
|
$widthNormal: 33.33%;
|
||||||
$widthExpanded: 42%;
|
$widthExpanded: 42%;
|
||||||
|
$widthContracted: 29%;
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -45,6 +46,7 @@ $widthExpanded: 42%;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 1 $widthNormal;
|
flex: 0 1 $widthNormal;
|
||||||
max-width: $widthNormal;
|
max-width: $widthNormal;
|
||||||
|
min-width: $widthContracted;
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
//! Validator set deserialization.
|
//! Validator set deserialization.
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use uint::Uint;
|
||||||
use hash::Address;
|
use hash::Address;
|
||||||
|
|
||||||
/// Different ways of specifying validators.
|
/// 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.
|
/// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions.
|
||||||
#[serde(rename="contract")]
|
#[serde(rename="contract")]
|
||||||
Contract(Address),
|
Contract(Address),
|
||||||
|
/// A map of starting blocks for each validator set.
|
||||||
|
#[serde(rename="multi")]
|
||||||
|
Multi(BTreeMap<Uint, ValidatorSet>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -40,11 +45,17 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn validator_set_deserialization() {
|
fn validator_set_deserialization() {
|
||||||
let s = r#"[{
|
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();
|
let _deserialized: Vec<ValidatorSet> = serde_json::from_str(s).unwrap();
|
||||||
|
@ -462,7 +462,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>1.6.4</string>
|
<string>1.6.5</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>UUID</key>
|
<key>UUID</key>
|
||||||
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.6.4</string>
|
<string>1.6.5</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
||||||
!define VERSIONMAJOR 1
|
!define VERSIONMAJOR 1
|
||||||
!define VERSIONMINOR 6
|
!define VERSIONMINOR 6
|
||||||
!define VERSIONBUILD 4
|
!define VERSIONBUILD 5
|
||||||
!define ARGS "--warp"
|
!define ARGS "--warp"
|
||||||
!define FIRST_START_ARGS "ui --warp --mode=passive"
|
!define FIRST_START_ARGS "ui --warp --mode=passive"
|
||||||
|
|
||||||
|
@ -158,6 +158,8 @@ pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x16;
|
|||||||
|
|
||||||
const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3;
|
const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3;
|
||||||
|
|
||||||
|
const MIN_SUPPORTED_SNAPSHOT_MANIFEST_VERSION: u64 = 1;
|
||||||
|
|
||||||
const WAIT_PEERS_TIMEOUT_SEC: u64 = 5;
|
const WAIT_PEERS_TIMEOUT_SEC: u64 = 5;
|
||||||
const STATUS_TIMEOUT_SEC: u64 = 5;
|
const STATUS_TIMEOUT_SEC: u64 = 5;
|
||||||
const HEADERS_TIMEOUT_SEC: u64 = 15;
|
const HEADERS_TIMEOUT_SEC: u64 = 15;
|
||||||
@ -1023,12 +1025,18 @@ impl ChainSync {
|
|||||||
let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) {
|
let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e);
|
trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e);
|
||||||
io.disconnect_peer(peer_id);
|
io.disable_peer(peer_id);
|
||||||
self.continue_sync(io);
|
self.continue_sync(io);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Ok(manifest) => manifest,
|
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());
|
self.snapshot.reset_to(&manifest, &manifest_rlp.as_raw().sha3());
|
||||||
io.snapshot_service().begin_restore(manifest);
|
io.snapshot_service().begin_restore(manifest);
|
||||||
self.state = SyncState::SnapshotData;
|
self.state = SyncState::SnapshotData;
|
||||||
|
@ -139,6 +139,7 @@ mod test {
|
|||||||
let state_chunks: Vec<Bytes> = (0..20).map(|_| H256::random().to_vec()).collect();
|
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 block_chunks: Vec<Bytes> = (0..20).map(|_| H256::random().to_vec()).collect();
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
||||||
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
||||||
state_root: H256::new(),
|
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 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 block_chunks: Vec<Bytes> = (0..num_block_chunks).map(|_| H256::random().to_vec()).collect();
|
||||||
let manifest = ManifestData {
|
let manifest = ManifestData {
|
||||||
|
version: 2,
|
||||||
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
state_hashes: state_chunks.iter().map(|data| data.sha3()).collect(),
|
||||||
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
block_hashes: block_chunks.iter().map(|data| data.sha3()).collect(),
|
||||||
state_root: H256::new(),
|
state_root: H256::new(),
|
||||||
|
@ -274,7 +274,7 @@ impl Updater {
|
|||||||
let running_latest = latest.track.version.hash == self.version_info().hash;
|
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);
|
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 let Some(b) = latest.track.binary {
|
||||||
if s.fetching.is_none() {
|
if s.fetching.is_none() {
|
||||||
if self.updates_path(&Self::update_file_name(&latest.track.version)).exists() {
|
if self.updates_path(&Self::update_file_name(&latest.track.version)).exists() {
|
||||||
|
@ -3,7 +3,7 @@ description = "Ethcore utility library"
|
|||||||
homepage = "http://parity.io"
|
homepage = "http://parity.io"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
name = "ethcore-util"
|
name = "ethcore-util"
|
||||||
version = "1.6.4"
|
version = "1.6.5"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
@ -380,10 +380,7 @@ impl JournalDB for OverlayRecentDB {
|
|||||||
|
|
||||||
match rc {
|
match rc {
|
||||||
0 => {}
|
0 => {}
|
||||||
1 => {
|
_ if rc > 0 => {
|
||||||
if cfg!(debug_assertions) && self.backing.get(self.column, &key)?.is_some() {
|
|
||||||
return Err(BaseDataError::AlreadyExists(key).into());
|
|
||||||
}
|
|
||||||
batch.put(self.column, &key, &value)
|
batch.put(self.column, &key, &value)
|
||||||
}
|
}
|
||||||
-1 => {
|
-1 => {
|
||||||
@ -392,7 +389,7 @@ impl JournalDB for OverlayRecentDB {
|
|||||||
}
|
}
|
||||||
batch.delete(self.column, &key)
|
batch.delete(self.column, &key)
|
||||||
}
|
}
|
||||||
_ => panic!("Attempted to inject invalid state."),
|
_ => panic!("Attempted to inject invalid state ({})", rc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user