Merge branch 'master' into jg-signer-decoding

# Conflicts:
#	js/src/views/Signer/components/RequestFinished/requestFinished.js
This commit is contained in:
Jaco Greeff 2016-12-02 11:21:17 +01:00
commit 2dd2004ed5
116 changed files with 2375 additions and 1507 deletions

View File

@ -8,7 +8,6 @@ variables:
RUST_BACKTRACE: "1"
RUSTFLAGS: ""
CARGOFLAGS: ""
NIGHTLY: "nigtly"
cache:
key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME"
untracked: true
@ -21,7 +20,7 @@ linux-stable:
- stable
- triggers
script:
- cargo build --release $CARGOFLAGS
- cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity
- md5sum target/release/parity > parity.md5
- sh scripts/deb-build.sh amd64
@ -53,7 +52,7 @@ linux-beta:
- stable
- triggers
script:
- cargo build --release $CARGOFLAGS
- cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity
tags:
- rust
@ -72,7 +71,7 @@ linux-nightly:
- stable
- triggers
script:
- cargo build --release $CARGOFLAGS
- cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity
tags:
- rust
@ -93,7 +92,7 @@ linux-centos:
script:
- export CXX="g++"
- export CC="gcc"
- cargo build --release $CARGOFLAGS
- cargo build -j $(nproc) --release $CARGOFLAGS
- strip target/release/parity
- md5sum target/release/parity > parity.md5
- aws configure set aws_access_key_id $s3_key
@ -120,7 +119,7 @@ linux-i686:
script:
- export HOST_CC=gcc
- export HOST_CXX=g++
- cargo build --target i686-unknown-linux-gnu --release $CARGOFLAGS
- cargo build -j $(nproc) --target i686-unknown-linux-gnu --release $CARGOFLAGS
- strip target/i686-unknown-linux-gnu/release/parity
- md5sum target/i686-unknown-linux-gnu/release/parity > parity.md5
- sh scripts/deb-build.sh i386
@ -162,7 +161,7 @@ linux-armv7:
- echo "[target.armv7-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config
- cargo build --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS
- cargo build -j $(nproc) --target armv7-unknown-linux-gnueabihf --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/armv7-unknown-linux-gnueabihf/release/parity
- md5sum target/armv7-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf
@ -204,7 +203,7 @@ linux-arm:
- echo "[target.arm-unknown-linux-gnueabihf]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config
- cat .cargo/config
- cargo build --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS
- cargo build -j $(nproc) --target arm-unknown-linux-gnueabihf --release $CARGOFLAGS
- arm-linux-gnueabihf-strip target/arm-unknown-linux-gnueabihf/release/parity
- md5sum target/arm-unknown-linux-gnueabihf/release/parity > parity.md5
- sh scripts/deb-build.sh armhf
@ -232,9 +231,9 @@ linux-armv6:
stage: build
image: ethcore/rust-armv6:latest
only:
- beta
- tags
- stable
# - beta
# - tags
# - stable
- triggers
script:
- export CC=arm-linux-gnueabi-gcc
@ -246,7 +245,7 @@ linux-armv6:
- echo "[target.arm-unknown-linux-gnueabi]" >> .cargo/config
- echo "linker= \"arm-linux-gnueabi-gcc\"" >> .cargo/config
- cat .cargo/config
- cargo build --target arm-unknown-linux-gnueabi --release $CARGOFLAGS
- cargo build -j $(nproc) --target arm-unknown-linux-gnueabi --release $CARGOFLAGS
- arm-linux-gnueabi-strip target/arm-unknown-linux-gnueabi/release/parity
- md5sum target/arm-unknown-linux-gnueabi/release/parity > parity.md5
- aws configure set aws_access_key_id $s3_key
@ -281,7 +280,7 @@ linux-aarch64:
- echo "[target.aarch64-unknown-linux-gnu]" >> .cargo/config
- echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config
- cat .cargo/config
- cargo build --target aarch64-unknown-linux-gnu --release $CARGOFLAGS
- cargo build -j $(nproc) --target aarch64-unknown-linux-gnu --release $CARGOFLAGS
- aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/parity
- md5sum target/aarch64-unknown-linux-gnu/release/parity > parity.md5
- sh scripts/deb-build.sh arm64
@ -305,41 +304,6 @@ linux-aarch64:
- target/aarch64-unknown-linux-gnu/release/parity
name: "aarch64-unknown-linux-gnu_parity"
allow_failure: true
#linux-alpine:
# stage: build
# image: ethcore/rust-alpine:latest
# only:
# - beta
# - tags
# - stable
# - triggers
# script:
# - export HOST_CC=gcc
# - export HOST_CXX=g++
# - cargo build --release $CARGOFLAGS
# - strip target/release/parity
# - md5sum target/release/parity > parity.md5
# - sh scripts/deb-build.sh arm64
# - cp target/aarch64-unknown-linux-gnu/release/parity deb/usr/bin/parity
# - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n")
# - dpkg-deb -b deb "parity_"$VER"_arm64.deb"
# - md5sum "parity_"$VER"_arm64.deb" > "parity_"$VER"_arm64.deb.md5"
# - aws configure set aws_access_key_id $s3_key
# - aws configure set aws_secret_access_key $s3_secret
# - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi
# - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity --body target/aarch64-unknown-linux-gnu/release/parity
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/parity.md5 --body parity.md5
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb"
# - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/aarch64-unknown-linux-gnu/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5"
# tags:
# - rust
# - rust-alpine
# artifacts:
# paths:
# - target/aarch64-unknown-linux-gnu/release/parity
# name: "aarch64-unknown-linux-gnu_parity"
# allow_failure: true
darwin:
stage: build
only:
@ -348,8 +312,8 @@ darwin:
- stable
- triggers
script:
- cargo build --release -p ethstore $CARGOFLAGS
- cargo build --release $CARGOFLAGS
- cargo build -j 8 --release -p ethstore #$CARGOFLAGS
- cargo build -j 8 --release #$CARGOFLAGS
- rm -rf parity.md5
- md5sum target/release/parity > parity.md5
- packagesbuild -v mac/Parity.pkgproj
@ -386,7 +350,7 @@ windows:
- set RUST_BACKTRACE=1
- set RUSTFLAGS=%RUSTFLAGS%
- rustup default stable-x86_64-pc-windows-msvc
- cargo build --release %CARGOFLAGS%
- cargo build -j 8 --release #%CARGOFLAGS%
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -o nsis\SimpleFC.dll
- curl -sL --url "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -o nsis\vc_redist.x64.exe
- signtool sign /f %keyfile% /p %certpass% target\release\parity.exe
@ -449,7 +413,7 @@ test-windows:
- git submodule update --init --recursive
script:
- set RUST_BACKTRACE=1
- cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
- cargo -j 8 test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release
tags:
- rust-windows
allow_failure: true

28
Cargo.lock generated
View File

@ -3,7 +3,7 @@ name = "parity"
version = "1.5.0"
dependencies = [
"ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)",
"daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)",
@ -146,15 +146,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clippy"
version = "0.0.96"
version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"clippy_lints 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clippy_lints"
version = "0.0.96"
version = "0.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -224,7 +224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "elastic-array"
version = "0.6.0"
source = "git+https://github.com/ethcore/elastic-array#70e4012e691b732c7c4cb04e9232799e6aa268bc"
source = "git+https://github.com/ethcore/elastic-array#346f1ba5982576dab9d0b8fa178b50e1db0a21cd"
dependencies = [
"heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -280,7 +280,7 @@ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.4.0",
@ -333,7 +333,7 @@ dependencies = [
name = "ethcore-dapps"
version = "1.5.0"
dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (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.4.0",
"ethcore-hash-fetch 1.5.0",
@ -490,7 +490,7 @@ dependencies = [
name = "ethcore-rpc"
version = "1.5.0"
dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.4.0",
"ethcore 1.5.0",
"ethcore-devtools 1.4.0",
@ -520,7 +520,7 @@ dependencies = [
name = "ethcore-signer"
version = "1.5.0"
dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (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.4.0",
"ethcore-io 1.5.0",
@ -559,7 +559,7 @@ version = "1.5.0"
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)",
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
@ -649,7 +649,7 @@ dependencies = [
name = "ethsync"
version = "1.5.0"
dependencies = [
"clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.5.0",
"ethcore-io 1.5.0",
@ -1263,7 +1263,7 @@ dependencies = [
[[package]]
name = "parity-ui-precompiled"
version = "1.4.0"
source = "git+https://github.com/ethcore/js-precompiled.git#cb6836dddf8c9951e056283dcd9e105e97923d07"
source = "git+https://github.com/ethcore/js-precompiled.git#a5a1c15f4d125654e1d1cdcb6b7f92a606f1d2d0"
dependencies = [
"parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2005,8 +2005,8 @@ dependencies = [
"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27"
"checksum bytes 0.4.0-dev (git+https://github.com/carllerche/bytes)" = "<none>"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
"checksum clippy 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "6eacf01b0aad84a0817703498f72d252df7c0faf6a5b86d0be4265f1829e459f"
"checksum clippy_lints 0.0.96 (registry+https://github.com/rust-lang/crates.io-index)" = "a49960c9aab544ce86b004dcb61620e8b898fea5fc0f697a028f460f48221ed6"
"checksum clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "5b4fabf979ddf6419a313c1c0ada4a5b95cfd2049c56e8418d622d27b4b6ff32"
"checksum clippy_lints 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "ce96ec05bfe018a0d5d43da115e54850ea2217981ff0f2e462780ab9d594651a"
"checksum cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90266f45846f14a1e986c77d1e9c2626b8c342ed806fe60241ec38cc8697b245"
"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc"
"checksum ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)" = "<none>"

View File

@ -47,7 +47,7 @@ ethcore-hash-fetch = { path = "ethcore/hash-fetch" }
rlp = { path = "util/rlp" }
ethcore-stratum = { path = "stratum" }
ethcore-dapps = { path = "dapps", optional = true }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
[target.'cfg(windows)'.dependencies]
winapi = "0.2"

View File

@ -34,7 +34,7 @@ ethcore-hash-fetch = { path = "../ethcore/hash-fetch" }
fetch = { path = "../util/fetch" }
parity-ui = { path = "./ui" }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
[build-dependencies]
serde_codegen = { version = "0.8", optional = true }

View File

@ -11,7 +11,7 @@ build = "build.rs"
ethcore-ipc-codegen = { path = "../ipc/codegen" }
[dependencies]
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
ethcore-devtools = { path = "../devtools" }
ethcore-ipc = { path = "../ipc/rpc" }
rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" }

View File

@ -29,7 +29,7 @@ byteorder = "0.5"
transient-hashmap = "0.1"
linked-hash-map = "0.3.0"
evmjit = { path = "../evmjit", optional = true }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
ethash = { path = "../ethash" }
ethcore-util = { path = "../util" }
ethcore-io = { path = "../util/io" }

View File

@ -121,10 +121,6 @@ impl<'db> HashDB for AccountDB<'db>{
fn remove(&mut self, _key: &H256) {
unimplemented!()
}
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
self.db.get_aux(hash)
}
}
/// DB backend wrapper for Account trie
@ -197,18 +193,6 @@ impl<'db> HashDB for AccountDBMut<'db>{
let key = combine_key(&self.address_hash, key);
self.db.remove(&key)
}
fn insert_aux(&mut self, hash: Vec<u8>, value: Vec<u8>) {
self.db.insert_aux(hash, value);
}
fn get_aux(&self, hash: &[u8]) -> Option<DBValue> {
self.db.get_aux(hash)
}
fn remove_aux(&mut self, hash: &[u8]) {
self.db.remove_aux(hash);
}
}
struct Wrapping<'db>(&'db HashDB);

View File

@ -594,9 +594,9 @@ mod tests {
use factory::Factories;
use state_db::StateDB;
use views::BlockView;
use util::Address;
use util::{Address, TrieFactory};
use util::hash::FixedHash;
use util::trie::TrieSpec;
use std::sync::Arc;
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
@ -637,7 +637,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
@ -653,7 +653,7 @@ mod tests {
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
.close_and_lock().seal(engine, vec![]).unwrap();
@ -662,7 +662,7 @@ mod tests {
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
assert_eq!(e.rlp_bytes(), orig_bytes);
@ -681,7 +681,7 @@ mod tests {
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut uncle1_header = Header::new();
@ -697,7 +697,7 @@ mod tests {
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let bytes = e.rlp_bytes();

View File

@ -22,7 +22,7 @@ use std::time::{Instant};
use time::precise_time_ns;
// util
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock};
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, Hashable};
use util::{journaldb, TrieFactory, Trie};
use util::trie::TrieSpec;
use util::{U256, H256, Address, H2048, Uint, FixedHash};
@ -172,9 +172,10 @@ impl Client {
false => TrieSpec::Secure,
};
let trie_factory = TrieFactory::new(trie_spec);
let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE);
let mut state_db = StateDB::new(journal_db, config.state_cache_size);
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db)) {
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db, &trie_factory)) {
let mut batch = DBTransaction::new(&db);
try!(state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash()));
try!(db.write(batch).map_err(ClientError::Database));
@ -216,7 +217,7 @@ impl Client {
let factories = Factories {
vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size),
trie: TrieFactory::new(trie_spec),
trie: trie_factory,
accountdb: Default::default(),
};
@ -869,8 +870,8 @@ impl BlockChainClient for Client {
}
fn keep_alive(&self) {
let should_wake = match &*self.mode.lock() {
&Mode::Dark(..) | &Mode::Passive(..) => true,
let should_wake = match *self.mode.lock() {
Mode::Dark(..) | Mode::Passive(..) => true,
_ => false,
};
if should_wake {
@ -952,6 +953,10 @@ impl BlockChainClient for Client {
self.state_at(id).map(|s| s.nonce(address))
}
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256> {
self.state_at(id).and_then(|s| s.storage_root(address))
}
fn block_hash(&self, id: BlockID) -> Option<H256> {
let chain = self.chain.read();
Self::block_hash(&chain, id)
@ -969,7 +974,7 @@ impl BlockChainClient for Client {
self.state_at(id).map(|s| s.storage_at(address, position))
}
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>> {
fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>> {
if !self.factories.trie.is_fat() {
trace!(target: "fatdb", "list_accounts: Not a fat DB");
return None;
@ -989,18 +994,68 @@ impl BlockChainClient for Client {
}
};
let iter = match trie.iter() {
let mut iter = match trie.iter() {
Ok(iter) => iter,
_ => return None,
};
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
}
}
let accounts = iter.filter_map(|item| {
item.ok().map(|(addr, _)| Address::from_slice(&addr))
}).collect();
}).take(count as usize).collect();
Some(accounts)
}
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>> {
if !self.factories.trie.is_fat() {
trace!(target: "fatdb", "list_stroage: Not a fat DB");
return None;
}
let state = match self.state_at(id) {
Some(state) => state,
_ => return None,
};
let root = match state.storage_root(account) {
Some(root) => root,
_ => return None,
};
let (_, db) = state.drop();
let account_db = self.factories.accountdb.readonly(db.as_hashdb(), account.sha3());
let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) {
Ok(trie) => trie,
_ => {
trace!(target: "fatdb", "list_storage: Couldn't open the DB");
return None;
}
};
let mut iter = match trie.iter() {
Ok(iter) => iter,
_ => return None,
};
if let Some(after) = after {
if let Err(e) = iter.seek(after) {
trace!(target: "fatdb", "list_accounts: Couldn't seek the DB: {:?}", e);
}
}
let keys = iter.filter_map(|item| {
item.ok().map(|(key, _)| H256::from_slice(&key))
}).take(count as usize).collect();
Some(keys)
}
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction> {
self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address))
}

View File

@ -333,7 +333,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
let genesis_header = self.spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
self.spec.ensure_db_good(&mut db).unwrap();
self.spec.ensure_db_good(&mut db, &TrieFactory::default()).unwrap();
let last_hashes = vec![genesis_header.hash()];
let mut open_block = OpenBlock::new(
@ -385,6 +385,10 @@ impl BlockChainClient for TestBlockChainClient {
}
}
fn storage_root(&self, _address: &Address, _id: BlockID) -> Option<H256> {
None
}
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockID::Latest).unwrap()
}
@ -416,10 +420,13 @@ impl BlockChainClient for TestBlockChainClient {
}
}
fn list_accounts(&self, _id: BlockID) -> Option<Vec<Address>> {
fn list_accounts(&self, _id: BlockID, _after: Option<&Address>, _count: u64) -> Option<Vec<Address>> {
None
}
fn list_storage(&self, _id: BlockID, _account: &Address, _after: Option<&H256>, _count: u64) -> Option<Vec<H256>> {
None
}
fn transaction(&self, _id: TransactionID) -> Option<LocalizedTransaction> {
None // Simple default.
}

View File

@ -68,6 +68,10 @@ pub trait BlockChainClient : Sync + Send {
/// May not fail on BlockID::Latest.
fn nonce(&self, address: &Address, id: BlockID) -> Option<U256>;
/// Attempt to get address storage root at given block.
/// May not fail on BlockID::Latest.
fn storage_root(&self, address: &Address, id: BlockID) -> Option<H256>;
/// Get address nonce at the latest block's state.
fn latest_nonce(&self, address: &Address) -> U256 {
self.nonce(address, BlockID::Latest)
@ -114,7 +118,12 @@ pub trait BlockChainClient : Sync + Send {
}
/// Get a list of all accounts in the block `id`, if fat DB is in operation, otherwise `None`.
fn list_accounts(&self, id: BlockID) -> Option<Vec<Address>>;
/// If `after` is set the list starts with the following item.
fn list_accounts(&self, id: BlockID, after: Option<&Address>, count: u64) -> Option<Vec<Address>>;
/// Get a list of all storage keys in the block `id`, if fat DB is in operation, otherwise `None`.
/// If `after` is set the list starts with the following item.
fn list_storage(&self, id: BlockID, account: &Address, after: Option<&H256>, count: u64) -> Option<Vec<H256>>;
/// Get transaction with given hash.
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction>;

View File

@ -124,7 +124,7 @@ impl AuthorityRound {
}
fn step_proposer(&self, step: usize) -> &Address {
let ref p = self.our_params;
let p = &self.our_params;
p.authorities.get(step % p.authority_n).expect("There are authority_n authorities; taking number modulo authority_n gives number in authority_n range; qed")
}
@ -211,7 +211,7 @@ impl Engine for AuthorityRound {
fn on_close_block(&self, _block: &mut ExecutedBlock) {}
fn is_sealer(&self, author: &Address) -> Option<bool> {
let ref p = self.our_params;
let p = &self.our_params;
Some(p.authorities.contains(author))
}
@ -279,7 +279,7 @@ impl Engine for AuthorityRound {
let step = try!(header_step(header));
// Check if parent is from a previous step.
if step == try!(header_step(parent)) {
if step == try!(header_step(parent)) {
trace!(target: "poa", "Multiple blocks proposed for step {}.", step);
try!(Err(BlockError::DoubleVote(header.author().clone())));
}
@ -315,6 +315,7 @@ impl Engine for AuthorityRound {
#[cfg(test)]
mod tests {
use util::*;
use util::trie::TrieSpec;
use env_info::EnvInfo;
use header::Header;
use error::{Error, BlockError};
@ -384,9 +385,9 @@ mod tests {
let engine = &*spec.engine;
let genesis_header = spec.genesis_header();
let mut db1 = get_temp_state_db().take();
spec.ensure_db_good(&mut db1).unwrap();
spec.ensure_db_good(&mut db1, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let mut db2 = get_temp_state_db().take();
spec.ensure_db_good(&mut db2).unwrap();
spec.ensure_db_good(&mut db2, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b1 = b1.close_and_lock();

View File

@ -184,6 +184,7 @@ impl Engine for BasicAuthority {
#[cfg(test)]
mod tests {
use util::*;
use util::trie::TrieSpec;
use block::*;
use env_info::EnvInfo;
use error::{BlockError, Error};
@ -256,7 +257,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();

View File

@ -68,6 +68,7 @@ impl Engine for InstantSeal {
#[cfg(test)]
mod tests {
use util::*;
use util::trie::TrieSpec;
use tests::helpers::*;
use account_provider::AccountProvider;
use spec::Spec;
@ -84,7 +85,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();

View File

@ -422,6 +422,7 @@ impl Header {
#[cfg(test)]
mod tests {
use util::*;
use util::trie::TrieSpec;
use block::*;
use tests::helpers::*;
use env_info::EnvInfo;
@ -438,7 +439,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close();
@ -452,7 +453,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut uncle = Header::new();

View File

@ -72,6 +72,7 @@ pub fn new_morden() -> Spec { load(include_bytes!("../../res/ethereum/morden.jso
#[cfg(test)]
mod tests {
use util::*;
use util::trie::TrieSpec;
use state::*;
use super::*;
use tests::helpers::*;
@ -84,7 +85,7 @@ mod tests {
let genesis_header = spec.genesis_header();
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
spec.ensure_db_good(&mut db).unwrap();
spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap();
assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()), 1u64.into());
assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into());

View File

@ -197,19 +197,17 @@ impl<Gas: CostType> Gasometer<Gas> {
let address = u256_to_address(stack.peek(1));
let is_value_transfer = !stack.peek(2).is_zero();
if instruction == instructions::CALL {
if (
!schedule.no_empty && !ext.exists(&address)
) || (
schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)
) {
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
}
};
if instruction == instructions::CALL && (
(!schedule.no_empty && !ext.exists(&address))
||
(schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address))
) {
gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
}
if is_value_transfer {
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
};
}
let requested = *stack.peek(0);
@ -347,7 +345,7 @@ fn test_mem_gas_cost() {
let result = gasometer.mem_gas_cost(&schedule, current_mem_size, &mem_size);
// then
if let Ok(_) = result {
if result.is_ok() {
assert!(false, "Should fail with OutOfGas");
}
}

View File

@ -95,7 +95,7 @@ impl Ext for FakeExt {
}
fn exists_and_not_null(&self, address: &Address) -> bool {
self.balances.get(address).map_or(false, |b| !b.is_zero())
self.balances.get(address).map_or(false, |b| !b.is_zero())
}
fn origin_balance(&self) -> U256 {
@ -103,7 +103,7 @@ impl Ext for FakeExt {
}
fn balance(&self, address: &Address) -> U256 {
*self.balances.get(address).unwrap()
self.balances[address]
}
fn blockhash(&self, number: &U256) -> H256 {

View File

@ -445,7 +445,7 @@ impl<'a> Executive<'a> {
trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender);
// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty);
self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty);
trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author);
self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule));
@ -514,9 +514,11 @@ impl<'a> Executive<'a> {
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use std::sync::Arc;
use ethkey::{Generator, Random};
use super::*;
use util::*;
use util::{H256, U256, U512, Address, Uint, FixedHash, FromHex, FromStr};
use util::bytes::BytesRef;
use action_params::{ActionParams, ActionValue};
use env_info::EnvInfo;
use evm::{Factory, VMType};

View File

@ -151,7 +151,7 @@ impl GasPriceCalibrator {
if Instant::now() >= self.next_calibration {
let usd_per_tx = self.options.usd_per_tx;
trace!(target: "miner", "Getting price info");
if let Ok(_) = PriceInfo::get(move |price: PriceInfo| {
let price_info = PriceInfo::get(move |price: PriceInfo| {
trace!(target: "miner", "Price info arrived: {:?}", price);
let usd_per_eth = price.ethusd;
let wei_per_usd: f32 = 1.0e18 / usd_per_eth;
@ -159,7 +159,9 @@ impl GasPriceCalibrator {
let wei_per_gas: f32 = wei_per_usd * usd_per_tx / gas_per_tx;
info!(target: "miner", "Updated conversion rate to Ξ1 = {} ({} wei/gas)", Colour::White.bold().paint(format!("US${}", usd_per_eth)), Colour::Yellow.bold().paint(format!("{}", wei_per_gas)));
set_price(U256::from(wei_per_gas as u64));
}) {
});
if price_info.is_ok() {
self.next_calibration = Instant::now() + self.options.recalibration_period;
} else {
warn!(target: "miner", "Unable to update Ether price.");
@ -1139,15 +1141,16 @@ impl MinerService for Miner {
#[cfg(test)]
mod tests {
use std::sync::Arc;
use std::time::Duration;
use super::super::{MinerService, PrioritizationStrategy};
use super::*;
use util::*;
use block::IsBlock;
use util::{U256, Uint, FromHex};
use ethkey::{Generator, Random};
use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult};
use header::BlockNumber;
use types::transaction::{Transaction, SignedTransaction, Action};
use block::*;
use spec::Spec;
use tests::helpers::{generate_dummy_client};

View File

@ -990,7 +990,7 @@ impl TransactionQueue {
let mut update_last_nonce_to = None;
{
let by_nonce = self.future.by_address.row_mut(&address);
if let None = by_nonce {
if by_nonce.is_none() {
return;
}
let mut by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed");
@ -1212,12 +1212,12 @@ mod test {
use util::table::*;
use util::*;
use ethkey::{Random, Generator};
use transaction::*;
use error::{Error, TransactionError};
use super::*;
use super::{TransactionSet, TransactionOrder, VerifiedTransaction};
use miner::local_transactions::LocalTransactionsList;
use client::TransactionImportResult;
use transaction::{SignedTransaction, Transaction, Action};
fn unwrap_tx_err(err: Result<TransactionImportResult, Error>) -> TransactionError {
match err.unwrap_err() {

View File

@ -64,13 +64,13 @@ impl PodAccount {
}
/// Place additional data into given hash DB.
pub fn insert_additional(&self, db: &mut AccountDBMut) {
pub fn insert_additional(&self, db: &mut AccountDBMut, factory: &TrieFactory) {
match self.code {
Some(ref c) if !c.is_empty() => { db.insert(c); }
_ => {}
}
let mut r = H256::new();
let mut t = SecTrieDBMut::new(db, &mut r);
let mut t = factory.create(db, &mut r);
for (k, v) in &self.storage {
if let Err(e) = t.insert(k, &rlp::encode(&U256::from(&**v))) {
warn!("Encountered potential DB corruption: {}", e);

View File

@ -552,11 +552,11 @@ const POW_VERIFY_RATE: f32 = 0.02;
pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain: &BlockChain, body: Option<&[u8]>, always: bool) -> Result<(), ::error::Error> {
if always || rng.gen::<f32>() <= POW_VERIFY_RATE {
match chain.block_header(header.parent_hash()) {
Some(parent) => engine.verify_block_family(&header, &parent, body),
None => engine.verify_block_seal(&header),
Some(parent) => engine.verify_block_family(header, &parent, body),
None => engine.verify_block_seal(header),
}
} else {
engine.verify_block_basic(&header, body)
engine.verify_block_basic(header, body)
}
}

View File

@ -244,13 +244,13 @@ impl Spec {
}
/// Ensure that the given state DB has the trie nodes in for the genesis state.
pub fn ensure_db_good(&self, db: &mut StateDB) -> Result<bool, Box<TrieError>> {
pub fn ensure_db_good(&self, db: &mut StateDB, factory: &TrieFactory) -> Result<bool, Box<TrieError>> {
if !db.as_hashdb().contains(&self.state_root()) {
trace!(target: "spec", "ensure_db_good: Fresh database? Cannot find state root {}", self.state_root());
let mut root = H256::new();
{
let mut t = SecTrieDBMut::new(db.as_hashdb_mut(), &mut root);
let mut t = factory.create(db.as_hashdb_mut(), &mut root);
for (address, account) in self.genesis_state.get().iter() {
try!(t.insert(&**address, &account.rlp()));
}
@ -258,7 +258,7 @@ impl Spec {
trace!(target: "spec", "ensure_db_good: Populated sec trie; root is {}", root);
for (address, account) in self.genesis_state.get().iter() {
db.note_non_null_account(address);
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address));
account.insert_additional(&mut AccountDBMut::new(db.as_hashdb_mut(), address), factory);
}
assert!(db.as_hashdb().contains(&self.state_root()));
Ok(true)

View File

@ -314,11 +314,10 @@ impl Account {
self.code_hash == SHA3_EMPTY
}
#[cfg(test)]
/// return the storage root associated with this account or None if it has been altered via the overlay.
/// Return the storage root associated with this account or None if it has been altered via the overlay.
pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} }
/// return the storage overlay.
/// Return the storage overlay.
pub fn storage_changes(&self) -> &HashMap<H256, H256> { &self.storage_changes }
/// Increment the nonce of the account by one.
@ -445,11 +444,10 @@ impl fmt::Debug for Account {
#[cfg(test)]
mod tests {
use rlp::{UntrustedRlp, RlpType, View, Compressible};
use util::*;
use super::*;
use account_db::*;
use rlp::*;
#[test]
fn account_compress() {

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@ impl Substate {
}
/// Get the cleanup mode object from this.
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
match (schedule.no_empty, schedule.kill_empty) {
(false, _) => CleanupMode::ForceCreate,

View File

@ -397,6 +397,7 @@ impl StateDB {
}
/// Get cached code based on hash.
#[cfg_attr(feature="dev", allow(map_clone))]
pub fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
let mut cache = self.code_cache.lock();

View File

@ -62,7 +62,7 @@ fn should_return_registrar() {
&db_config
).unwrap();
let params = client.additional_params();
let address = params.get("registrar").unwrap();
let address = &params["registrar"];
assert_eq!(address.len(), 40);
assert!(U256::from_str(address).is_ok());
@ -93,7 +93,7 @@ fn imports_good_block() {
&db_config
).unwrap();
let good_block = get_good_dummy_block();
if let Err(_) = client.import_block(good_block) {
if client.import_block(good_block).is_err() {
panic!("error importing block being good by definition");
}
client.flush_queue();
@ -203,18 +203,18 @@ fn can_collect_garbage() {
#[test]
fn can_generate_gas_price_median() {
let client_result = generate_dummy_client_with_data(3, 1, &vec_into![1, 2, 3]);
let client_result = generate_dummy_client_with_data(3, 1, slice_into![1, 2, 3]);
let client = client_result.reference();
assert_eq!(Some(U256::from(2)), client.gas_price_median(3));
let client_result = generate_dummy_client_with_data(4, 1, &vec_into![1, 4, 3, 2]);
let client_result = generate_dummy_client_with_data(4, 1, slice_into![1, 4, 3, 2]);
let client = client_result.reference();
assert_eq!(Some(U256::from(3)), client.gas_price_median(4));
}
#[test]
fn can_generate_gas_price_histogram() {
let client_result = generate_dummy_client_with_data(20, 1, &vec_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]);
let client_result = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]);
let client = client_result.reference();
let hist = client.gas_price_histogram(20, 5).unwrap();
@ -224,7 +224,7 @@ fn can_generate_gas_price_histogram() {
#[test]
fn empty_gas_price_histogram() {
let client_result = generate_dummy_client_with_data(20, 0, &vec_into![]);
let client_result = generate_dummy_client_with_data(20, 0, slice_into![]);
let client = client_result.reference();
assert!(client.gas_price_histogram(20, 5).is_none());

View File

@ -18,6 +18,7 @@ use ethkey::KeyPair;
use io::*;
use client::{BlockChainClient, Client, ClientConfig};
use util::*;
use util::trie::TrieSpec;
use spec::*;
use state_db::StateDB;
use block::{OpenBlock, Drain};
@ -157,7 +158,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
let mut db_result = get_temp_state_db();
let mut db = db_result.take();
test_spec.ensure_db_good(&mut db).unwrap();
test_spec.ensure_db_good(&mut db, &TrieFactory::new(TrieSpec::Secure)).unwrap();
let genesis_header = test_spec.genesis_header();
let mut rolling_timestamp = 40;
@ -262,7 +263,7 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<
).unwrap();
for block in &blocks {
if let Err(_) = client.import_block(block.clone()) {
if client.import_block(block.clone()).is_err() {
panic!("panic importing block which is well-formed");
}
}

View File

@ -19,16 +19,16 @@
pub use std::time::Duration;
use client::Mode as ClientMode;
/// IPC-capable shadow-type for client::config::Mode
/// IPC-capable shadow-type for `client::config::Mode`
#[derive(Clone, Binary, Debug)]
pub enum Mode {
/// Same as ClientMode::Off.
/// Same as `ClientMode::Off`.
Off,
/// Same as ClientMode::Dark; values in seconds.
/// Same as `ClientMode::Dark`; values in seconds.
Dark(u64),
/// Same as ClientMode::Passive; values in seconds.
/// Same as `ClientMode::Passive`; values in seconds.
Passive(u64, u64),
/// Same as ClientMode::Active.
/// Same as `ClientMode::Active`.
Active,
}
@ -52,4 +52,4 @@ impl From<Mode> for ClientMode {
Mode::Active => ClientMode::Active,
}
}
}
}

View File

@ -73,7 +73,7 @@ pub struct Transaction {
impl Transaction {
/// Append object with a without signature into RLP stream
pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream, network_id: Option<u8>) {
s.begin_list(if let None = network_id { 6 } else { 9 });
s.begin_list(if network_id.is_none() { 6 } else { 9 });
s.append(&self.nonce);
s.append(&self.gas_price);
s.append(&self.gas);
@ -210,7 +210,7 @@ pub struct SignedTransaction {
/// Plain Transaction.
unsigned: Transaction,
/// The V field of the signature; the LS bit described which half of the curve our point falls
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
/// in. The MS bits describe which network this transaction is for. If 27/28, its for all networks.
v: u8,
/// The R field of the signature; helps describe the point on the curve.
r: U256,
@ -304,7 +304,7 @@ impl SignedTransaction {
/// 0 if `v` would have been 27 under "Electrum" notation, 1 if 28 or 4 if invalid.
pub fn standard_v(&self) -> u8 { match self.v { v if v == 27 || v == 28 || v > 36 => (v - 1) % 2, _ => 4 } }
/// The network ID, or `None` if this is a global transaction.
/// The network ID, or `None` if this is a global transaction.
pub fn network_id(&self) -> Option<u8> {
match self.v {
v if v > 36 => Some((v - 35) / 2),
@ -461,7 +461,7 @@ fn should_agree_with_vitalik() {
let signed: SignedTransaction = decode(&FromHex::from_hex(tx_data).unwrap());
signed.check_low_s().unwrap();
assert_eq!(signed.sender().unwrap(), address.into());
flushln!("networkid: {:?}", signed.network_id());
flushln!("networkid: {:?}", signed.network_id());
};
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce")
@ -474,4 +474,4 @@ fn should_agree_with_vitalik() {
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332")
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029")
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f")
}
}

View File

@ -29,6 +29,7 @@ use header::{BlockNumber, Header};
use rlp::{UntrustedRlp, View};
use transaction::SignedTransaction;
use views::BlockView;
use time::get_time;
/// Preprocessed block data gathered in `verify_block_unordered` call
pub struct PreverifiedBlock {
@ -209,6 +210,10 @@ pub fn verify_header_params(header: &Header, engine: &Engine) -> Result<(), Erro
if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size {
return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() })));
}
let max_time = get_time().sec as u64 + 30;
if header.timestamp() > max_time {
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() })))
}
Ok(())
}
@ -258,6 +263,7 @@ mod tests {
use tests::helpers::*;
use types::log_entry::{LogEntry, LocalizedLogEntry};
use rlp::View;
use time::get_time;
fn check_ok(result: Result<(), Error>) {
result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e));
@ -271,6 +277,14 @@ mod tests {
}
}
fn check_fail_timestamp(result: Result<(), Error>) {
match result {
Err(Error::Block(BlockError::InvalidTimestamp(_))) => (),
Err(other) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: {:?}", other),
Ok(_) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: Ok"),
}
}
struct TestBlockChain {
blocks: HashMap<H256, Bytes>,
numbers: HashMap<BlockNumber, H256>,
@ -515,6 +529,14 @@ mod tests {
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() }));
header = good.clone();
header.set_timestamp(2450000000);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_timestamp(get_time().sec as u64 + 40);
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
header = good.clone();
header.set_number(9);
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),

View File

@ -0,0 +1,4 @@
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle fill="#4A90E2" cx="50" cy="50" r="50"/>
<path d="M20 45 L10 55 L35 85 L90 35 L80 25 L36 65 z" fill="#FFF"/>
</svg>

After

Width:  |  Height:  |  Size: 213 B

View File

@ -1,6 +1,6 @@
{
"name": "parity.js",
"version": "0.2.78",
"version": "0.2.84",
"main": "release/index.js",
"jsnext:main": "src/index.js",
"author": "Parity Team <admin@parity.io>",
@ -72,6 +72,7 @@
"core-js": "~2.4.1",
"coveralls": "~2.11.11",
"css-loader": "~0.26.0",
"ejs-loader": "~0.3.0",
"enzyme": "2.3.0",
"eslint": "~3.10.2",
"eslint-config-semistandard": "~7.0.0",

View File

@ -144,7 +144,8 @@ export function outSignerRequest (request) {
break;
case 'payload':
request[key].transaction = outTransaction(request[key].transaction);
request[key].signTransaction = outTransaction(request[key].signTransaction);
request[key].sendTransaction = outTransaction(request[key].sendTransaction);
break;
}
});

View File

@ -0,0 +1 @@
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]

View File

@ -0,0 +1 @@
[{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"}]

View File

@ -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/>.
import badgereg from './badgereg.json';
import basiccoin from './basiccoin.json';
import basiccoinmanager from './basiccoinmanager.json';
import dappreg from './dappreg.json';
@ -28,6 +29,7 @@ import tokenreg from './tokenreg.json';
import wallet from './wallet.json';
export {
badgereg,
basiccoin,
basiccoinmanager,
dappreg,

View File

@ -0,0 +1,66 @@
// Copyright 2015, 2016 Ethcore (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 { bytesToHex, hex2Ascii } from '../api/util/format';
import ABI from './abi/certifier.json';
const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000';
export default class BadgeReg {
constructor (api, registry) {
this._api = api;
this._registry = registry;
registry.getContract('badgereg');
this.certifiers = {}; // by name
this.contracts = {}; // by name
}
fetchCertifier (name) {
if (this.certifiers[name]) {
return Promise.resolve(this.certifiers[name]);
}
return this._registry.getContract('badgereg')
.then((badgeReg) => {
return badgeReg.instance.fromName.call({}, [name])
.then(([ id, address ]) => {
return Promise.all([
badgeReg.instance.meta.call({}, [id, 'TITLE']),
badgeReg.instance.meta.call({}, [id, 'IMG'])
])
.then(([ title, img ]) => {
title = bytesToHex(title);
title = title === ZERO ? null : hex2Ascii(title);
if (bytesToHex(img) === ZERO) img = null;
const data = { address, name, title, icon: img };
this.certifiers[name] = data;
return data;
});
});
});
}
checkIfCertified (certifier, address) {
if (!this.contracts[certifier]) {
this.contracts[certifier] = this._api.newContract(ABI, certifier);
}
const contract = this.contracts[certifier];
return contract.instance.certified.call({}, [address]);
}
}

View File

@ -20,6 +20,7 @@ import SignatureReg from './signaturereg';
import TokenReg from './tokenreg';
import GithubHint from './githubhint';
import * as smsVerification from './sms-verification';
import BadgeReg from './badgereg';
let instance = null;
@ -33,6 +34,7 @@ export default class Contracts {
this._signaturereg = new SignatureReg(api, this._registry);
this._tokenreg = new TokenReg(api, this._registry);
this._githubhint = new GithubHint(api, this._registry);
this.badgeReg = new BadgeReg(api, this._registry);
}
get registry () {

View File

@ -17,10 +17,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
import { useStrict } from 'mobx';
injectTapEventPlugin();
useStrict(true);
import Application from './dappreg/Application';

View File

@ -11,28 +11,23 @@
height: 100%;
margin: 0;
padding: 0;
}
.loading-container {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: Roboto;
background-color: rgba(0, 0, 0, 0.8);
color: #ddd;
background: white;
font-family: 'Roboto', sans-serif;
font-size: 16px;
font-weight: 300;
}
.loading {
font-size: 4em;
text-align: center;
padding-top: 5em;
font-size: 2em;
color: #999;
}
</style>
</head>
<body>
<div id="container">
<div class="loading-container">
<span class="loading">Loading...</span>
</div>
<div class="loading">Loading</div>
</div>
<script src="vendor.js"></script>
<% if (!htmlWebpackPlugin.options.secure) { %>

View File

@ -11,28 +11,23 @@
height: 100%;
margin: 0;
padding: 0;
}
.loading-container {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: Roboto;
background-color: rgba(0, 0, 0, 0.8);
color: #ddd;
background: white;
font-family: 'Roboto', sans-serif;
font-size: 16px;
font-weight: 300;
}
.loading {
font-size: 4em;
text-align: center;
padding-top: 5em;
font-size: 2em;
color: #999;
}
</style>
</head>
<body>
<div id="container">
<div class="loading-container">
<span class="loading">Loading...</span>
</div>
<div class="loading">Loading</span>
</div>
<script src="vendor.js"></script>
</body>

View File

@ -20,6 +20,7 @@ import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
import ContentClear from 'material-ui/svg-icons/content/clear';
import NavigationArrowBack from 'material-ui/svg-icons/navigation/arrow-back';
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
import PrintIcon from 'material-ui/svg-icons/action/print';
import { Button, Modal } from '../../ui';
@ -32,6 +33,11 @@ import NewImport from './NewImport';
import RawKey from './RawKey';
import RecoveryPhrase from './RecoveryPhrase';
import { createIdentityImg } from '../../api/util/identity';
import print from './print';
import recoveryPage from './recovery-page.ejs';
import ParityLogo from '../../../assets/images/parity-logo-black-no-text.svg';
const TITLES = {
type: 'creation type',
create: 'create account',
@ -179,12 +185,18 @@ export default class CreateAccount extends Component {
];
case 2:
return (
return [
createType === 'fromNew' || createType === 'fromPhrase' ? (
<Button
icon={ <PrintIcon /> }
label='Print Phrase'
onClick={ this.printPhrase } />
) : null,
<Button
icon={ <ActionDoneAll /> }
label='Close'
onClick={ this.onClose } />
);
];
}
}
@ -377,4 +389,11 @@ export default class CreateAccount extends Component {
store.dispatch({ type: 'newError', error });
}
printPhrase = () => {
const { address, phrase, name } = this.state;
const identity = createIdentityImg(address);
print(recoveryPage({ phrase, name, identity, address, logo: ParityLogo }));
}
}

View File

@ -0,0 +1,63 @@
// Copyright 2015, 2016 Ethcore (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/>.
export const onPrint = (window, cb) => {
let called = false; let query, queryFn;
const onPrint = () => {
if (queryFn) {
query.removeListener(queryFn);
}
window.removeEventListener('afterprint', onPrint, false);
if (!called) {
called = true;
cb();
}
};
if (window.matchMedia) {
queryFn = (query) => {
if (!query.matches) {
onPrint();
}
};
query = window.matchMedia('print');
query.addListener(queryFn);
}
window.addEventListener('afterprint', onPrint, false);
};
export default (html) => {
const iframe = document.createElement('iframe');
iframe.setAttribute('sandbox', 'allow-modals allow-same-origin allow-scripts');
iframe.setAttribute('src', '/');
iframe.setAttribute('style', 'display: none');
document.body.appendChild(iframe);
const teardown = () => {
// Safari crashes without a timeout.
setTimeout(() => document.body.removeChild(iframe), 0);
};
setTimeout(() => {
iframe.contentDocument.write(html);
setTimeout(() => {
onPrint(iframe.contentWindow, teardown);
iframe.contentWindow.focus();
iframe.contentWindow.print();
}, 20);
}, 0);
};

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Recovery phrase for <%= name %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
body {
margin: 2em auto;
max-width: 30em;
padding: 1em;
text-align: center;
font-size: 110%;
font-family: sans-serif;
font-weight: 300;
}
#logo {
max-width: 4rem;
margin-bottom: 3rem;
}
p {
margin-bottom: 1rem;
}
figure {
margin-bottom: 1rem;
}
figure.address img {
border-radius: 100%;
}
pre code {
display: inline-block;
text-align: center;
white-space: normal;
line-height: 1.3;
}
</style>
</head>
<body>
<img id="logo" src="<%= logo %>" alt="Parity Logo" />
<p>This is your account <em><%= name %></em>:</p>
<figure class="address">
<img src="<%= identity %>" alt="symbol for the address of the account" />
<figcaption><code><%= address %></code></figcaption>
</figure>
<p>This is the recovery phrase:</p>
<pre><code><%= phrase %></code></pre>
</body>
</html>

View File

@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
import ActionDone from 'material-ui/svg-icons/action/done';
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
import PrintIcon from 'material-ui/svg-icons/action/print';
import { Button, Modal } from '../../ui';
@ -27,6 +28,11 @@ import Completed from './Completed';
import TnC from './TnC';
import Welcome from './Welcome';
import { createIdentityImg } from '../../api/util/identity';
import print from '../CreateAccount/print';
import recoveryPage from '../CreateAccount/recovery-page.ejs';
import ParityLogo from '../../../assets/images/parity-logo-black-no-text.svg';
const STAGE_NAMES = ['welcome', 'terms', 'new account', 'recovery', 'completed'];
export default class FirstRun extends Component {
@ -107,7 +113,6 @@ export default class FirstRun extends Component {
switch (stage) {
case 0:
case 3:
return (
<Button
icon={ <NavigationArrowForward /> }
@ -133,6 +138,20 @@ export default class FirstRun extends Component {
onClick={ this.onCreate } />
);
case 3:
return [
<Button
icon={ <PrintIcon /> }
label='Print Phrase'
onClick={ this.printPhrase }
/>,
<Button
icon={ <NavigationArrowForward /> }
label='Next'
onClick={ this.onNext }
/>
];
case 4:
return (
<Button
@ -205,4 +224,11 @@ export default class FirstRun extends Component {
store.dispatch({ type: 'newError', error });
}
printPhrase = () => {
const { address, phrase, name } = this.state;
const identity = createIdentityImg(address);
print(recoveryPage({ phrase, name, identity, address, logo: ParityLogo }));
}
}

View File

@ -20,17 +20,20 @@ import SettingsMiddleware from '../views/Settings/middleware';
import SignerMiddleware from './providers/signerMiddleware';
import statusMiddleware from '../views/Status/middleware';
import CertificationsMiddleware from './providers/certifications/middleware';
export default function (api) {
const errors = new ErrorsMiddleware();
const signer = new SignerMiddleware(api);
const settings = new SettingsMiddleware();
const status = statusMiddleware();
const certifications = new CertificationsMiddleware();
const middleware = [
settings.toMiddleware(),
signer.toMiddleware(),
errors.toMiddleware()
errors.toMiddleware(),
certifications.toMiddleware()
];
return middleware.concat(status, thunk);

View File

@ -0,0 +1,23 @@
// Copyright 2015, 2016 Ethcore (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/>.
export const fetchCertifications = (address) => ({
type: 'fetchCertifications', address
});
export const addCertification = (address, name, title, icon) => ({
type: 'addCertification', address, name, title, icon
});

View File

@ -0,0 +1,51 @@
// Copyright 2015, 2016 Ethcore (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 Contracts from '../../../contracts';
import { addCertification } from './actions';
const knownCertifiers = [ 'smsverification' ];
export default class CertificationsMiddleware {
toMiddleware () {
return (store) => (next) => (action) => {
if (action.type !== 'fetchCertifications') {
return next(action);
}
const { address } = action;
const badgeReg = Contracts.get().badgeReg;
knownCertifiers.forEach((name) => {
badgeReg.fetchCertifier(name)
.then((cert) => {
return badgeReg.checkIfCertified(cert.address, address)
.then((isCertified) => {
if (isCertified) {
const { name, title, icon } = cert;
store.dispatch(addCertification(address, name, title, icon));
}
});
})
.catch((err) => {
if (err) {
console.error(`Failed to check if ${address} certified by ${name}:`, err);
}
});
});
};
}
}

View File

@ -0,0 +1,33 @@
// Copyright 2015, 2016 Ethcore (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/>.
const initialState = {};
export default (state = initialState, action) => {
if (action.type !== 'addCertification') {
return state;
}
const { address, name, icon, title } = action;
const certifications = state[address] || [];
if (certifications.some((c) => c.name === name)) {
return state;
}
const newCertifications = certifications.concat({ name, icon, title });
return { ...state, [address]: newCertifications };
};

View File

@ -72,9 +72,8 @@ export default class SignerMiddleware {
};
// Sign request in-browser
if (wallet && payload.transaction) {
const { transaction } = payload;
const transaction = payload.sendTransaction || payload.signTransaction;
if (wallet && transaction) {
(transaction.nonce.isZero()
? this._api.parity.nextNonce(transaction.from)
: Promise.resolve(transaction.nonce)

View File

@ -18,6 +18,7 @@ import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer } from './providers';
import certificationsReducer from './providers/certifications/reducer';
import errorReducer from '../ui/Errors/reducers';
import settingsReducer from '../views/Settings/reducers';
@ -32,6 +33,7 @@ export default function () {
settings: settingsReducer,
balances: balancesReducer,
certifications: certificationsReducer,
blockchain: blockchainReducer,
compiler: compilerReducer,
images: imagesReducer,

View File

@ -0,0 +1,46 @@
/* Copyright 2015, 2016 Ethcore (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/>.
*/
.certifications {
margin-top: 1em;
}
.certification {
display: inline-block;
position: relative;
margin-right: .5em;
padding: .3em .6em .2em 2.6em;
border-radius: 1em;
line-height: 1em;
text-transform: uppercase;
background-color: rgba(255, 255, 255, 0.07);
}
.certification:last-child {
margin-right: 0;
}
.icon {
position: absolute;
top: -.25em;
left: 0;
width: 2em;
height: 2em;
margin: 0;
padding: 0;
border-radius: 1em;
}

View File

@ -0,0 +1,87 @@
// Copyright 2015, 2016 Ethcore (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 React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { hashToImageUrl } from '../../redux/providers/imagesReducer';
import { fetchCertifications } from '../../redux/providers/certifications/actions';
import defaultIcon from '../../../assets/images/certifications/unknown.svg';
import styles from './certifications.css';
class Certifications extends Component {
static propTypes = {
account: PropTypes.string.isRequired,
certifications: PropTypes.array.isRequired,
dappsUrl: PropTypes.string.isRequired,
fetchCertifications: PropTypes.func.isRequired
}
componentWillMount () {
const { account, fetchCertifications } = this.props;
fetchCertifications(account);
}
render () {
const { certifications } = this.props;
if (certifications.length === 0) {
return null;
}
return (
<div className={ styles.certifications }>
{ certifications.map(this.renderCertification) }
</div>
);
}
renderCertification = (certification) => {
const { name, title, icon } = certification;
const { dappsUrl } = this.props;
const classNames = `${styles.certification} ${!icon ? styles.noIcon : ''}`;
const img = icon ? dappsUrl + hashToImageUrl(icon) : defaultIcon;
return (
<div className={ classNames } key={ name }>
<img className={ styles.icon } src={ img } />
<div className={ styles.text }>{ title || name }</div>
</div>
);
}
}
function mapStateToProps (_, initProps) {
const { account } = initProps;
return (state) => {
const certifications = state.certifications[account] || [];
return { certifications };
};
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({ fetchCertifications }, dispatch);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Certifications);

View File

@ -0,0 +1,17 @@
// Copyright 2015, 2016 Ethcore (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/>.
export default from './certifications';

View File

@ -92,7 +92,9 @@ export default class Store {
Promise
.all(txhashes.map((txhash) => this._api.eth.getTransactionByHash(txhash)))
.then((transactions) => {
.then((_transactions) => {
const transactions = _transactions.filter((tx) => tx);
this.addTransactions(
transactions.reduce((transactions, tx, index) => {
transactions[txhashes[index]] = tx;

View File

@ -23,6 +23,7 @@ import Badge from './Badge';
import Balance from './Balance';
import BlockStatus from './BlockStatus';
import Button from './Button';
import Certifications from './Certifications';
import ConfirmDialog from './ConfirmDialog';
import Container, { Title as ContainerTitle } from './Container';
import ContextProvider from './ContextProvider';
@ -55,6 +56,7 @@ export {
Balance,
BlockStatus,
Button,
Certifications,
ConfirmDialog,
Container,
ContainerTitle,

View File

@ -18,6 +18,7 @@ import React, { Component, PropTypes } from 'react';
import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags } from '../../../ui';
import CopyToClipboard from '../../../ui/CopyToClipboard';
import Certifications from '../../../ui/Certifications';
import styles from './header.css';
@ -32,6 +33,7 @@ export default class Header extends Component {
}
render () {
const { api } = this.context;
const { account, balance } = this.props;
const { address, meta, uuid } = account;
@ -67,6 +69,10 @@ export default class Header extends Component {
<Balance
account={ account }
balance={ balance } />
<Certifications
account={ account.address }
dappsUrl={ api.dappsUrl }
/>
</div>
</Container>
</div>

View File

@ -64,12 +64,6 @@ class Account extends Component {
}
componentDidMount () {
const { api } = this.context;
const { address } = this.props.params;
const { isTestnet } = this.props;
const verificationStore = new VerificationStore(api, address, isTestnet);
this.setState({ verificationStore });
this.setVisibleAccounts();
}
@ -80,6 +74,15 @@ class Account extends Component {
if (prevAddress !== nextAddress) {
this.setVisibleAccounts(nextProps);
}
const { isTestnet } = nextProps;
if (typeof isTestnet === 'boolean' && !this.state.verificationStore) {
const { api } = this.context;
const { address } = nextProps.params;
this.setState({
verificationStore: new VerificationStore(api, address, isTestnet)
});
}
}
componentWillUnmount () {
@ -115,7 +118,8 @@ class Account extends Component {
<Page>
<Header
account={ account }
balance={ balance } />
balance={ balance }
/>
<Transactions
accounts={ accounts }
address={ address } />

View File

@ -19,10 +19,17 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Snackbar as SnackbarMUI } from 'material-ui';
import { darkBlack } from 'material-ui/styles/colors';
import { darkBlack, grey800 } from 'material-ui/styles/colors';
import { closeSnackbar } from '../../../redux/providers/snackbarActions';
const bodyStyle = {
backgroundColor: darkBlack,
borderStyle: 'solid',
borderColor: grey800,
borderWidth: '1px 1px 0 1px'
};
class Snackbar extends Component {
static propTypes = {
closeSnackbar: PropTypes.func.isRequired,
@ -40,7 +47,7 @@ class Snackbar extends Component {
open={ open }
message={ message }
autoHideDuration={ cooldown }
bodyStyle={ { backgroundColor: darkBlack } }
bodyStyle={ bodyStyle }
onRequestClose={ this.handleClose }
/>
);

View File

@ -15,45 +15,46 @@
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/
.status {
padding: 0.5em;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
display: flex;
align-items: center;
padding: .4em .5em;
font-size: x-small;
color: #ccc;
background-color: rgba(0, 0, 0, 0.2)
}
.title {
margin: 0 0.5em 0 2em;
background-color: rgba(0, 0, 0, 0.8);
}
.enode {
word-wrap: break-word;
float: right;
}
.enode > * {
display: inline-block;
margin: 0.25em 0.5em;
vertical-align: top;
margin: 0 .25em;
vertical-align: middle;
}
.block {
.enode > :last-child {
margin-right: 0;
}
.netinfo {
display: flex;
flex-grow: 1;
align-items: center;
color: #ddd;
color: #ddd;
}
.netinfo > * {
display: inline-block;
margin-left: 1em;
}
.network {
padding: 0.25em 0.5em;
display: inline-block;
border-radius: 4px;
border-radius: .4em;
line-height: 1.2;
text-transform: uppercase;
}
@ -65,14 +66,3 @@
.networktest {
background: rgb(136, 0, 0);
}
.peers {
}
.version {
padding: 0.25em 0.5em;
float: left;
}
.syncing {
}

View File

@ -46,7 +46,6 @@ class Status extends Component {
<div className={ styles.version }>
{ clientVersion }
</div>
{ this.renderEnode() }
<div className={ styles.netinfo }>
<BlockStatus />
<div className={ netStyle }>
@ -56,6 +55,7 @@ class Status extends Component {
{ netPeers.active.toFormat() }/{ netPeers.connected.toFormat() }/{ netPeers.max.toFormat() } peers
</div>
</div>
{ this.renderEnode() }
</div>
);
}
@ -73,7 +73,7 @@ class Status extends Component {
return (
<div className={ styles.enode }>
<CopyToClipboard data={ enode } />
<CopyToClipboard data={ enode } size={ 12 } />
<div>{ abbreviated }</div>
</div>
);

View File

@ -59,7 +59,7 @@ class Tab extends Component {
selected={ active }
icon={ view.icon }
label={ label }
onClick={ this.handleClick }
onTouchTap={ this.handleClick }
>
{ children }
</MUITab>

View File

@ -21,3 +21,7 @@
display: flex;
flex-direction: column;
}
.container {
padding-bottom: 1.6em;
}

View File

@ -16,7 +16,7 @@
import React, { Component, PropTypes } from 'react';
import { Container, ContainerTitle } from '../../../ui';
import { Container } from '../../../ui';
import Event from './Event';
import styles from '../contract.css';
@ -48,8 +48,7 @@ export default class Events extends Component {
});
return (
<Container>
<ContainerTitle title='events' />
<Container title='events'>
<table className={ styles.events }>
<tbody>{ list }</tbody>
</table>

View File

@ -19,7 +19,7 @@ import React, { Component, PropTypes } from 'react';
import { Card, CardTitle, CardText } from 'material-ui/Card';
import InputQuery from './inputQuery';
import { Container, ContainerTitle, Input, InputAddress } from '../../../ui';
import { Container, Input, InputAddress } from '../../../ui';
import styles from './queries.css';
@ -55,8 +55,7 @@ export default class Queries extends Component {
.map((fn) => this.renderInputQuery(fn));
return (
<Container>
<ContainerTitle title='queries' />
<Container title='queries'>
<div className={ styles.methods }>
<div className={ styles.vMethods }>
{ noInputQueries }

View File

@ -132,7 +132,8 @@ class Contract extends Component {
<Page>
<Header
account={ account }
balance={ balance } />
balance={ balance }
/>
<Queries
contract={ contract }
values={ queryValues } />
@ -447,7 +448,10 @@ function mapStateToProps (state) {
}
function mapDispatchToProps (dispatch) {
return bindActionCreators({ newError, setVisibleAccounts }, dispatch);
return bindActionCreators({
newError,
setVisibleAccounts
}, dispatch);
}
export default connect(

View File

@ -42,25 +42,26 @@
}
.expanded {
right: 16px;
max-height: 300px;
right: 1em;
border-radius: 4px 4px 0 0;
overflow-y: auto;
display: flex;
flex-direction: column;
max-height: 19em;
}
.expanded .content {
flex: 1;
overflow: auto;
overflow-y: auto;
overflow-x: hidden;
display: flex;
background: rgba(0, 0, 0, 0.8);
min-height: 16em;
}
.corner {
position: absolute;
bottom: 0;
right: 16px;
right: 1em;
border-radius: 4px 4px 0 0;
}
@ -118,7 +119,7 @@
}
.header {
height: 36px;
height: 2em;
padding: 0.5em 1em;
background: rgba(0, 0, 0, 0.25);
margin-bottom: 0;
@ -148,6 +149,7 @@
.actions {
float: right;
margin-top: -2px;
}
.actions div {

View File

@ -19,7 +19,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import NavigationRefresh from 'material-ui/svg-icons/navigation/refresh';
import { Button, Container, ContainerTitle, ParityBackground } from '../../../ui';
import { Button, Container, ParityBackground } from '../../../ui';
import { updateBackground } from '../actions';
@ -55,8 +55,7 @@ class Background extends Component {
render () {
return (
<Container>
<ContainerTitle title='Background Pattern' />
<Container title='Background Pattern'>
<div className={ layout.layout }>
<div className={ layout.overview }>
<div>The background pattern you can see right now is unique to your Parity installation. It will change every time you create a new Signer token. This is so that decentralized applications cannot pretend to be trustworthy.</div>

View File

@ -17,7 +17,7 @@
import React, { Component, PropTypes } from 'react';
import { MenuItem } from 'material-ui';
import { Select, Container, ContainerTitle } from '../../../ui';
import { Select, Container } from '../../../ui';
import layout from '../layout.css';
@ -43,8 +43,7 @@ export default class Parity extends Component {
render () {
return (
<Container>
<ContainerTitle title='Parity' />
<Container title='Parity'>
<div className={ layout.layout }>
<div className={ layout.overview }>
<div>Control the Parity node settings and mode of operation via this interface.</div>

View File

@ -16,7 +16,7 @@
import React, { Component, PropTypes } from 'react';
import { Container, ContainerTitle } from '../../../ui';
import { Container } from '../../../ui';
import layout from '../layout.css';
import styles from './proxy.css';
@ -31,8 +31,7 @@ export default class Proxy extends Component {
const proxyurl = `${dappsUrl}/proxy/proxy.pac`;
return (
<Container>
<ContainerTitle title='Proxy' />
<Container title='Proxy'>
<div className={ layout.layout }>
<div className={ layout.overview }>
<div>The proxy setup allows you to access Parity and all associated decentralized applications via memorable addresses.</div>

View File

@ -19,7 +19,7 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Checkbox } from 'material-ui';
import { Container, ContainerTitle } from '../../../ui';
import { Container } from '../../../ui';
import { toggleView } from '../actions';
@ -34,8 +34,7 @@ class Views extends Component {
render () {
return (
<Container>
<ContainerTitle title='Views' />
<Container title='Views'>
<div className={ layout.layout }>
<div className={ layout.overview }>
<div>Manage the available application views, using only the parts of the application that is applicable to you.</div>

View File

@ -27,7 +27,8 @@ export default class RequestPending extends Component {
isSending: PropTypes.bool.isRequired,
date: PropTypes.instanceOf(Date).isRequired,
payload: PropTypes.oneOfType([
PropTypes.shape({ transaction: PropTypes.object.isRequired }),
PropTypes.shape({ signTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sendTransaction: PropTypes.object.isRequired }),
PropTypes.shape({ sign: PropTypes.object.isRequired })
]).isRequired,
className: PropTypes.string,
@ -64,9 +65,8 @@ export default class RequestPending extends Component {
);
}
if (payload.transaction) {
const { transaction } = payload;
const transaction = payload.sendTransaction || payload.signTransaction;
if (transaction) {
return (
<TransactionPending
className={ className }

View File

@ -20,7 +20,7 @@ import AvPlay from 'material-ui/svg-icons/av/play-arrow';
import AvReplay from 'material-ui/svg-icons/av/replay';
import ReorderIcon from 'material-ui/svg-icons/action/reorder';
import { Container, ContainerTitle } from '../../../../ui';
import { Container } from '../../../../ui';
import styles from './Debug.css';
@ -42,9 +42,7 @@ export default class Debug extends Component {
const { devLogsLevels } = nodeStatus;
return (
<Container>
<ContainerTitle
title='Node Logs' />
<Container title='Node Logs'>
{ this.renderActions() }
<h2 className={ styles.subheader }>
{ devLogsLevels || '-' }

View File

@ -64,6 +64,10 @@ module.exports = {
test: /\.json$/,
use: [ 'json-loader' ]
},
{
test: /\.ejs$/,
use: [ 'ejs-loader' ]
},
{
test: /\.html$/,
use: [

View File

@ -10,7 +10,7 @@ rustc-serialize = "0.3"
serde = "0.8"
serde_json = "0.8"
serde_macros = { version = "0.8", optional = true }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
[build-dependencies]
serde_codegen = { version = "0.8", optional = true }

View File

@ -22,7 +22,7 @@ use std::thread::sleep;
use std::sync::Arc;
use rustc_serialize::hex::FromHex;
use io::{PanicHandler, ForwardPanic};
use util::{ToPretty, Uint};
use util::{ToPretty, Uint, U256, H256, Address, Hashable};
use rlp::PayloadInfo;
use ethcore::service::ClientService;
use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockImportError, BlockChainClient, BlockID};
@ -65,6 +65,7 @@ impl FromStr for DataFormat {
pub enum BlockchainCmd {
Import(ImportBlockchain),
Export(ExportBlockchain),
ExportState(ExportState),
}
#[derive(Debug, PartialEq)]
@ -103,10 +104,31 @@ pub struct ExportBlockchain {
pub check_seal: bool,
}
#[derive(Debug, PartialEq)]
pub struct ExportState {
pub spec: SpecType,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
pub format: Option<DataFormat>,
pub pruning: Pruning,
pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub fat_db: Switch,
pub tracing: Switch,
pub at: BlockID,
pub storage: bool,
pub code: bool,
pub min_balance: Option<U256>,
pub max_balance: Option<U256>,
}
pub fn execute(cmd: BlockchainCmd) -> Result<String, String> {
match cmd {
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
BlockchainCmd::Export(export_cmd) => execute_export(export_cmd),
BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd),
}
}
@ -245,6 +267,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
// save user defaults
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
try!(user_defaults.save(&user_defaults_path));
let report = client.report();
@ -261,23 +284,28 @@ fn execute_import(cmd: ImportBlockchain) -> Result<String, String> {
).into())
}
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
// Setup panic handler
let panic_handler = PanicHandler::new_in_arc();
fn start_client(
dirs: Directories,
spec: SpecType,
pruning: Pruning,
pruning_history: u64,
tracing: Switch,
fat_db: Switch,
compaction: DatabaseCompactionProfile,
wal: bool,
cache_config: CacheConfig) -> Result<ClientService, String> {
// create dirs used by parity
try!(cmd.dirs.create_dirs(false, false));
let format = cmd.format.unwrap_or_default();
try!(dirs.create_dirs(false, false));
// load spec file
let spec = try!(cmd.spec.spec());
let spec = try!(spec.spec());
// load genesis hash
let genesis_hash = spec.genesis_header().hash();
// database paths
let db_dirs = cmd.dirs.database(genesis_hash, spec.fork_name.clone());
let db_dirs = dirs.database(genesis_hash, spec.fork_name.clone());
// user defaults path
let user_defaults_path = db_dirs.user_defaults_path();
@ -288,34 +316,42 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
fdlimit::raise_fd_limit();
// select pruning algorithm
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
let algorithm = pruning.to_algorithm(&user_defaults);
// check if tracing is on
let tracing = try!(tracing_switch_to_bool(cmd.tracing, &user_defaults));
let tracing = try!(tracing_switch_to_bool(tracing, &user_defaults));
// check if fatdb is on
let fat_db = try!(fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm));
let fat_db = try!(fatdb_switch_to_bool(fat_db, &user_defaults, algorithm));
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
// execute upgrades
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile(db_dirs.fork_path().as_path())));
try!(execute_upgrades(&db_dirs, algorithm, compaction.compaction_profile(db_dirs.fork_path().as_path())));
// prepare client config
let client_config = to_client_config(&cmd.cache_config, Mode::Active, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history, cmd.check_seal);
let client_config = to_client_config(&cache_config, Mode::Active, tracing, fat_db, compaction, wal, VMType::default(), "".into(), algorithm, pruning_history, true);
let service = try!(ClientService::start(
client_config,
&spec,
&client_path,
&snapshot_path,
&cmd.dirs.ipc_path(),
&dirs.ipc_path(),
Arc::new(Miner::with_spec(&spec)),
).map_err(|e| format!("Client service error: {:?}", e)));
drop(spec);
Ok(service)
}
fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
// Setup panic handler
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
let panic_handler = PanicHandler::new_in_arc();
let format = cmd.format.unwrap_or_default();
panic_handler.forward_from(&service);
let client = service.client();
@ -329,6 +365,9 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
let to = try!(client.block_number(cmd.to_block).ok_or("To block could not be found"));
for i in from..(to + 1) {
if i % 10000 == 0 {
info!("#{}", i);
}
let b = try!(client.block(BlockID::Number(i)).ok_or("Error exporting incomplete chain"));
match format {
DataFormat::Binary => { out.write(&b).expect("Couldn't write to stream."); }
@ -339,6 +378,85 @@ fn execute_export(cmd: ExportBlockchain) -> Result<String, String> {
Ok("Export completed.".into())
}
fn execute_export_state(cmd: ExportState) -> Result<String, String> {
// Setup panic handler
let service = try!(start_client(cmd.dirs, cmd.spec, cmd.pruning, cmd.pruning_history, cmd.tracing, cmd.fat_db, cmd.compaction, cmd.wal, cmd.cache_config));
let panic_handler = PanicHandler::new_in_arc();
panic_handler.forward_from(&service);
let client = service.client();
let mut out: Box<io::Write> = match cmd.file_path {
Some(f) => Box::new(try!(fs::File::create(&f).map_err(|_| format!("Cannot write to file given: {}", f)))),
None => Box::new(io::stdout()),
};
let mut last: Option<Address> = None;
let at = cmd.at;
let mut i = 0usize;
out.write_fmt(format_args!("{{ \"state\": [", )).expect("Couldn't write to stream.");
loop {
let accounts = try!(client.list_accounts(at, last.as_ref(), 1000).ok_or("Specified block not found"));
if accounts.is_empty() {
break;
}
for account in accounts.into_iter() {
let balance = client.balance(&account, at).unwrap_or_else(U256::zero);
if cmd.min_balance.map_or(false, |m| balance < m) || cmd.max_balance.map_or(false, |m| balance > m) {
last = Some(account);
continue; //filtered out
}
if i != 0 {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\"0x{}\": {{\"balance\": \"{:x}\", \"nonce\": \"{:x}\"", account.hex(), balance, client.nonce(&account, at).unwrap_or_else(U256::zero))).expect("Write error");
let code = client.code(&account, at).unwrap_or(None).unwrap_or_else(Vec::new);
if !code.is_empty() {
out.write_fmt(format_args!(", \"code_hash\": \"0x{}\"", code.sha3().hex())).expect("Write error");
if cmd.code {
out.write_fmt(format_args!(", \"code\": \"{}\"", code.to_hex())).expect("Write error");
}
}
let storage_root = client.storage_root(&account, at).unwrap_or(::util::SHA3_NULL_RLP);
if storage_root != ::util::SHA3_NULL_RLP {
out.write_fmt(format_args!(", \"storage_root\": \"0x{}\"", storage_root.hex())).expect("Write error");
if cmd.storage {
out.write_fmt(format_args!(", \"storage\": {{")).expect("Write error");
let mut last_storage: Option<H256> = None;
loop {
let keys = try!(client.list_storage(at, &account, last_storage.as_ref(), 1000).ok_or("Specified block not found"));
if keys.is_empty() {
break;
}
let mut si = 0;
for key in keys.into_iter() {
if si != 0 {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!("\n\t\"0x{}\": \"0x{}\"", key.hex(), client.storage_at(&account, &key, at).unwrap_or_else(Default::default).hex())).expect("Write error");
si += 1;
last_storage = Some(key);
}
}
out.write(b"\n}").expect("Write error");
}
}
out.write(b"}").expect("Write error");
i += 1;
if i % 10000 == 0 {
info!("Account #{}", i);
}
last = Some(account);
}
}
out.write_fmt(format_args!("\n]}}")).expect("Write error");
Ok("Export completed.".into())
}
#[cfg(test)]
mod test {
use super::DataFormat;

View File

@ -26,6 +26,8 @@ usage! {
cmd_new: bool,
cmd_list: bool,
cmd_export: bool,
cmd_blocks: bool,
cmd_state: bool,
cmd_import: bool,
cmd_signer: bool,
cmd_new_token: bool,
@ -246,6 +248,10 @@ usage! {
flag_to: String = "latest", or |_| None,
flag_format: Option<String> = None, or |_| None,
flag_no_seal_check: bool = false, or |_| None,
flag_no_storage: bool = false, or |_| None,
flag_no_code: bool = false, or |_| None,
flag_min_balance: Option<String> = None, or |_| None,
flag_max_balance: Option<String> = None, or |_| None,
// -- Snapshot Optons
flag_at: String = "latest", or |_| None,
@ -484,6 +490,8 @@ mod tests {
cmd_new: false,
cmd_list: false,
cmd_export: false,
cmd_state: false,
cmd_blocks: false,
cmd_import: false,
cmd_signer: false,
cmd_new_token: false,
@ -600,6 +608,10 @@ mod tests {
flag_to: "latest".into(),
flag_format: None,
flag_no_seal_check: false,
flag_no_code: false,
flag_no_storage: false,
flag_min_balance: None,
flag_max_balance: None,
// -- Snapshot Optons
flag_at: "latest".into(),

View File

@ -10,7 +10,7 @@ Usage:
parity account import <path>... [options]
parity wallet import <path> --password FILE [options]
parity import [ <file> ] [options]
parity export [ <file> ] [options]
parity export (blocks | state) [ <file> ] [options]
parity signer new-token [options]
parity snapshot <file> [options]
parity restore [ <file> ] [options]
@ -271,6 +271,16 @@ Import/Export Options:
one of 'hex' and 'binary'.
(default: {flag_format:?} = Import: auto, Export: binary)
--no-seal-check Skip block seal check. (default: {flag_no_seal_check})
--at BLOCK Export state at the given block, which may be an
index, hash, or 'latest'. Note that taking snapshots at
non-recent blocks will only work with --pruning archive
(default: {flag_at})
--no-storage Don't export account storge. (default: {flag_no_storage})
--no-code Don't export account code. (default: {flag_no_code})
--min-balance WEI Don't export accounts with balance less than specified.
(default: {flag_min_balance:?})
--max-balance WEI Don't export accounts with balance greater than specified.
(default: {flag_max_balance:?})
Snapshot Options:
--at BLOCK Take a snapshot at the given block, which may be an

View File

@ -37,7 +37,7 @@ use dir::Directories;
use dapps::Configuration as DappsConfiguration;
use signer::{Configuration as SignerConfiguration};
use run::RunCmd;
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, ExportState, DataFormat};
use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ImportAccounts, ImportFromGethAccounts};
use snapshot::{self, SnapshotCommand};
@ -161,23 +161,47 @@ impl Configuration {
};
Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
} else if self.args.cmd_export {
let export_cmd = ExportBlockchain {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
from_block: try!(to_block_id(&self.args.flag_from)),
to_block: try!(to_block_id(&self.args.flag_to)),
check_seal: !self.args.flag_no_seal_check,
};
Cmd::Blockchain(BlockchainCmd::Export(export_cmd))
if self.args.cmd_blocks {
let export_cmd = ExportBlockchain {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
from_block: try!(to_block_id(&self.args.flag_from)),
to_block: try!(to_block_id(&self.args.flag_to)),
check_seal: !self.args.flag_no_seal_check,
};
Cmd::Blockchain(BlockchainCmd::Export(export_cmd))
} else if self.args.cmd_state {
let export_cmd = ExportState {
spec: spec,
cache_config: cache_config,
dirs: dirs,
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
pruning_history: pruning_history,
compaction: compaction,
wal: wal,
tracing: tracing,
fat_db: fat_db,
at: try!(to_block_id(&self.args.flag_at)),
storage: !self.args.flag_no_storage,
code: !self.args.flag_no_code,
min_balance: self.args.flag_min_balance.and_then(|s| to_u256(&s).ok()),
max_balance: self.args.flag_max_balance.and_then(|s| to_u256(&s).ok()),
};
Cmd::Blockchain(BlockchainCmd::ExportState(export_cmd))
} else {
unreachable!();
}
} else if self.args.cmd_snapshot {
let snapshot_cmd = SnapshotCommand {
cache_config: cache_config,
@ -690,7 +714,7 @@ mod tests {
use helpers::{replace_home, default_network_config};
use run::RunCmd;
use signer::{Configuration as SignerConfiguration};
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat};
use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, DataFormat, ExportState};
use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ImportAccounts};
use devtools::{RandomTempPath};
@ -779,7 +803,7 @@ mod tests {
#[test]
fn test_command_blockchain_export() {
let args = vec!["parity", "export", "blockchain.json"];
let args = vec!["parity", "export", "blocks", "blockchain.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(),
@ -799,9 +823,33 @@ mod tests {
})));
}
#[test]
fn test_command_state_export() {
let args = vec!["parity", "export", "state", "state.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::ExportState(ExportState {
spec: Default::default(),
cache_config: Default::default(),
dirs: Default::default(),
file_path: Some("state.json".into()),
pruning: Default::default(),
pruning_history: 64,
format: Default::default(),
compaction: Default::default(),
wal: true,
tracing: Default::default(),
fat_db: Default::default(),
at: BlockID::Latest,
storage: true,
code: true,
min_balance: None,
max_balance: None,
})));
}
#[test]
fn test_command_blockchain_export_with_custom_format() {
let args = vec!["parity", "export", "--format", "hex", "blockchain.json"];
let args = vec!["parity", "export", "blocks", "--format", "hex", "blockchain.json"];
let conf = parse(&args);
assert_eq!(conf.into_command().unwrap().cmd, Cmd::Blockchain(BlockchainCmd::Export(ExportBlockchain {
spec: Default::default(),

View File

@ -257,17 +257,13 @@ pub fn tracing_switch_to_bool(switch: Switch, user_defaults: &UserDefaults) -> R
}
}
pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, algorithm: Algorithm) -> Result<bool, String> {
pub fn fatdb_switch_to_bool(switch: Switch, user_defaults: &UserDefaults, _algorithm: Algorithm) -> Result<bool, String> {
let result = match (user_defaults.is_first_launch, switch, user_defaults.fat_db) {
(false, Switch::On, false) => Err("FatDB resync required".into()),
(_, Switch::On, _) => Ok(true),
(_, Switch::Off, _) => Ok(false),
(_, Switch::Auto, def) => Ok(def),
};
if result.clone().unwrap_or(false) && algorithm != Algorithm::Archive {
return Err("Fat DB is not supported with the chosen pruning option. Please rerun with `--pruning=archive`".into());
}
result
}

View File

@ -156,7 +156,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// get the mode
let mode = try!(mode_switch_to_bool(cmd.mode, &user_defaults));
trace!(target: "mode", "mode is {:?}", mode);
let network_enabled = match &mode { &Mode::Dark(_) | &Mode::Off => false, _ => true, };
let network_enabled = match mode { Mode::Dark(_) | Mode::Off => false, _ => true, };
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
@ -219,7 +219,7 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// create client config
let client_config = to_client_config(
&cmd.cache_config,
mode,
mode.clone(),
tracing,
fat_db,
cmd.compaction,
@ -354,6 +354,8 @@ pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<(), String> {
// save user defaults
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
user_defaults.mode = mode;
try!(user_defaults.save(&user_defaults_path));
let on_mode_change = move |mode: &Mode| {

View File

@ -29,7 +29,7 @@ fetch = { path = "../util/fetch" }
rustc-serialize = "0.3"
transient-hashmap = "0.1"
serde_macros = { version = "0.8.0", optional = true }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" }
ethcore-ipc = { path = "../ipc/rpc" }
time = "0.1"

View File

@ -28,7 +28,6 @@ use ethstore::random_phrase;
use ethsync::{SyncProvider, ManageNetwork};
use ethcore::miner::MinerService;
use ethcore::client::{MiningBlockChainClient};
use ethcore::ids::BlockID;
use ethcore::mode::Mode;
use ethcore::account_provider::AccountProvider;
@ -38,9 +37,11 @@ use v1::types::{
Bytes, U256, H160, H256, H512,
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber,
};
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
use v1::helpers::dispatch::DEFAULT_MAC;
use v1::helpers::auto_args::Trailing;
/// Parity implementation.
pub struct ParityClient<C, M, S: ?Sized> where
@ -234,19 +235,20 @@ impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
Ok(Brain::new(phrase).generate().unwrap().address().into())
}
fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error> {
fn list_accounts(&self, count: u64, after: Option<H160>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H160>>, Error> {
try!(self.active());
Ok(take_weak!(self.client)
.list_accounts(BlockID::Latest)
.list_accounts(block_number.0.into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect()))
}
fn list_storage_keys(&self, _address: H160) -> Result<Option<Vec<H256>>, Error> {
fn list_storage_keys(&self, address: H160, count: u64, after: Option<H256>, block_number: Trailing<BlockNumber>) -> Result<Option<Vec<H256>>, Error> {
try!(self.active());
// TODO: implement this
Ok(None)
Ok(take_weak!(self.client)
.list_storage(block_number.0.into(), &address.into(), after.map(Into::into).as_ref(), count)
.map(|a| a.into_iter().map(Into::into).collect()))
}
fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result<Bytes, Error> {

View File

@ -89,7 +89,7 @@ fn should_return_list_of_items_to_confirm() {
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
let response = concat!(
r#"{"jsonrpc":"2.0","result":["#,
r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#,
r#"],"id":1}"#
);

View File

@ -18,11 +18,12 @@
use jsonrpc_core::Error;
use std::collections::BTreeMap;
use v1::helpers::auto_args::Wrap;
use v1::helpers::auto_args::{Wrap, Trailing};
use v1::types::{
H160, H256, H512, U256, Bytes,
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber
};
build_rpc_trait! {
@ -103,12 +104,12 @@ build_rpc_trait! {
/// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not.
#[rpc(name = "parity_listAccounts")]
fn list_accounts(&self) -> Result<Option<Vec<H160>>, Error>;
fn list_accounts(&self, u64, Option<H160>, Trailing<BlockNumber>) -> Result<Option<Vec<H160>>, Error>;
/// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`),
/// or null if not.
#[rpc(name = "parity_listStorageKeys")]
fn list_storage_keys(&self, H160) -> Result<Option<Vec<H256>>, Error>;
fn list_storage_keys(&self, H160, u64, Option<H256>, Trailing<BlockNumber>) -> Result<Option<Vec<H256>>, Error>;
/// Encrypt some data with a public key under ECIES.
/// First parameter is the 512-byte destination public key, second is the message.

View File

@ -105,10 +105,10 @@ impl Serialize for ConfirmationResponse {
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
pub enum ConfirmationPayload {
/// Send Transaction
#[serde(rename="transaction")]
#[serde(rename="sendTransaction")]
SendTransaction(TransactionRequest),
/// Sign Transaction
#[serde(rename="transaction")]
#[serde(rename="signTransaction")]
SignTransaction(TransactionRequest),
/// Signature
#[serde(rename="sign")]
@ -221,7 +221,49 @@ mod tests {
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"transaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());
}
#[test]
fn should_serialize_sign_transaction_confirmation() {
// given
let request = helpers::ConfirmationRequest {
id: 15.into(),
payload: helpers::ConfirmationPayload::SignTransaction(helpers::FilledTransactionRequest {
from: 0.into(),
to: None,
gas: 15_000.into(),
gas_price: 10_000.into(),
value: 100_000.into(),
data: vec![1, 2, 3],
nonce: Some(1.into()),
}),
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());
}
#[test]
fn should_serialize_decrypt_confirmation() {
// given
let request = helpers::ConfirmationRequest {
id: 15.into(),
payload: helpers::ConfirmationPayload::Decrypt(
10.into(), vec![1, 2, 3].into(),
),
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"decrypt":{"address":"0x000000000000000000000000000000000000000a","msg":"0x010203"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());

View File

@ -23,7 +23,7 @@ ethcore-rpc = { path = "../rpc" }
ethcore-devtools = { path = "../devtools" }
parity-ui = { path = "../dapps/ui", version = "1.4", optional = true }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
[features]
dev = ["clippy"]

View File

@ -80,6 +80,7 @@ pub struct AuthCodes<T: TimeProvider = DefaultTimeProvider> {
impl AuthCodes<DefaultTimeProvider> {
/// Reads `AuthCodes` from file and creates new instance using `DefaultTimeProvider`.
#[cfg_attr(feature="dev", allow(single_char_pattern))]
pub fn from_file(file: &Path) -> io::Result<AuthCodes> {
let content = {
if let Ok(mut file) = fs::File::open(file) {
@ -128,7 +129,7 @@ impl<T: TimeProvider> AuthCodes<T> {
let mut file = try!(fs::File::create(file));
let content = self.codes.iter().map(|code| {
let mut data = vec![code.code.clone(), encode_time(code.created_at.clone())];
if let Some(used_at) = code.last_used_at.clone() {
if let Some(used_at) = code.last_used_at {
data.push(encode_time(used_at));
}
data.join(SEPARATOR)

View File

@ -99,7 +99,7 @@ fn auth_is_valid(codes_path: &Path, protocols: ws::Result<Vec<&str>>) -> bool {
let res = codes.is_valid(&auth, time);
// make sure to save back authcodes - it might have been modified
if let Err(_) = codes.to_file(codes_path) {
if codes.to_file(codes_path).is_err() {
warn!(target: "signer", "Couldn't save authorization codes to file.");
}
res

View File

@ -17,7 +17,7 @@ ethcore-network = { path = "../util/network" }
ethcore-io = { path = "../util/io" }
ethcore = { path = "../ethcore" }
rlp = { path = "../util/rlp" }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
log = "0.3"
env_logger = "0.3"
time = "0.1.34"

View File

@ -625,7 +625,7 @@ impl ChainSync {
Ok(())
}
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
#[cfg_attr(feature="dev", allow(cyclomatic_complexity, needless_borrow))]
/// Called by peer once it has new block headers during sync
fn on_peer_block_headers(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> {
let confirmed = match self.peers.get_mut(&peer_id) {
@ -1174,7 +1174,7 @@ impl ChainSync {
}
},
SyncState::SnapshotData => {
if let RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } = io.snapshot_service().status() {
if let RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } = io.snapshot_service().status() {
if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD {
trace!(target: "sync", "Snapshot queue full, pausing sync");
self.state = SyncState::SnapshotWaiting;
@ -1426,7 +1426,10 @@ impl ChainSync {
packet.append(&chain.best_block_hash);
packet.append(&chain.genesis_hash);
if warp_protocol {
let manifest = io.snapshot_service().manifest();
let manifest = match self.old_blocks.is_some() {
true => None,
false => io.snapshot_service().manifest(),
};
let block_number = manifest.as_ref().map_or(0, |m| m.block_number);
let manifest_hash = manifest.map_or(H256::new(), |m| m.into_rlp().sha3());
packet.append(&manifest_hash);
@ -1745,7 +1748,7 @@ impl ChainSync {
self.restart(io);
self.continue_sync(io);
},
RestorationStatus::Ongoing { state_chunks: _, block_chunks: _, state_chunks_done, block_chunks_done, } => {
RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => {
if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD {
trace!(target:"sync", "Resuming snapshot sync");
self.state = SyncState::SnapshotData;
@ -1999,12 +2002,16 @@ impl ChainSync {
#[cfg(test)]
mod tests {
use std::collections::{HashSet, VecDeque};
use tests::helpers::*;
use tests::snapshot::TestSnapshotService;
use util::{U256, RwLock};
use util::sha3::Hashable;
use util::hash::{H256, FixedHash};
use util::bytes::Bytes;
use rlp::{Rlp, RlpStream, UntrustedRlp, View, Stream};
use super::*;
use ::SyncConfig;
use util::*;
use rlp::*;
use super::{PeerInfo, PeerAsking};
use ethcore::views::BlockView;
use ethcore::header::*;

View File

@ -158,19 +158,19 @@ impl TestNet {
}
pub fn peer(&self, i: usize) -> &TestPeer {
self.peers.get(i).unwrap()
&self.peers[i]
}
pub fn peer_mut(&mut self, i: usize) -> &mut TestPeer {
self.peers.get_mut(i).unwrap()
&mut self.peers[i]
}
pub fn start(&mut self) {
for peer in 0..self.peers.len() {
for client in 0..self.peers.len() {
if peer != client {
let mut p = self.peers.get_mut(peer).unwrap();
p.sync.write().update_targets(&mut p.chain);
let mut p = &mut self.peers[peer];
p.sync.write().update_targets(&p.chain);
p.sync.write().on_peer_connected(&mut TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(client as PeerId)), client as PeerId);
}
}
@ -181,7 +181,7 @@ impl TestNet {
for peer in 0..self.peers.len() {
if let Some(packet) = self.peers[peer].queue.pop_front() {
let disconnecting = {
let mut p = self.peers.get_mut(packet.recipient).unwrap();
let mut p = &mut self.peers[packet.recipient];
trace!("--- {} -> {} ---", peer, packet.recipient);
let to_disconnect = {
let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId));
@ -198,7 +198,7 @@ impl TestNet {
};
for d in &disconnecting {
// notify other peers that this peer is disconnecting
let mut p = self.peers.get_mut(*d).unwrap();
let mut p = &mut self.peers[*d];
let mut io = TestIo::new(&mut p.chain, &p.snapshot_service, &mut p.queue, Some(peer as PeerId));
p.sync.write().on_peer_aborting(&mut io, peer as PeerId);
}

View File

@ -19,5 +19,5 @@ case $1 in
esac
. ./scripts/targets.sh
cargo test $OPTIONS --features "$FEATURES" $TARGETS $1 \
cargo test -j 8 $OPTIONS --features "$FEATURES" $TARGETS $1 \

View File

@ -23,7 +23,7 @@ rlp = { path = "rlp" }
heapsize = { version = "0.3", features = ["unstable"] }
itertools = "0.4"
sha3 = { path = "sha3" }
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
ethcore-devtools = { path = "../devtools" }
libc = "0.2.7"
vergen = "0.1"

View File

@ -15,7 +15,7 @@ time = "0.1.34"
tiny-keccak = "1.0"
rust-crypto = "0.2.34"
slab = "0.2"
clippy = { version = "0.0.96", optional = true}
clippy = { version = "0.0.103", optional = true}
igd = "0.5.0"
libc = "0.2.7"
parking_lot = "0.3"

View File

@ -507,7 +507,7 @@ mod tests {
use std::io::{Read, Write, Error, Cursor, ErrorKind};
use mio::{Ready};
use std::collections::VecDeque;
use util::bytes::*;
use util::bytes::Bytes;
use devtools::*;
use io::*;

View File

@ -555,10 +555,11 @@ impl Discovery {
#[cfg(test)]
mod tests {
use super::*;
use util::hash::*;
use util::sha3::*;
use std::net::*;
use node_table::*;
use std::net::{SocketAddr};
use util::sha3::Hashable;
use util::FixedHash;
use node_table::{Node, NodeId, NodeEndpoint};
use std::str::FromStr;
use rustc_serialize::hex::FromHex;
use ethkey::{Random, Generator};

Some files were not shown because too many files have changed in this diff Show More