Backports to 1.11.7-stable (#9093)
* parity-version: stabelize 1.11
* parity-version: bump stable to 1.11.7
* Don't fetch snapshot chunks at random (#9088)
* Offload cull to IoWorker.
* Limit the number of transactions in pending set (#8777)
* Unordered iterator.
* Use unordered and limited set if full not required.
* Split timeout work into smaller timers.
* Avoid collecting all pending transactions when mining
* Remove println.
* Use priority ordering in eth-filter.
* Fix ethcore-miner tests and tx propagation.
* Review grumbles addressed.
* Add test for unordered not populating the cache.
* Fix ethcore tests.
* Fix light tests.
* Fix ethcore-sync tests.
* Fix RPC tests.
* Make sure to produce full blocks.
* Update hidapi, fixes #7542 (#9108)
* docker: add cmake dependency (#9111)
* Fix miner tests.
* Revert "Make sure to produce full blocks."
This reverts commit b12d5920b2
.
* Update light client hardcoded headers (#9098)
* Insert Kovan hardcoded headers until #7690241
* Insert Kovan hardcoded headers until block 7690241
* Insert Ropsten hardcoded headers until #3612673
* Insert Mainnet hardcoded headers until block 5941249
* Make sure to produce full blocks. (#9115)
* Insert ETC (classic) hardcoded headers until block #6170625 (#9121)
* fix verification in ethcore-sync collect_blocks (#9135)
* `evm bench` fix broken dependencies (#9134)
* `evm bench` use valid dependencies
Benchmarks of the `evm` used stale versions of a couple a crates that
this commit fixes!
* fix warnings
This commit is contained in:
parent
4ba600fcc4
commit
085035fa2e
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -1219,7 +1219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "hidapi"
|
name = "hidapi"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
source = "git+https://github.com/paritytech/hidapi-rs#70ec4bd1b755ec5dd32ad2be0c8345864147c8bc"
|
source = "git+https://github.com/paritytech/hidapi-rs#d4d323767d6f27cf5a3d73fbae0b0f2134d579bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1963,7 +1963,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity"
|
name = "parity"
|
||||||
version = "1.11.6"
|
version = "1.11.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2014,7 +2014,7 @@ dependencies = [
|
|||||||
"parity-rpc 1.11.0",
|
"parity-rpc 1.11.0",
|
||||||
"parity-rpc-client 1.4.0",
|
"parity-rpc-client 1.4.0",
|
||||||
"parity-updater 1.11.0",
|
"parity-updater 1.11.0",
|
||||||
"parity-version 1.11.6",
|
"parity-version 1.11.7",
|
||||||
"parity-whisper 0.1.0",
|
"parity-whisper 0.1.0",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"path 0.1.0",
|
"path 0.1.0",
|
||||||
@ -2062,7 +2062,7 @@ dependencies = [
|
|||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parity-ui 1.11.0",
|
"parity-ui 1.11.0",
|
||||||
"parity-ui-deprecation 1.10.0",
|
"parity-ui-deprecation 1.10.0",
|
||||||
"parity-version 1.11.6",
|
"parity-version 1.11.7",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"registrar 0.0.1",
|
"registrar 0.0.1",
|
||||||
@ -2204,7 +2204,7 @@ dependencies = [
|
|||||||
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parity-updater 1.11.0",
|
"parity-updater 1.11.0",
|
||||||
"parity-version 1.11.6",
|
"parity-version 1.11.7",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"patricia-trie 0.1.0",
|
"patricia-trie 0.1.0",
|
||||||
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2325,7 +2325,7 @@ dependencies = [
|
|||||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-hash-fetch 1.11.0",
|
"parity-hash-fetch 1.11.0",
|
||||||
"parity-version 1.11.6",
|
"parity-version 1.11.7",
|
||||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"path 0.1.0",
|
"path 0.1.0",
|
||||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2336,7 +2336,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parity-version"
|
name = "parity-version"
|
||||||
version = "1.11.6"
|
version = "1.11.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ethcore-bytes 0.1.0",
|
"ethcore-bytes 0.1.0",
|
||||||
"rlp 0.2.1",
|
"rlp 0.2.1",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
description = "Parity Ethereum client"
|
description = "Parity Ethereum client"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||||
version = "1.11.6"
|
version = "1.11.7"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
@ -100,6 +100,7 @@ ui-precompiled = [
|
|||||||
]
|
]
|
||||||
ui-enabled = ["dapps"]
|
ui-enabled = ["dapps"]
|
||||||
dapps = ["parity-dapps"]
|
dapps = ["parity-dapps"]
|
||||||
|
miner-debug = ["ethcore/miner-debug"]
|
||||||
json-tests = ["ethcore/json-tests"]
|
json-tests = ["ethcore/json-tests"]
|
||||||
test-heavy = ["ethcore/test-heavy"]
|
test-heavy = ["ethcore/test-heavy"]
|
||||||
evm-debug = ["ethcore/evm-debug"]
|
evm-debug = ["ethcore/evm-debug"]
|
||||||
|
29
docker/alpine/Dockerfile
Normal file
29
docker/alpine/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM alpine:edge
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
# install tools and dependencies
|
||||||
|
RUN apk add --no-cache gcc musl-dev pkgconfig g++ make curl \
|
||||||
|
eudev-dev rust cargo git file binutils \
|
||||||
|
libusb-dev linux-headers perl cmake
|
||||||
|
|
||||||
|
# show backtraces
|
||||||
|
ENV RUST_BACKTRACE 1
|
||||||
|
|
||||||
|
# show tools
|
||||||
|
RUN rustc -vV && \
|
||||||
|
cargo -V && \
|
||||||
|
gcc -v &&\
|
||||||
|
g++ -v
|
||||||
|
|
||||||
|
# build parity
|
||||||
|
ADD . /build/parity
|
||||||
|
RUN cd parity && \
|
||||||
|
cargo build --release --verbose && \
|
||||||
|
ls /build/parity/target/release/parity && \
|
||||||
|
strip /build/parity/target/release/parity
|
||||||
|
|
||||||
|
RUN file /build/parity/target/release/parity
|
||||||
|
|
||||||
|
EXPOSE 8080 8545 8180
|
||||||
|
ENTRYPOINT ["/build/parity/target/release/parity"]
|
@ -3,7 +3,7 @@ WORKDIR /build
|
|||||||
|
|
||||||
# install tools and dependencies
|
# install tools and dependencies
|
||||||
RUN yum -y update&& \
|
RUN yum -y update&& \
|
||||||
yum install -y git make gcc-c++ gcc file binutils
|
yum install -y git make gcc-c++ gcc file binutils cmake
|
||||||
|
|
||||||
# install rustup
|
# install rustup
|
||||||
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
|
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
|
||||||
|
@ -13,6 +13,7 @@ RUN apt-get update && \
|
|||||||
# add-apt-repository
|
# add-apt-repository
|
||||||
software-properties-common \
|
software-properties-common \
|
||||||
make \
|
make \
|
||||||
|
cmake \
|
||||||
curl \
|
curl \
|
||||||
wget \
|
wget \
|
||||||
git \
|
git \
|
||||||
|
@ -6,7 +6,7 @@ RUN apt-get -y update && \
|
|||||||
apt-get install -y --force-yes --no-install-recommends \
|
apt-get install -y --force-yes --no-install-recommends \
|
||||||
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
|
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
|
||||||
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
|
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
|
||||||
binutils-aarch64-linux-gnu \
|
binutils-aarch64-linux-gnu cmake \
|
||||||
&& \
|
&& \
|
||||||
apt-get clean
|
apt-get clean
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ RUN apt-get -y update && \
|
|||||||
apt-get install -y --force-yes --no-install-recommends \
|
apt-get install -y --force-yes --no-install-recommends \
|
||||||
curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
|
curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
|
||||||
libc6-dev-armhf-cross wget file ca-certificates \
|
libc6-dev-armhf-cross wget file ca-certificates \
|
||||||
binutils-arm-linux-gnueabihf \
|
binutils-arm-linux-gnueabihf cmake \
|
||||||
&& \
|
&& \
|
||||||
apt-get clean
|
apt-get clean
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ RUN apt-get update && \
|
|||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
g++ \
|
g++ \
|
||||||
build-essential \
|
build-essential \
|
||||||
|
cmake \
|
||||||
curl \
|
curl \
|
||||||
git \
|
git \
|
||||||
file \
|
file \
|
||||||
|
@ -74,6 +74,10 @@ trie-standardmap = { path = "../util/trie-standardmap" }
|
|||||||
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
|
kvdb-rocksdb = { path = "../util/kvdb-rocksdb" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
# Disables seal verification for mined blocks.
|
||||||
|
# This allows you to submit any seal via RPC to test and benchmark
|
||||||
|
# how fast pending block get's created while running on the mainnet.
|
||||||
|
miner-debug = []
|
||||||
# Display EVM debug traces.
|
# Display EVM debug traces.
|
||||||
evm-debug = ["slow-blocks"]
|
evm-debug = ["slow-blocks"]
|
||||||
# Display EVM debug traces when running tests.
|
# Display EVM debug traces when running tests.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||||
// This file is part of Parity.
|
// This file is part of Parity.
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
@ -16,18 +16,16 @@
|
|||||||
|
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
extern crate ethcore_util as util;
|
|
||||||
extern crate rand;
|
|
||||||
extern crate bn;
|
extern crate bn;
|
||||||
extern crate crypto;
|
extern crate ethereum_types;
|
||||||
extern crate ethkey;
|
extern crate ethkey;
|
||||||
|
extern crate parity_crypto;
|
||||||
|
extern crate rand;
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate ethcore_bigint;
|
extern crate test;
|
||||||
|
|
||||||
use self::test::{Bencher};
|
|
||||||
use rand::{StdRng};
|
|
||||||
|
|
||||||
|
use self::test::Bencher;
|
||||||
|
use rand::StdRng;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bn_128_pairing(b: &mut Bencher) {
|
fn bn_128_pairing(b: &mut Bencher) {
|
||||||
@ -61,16 +59,12 @@ fn bn_128_mul(b: &mut Bencher) {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn sha256(b: &mut Bencher) {
|
fn sha256(b: &mut Bencher) {
|
||||||
use crypto::sha2::Sha256;
|
use parity_crypto::digest::sha256;
|
||||||
use crypto::digest::Digest;
|
|
||||||
|
|
||||||
let mut input: [u8; 256] = [0; 256];
|
let input = [0_u8; 256];
|
||||||
let mut out = [0; 32];
|
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut sha = Sha256::new();
|
sha256(&input);
|
||||||
sha.input(&input);
|
|
||||||
sha.result(&mut input[0..32]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +72,7 @@ fn sha256(b: &mut Bencher) {
|
|||||||
fn ecrecover(b: &mut Bencher) {
|
fn ecrecover(b: &mut Bencher) {
|
||||||
use rustc_hex::FromHex;
|
use rustc_hex::FromHex;
|
||||||
use ethkey::{Signature, recover as ec_recover};
|
use ethkey::{Signature, recover as ec_recover};
|
||||||
use ethcore_bigint::hash::H256;
|
use ethereum_types::H256;
|
||||||
let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap();
|
let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap();
|
||||||
let hash = H256::from_slice(&input[0..32]);
|
let hash = H256::from_slice(&input[0..32]);
|
||||||
let v = H256::from_slice(&input[32..64]);
|
let v = H256::from_slice(&input[32..64]);
|
||||||
@ -95,4 +89,3 @@ fn ecrecover(b: &mut Bencher) {
|
|||||||
let _ = ec_recover(&s, &hash);
|
let _ = ec_recover(&s, &hash);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,9 @@ const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
|
|||||||
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
|
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
|
||||||
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
|
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
|
||||||
|
|
||||||
|
/// Max number of transactions in a single packet.
|
||||||
|
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
||||||
|
|
||||||
// minimum interval between updates.
|
// minimum interval between updates.
|
||||||
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
|
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
|
||||||
|
|
||||||
@ -648,7 +651,7 @@ impl LightProtocol {
|
|||||||
fn propagate_transactions(&self, io: &IoContext) {
|
fn propagate_transactions(&self, io: &IoContext) {
|
||||||
if self.capabilities.read().tx_relay { return }
|
if self.capabilities.read().tx_relay { return }
|
||||||
|
|
||||||
let ready_transactions = self.provider.ready_transactions();
|
let ready_transactions = self.provider.ready_transactions(MAX_TRANSACTIONS_TO_PROPAGATE);
|
||||||
if ready_transactions.is_empty() { return }
|
if ready_transactions.is_empty() { return }
|
||||||
|
|
||||||
trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len());
|
trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len());
|
||||||
|
@ -173,8 +173,8 @@ impl Provider for TestProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||||
self.0.client.ready_transactions()
|
self.0.client.ready_transactions(max_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ pub trait Provider: Send + Sync {
|
|||||||
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
|
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
|
||||||
|
|
||||||
/// Provide pending transactions.
|
/// Provide pending transactions.
|
||||||
fn ready_transactions(&self) -> Vec<PendingTransaction>;
|
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction>;
|
||||||
|
|
||||||
/// Provide a proof-of-execution for the given transaction proof request.
|
/// Provide a proof-of-execution for the given transaction proof request.
|
||||||
/// Returns a vector of all state items necessary to execute the transaction.
|
/// Returns a vector of all state items necessary to execute the transaction.
|
||||||
@ -283,8 +283,8 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
|
|||||||
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
|
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||||
BlockChainClient::ready_transactions(self)
|
BlockChainClient::ready_transactions(self, max_len)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|tx| tx.pending().clone())
|
.map(|tx| tx.pending().clone())
|
||||||
.collect()
|
.collect()
|
||||||
@ -370,9 +370,12 @@ impl<L: AsLightClient + Send + Sync> Provider for LightProvider<L> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<PendingTransaction> {
|
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
|
||||||
let chain_info = self.chain_info();
|
let chain_info = self.chain_info();
|
||||||
self.txqueue.read().ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
|
let mut transactions = self.txqueue.read()
|
||||||
|
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
|
||||||
|
transactions.truncate(max_len);
|
||||||
|
transactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -174,8 +174,8 @@
|
|||||||
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
|
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
|
||||||
},
|
},
|
||||||
"hardcodedSync": {
|
"hardcodedSync": {
|
||||||
"header": "f90207a0cdaf426b80edd4363b336b351cbfec8c38b44847cdbd814aa92e92bc9ec05333a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949435d50503aee35c8757ae4933f7a0ab56597805a03f28b2b384dbfd29bc0a10343e8a419e61b92782f880046170bf1d11455e94bba0f3712ef3ff24efe1afc7da11ffb2ca495a94fe7958f42e9f1599d66ed72af13ba06d01d03a15f807da601bd2dfde7490bbe91d9bb11c11eda435db9daad6e7b1efb9010000008c0000c000000000440100108040000082000800000000000000040801001004001000000010000000001000043300001000008000800000002000200040000000580c0004108000040c0008000006000000000280800080000800000000402000000a000000a810226200002881004000208006020000000510030000100040010100000086c20000000009000100000190008c80060000008000202080420008056040000000001000400001100010140822800220000c804004002000108000160001400200088082008000000412100010080205011000000800a0000810021005000000000002840000000400000000880000006000000000200002870bfca554dbc6398358b001837a137083473c8e845b27f4fd86436f72746578a0dbf31fd28bd8f69f1103196e1782a9dfb636bcfa726362ab0767235cb8d56e7188264402501145497f",
|
"header": "f9020ba0bb120488b73cb04a3c423dfa6760eb631165fa3d6d8e0b1be360d3e2a00add78a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca02d2cbb3c43370257122898259f1e06da38fd23031f74b40d6bd022b037ecd3daa0107b3a01662ca77aa1c72cde45bd66c062d781310d7a364e5b6442bd791431cea011e451bfe7b89addb96020182e0e7eb448d0a66303924a2835a149247bea4188b90100000000200004820000130000020000322004002000140000801000081208000880800200100000000a080000000800400000000000080240800000020028a100000400410000001088008008400080000100000000200000000220804028000000302000000180200c004644000000000101800000040040020200100020100220200a00000000280002011040000000000080a00000002002048000100001000206000000c000002010000004800030000000000300884008121000208020080000020280000000010104002000004000002084000c08402820000004000001841109008410040410080080004121044080800800000000004858040000c000870c64944ccfd130835aa801837a212d8320dc6b845b452c758a7777772e62772e636f6da02078861f3b30aaea6fad290d86919dd7542433a56edc1af557426cbd2eacd60d88a68a26940894b23f",
|
||||||
"totalDifficulty": "4838383800145139949936",
|
"totalDifficulty": "5282739680501645457616",
|
||||||
"CHTs": [
|
"CHTs": [
|
||||||
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
|
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
|
||||||
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
|
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
|
||||||
@ -3014,7 +3014,70 @@
|
|||||||
"0x118b3ae7ad25ab96fe8a63973312c758d4ce9ecd39cc24913c26a65b4b5534de",
|
"0x118b3ae7ad25ab96fe8a63973312c758d4ce9ecd39cc24913c26a65b4b5534de",
|
||||||
"0x19cd088af8dbe2d3e6ca7987d9ee1564ea2256f482840b1d2f0da85060de9a86",
|
"0x19cd088af8dbe2d3e6ca7987d9ee1564ea2256f482840b1d2f0da85060de9a86",
|
||||||
"0x98bc07422cf8b0c4d1428afb759300d9a7637de2518528d34f7d237be7e863be",
|
"0x98bc07422cf8b0c4d1428afb759300d9a7637de2518528d34f7d237be7e863be",
|
||||||
"0x0c64526b393066911c7da3f17f9e652cfa38112ae324e3c84416e811d3fe7cad"
|
"0x0c64526b393066911c7da3f17f9e652cfa38112ae324e3c84416e811d3fe7cad",
|
||||||
|
"0xa30cbfaf518996ba776b426a7068faad4ee49775db45565ebd327f9c679a45b4",
|
||||||
|
"0xd3e1a807f5940ee1a321b20b7931bef90515132ea9959df94e55529e05802cab",
|
||||||
|
"0x338aef579d9ec8acc1a0411c1674bcf213d03aa7d4bbc56707e081829ce30004",
|
||||||
|
"0x68c7a603089a220273f019001a39bfa9194590a6fa6d8ba960ddf4888b105a6b",
|
||||||
|
"0xd6a9d2c354e1dd77322800d24774eb03b589dd94bcdb3cc2b70437ed70411e6a",
|
||||||
|
"0x39c017c42ad571564792bf5741b3ae786ff0c24ebcb5ee46882ce0545b8a2262",
|
||||||
|
"0xf5caea6b23f4085c9f94c880d89b1c23eb69c03dc098b426143ae4b28969a2d8",
|
||||||
|
"0x959eebc05ff0dfae8c7e6699f069b38b5f2e5bc8c155bc35fc7f578d2d112993",
|
||||||
|
"0x199e90557d4d9e13c3e7a4b5b4ef6fe52cd2c724c36eaa44b7fa151efebbbeee",
|
||||||
|
"0x0bfe35d253227696e76f92ff13e4c545c57fca51186a16f687e76d2e6707d34f",
|
||||||
|
"0xadf8b7678f98b0e5009130d9d5d77add6e460b67b0529abc5315c44dadea0cb4",
|
||||||
|
"0x86582f3a98b218939aefd7eea438ee278d1faaf41920e8c72922c46fd56f1c32",
|
||||||
|
"0x001b728a4737fdd53cde20341fa0adec9aa8ab7c7c1db244fbd509a6c4f3f364",
|
||||||
|
"0x9207900bfdd6c87e2ba8498c0372706799604a207930eeb331580459d17f89cb",
|
||||||
|
"0xd2192fcf74cad70e6f7986a0b088de8658a14638a4c03d7ae616a88ceea00ba2",
|
||||||
|
"0xbf6f6b91742eebe70204eb7a70196ef636fc2db4d4c4f89cd5826fbf990a945d",
|
||||||
|
"0x5c1210951949402fe3b012577f1af0d3e285a0b39c3fe19c84f7930e003c06de",
|
||||||
|
"0xa16d57f777f94f032f7f2f75b2e25ebd11559effee98b39a5a1e7cc804cfbf06",
|
||||||
|
"0x1b9561fb8035ec6955454d6710f053d7ad3d8e0753aaac568ac3bc98f874465e",
|
||||||
|
"0x1a622da786425e0b65b9083a451a419c75e16908fa04d89ddc2c11d94ffe65a0",
|
||||||
|
"0xbfcb9b1d847eb40b6808e45bf3d2fb8f6588d6f103167be65f246d0733afd1f7",
|
||||||
|
"0x2317640589ab9d52e7f5e8dda95ff3b1beceacc5832341e9053b71209bfad07f",
|
||||||
|
"0xa10611b829dbb533e565ad01632b26b1fd642a4393e7fdd9b8f235f11bb606c8",
|
||||||
|
"0xe4ea4173982f342e396356b0bb0eb47e6748461ecce0f34dbe8fc084cf6a9fbc",
|
||||||
|
"0xd58399c0d0ae878338d2915eaf2d65f2d1e29eb8d551d254e68bce7a8235adcb",
|
||||||
|
"0xc0c8b73ffc675a207f73903c49d81131e6831e4c8e071b988ed9f2a5d2277024",
|
||||||
|
"0xe1ca77bafa66bb055c671978b3d1bd5df32f8e269330507f071afd627012b6af",
|
||||||
|
"0x67a1093cbddf41264009d1dbbc33fbc25a337339be0727e70c512b585897749c",
|
||||||
|
"0x0fd615782db5cf4c0a3686721cbc6245696c1bc9b403a9eaffae00968d2c8ece",
|
||||||
|
"0xc3c2dcaee8954ca86d9b3e4e98c4bb4f6b6bc183f9eb062016c5a25b2280717b",
|
||||||
|
"0x70265915f5ed94d589afafa3d0d0eab6310195cc690aa82bd65e4a488b398c58",
|
||||||
|
"0xde3fead8ce29c04a86dcb081da2cabda5366d28de5ebfe2f8064780413f71edf",
|
||||||
|
"0x0ae43394fcf6ebdabdcc1ede314fe779eb61a12eab807a9d3437d9167e2247e3",
|
||||||
|
"0x3241127e2c7fbb3db9fe0c602b0c94e22c684b7910ffcf09c1c443e567f95e4d",
|
||||||
|
"0xcb94ba286eeaa1129b490bb5891e603fd35e85c97c2132c1216d1774f9017f35",
|
||||||
|
"0xbf396cd23c29ef21fb535880ef621457fb71981f856f2a09c494cd005d38f981",
|
||||||
|
"0x3df0c90ed7aba260e820ca1d28ce1778149e163524e306309aa346bbadedcf2b",
|
||||||
|
"0x66a2724f7481aa3ab83a8f1bae2caef8a7bc607c7ffd5bbb1cf3766741db804f",
|
||||||
|
"0x7a0c3492f4022322e10d81bc10a5db9aceec81d1ab70cdffd31418b79d750fd2",
|
||||||
|
"0x96a826cb667924ed75ec708bf07cf4c7c05f84a0132e154b71eaf6e193590e87",
|
||||||
|
"0xcc7030fe617c318a31984d04e3d7f2ff2196894bc429f3f64bfd69b969dc9b56",
|
||||||
|
"0x3fa94aae223f5aeb593246f1a93d6d694b48946c09d879e791f1188a9dedc4c0",
|
||||||
|
"0xd49e51fc324fe58159575c0c24171f4eb1aaf58ed8e1311c3849538c8cec3ce1",
|
||||||
|
"0xc474123906eae5cd48a10e0d93fcbbd653f0c6d25275f827d4fac51e696c3d91",
|
||||||
|
"0xacd7b790a19026fa3f3b0a354878d4fcd79dc600f7ba5cedd2eefffe1ceda76c",
|
||||||
|
"0x41b311a188cd7ce1444d258dc379994b81a895226276c7bfe5e6cb29a5f92142",
|
||||||
|
"0xda0ae01db7f73f07fce46b94c24d6e400598378a6baf01123dd710c5425fb8c9",
|
||||||
|
"0xe62e08175a02b575e28b9e029a838c365e3ce4278f60c2d3b5d529768a4b47c4",
|
||||||
|
"0x99b804c8d0feda7f9df961527d634fb8b2d477a362e1d8158856885a13425fa9",
|
||||||
|
"0xe73597be8ef7d78f862c7a94a8ccff17f559816eba2f830821c6f6436898f9fb",
|
||||||
|
"0x36de9ee4c80853c865b16904cd8f6c0e9a99ff9e7bf05100bfbc76789cedd4d1",
|
||||||
|
"0xf480b762872373102393461ff3a21323a1df799c315fd167780a45d7bfaae84e",
|
||||||
|
"0x303b66babd21e72449cad413e04bdb0bc3ebcbb84a79dd30ed7c972c5341b82b",
|
||||||
|
"0xbf111684fbe44a973594f31cdee2c94e807bff9cf7584c22dcd609d8234f6e62",
|
||||||
|
"0x79b26cc3bbf49b6f25afbff7e97e4e45f2dcb359095fdbeb7fb7addee692afc3",
|
||||||
|
"0x2839d620cc140ba838ecba6e7e52db8cf7b5cd4cf4857f72f3bfbc9b1cf0fbd9",
|
||||||
|
"0x93074136f4eec367adcf27955d38efc0dc6da514693bfc97935c7871793e35ea",
|
||||||
|
"0x21f5af18a4cf0096b6e6a3d4c98f4043cfee5c4ee085ce106f86b713160144b8",
|
||||||
|
"0x90d16b403e2deca6cd5c80e52eba0b84b2875e1dfd75fffb1a2f82bc91eb6942",
|
||||||
|
"0x8a5cb6854c19a865f51e3ee9eaf8e843a97b272f6467634ba40e547a435ef624",
|
||||||
|
"0x9afe42a0dffca8ec063c83908fd6237d6130c9dfeab57078bdd02b6ac6d0ea07",
|
||||||
|
"0xa05cc6108b475d3e68e280e98f514cfb6df4f004e1b7708fcfd4528d346bea6b",
|
||||||
|
"0x71f10879b875caefab46669e8525b9c0487bbe3247e43a6cdb1dedbfb4d4ba33"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nodes": [
|
"nodes": [
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
"hardcodedSync": {
|
"hardcodedSync": {
|
||||||
"header": "f9023ea070413bfe3ceb9160c7dee87bf060a0cc5e324f7c539cfce4e78802ff805063b6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e4a10650e5a6d6001c38ff8e64f97016a1645ca0f8ac12c30b4fd0d27a1a50c090659014574b554ba6e9cdb76f57efbcfbd390a9a0b474ac6cc4673c17c5f511a8b43cc44dbb01bb028735830163667d7a3a2582b9a0bcd44b7c04fa24760df7d733ca8ecd99e8da89de0716e6017fffa434bfd7519ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd83755801837a11f88301d8de845b27471c96d583010b038650617269747986312e32362e31826c698416c9d1c7b8418bc805f23fb01fdd498b37df5519f49691d65160fe6a6794b8106e2ecc4782407f0dae3a512546b7d93e89bbb2a761c750553deeea1f9401231f56ae0ccb059201",
|
"header": "f9023ea070413bfe3ceb9160c7dee87bf060a0cc5e324f7c539cfce4e78802ff805063b6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e4a10650e5a6d6001c38ff8e64f97016a1645ca0f8ac12c30b4fd0d27a1a50c090659014574b554ba6e9cdb76f57efbcfbd390a9a0b474ac6cc4673c17c5f511a8b43cc44dbb01bb028735830163667d7a3a2582b9a0bcd44b7c04fa24760df7d733ca8ecd99e8da89de0716e6017fffa434bfd7519ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd83755801837a11f88301d8de845b27471c96d583010b038650617269747986312e32362e31826c698416c9d1c7b8418bc805f23fb01fdd498b37df5519f49691d65160fe6a6794b8106e2ecc4782407f0dae3a512546b7d93e89bbb2a761c750553deeea1f9401231f56ae0ccb059201",
|
||||||
"totalDifficulty": "2566410291882451733317698215999610733750372193",
|
"totalDifficulty": "2654916374389120143910668097894183918476475680",
|
||||||
"CHTs": [
|
"CHTs": [
|
||||||
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
|
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
|
||||||
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
|
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
|
||||||
@ -3813,7 +3813,134 @@
|
|||||||
"0x5d71aff2a12d4f1d05c7f760d07b417a39eb0eaa72a01333befc6a2eb6b7d72a",
|
"0x5d71aff2a12d4f1d05c7f760d07b417a39eb0eaa72a01333befc6a2eb6b7d72a",
|
||||||
"0x8dd7de9195d2852aeb6812638ba22e73ff5ca0a8ad921c6e924cae1dd5952255",
|
"0x8dd7de9195d2852aeb6812638ba22e73ff5ca0a8ad921c6e924cae1dd5952255",
|
||||||
"0x8f1828b4cdc6c38c112b1ffee7790953112dd2225ec82581a5095e5ae4d71cae",
|
"0x8f1828b4cdc6c38c112b1ffee7790953112dd2225ec82581a5095e5ae4d71cae",
|
||||||
"0xfeac88ae6c8529e87a55a259f475b7d162d01e8fa5f36c90d4665dd6105b1743"
|
"0xfeac88ae6c8529e87a55a259f475b7d162d01e8fa5f36c90d4665dd6105b1743",
|
||||||
|
"0x2e37011bd97c6e8a24e130fdc2c60c39b14ab3eb426a4f654bf3158a19aca88b",
|
||||||
|
"0xdb59b565de21902c50e2e204374ae1ce487656eb74145c103a86707b45a63eaf",
|
||||||
|
"0xf75c26a7214acf2d050ff5c7cc8b76e1a90540410b5c8b2bc9edbfe8fb2268e6",
|
||||||
|
"0x6ca7554f2abfd22951bec80f9d280abb6f060dde4a9a829ff7a0457d67a99edd",
|
||||||
|
"0x0324bceb8b61fa7092396764d7e1933697806c6d785446e3bbab3fc3be0ab259",
|
||||||
|
"0xeb4880f177e3e673f8ee04be1451a38bd8a2c0bac681d82a19327ae2d9769d32",
|
||||||
|
"0xec6a868cd9fba9e4f5b0d4276f44aee71056fbb7f425f717d0ce9d1fa5442ded",
|
||||||
|
"0xdc12b36d165eae197487ec930e35489545d2867b6fb9f8604d279337b6a8f949",
|
||||||
|
"0xcf1241b1c9b054df34638e99447bb0359aa01ad13c38650b872f2d727e6f68f6",
|
||||||
|
"0x713765e9b76c73c2de58c480600a7125972246fdcce2324993cd6bbe49cce67f",
|
||||||
|
"0x81e096e97dd8bf1d206d0ed41c9feaad24d344323ff74707112ee8fac218994e",
|
||||||
|
"0x8943c2246d5ae3e8db5fc012e9613642c6b713e5f2a89d00f09fa73246f88d5f",
|
||||||
|
"0x5b2d0bcbd893fab4e58d4ef698d1e8d3001799b61e758b7711f319e2b8eaa645",
|
||||||
|
"0xf3e4da2cf4579f52b7e4d632d93b79714487ef179a8f5d5c46af9154efad20fd",
|
||||||
|
"0xa2348ea2cd7a5a32779e9d292a9428fa475fae790f08e42f7699ef5eb2489188",
|
||||||
|
"0x62dd923966e02db7d0d27cfdd4aeac081f9827288c8b54d9f19035331a109f53",
|
||||||
|
"0xaa1aafa8f9d9d3e0668eff761fbfc2657d1e1906c077d93200ec000643c6c272",
|
||||||
|
"0xbf40cb21561989004434d6d908451d5b63045c89c2ac9b1eb617ec0054dc18be",
|
||||||
|
"0xdae53edbb07fe84623451da0e25da631ad3465e5bc12ef8fd8323c8a72f57130",
|
||||||
|
"0x685115b38f307f984c7c90e85d167d62b0ec2c924a0bca5f23b1cac12a8f72fa",
|
||||||
|
"0x2ad7e8f86c872504d7c2c48b0db141955d770acc84222fd725ffbd2dc4095b1d",
|
||||||
|
"0x9268b3b175aa6025b959b8fcdb416c39dd339e6f1fde3c427bd1bada36e4384c",
|
||||||
|
"0x502ee814cecc8454abb95591b0d07ed5170db94af7fda8878b9b4287fd68c9f8",
|
||||||
|
"0x6b19baf6b7eae36c0b1d2754645ff282fc2905802ca6394ac00bc22eb1582eb9",
|
||||||
|
"0xecad17ae39f897ab38850cac40480b4fafcafd6624f8fdfcaa69849f3fa101ec",
|
||||||
|
"0xb0804719b391b4b5f554a49f99df3a9d1c3a9884cefc268dcb27e3821aebe385",
|
||||||
|
"0x3018401c9a31f97881852c1bd65a964bfd3011659725c849a8de4b5ad8f26490",
|
||||||
|
"0x48a6b687e62a42dc44ecb56f4187e293d6f87d328b1edf409c8f2fa6568dfddc",
|
||||||
|
"0x8e3bc1ec926a68e22ed525485186a4d9160a54bd3e80107bb77c09911564effa",
|
||||||
|
"0xd7a7cce632e1746120476a3271ea09689380eb833d5538310fa0029f9174e0de",
|
||||||
|
"0x7bae074c51f3b547568d18e85b73fcb9b5f8040ed5f96f3523f53197150517a4",
|
||||||
|
"0x9ba39f376b9444dab04e0a52e4728ec842a0aa4880d9aa9819de3f0694f46e60",
|
||||||
|
"0x40a2b84bd3d05d28d51a39deae5f23b4f7370c70ac70d1cc81224eac4939d69f",
|
||||||
|
"0x2b9f57c8c43284ba929df8f896a966afbdd341f145b6b2b2fa98382950ad915d",
|
||||||
|
"0xcaf3d2a336cf17c9b2d7116a14e654bcece012b07bc020ac30feb71d7f6cead1",
|
||||||
|
"0xd3b68cf2337ca26a9c4bf6b6b286dc65bf66641d5e9c241f4c1b147994253ac5",
|
||||||
|
"0xefc11a5944a8061c87f274515e810fee13f4c350c625a988c27ed276b6c55b6d",
|
||||||
|
"0x7a93732151f7145059424aa823b24e26341cfa57f612e6de3bddbe23562ae918",
|
||||||
|
"0x2594b625d0f5ed52425ccda4e7898a8a554300791027af6f3a19239a15868ea8",
|
||||||
|
"0x1db00091145b1b0830983b5eaa5cd3d0e4ad71c09d1b2dc20c47815bc2de5917",
|
||||||
|
"0x60563bce11f028691cf78da7326f22a4ab01d980020e61bcf2e4bdb5912b7b1d",
|
||||||
|
"0xe6515bdf1f22469a4218f54791d12698d1bc555b3e54b04cf46b10effa8ce74c",
|
||||||
|
"0x990831a56958a6bf131697e2f35ab2a45fa228eb7435c7e65814ba28778d513f",
|
||||||
|
"0x1b6e4085f0e291a8ee4d7e90158dcf15702b4e6e634d1d3bb5c4bab11bf70068",
|
||||||
|
"0xd0d4a6061bcab0f8e645ea16b285eee7f2ff84c7765d7543aa318edbced2408d",
|
||||||
|
"0x2da1a609eb1b572a47f187dd5a1e9f4cb1e1885c841f91ca82137e01a9eb4288",
|
||||||
|
"0x1293686df427f9ee1c2116000735642b3d09511cf2889dde21e1bee427d8c273",
|
||||||
|
"0x8a990d66370eaab3a46d9e4fa9b7d0c621020cd3b897d9e5b3e5fea6a6979f3c",
|
||||||
|
"0x10030534d5a06bce47d72998ad4c042f5e445a505920723d14b1d93a3a23af82",
|
||||||
|
"0xf29a399e8879386e4c2bd8e873dc8aed612cfa8dfa9e5b56f9c51d4c4d1774ad",
|
||||||
|
"0xb252062ccbb11c3181338d9912ed0d4dabcfa4d61860c211f2f702a641fe936e",
|
||||||
|
"0x822c7abd11b80c862bd67d39e16a208c8462936ca86b5cd5dd20c51d35cbfbb1",
|
||||||
|
"0x6b62aea651f1407f94906db704a364f70d827e0efba981a8515d1f515a46b266",
|
||||||
|
"0xa57b7661c0471cbd7eb35becdf468622df8338a48a075b722ebc5550bbf6b9ae",
|
||||||
|
"0xefc593d38afead5ee1fea5d8b41a52bd2a5b5a059774d0b951bb7eadaa41a46a",
|
||||||
|
"0xa556e684c26e7fd6f902b82ecdf721fc292c35e0d2240c1f362c4861c366c4c6",
|
||||||
|
"0xc9f274efc308d1e97ba9b59c92735d1ab2a72d033ed02a543dab301610e96e33",
|
||||||
|
"0xd7b43559126f88c59392fc54e2b416d2a67014abce12ddf61764df989a897bd3",
|
||||||
|
"0xc860842132de3d8c1d0ba2cdc0a7c2853ee568789f1190738862667e3539a958",
|
||||||
|
"0x2f330354084635eb507cd54549ab89fecc41886d295b1d8c91efd8ca27fe4f7d",
|
||||||
|
"0xda6edc97997b9cea1bc90662c6a8180fa03cef6189e09c86f36adb91400abe74",
|
||||||
|
"0x0d2853b5a3f02ae9e4a1c5a0534a5329d2e877d4d77f60dddb36b84b4fdf7e2f",
|
||||||
|
"0xf048b5acc9e9191ce0ab8c390bfe03d89cbed91db5b9e7c7452b01bf56bcf5ac",
|
||||||
|
"0x30fb6f6093bf59794d37ddf850c315dd9491a4cf5df378b4468dca96acf78e77",
|
||||||
|
"0xa04eeaa9d1d767c0f93553af3a259390a9576e8b6015ffa8f0e4fdf37f41f28e",
|
||||||
|
"0x02411cd53ac55407e0d31520a8c3274a2f4d1fbb2541bb140f30f25843c76860",
|
||||||
|
"0x65bc790d632d5fe2446c65325df875ba59af3c3aa7357bbbbf47c7e5f7663a7d",
|
||||||
|
"0x5f364562fed351d932eff956c3ac489ea51ad2cb12a81bd8db4fe0b76e3cbb92",
|
||||||
|
"0x104f7070d5da1aca5c8b20a96d36638e4b5f8be4e86be83f0aed7234fcece445",
|
||||||
|
"0xb2fc7a73d8d859d531e51532928671ea59ae6538d4572fd5c2d76c70920aff7f",
|
||||||
|
"0x7ebecf446825dd0010fbf47afce8b9c3b3901c839ec46269eb8744bd799699ca",
|
||||||
|
"0xc64002b5a70f18b7c51ea3d3f5246fe8db16781e146d777aaa12f3b765d108e9",
|
||||||
|
"0x9d136068c7002d2780abfefcaedc79424d3e89b17718ec369d9e64ab7b63a81f",
|
||||||
|
"0x7b9819e62e92dcead89329bcb3f1a1d6bd10794d1a22d30c3d0369a264029543",
|
||||||
|
"0x8a8c9e66f343d09d5b7897c491c851143ca4f337ddcb5c2b1462b150e22c6f47",
|
||||||
|
"0x9d86faa1a5d355d6071e09c8cca50e2dd7e7dc117c2e4f6c0136a2789e84aa8b",
|
||||||
|
"0x234e156c10a80422ca1aafd49d614e02b698a0d89a7080f87db5dd5169b419bf",
|
||||||
|
"0xafbb572b8d9119ba8126fdd5a593663db3a3e6165a60f1f439902a6321a8d243",
|
||||||
|
"0xcbfeb8af8c93b11eaddb05df2f2a8772da694f9cc16878d3154d0857f17274ae",
|
||||||
|
"0x7253cf6bd2b4d158c2bd60acf5fda9dff6cbc6468ca9b549efcd824410d2e719",
|
||||||
|
"0x67fa14af20fe738ec5c9414401149a1f198207969768a5b982454146ef720b85",
|
||||||
|
"0x6c0ddef53c7d58839c3013f2accb72190b7dcc52fbe5d71f4a20f849dd72725f",
|
||||||
|
"0x89e77c0dd9fcb4b4d4d10c25903ff5b905f5d64b6bed9a0736e9dc2035ade3eb",
|
||||||
|
"0x42466344821fc29dcdb5fe7dcbda00b3779736ca90f87ca1802207f61633877b",
|
||||||
|
"0x6e2303e8ed41e6d39488c57dff8d50c548a7079a26c3fb86d925c0aca5b8f67b",
|
||||||
|
"0xb8a14969606442bd94048f2b2dc7b87662d801097537f51c8eb8f026c52f1fe9",
|
||||||
|
"0xd7ee25e0bfd080d89c475942575fa055ce5ae268a6f01b916b399f6ff7e94a39",
|
||||||
|
"0xaf5e7da13dc0ab08ba5185074657acaa2ce753a20a364f3a97d230c247bc8d1c",
|
||||||
|
"0x92f9106bc9ccbb4e0b4c0d1b96c5bf347d856884eca91a0bcf29e896789fd9c2",
|
||||||
|
"0x4bc12bfadacd6af0737646b813b1a4a9c005e97ef4b090bb74b7475b50c85dfe",
|
||||||
|
"0x91e4ef72d0bdef33e2e2c8acbdd7926182568f559397bfc086b96979e7c4f53b",
|
||||||
|
"0xb2f57e050021b238e0b47b0b46a641644645db5bbd987e8d957038655d1fa83a",
|
||||||
|
"0xaf221401f4cfa3db7879237b40c68300060df9f65dbf68bb02694837eaa8af7a",
|
||||||
|
"0x2dd280e98a0d6bc950b7f3f0bd11a9e74105d4d15463184a3f8c03d40f3193ef",
|
||||||
|
"0x2538560e5b802a89a021685f994acbdb3181f25d0cae17160aedfc619ca2954b",
|
||||||
|
"0x133cfa3f5d6a00f7392a6b0c6a97a9ba10ec50b24cfbbe6028995258cbaa065e",
|
||||||
|
"0xc120807872f07adeb144905ff323ea79880389a2815f8441befbfa82835555b2",
|
||||||
|
"0xa2c5c5a3cbf6db506dfc13285b07c24ca7e70d9e75d80fe711c3082ba119d77a",
|
||||||
|
"0x837622b7bbb8bb18b3d42058426ef97e3fbc2842d2b64b339733b52313557562",
|
||||||
|
"0x29eda2468556699747beef75f015e6772980056cf367b819d05a4822b7d54712",
|
||||||
|
"0xc6ec29323368dc29a1d4c3c11e945ef7fdb56db78808c4c9688ab5f9eb7f27cd",
|
||||||
|
"0x44b368ab63e1fe0e0da031a4e6628ed1a4fc69fa4083cc056dd9443400be3326",
|
||||||
|
"0xf153dbc5fc03a89e80d2808ecd45e9fe6453d112508d32ffc6305d5a577d14d8",
|
||||||
|
"0x32452c0d51df7a85eac3edec46bbfe376c971ac4df4512d7e050e6fa711373ca",
|
||||||
|
"0x70cb25f3d60126cf0104a40b2a49b44ef8a42f60b93f929594938ac00647b639",
|
||||||
|
"0xed63fb33d707b93e45e958d5d5f9d3f0898c3676e43eeca55c788cbb2df3170d",
|
||||||
|
"0x93ff103a026350b0e9c2b30c36e079145892e8e3756678e8ae4b0065fb6a04ec",
|
||||||
|
"0xa466cdf6063bfe155ed75c115484ce113227385eff2cdc07dd90405239842f3f",
|
||||||
|
"0x2883c296d9ce6b1e6e7b4f471e841437603ecbb867570cbc46d86f0f26871600",
|
||||||
|
"0xea5e5b84183a3a709a51c1c6f3e7b039c4663d7495b9bdcfbd4ecb0a95ea994c",
|
||||||
|
"0xc0e97318bd3ee2957c09d6acedac77ce6b219608e5dd63ef512aa08d63c3a114",
|
||||||
|
"0xd3ccc7fcd24076afdf6249f671de402b515a131913df2da17118be47b3720b33",
|
||||||
|
"0x4f5be5a6edd66ec496207b33cefd00722f3167b9e6f2a44d9613c4c7d6541aba",
|
||||||
|
"0xfecdd1844517d0523a7b45d7b51769728902b881b7fc308f486e850c870eef5b",
|
||||||
|
"0x01a22dea1d0e25885e0a03e56489bcaf6747e712ceb5a42c74430fa6ffcc1c21",
|
||||||
|
"0x06cc521a05ce856dc55041b90dc4bbafffee578c1c315b5cfa4cc2d1ccba891f",
|
||||||
|
"0xac21d4b08fbf2891e0b3645b870695434fe703101f74e7fcf0d0e1304ce65b54",
|
||||||
|
"0xd62584c47aa1d8554cc08cf675bed128e541df54900fbfae958877595ad168ff",
|
||||||
|
"0xd8f1806ddaee8e729218fea1911efc5e663666ffb3acad4a2fda3757700d6d88",
|
||||||
|
"0x9dab2acfe01506a185276145deeecdb5c8fe0937feacffd40fb25a83e8eecc72",
|
||||||
|
"0xf0b74c6b1a441fc2ee8b2f25d2f03307164014d42a0784683a9d6cb7d2179064",
|
||||||
|
"0x7d590f0bcc891e30996adf8583803a9dd1271442c3f0e69502addbd371437767",
|
||||||
|
"0x3a66601fff95b0aa0d0660c12788ad56d2383cae290ceb2fb9ff41794abbc55a",
|
||||||
|
"0x36e94b03402f18c689f5234973ce1e626a82aac085dbdd682b51cce21f8c1872",
|
||||||
|
"0x00abd1d34c7e55f58681866558cb844c11faa55e8cac70ede75811f55341cfde",
|
||||||
|
"0x9983fc20e63e77ec0680522035b03167403681674ec62293cd6b7fe360c69157",
|
||||||
|
"0xe98b658fb8b6b7fba7463562f86348bf1e3534bc9148e8559423b3ee5ab68472"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"accounts": {
|
"accounts": {
|
||||||
|
@ -53,8 +53,8 @@
|
|||||||
"gasLimit": "0x1000000"
|
"gasLimit": "0x1000000"
|
||||||
},
|
},
|
||||||
"hardcodedSync":{
|
"hardcodedSync":{
|
||||||
"header": "f90214a04d45aaeb1f0e00495b99f5fdc46c2c1e6b0fd48c693678de72afc1cb6f47a086a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794120c78af68df5957e776554d138a6b75f2c34b6ca0f2746b213421be4ec9cab40fa41aabfb4a3e8acccb6506d6cea4863774374dafa0225a348dfb2ef00db09da39b1a11b31741b6d14fd4456cdf4c2528961f398b74a09528322c1ce98449eed355ddabe0192fac920910a0d88965444b9efc1ac218eab901008000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000040000000000000000000000200000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000000008426e4d4518334e0018389545c8306529d845b284db896d583010a068650617269747986312e32362e32826c69a066f990a9ad374c2cb0017e96d3776e6c787f679d77c9079fe2b046279453d0f88851bec8da753bda19",
|
"header": "f90213a0f6a1b2e8155af1d1d77879826e2535cb6023ba35705934380ab05f65bcbfb107a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f3af96f89b3d7cdcbe0c083690a28185feb0b3cea015ca95dffe4c5de6d9c02d9282df0db94855b0d602738f4b6fcb2268694cd92aa07ecb0900077c45bd4d3ca910218099f726fea18461f90be18897710767a51559a0251f2cb798e965c5d9b11c882f37c69fd2c42b314fabe64d2b4998c76eb93ae8b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008439b475f9833720018389769d82f618845b45928b96d583010b038650617269747986312e32362e31826c69a0fbd0db05012df54423a6b25395ec4f6e66d9f11af8b9c492c4fb7197fcd6a5ba8877d4a227c2bdf4de",
|
||||||
"totalDifficulty": "8635599198809021",
|
"totalDifficulty": "8809217991079619",
|
||||||
"CHTs": [
|
"CHTs": [
|
||||||
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
|
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
|
||||||
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
|
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
|
||||||
@ -1747,7 +1747,79 @@
|
|||||||
"0x8baa0703e1a050c40f85dc850fe477881f432c951b1cc1b2b71ffb68ab7fe0d7",
|
"0x8baa0703e1a050c40f85dc850fe477881f432c951b1cc1b2b71ffb68ab7fe0d7",
|
||||||
"0x14ca94dfd343548e32ef5659c043d6e28f0e577fd38da1ee12f11c08e281d775",
|
"0x14ca94dfd343548e32ef5659c043d6e28f0e577fd38da1ee12f11c08e281d775",
|
||||||
"0xef25357970c76a8b72a6e52f49bc30651f711c7df70444d4667e80febc0e3b2a",
|
"0xef25357970c76a8b72a6e52f49bc30651f711c7df70444d4667e80febc0e3b2a",
|
||||||
"0x41b8b4ebd5919dad3bc609ded524b97403d88f019367f0f4f622561131644ffb"
|
"0x41b8b4ebd5919dad3bc609ded524b97403d88f019367f0f4f622561131644ffb",
|
||||||
|
"0xb29a8ad1157621d0120aedbd8dfeb4b318979bd43a5b018bf7b9ce33d85da312",
|
||||||
|
"0x9ddf78b5d67ef40454867ed33de83a01cbd8c18fe09da3d9f991a196811dfccd",
|
||||||
|
"0x3604121f9cfbb5cf552cf8bfc9a7958332eb97131158e4f40f4eda481e553991",
|
||||||
|
"0xf1778830f694720a6f990f9d476b0f365e8a74880253b55ee16f5cbd6c8082a4",
|
||||||
|
"0x89831626d154fbe84a4c62c3e2638cd00e42b3844c7c7b98cfad113abdbc5347",
|
||||||
|
"0x650573f5ef274b2aeb40642e25fbd661cb0eff66245d7cc8f6fb9e9daa80fc12",
|
||||||
|
"0x479f6c652173efe94abaa850bffe1557847b26f286467013a4d72973e05e8e54",
|
||||||
|
"0x7096619d5716c34592ac2d9907ac28a74c6f6b1ebb1962a0217df82bf3e714d4",
|
||||||
|
"0xb7c7edbd8ae7eed58e973dc0750adfd04042ed56baabf372b111fce3e4b4469a",
|
||||||
|
"0x25529b597bd15317e55767b3fbfecad0657aaeda99f098186b41b70811f7af2a",
|
||||||
|
"0xd790747b09f925fd155b7bbdb5ccd89d873277163e4fe7054bbf71c0b26b8072",
|
||||||
|
"0x3aa0b221d1c4743a06692f645f38a8128d55f1c07cfa6e9711b0d2e0f2e0e738",
|
||||||
|
"0x26fb5017218cbe4250d2ceae751e99b9a34d7befa162dc248ac008c5d1221e71",
|
||||||
|
"0x0e4ada59854027601f8f81fbdceb95228db667eb65fed97cefbb35dba21d3b52",
|
||||||
|
"0xd3be75ae2da3e271dd85cd8226d789aa12d108a4b0d2681462f6539637572e50",
|
||||||
|
"0x6f041891c8219b508138f67c95a1765d08c5ec06b9ce585f52f837806fce0609",
|
||||||
|
"0x9e106515d0e80b41397b2e8e98adbb7333e76265917339a62063a07d9a7ed311",
|
||||||
|
"0x25f47483ecc5ec32f94b3dbcb4d42a4cdbf5c279e93567e14afc742a4619d3e0",
|
||||||
|
"0x5d81afc54f6b68bd820dcc629ff7e9d8397da56ffedef9addab0eec620de0757",
|
||||||
|
"0x36e192130485f248925d4b0d2fd98745a76099eb13f53093621d216d0aff0d6c",
|
||||||
|
"0xb906e5e33b63f6cc355c13b8461a260ee25376ee96909fad2c6ac121ad831496",
|
||||||
|
"0xd68e7e0d136e30f67ccb7c21e4dc43b0ad5536584e4b77c9da8d903a04e9d212",
|
||||||
|
"0x5aa7847a4bddda7fbffa62325da920a21a11524ac1b691bc3b55e4d1790f24bc",
|
||||||
|
"0x331f95f062ed1d38dd02b5ab6a95dd238ef97c5ee9777c938697340c902b4b5d",
|
||||||
|
"0x8c6a580c8b07567f747bf20946023c3b581c51075cce5cd5d47b0d81d8922135",
|
||||||
|
"0x8b89483810a49626f90846a0b49ad3e2172657dfa3003d58fa2a43d12c8f4090",
|
||||||
|
"0x944f9a5754800a33d903c8a464d602fc9da6af8ff3990c3eb669ac9cd17891f9",
|
||||||
|
"0xc75c82a2c1ecd875d16f343a58835d756740902c246d3b1deae97e49aa19f98b",
|
||||||
|
"0x1d2e0f2f87ff2b08514b18855c343966d42e0f1a048ddd3d316dca6e06292db9",
|
||||||
|
"0xa6508507463e53b3a840dd55ed9be57c8a56e1533c9001276750bdf19796f8ea",
|
||||||
|
"0x01eb6b636b1852e8f9066c12d4e6b7b06b90a325be4d97e08f7f560bab4796a1",
|
||||||
|
"0x8a0d77fb41f50808ff0a46dc9f3831a2b5093f55ec2e94a3d2e92373ff3b5695",
|
||||||
|
"0xea3383ba1d30891d1e236db2b31373541f51a9e5c4b4d017cc4960480dd20311",
|
||||||
|
"0x01129e8d7eff516a225cc0db090e4e38362d9eb2d0571ce00f4417836de2e375",
|
||||||
|
"0x92feaefb7f9466814a0220e536fe5ee73560507d071e059827d406329e609f87",
|
||||||
|
"0xac149150c11b3bdc660320a0e955f154fa3137549a73951207659e2b903c145b",
|
||||||
|
"0xcb68cdb224f9b3b0b0f3ca0056e70817146c9ebc75876dd952e6ca8ea896f2ac",
|
||||||
|
"0x157565282a12d790452e343c9762c2124456039729f3a8f97a2cee60d85628fa",
|
||||||
|
"0x42eadc181d59d8d8b26b37e0e9c9052e45bde72090d330bf9cf21d9d3c7d9048",
|
||||||
|
"0x1ea0ec8879b200e259a3a2a0f2a7aa292301784fa422f7c32ed5d945183948b2",
|
||||||
|
"0x06aeb2956be9d74ae4ff0b8a6c1874ed8ba46a186616356dc060bea1cbe5c628",
|
||||||
|
"0x814b0382b52a155a4e35639aeb3d8c859afc4fe5d151de3b0f1bac646e40f2eb",
|
||||||
|
"0xb30bf3e85be41a2a9e53321ee9f03c7078516c72c7e2d8e7e3134de709b61c36",
|
||||||
|
"0x1f97f5d334b5e6ebc72f5b846f24c7911f4fd1653f89b3477ce4b8108342810f",
|
||||||
|
"0x84c6fd181c28ad159ff18d203d14f966668468c9ef0a5d6dbd863886a7e0af1e",
|
||||||
|
"0x4b2e6947d55ea504bf205bae9dfc0e5402efd33757eea4da00a8ed2a6a3838ae",
|
||||||
|
"0x85f31d45128bb91cd3490b58a0a641ef77246ea9c83de30fa89b621307fd96f3",
|
||||||
|
"0xd362f5e6f8cbb216e66eaf49e4df25e01504ac729da86c530871a34e11d302f6",
|
||||||
|
"0xb7860983b043bc13ce5a27135eea12ffaeff71879404b18af3079b98da156bf2",
|
||||||
|
"0xf2ff82a679b2b90cb9f4a3bb903eb7ab36ee1c47cbe40024d8d570f5e16bbf4e",
|
||||||
|
"0x7e34a7e6673146b6bb7f78593b6093ef15b8e9fd1271b33dc5f7d17876b31871",
|
||||||
|
"0x725c97f83b4cf213296ef353e1c8d64854ef08983fd61320088b8d9e2ab33849",
|
||||||
|
"0x18085800d10fc7845148835d0ef0ac980a82eeafc44e12bfa296f9c38fc6e19d",
|
||||||
|
"0xc6c3cf95310cfd0254f0f8e93a3c25bad2b17df04f9c51a25927b80d02e06b69",
|
||||||
|
"0x822213c1b03cf68ecadc0b7572d37266207d5fe4efd5e56a924b0a1aab8a8e84",
|
||||||
|
"0x1ff46ffd2dd880cca76244f6af1fd8bddbb4b9ec58f86639821a16f2ff08f3a8",
|
||||||
|
"0xe9d00df19d716dc859922f2e6c907263191c8e531498ea557869ea1115317c95",
|
||||||
|
"0x6d3f1edebd562e9d1a236ed7a1d9104fd8f5a086cd78d35c7a65f27c269d98ca",
|
||||||
|
"0xfea701ced5bca0d5043512700598d3eafa0b89dc02f3c157cd1d52bcf4d84d9b",
|
||||||
|
"0x556c1cd8ff3ebc2ccd4eee9f1ad3837e346ecda961da17c0ee9cd4d084a47653",
|
||||||
|
"0x5606be2fba065424af76c94d4156ea82f77d9872ddac7a4c2517957a169e58f9",
|
||||||
|
"0x8d0223425b48487db1b371c966c7688435f4b9fcda75b088f0aac203d6657cb1",
|
||||||
|
"0xfceb55d8f3048a3f2255562e0a9ee342439253abcd048fac151ef4b910048e22",
|
||||||
|
"0x360f76e4f2ef49632e3bf8cfc3afeccff6917e98a48d3568148c3bb13f9d2d7e",
|
||||||
|
"0xd87bbf8397204cc2af883362646b0ae95392303935ec1997ab052c194e0ef117",
|
||||||
|
"0x9f1dad9dfecaaf117ab5277caf672b70540578e703c2024d3f23bb7cf8d6410b",
|
||||||
|
"0x5e130ccb23b7b66dd2fbdd912d6006d2820071dafe2890f593f952028aaa19c0",
|
||||||
|
"0xccd2f182107992fb9b002b87cdf7990cb2810b202b2ae5d6ef5e0b3bd69632e2",
|
||||||
|
"0x4b40cd83205f8b946ca9f11fc3306872650e658e631511fd4080bc8ca749d913",
|
||||||
|
"0x652acc59b71ca20bb65ca195d1a4b3e177f6a3985bdcd6120e1a45b7d4a0c7ca",
|
||||||
|
"0x49a5e2580ceb329665244e489592aea27d54da8189a665d9435e037ea70c46a5",
|
||||||
|
"0x379801356beb3a8e5fa7311792c69c7ac1f675a9c08c837f9f0e9f53c243d6a7"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nodes": [
|
"nodes": [
|
||||||
|
@ -94,6 +94,7 @@ impl ClientService {
|
|||||||
|
|
||||||
let pruning = config.pruning;
|
let pruning = config.pruning;
|
||||||
let client = Client::new(config, &spec, client_db.clone(), miner.clone(), io_service.channel())?;
|
let client = Client::new(config, &spec, client_db.clone(), miner.clone(), io_service.channel())?;
|
||||||
|
miner.set_io_channel(io_service.channel());
|
||||||
|
|
||||||
let snapshot_params = SnapServiceParams {
|
let snapshot_params = SnapServiceParams {
|
||||||
engine: spec.engine.clone(),
|
engine: spec.engine.clone(),
|
||||||
|
@ -200,7 +200,7 @@ pub struct Client {
|
|||||||
|
|
||||||
/// Flag changed by `sleep` and `wake_up` methods. Not to be confused with `enabled`.
|
/// Flag changed by `sleep` and `wake_up` methods. Not to be confused with `enabled`.
|
||||||
liveness: AtomicBool,
|
liveness: AtomicBool,
|
||||||
io_channel: Mutex<IoChannel<ClientIoMessage>>,
|
io_channel: RwLock<IoChannel<ClientIoMessage>>,
|
||||||
|
|
||||||
/// List of actors to be notified on certain chain events
|
/// List of actors to be notified on certain chain events
|
||||||
notify: RwLock<Vec<Weak<ChainNotify>>>,
|
notify: RwLock<Vec<Weak<ChainNotify>>>,
|
||||||
@ -712,7 +712,7 @@ impl Client {
|
|||||||
db: RwLock::new(db.clone()),
|
db: RwLock::new(db.clone()),
|
||||||
state_db: RwLock::new(state_db),
|
state_db: RwLock::new(state_db),
|
||||||
report: RwLock::new(Default::default()),
|
report: RwLock::new(Default::default()),
|
||||||
io_channel: Mutex::new(message_channel),
|
io_channel: RwLock::new(message_channel),
|
||||||
notify: RwLock::new(Vec::new()),
|
notify: RwLock::new(Vec::new()),
|
||||||
queue_transactions: IoChannelQueue::new(config.transaction_verification_queue_size),
|
queue_transactions: IoChannelQueue::new(config.transaction_verification_queue_size),
|
||||||
queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE),
|
queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE),
|
||||||
@ -947,7 +947,7 @@ impl Client {
|
|||||||
|
|
||||||
/// Replace io channel. Useful for testing.
|
/// Replace io channel. Useful for testing.
|
||||||
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||||
*self.io_channel.lock() = io_channel;
|
*self.io_channel.write() = io_channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a copy of the best block's state.
|
/// Get a copy of the best block's state.
|
||||||
@ -1893,8 +1893,8 @@ impl BlockChainClient for Client {
|
|||||||
(*self.build_last_hashes(&self.chain.read().best_block_hash())).clone()
|
(*self.build_last_hashes(&self.chain.read().best_block_hash())).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<Arc<VerifiedTransaction>> {
|
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
|
||||||
self.importer.miner.ready_transactions(self)
|
self.importer.miner.ready_transactions(self, max_len, ::miner::PendingOrdering::Priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_chain_id(&self) -> Option<u64> {
|
fn signing_chain_id(&self) -> Option<u64> {
|
||||||
@ -1952,7 +1952,7 @@ impl IoClient for Client {
|
|||||||
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize) {
|
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize) {
|
||||||
trace_time!("queue_transactions");
|
trace_time!("queue_transactions");
|
||||||
let len = transactions.len();
|
let len = transactions.len();
|
||||||
self.queue_transactions.queue(&mut self.io_channel.lock(), len, move |client| {
|
self.queue_transactions.queue(&self.io_channel.read(), len, move |client| {
|
||||||
trace_time!("import_queued_transactions");
|
trace_time!("import_queued_transactions");
|
||||||
|
|
||||||
let txs: Vec<UnverifiedTransaction> = transactions
|
let txs: Vec<UnverifiedTransaction> = transactions
|
||||||
@ -2001,7 +2001,7 @@ impl IoClient for Client {
|
|||||||
|
|
||||||
let queued = self.queued_ancient_blocks.clone();
|
let queued = self.queued_ancient_blocks.clone();
|
||||||
let lock = self.ancient_blocks_import_lock.clone();
|
let lock = self.ancient_blocks_import_lock.clone();
|
||||||
match self.queue_ancient_blocks.queue(&mut self.io_channel.lock(), 1, move |client| {
|
match self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
|
||||||
trace_time!("import_ancient_block");
|
trace_time!("import_ancient_block");
|
||||||
// Make sure to hold the lock here to prevent importing out of order.
|
// Make sure to hold the lock here to prevent importing out of order.
|
||||||
// We use separate lock, cause we don't want to block queueing.
|
// We use separate lock, cause we don't want to block queueing.
|
||||||
@ -2033,7 +2033,7 @@ impl IoClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn queue_consensus_message(&self, message: Bytes) {
|
fn queue_consensus_message(&self, message: Bytes) {
|
||||||
match self.queue_consensus_message.queue(&mut self.io_channel.lock(), 1, move |client| {
|
match self.queue_consensus_message.queue(&self.io_channel.read(), 1, move |client| {
|
||||||
if let Err(e) = client.engine().handle_message(&message) {
|
if let Err(e) = client.engine().handle_message(&message) {
|
||||||
debug!(target: "poa", "Invalid message received: {}", e);
|
debug!(target: "poa", "Invalid message received: {}", e);
|
||||||
}
|
}
|
||||||
@ -2142,7 +2142,14 @@ impl ImportSealedBlock for Client {
|
|||||||
route
|
route
|
||||||
};
|
};
|
||||||
let route = ChainRoute::from([route].as_ref());
|
let route = ChainRoute::from([route].as_ref());
|
||||||
self.importer.miner.chain_new_blocks(self, &[h.clone()], &[], route.enacted(), route.retracted(), true);
|
self.importer.miner.chain_new_blocks(
|
||||||
|
self,
|
||||||
|
&[h.clone()],
|
||||||
|
&[],
|
||||||
|
route.enacted(),
|
||||||
|
route.retracted(),
|
||||||
|
self.engine.seals_internally().is_some(),
|
||||||
|
);
|
||||||
self.notify(|notify| {
|
self.notify(|notify| {
|
||||||
notify.new_blocks(
|
notify.new_blocks(
|
||||||
vec![h.clone()],
|
vec![h.clone()],
|
||||||
@ -2452,7 +2459,7 @@ impl IoChannelQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn queue<F>(&self, channel: &mut IoChannel<ClientIoMessage>, count: usize, fun: F) -> Result<(), QueueError> where
|
pub fn queue<F>(&self, channel: &IoChannel<ClientIoMessage>, count: usize, fun: F) -> Result<(), QueueError> where
|
||||||
F: Fn(&Client) + Send + Sync + 'static,
|
F: Fn(&Client) + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed);
|
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed);
|
||||||
|
@ -48,7 +48,7 @@ use log_entry::LocalizedLogEntry;
|
|||||||
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
|
use receipt::{Receipt, LocalizedReceipt, TransactionOutcome};
|
||||||
use error::ImportResult;
|
use error::ImportResult;
|
||||||
use vm::Schedule;
|
use vm::Schedule;
|
||||||
use miner::{Miner, MinerService};
|
use miner::{self, Miner, MinerService};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use types::basic_account::BasicAccount;
|
use types::basic_account::BasicAccount;
|
||||||
use types::mode::Mode;
|
use types::mode::Mode;
|
||||||
@ -806,8 +806,8 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
self.traces.read().clone()
|
self.traces.read().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions(&self) -> Vec<Arc<VerifiedTransaction>> {
|
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
|
||||||
self.miner.ready_transactions(self)
|
self.miner.ready_transactions(self, max_len, miner::PendingOrdering::Priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signing_chain_id(&self) -> Option<u64> { None }
|
fn signing_chain_id(&self) -> Option<u64> { None }
|
||||||
|
@ -321,7 +321,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
|||||||
fn last_hashes(&self) -> LastHashes;
|
fn last_hashes(&self) -> LastHashes;
|
||||||
|
|
||||||
/// List all transactions that are allowed into the next block.
|
/// List all transactions that are allowed into the next block.
|
||||||
fn ready_transactions(&self) -> Vec<Arc<VerifiedTransaction>>;
|
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>>;
|
||||||
|
|
||||||
/// Sorted list of transaction gas prices from at least last sample_size blocks.
|
/// Sorted list of transaction gas prices from at least last sample_size blocks.
|
||||||
fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus<U256> {
|
fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus<U256> {
|
||||||
|
@ -289,11 +289,18 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
|||||||
self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards)
|
self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "miner-debug"))]
|
||||||
fn verify_local_seal(&self, header: &Header) -> Result<(), Error> {
|
fn verify_local_seal(&self, header: &Header) -> Result<(), Error> {
|
||||||
self.verify_block_basic(header)
|
self.verify_block_basic(header)
|
||||||
.and_then(|_| self.verify_block_unordered(header))
|
.and_then(|_| self.verify_block_unordered(header))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "miner-debug")]
|
||||||
|
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> {
|
||||||
|
warn!("Skipping seal verification, running in miner testing mode.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
|
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
|
||||||
// check the seal fields.
|
// check the seal fields.
|
||||||
let seal = Seal::parse_seal(header.seal())?;
|
let seal = Seal::parse_seal(header.seal())?;
|
||||||
|
@ -27,6 +27,7 @@ use ethcore_miner::gas_pricer::GasPricer;
|
|||||||
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy};
|
use ethcore_miner::pool::{self, TransactionQueue, VerifiedTransaction, QueueStatus, PrioritizationStrategy};
|
||||||
use ethcore_miner::work_notify::NotifyWork;
|
use ethcore_miner::work_notify::NotifyWork;
|
||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
|
use io::IoChannel;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use transaction::{
|
use transaction::{
|
||||||
@ -43,7 +44,7 @@ use block::{ClosedBlock, IsBlock, Block, SealedBlock};
|
|||||||
use client::{
|
use client::{
|
||||||
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce
|
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce
|
||||||
};
|
};
|
||||||
use client::BlockId;
|
use client::{BlockId, ClientIoMessage};
|
||||||
use executive::contract_address;
|
use executive::contract_address;
|
||||||
use header::{Header, BlockNumber};
|
use header::{Header, BlockNumber};
|
||||||
use miner;
|
use miner;
|
||||||
@ -94,7 +95,7 @@ const DEFAULT_MINIMAL_GAS_PRICE: u64 = 20_000_000_000;
|
|||||||
/// before stopping attempts to push more transactions to the block.
|
/// before stopping attempts to push more transactions to the block.
|
||||||
/// This is an optimization that prevents traversing the entire pool
|
/// This is an optimization that prevents traversing the entire pool
|
||||||
/// in case we have only a fraction of available block gas limit left.
|
/// in case we have only a fraction of available block gas limit left.
|
||||||
const MAX_SKIPPED_TRANSACTIONS: usize = 8;
|
const MAX_SKIPPED_TRANSACTIONS: usize = 128;
|
||||||
|
|
||||||
/// Configures the behaviour of the miner.
|
/// Configures the behaviour of the miner.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
@ -209,6 +210,7 @@ pub struct Miner {
|
|||||||
transaction_queue: Arc<TransactionQueue>,
|
transaction_queue: Arc<TransactionQueue>,
|
||||||
engine: Arc<EthEngine>,
|
engine: Arc<EthEngine>,
|
||||||
accounts: Option<Arc<AccountProvider>>,
|
accounts: Option<Arc<AccountProvider>>,
|
||||||
|
io_channel: RwLock<Option<IoChannel<ClientIoMessage>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Miner {
|
impl Miner {
|
||||||
@ -224,7 +226,12 @@ impl Miner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates new instance of miner Arc.
|
/// Creates new instance of miner Arc.
|
||||||
pub fn new(options: MinerOptions, gas_pricer: GasPricer, spec: &Spec, accounts: Option<Arc<AccountProvider>>) -> Self {
|
pub fn new(
|
||||||
|
options: MinerOptions,
|
||||||
|
gas_pricer: GasPricer,
|
||||||
|
spec: &Spec,
|
||||||
|
accounts: Option<Arc<AccountProvider>>,
|
||||||
|
) -> Self {
|
||||||
let limits = options.pool_limits.clone();
|
let limits = options.pool_limits.clone();
|
||||||
let verifier_options = options.pool_verification_options.clone();
|
let verifier_options = options.pool_verification_options.clone();
|
||||||
let tx_queue_strategy = options.tx_queue_strategy;
|
let tx_queue_strategy = options.tx_queue_strategy;
|
||||||
@ -247,6 +254,7 @@ impl Miner {
|
|||||||
transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)),
|
transaction_queue: Arc::new(TransactionQueue::new(limits, verifier_options, tx_queue_strategy)),
|
||||||
accounts,
|
accounts,
|
||||||
engine: spec.engine.clone(),
|
engine: spec.engine.clone(),
|
||||||
|
io_channel: RwLock::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,6 +274,11 @@ impl Miner {
|
|||||||
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts)
|
}, GasPricer::new_fixed(minimal_gas_price), spec, accounts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets `IoChannel`
|
||||||
|
pub fn set_io_channel(&self, io_channel: IoChannel<ClientIoMessage>) {
|
||||||
|
*self.io_channel.write() = Some(io_channel);
|
||||||
|
}
|
||||||
|
|
||||||
/// Clear all pending block states
|
/// Clear all pending block states
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
self.sealing.lock().queue.reset();
|
self.sealing.lock().queue.reset();
|
||||||
@ -368,18 +381,28 @@ impl Miner {
|
|||||||
|
|
||||||
let client = self.pool_client(chain);
|
let client = self.pool_client(chain);
|
||||||
let engine_params = self.engine.params();
|
let engine_params = self.engine.params();
|
||||||
let min_tx_gas = self.engine.schedule(chain_info.best_block_number).tx_gas.into();
|
let min_tx_gas: U256 = self.engine.schedule(chain_info.best_block_number).tx_gas.into();
|
||||||
let nonce_cap: Option<U256> = if chain_info.best_block_number + 1 >= engine_params.dust_protection_transition {
|
let nonce_cap: Option<U256> = if chain_info.best_block_number + 1 >= engine_params.dust_protection_transition {
|
||||||
Some((engine_params.nonce_cap_increment * (chain_info.best_block_number + 1)).into())
|
Some((engine_params.nonce_cap_increment * (chain_info.best_block_number + 1)).into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
// we will never need more transactions than limit divided by min gas
|
||||||
|
let max_transactions = if min_tx_gas.is_zero() {
|
||||||
|
usize::max_value()
|
||||||
|
} else {
|
||||||
|
MAX_SKIPPED_TRANSACTIONS.saturating_add((*open_block.block().header().gas_limit() / min_tx_gas).as_u64() as usize)
|
||||||
|
};
|
||||||
|
|
||||||
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
|
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
chain_info.best_block_number,
|
pool::PendingSettings {
|
||||||
chain_info.best_block_timestamp,
|
block_number: chain_info.best_block_number,
|
||||||
|
current_timestamp: chain_info.best_block_timestamp,
|
||||||
nonce_cap,
|
nonce_cap,
|
||||||
|
max_len: max_transactions,
|
||||||
|
ordering: miner::PendingOrdering::Priority,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let took_ms = |elapsed: &Duration| {
|
let took_ms = |elapsed: &Duration| {
|
||||||
@ -871,7 +894,7 @@ impl miner::MinerService for Miner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions<C>(&self, chain: &C)
|
fn ready_transactions<C>(&self, chain: &C, max_len: usize, ordering: miner::PendingOrdering)
|
||||||
-> Vec<Arc<VerifiedTransaction>>
|
-> Vec<Arc<VerifiedTransaction>>
|
||||||
where
|
where
|
||||||
C: ChainInfo + Nonce + Sync,
|
C: ChainInfo + Nonce + Sync,
|
||||||
@ -879,14 +902,20 @@ impl miner::MinerService for Miner {
|
|||||||
let chain_info = chain.chain_info();
|
let chain_info = chain.chain_info();
|
||||||
|
|
||||||
let from_queue = || {
|
let from_queue = || {
|
||||||
self.transaction_queue.pending(
|
|
||||||
CachedNonceClient::new(chain, &self.nonce_cache),
|
|
||||||
chain_info.best_block_number,
|
|
||||||
chain_info.best_block_timestamp,
|
|
||||||
// We propagate transactions over the nonce cap.
|
// We propagate transactions over the nonce cap.
|
||||||
// The mechanism is only to limit number of transactions in pending block
|
// The mechanism is only to limit number of transactions in pending block
|
||||||
// those transactions are valid and will just be ready to be included in next block.
|
// those transactions are valid and will just be ready to be included in next block.
|
||||||
None,
|
let nonce_cap = None;
|
||||||
|
|
||||||
|
self.transaction_queue.pending(
|
||||||
|
CachedNonceClient::new(chain, &self.nonce_cache),
|
||||||
|
pool::PendingSettings {
|
||||||
|
block_number: chain_info.best_block_number,
|
||||||
|
current_timestamp: chain_info.best_block_timestamp,
|
||||||
|
nonce_cap,
|
||||||
|
max_len,
|
||||||
|
ordering,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -896,6 +925,7 @@ impl miner::MinerService for Miner {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
.map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone()))
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
|
.take(max_len)
|
||||||
.collect()
|
.collect()
|
||||||
}, chain_info.best_block_number)
|
}, chain_info.best_block_number)
|
||||||
};
|
};
|
||||||
@ -1130,9 +1160,34 @@ impl miner::MinerService for Miner {
|
|||||||
// (thanks to Ready), but culling can take significant amount of time,
|
// (thanks to Ready), but culling can take significant amount of time,
|
||||||
// so best to leave it after we create some work for miners to prevent increased
|
// so best to leave it after we create some work for miners to prevent increased
|
||||||
// uncle rate.
|
// uncle rate.
|
||||||
|
// If the io_channel is available attempt to offload culling to a separate task
|
||||||
|
// to avoid blocking chain_new_blocks
|
||||||
|
if let Some(ref channel) = *self.io_channel.read() {
|
||||||
|
let queue = self.transaction_queue.clone();
|
||||||
|
let nonce_cache = self.nonce_cache.clone();
|
||||||
|
let engine = self.engine.clone();
|
||||||
|
let accounts = self.accounts.clone();
|
||||||
|
let refuse_service_transactions = self.options.refuse_service_transactions;
|
||||||
|
|
||||||
|
let cull = move |chain: &::client::Client| {
|
||||||
|
let client = PoolClient::new(
|
||||||
|
chain,
|
||||||
|
&nonce_cache,
|
||||||
|
&*engine,
|
||||||
|
accounts.as_ref().map(|x| &**x),
|
||||||
|
refuse_service_transactions,
|
||||||
|
);
|
||||||
|
queue.cull(client);
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = channel.send(ClientIoMessage::execute(cull)) {
|
||||||
|
warn!(target: "miner", "Error queueing cull: {:?}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
self.transaction_queue.cull(client);
|
self.transaction_queue.cull(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State> {
|
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State> {
|
||||||
self.map_existing_pending_block(|b| b.state().clone(), latest_block_number)
|
self.map_existing_pending_block(|b| b.state().clone(), latest_block_number)
|
||||||
@ -1160,7 +1215,7 @@ mod tests {
|
|||||||
use rustc_hex::FromHex;
|
use rustc_hex::FromHex;
|
||||||
|
|
||||||
use client::{TestBlockChainClient, EachBlockWith, ChainInfo, ImportSealedBlock};
|
use client::{TestBlockChainClient, EachBlockWith, ChainInfo, ImportSealedBlock};
|
||||||
use miner::MinerService;
|
use miner::{MinerService, PendingOrdering};
|
||||||
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts};
|
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts};
|
||||||
use transaction::{Transaction};
|
use transaction::{Transaction};
|
||||||
|
|
||||||
@ -1259,7 +1314,7 @@ mod tests {
|
|||||||
assert_eq!(res.unwrap(), ());
|
assert_eq!(res.unwrap(), ());
|
||||||
assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 1);
|
assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 1);
|
||||||
assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 1);
|
assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 1);
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 1);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
|
||||||
// This method will let us know if pending block was created (before calling that method)
|
// This method will let us know if pending block was created (before calling that method)
|
||||||
assert!(!miner.prepare_pending_block(&client));
|
assert!(!miner.prepare_pending_block(&client));
|
||||||
}
|
}
|
||||||
@ -1278,7 +1333,7 @@ mod tests {
|
|||||||
assert_eq!(res.unwrap(), ());
|
assert_eq!(res.unwrap(), ());
|
||||||
assert_eq!(miner.pending_transactions(best_block), None);
|
assert_eq!(miner.pending_transactions(best_block), None);
|
||||||
assert_eq!(miner.pending_receipts(best_block), None);
|
assert_eq!(miner.pending_receipts(best_block), None);
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 1);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1297,11 +1352,11 @@ mod tests {
|
|||||||
assert_eq!(miner.pending_transactions(best_block), None);
|
assert_eq!(miner.pending_transactions(best_block), None);
|
||||||
assert_eq!(miner.pending_receipts(best_block), None);
|
assert_eq!(miner.pending_receipts(best_block), None);
|
||||||
// By default we use PendingSet::AlwaysSealing, so no transactions yet.
|
// By default we use PendingSet::AlwaysSealing, so no transactions yet.
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 0);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 0);
|
||||||
// This method will let us know if pending block was created (before calling that method)
|
// This method will let us know if pending block was created (before calling that method)
|
||||||
assert!(miner.prepare_pending_block(&client));
|
assert!(miner.prepare_pending_block(&client));
|
||||||
// After pending block is created we should see a transaction.
|
// After pending block is created we should see a transaction.
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 1);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1333,9 +1388,9 @@ mod tests {
|
|||||||
assert_eq!(res.unwrap(), ());
|
assert_eq!(res.unwrap(), ());
|
||||||
assert_eq!(miner.pending_transactions(best_block), None);
|
assert_eq!(miner.pending_transactions(best_block), None);
|
||||||
assert_eq!(miner.pending_receipts(best_block), None);
|
assert_eq!(miner.pending_receipts(best_block), None);
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 0);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 0);
|
||||||
assert!(miner.prepare_pending_block(&client));
|
assert!(miner.prepare_pending_block(&client));
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 1);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
|
||||||
|
|
||||||
// when - 2nd part: create a local transaction from account_provider.
|
// when - 2nd part: create a local transaction from account_provider.
|
||||||
// Borrow the transaction used before & sign with our generated keypair.
|
// Borrow the transaction used before & sign with our generated keypair.
|
||||||
@ -1347,7 +1402,7 @@ mod tests {
|
|||||||
assert_eq!(res2.unwrap(), ());
|
assert_eq!(res2.unwrap(), ());
|
||||||
assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 2);
|
assert_eq!(miner.pending_transactions(best_block).unwrap().len(), 2);
|
||||||
assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 2);
|
assert_eq!(miner.pending_receipts(best_block).unwrap().len(), 2);
|
||||||
assert_eq!(miner.ready_transactions(&client).len(), 2);
|
assert_eq!(miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 2);
|
||||||
assert!(!miner.prepare_pending_block(&client));
|
assert!(!miner.prepare_pending_block(&client));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ pub mod pool_client;
|
|||||||
pub mod stratum;
|
pub mod stratum;
|
||||||
|
|
||||||
pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams};
|
pub use self::miner::{Miner, MinerOptions, Penalization, PendingSet, AuthoringParams};
|
||||||
|
pub use ethcore_miner::pool::PendingOrdering;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::{BTreeSet, BTreeMap};
|
use std::collections::{BTreeSet, BTreeMap};
|
||||||
@ -173,7 +174,9 @@ pub trait MinerService : Send + Sync {
|
|||||||
/// Get a list of all ready transactions either ordered by priority or unordered (cheaper).
|
/// Get a list of all ready transactions either ordered by priority or unordered (cheaper).
|
||||||
///
|
///
|
||||||
/// Depending on the settings may look in transaction pool or only in pending block.
|
/// Depending on the settings may look in transaction pool or only in pending block.
|
||||||
fn ready_transactions<C>(&self, chain: &C) -> Vec<Arc<VerifiedTransaction>>
|
/// If you don't need a full set of transactions, you can add `max_len` and create only a limited set of
|
||||||
|
/// transactions.
|
||||||
|
fn ready_transactions<C>(&self, chain: &C, max_len: usize, ordering: PendingOrdering) -> Vec<Arc<VerifiedTransaction>>
|
||||||
where C: ChainInfo + Nonce + Sync;
|
where C: ChainInfo + Nonce + Sync;
|
||||||
|
|
||||||
/// Get a list of all transactions in the pool (some of them might not be ready for inclusion yet).
|
/// Get a list of all transactions in the pool (some of them might not be ready for inclusion yet).
|
||||||
|
@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
//! Blockchain access for transaction pool.
|
//! Blockchain access for transaction pool.
|
||||||
|
|
||||||
use std::fmt;
|
use std::{
|
||||||
use std::collections::HashMap;
|
collections::HashMap,
|
||||||
|
fmt,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
use ethcore_miner::pool;
|
use ethcore_miner::pool;
|
||||||
@ -37,9 +40,9 @@ use miner;
|
|||||||
use miner::service_transaction_checker::ServiceTransactionChecker;
|
use miner::service_transaction_checker::ServiceTransactionChecker;
|
||||||
|
|
||||||
/// Cache for state nonces.
|
/// Cache for state nonces.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NonceCache {
|
pub struct NonceCache {
|
||||||
nonces: RwLock<HashMap<Address, U256>>,
|
nonces: Arc<RwLock<HashMap<Address, U256>>>,
|
||||||
limit: usize
|
limit: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ impl NonceCache {
|
|||||||
/// Create new cache with a limit of `limit` entries.
|
/// Create new cache with a limit of `limit` entries.
|
||||||
pub fn new(limit: usize) -> Self {
|
pub fn new(limit: usize) -> Self {
|
||||||
NonceCache {
|
NonceCache {
|
||||||
nonces: RwLock::new(HashMap::with_capacity(limit / 2)),
|
nonces: Arc::new(RwLock::new(HashMap::with_capacity(limit / 2))),
|
||||||
limit,
|
limit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ use test_helpers::{
|
|||||||
use types::filter::Filter;
|
use types::filter::Filter;
|
||||||
use ethereum_types::{U256, Address};
|
use ethereum_types::{U256, Address};
|
||||||
use kvdb_rocksdb::{Database, DatabaseConfig};
|
use kvdb_rocksdb::{Database, DatabaseConfig};
|
||||||
use miner::Miner;
|
use miner::{Miner, PendingOrdering};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use views::BlockView;
|
use views::BlockView;
|
||||||
use ethkey::KeyPair;
|
use ethkey::KeyPair;
|
||||||
@ -345,12 +345,12 @@ fn does_not_propagate_delayed_transactions() {
|
|||||||
|
|
||||||
client.miner().import_own_transaction(&*client, tx0).unwrap();
|
client.miner().import_own_transaction(&*client, tx0).unwrap();
|
||||||
client.miner().import_own_transaction(&*client, tx1).unwrap();
|
client.miner().import_own_transaction(&*client, tx1).unwrap();
|
||||||
assert_eq!(0, client.ready_transactions().len());
|
assert_eq!(0, client.ready_transactions(10).len());
|
||||||
assert_eq!(0, client.miner().ready_transactions(&*client).len());
|
assert_eq!(0, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
|
||||||
push_blocks_to_client(&client, 53, 2, 2);
|
push_blocks_to_client(&client, 53, 2, 2);
|
||||||
client.flush_queue();
|
client.flush_queue();
|
||||||
assert_eq!(2, client.ready_transactions().len());
|
assert_eq!(2, client.ready_transactions(10).len());
|
||||||
assert_eq!(2, client.miner().ready_transactions(&*client).len());
|
assert_eq!(2, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -357,6 +357,10 @@ impl SyncProvider for EthSync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PEERS_TIMER: TimerToken = 0;
|
||||||
|
const SYNC_TIMER: TimerToken = 1;
|
||||||
|
const TX_TIMER: TimerToken = 2;
|
||||||
|
|
||||||
struct SyncProtocolHandler {
|
struct SyncProtocolHandler {
|
||||||
/// Shared blockchain client.
|
/// Shared blockchain client.
|
||||||
chain: Arc<BlockChainClient>,
|
chain: Arc<BlockChainClient>,
|
||||||
@ -371,7 +375,9 @@ struct SyncProtocolHandler {
|
|||||||
impl NetworkProtocolHandler for SyncProtocolHandler {
|
impl NetworkProtocolHandler for SyncProtocolHandler {
|
||||||
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
fn initialize(&self, io: &NetworkContext, _host_info: &HostInfo) {
|
||||||
if io.subprotocol_name() != WARP_SYNC_PROTOCOL_ID {
|
if io.subprotocol_name() != WARP_SYNC_PROTOCOL_ID {
|
||||||
io.register_timer(0, Duration::from_secs(1)).expect("Error registering sync timer");
|
io.register_timer(PEERS_TIMER, Duration::from_millis(700)).expect("Error registering peers timer");
|
||||||
|
io.register_timer(SYNC_TIMER, Duration::from_millis(1100)).expect("Error registering sync timer");
|
||||||
|
io.register_timer(TX_TIMER, Duration::from_millis(1300)).expect("Error registering transactions timer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,12 +402,17 @@ impl NetworkProtocolHandler for SyncProtocolHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeout(&self, io: &NetworkContext, _timer: TimerToken) {
|
fn timeout(&self, io: &NetworkContext, timer: TimerToken) {
|
||||||
trace_time!("sync::timeout");
|
trace_time!("sync::timeout");
|
||||||
let mut io = NetSyncIo::new(io, &*self.chain, &*self.snapshot_service, &self.overlay);
|
let mut io = NetSyncIo::new(io, &*self.chain, &*self.snapshot_service, &self.overlay);
|
||||||
self.sync.write().maintain_peers(&mut io);
|
match timer {
|
||||||
self.sync.write().maintain_sync(&mut io);
|
PEERS_TIMER => self.sync.write().maintain_peers(&mut io),
|
||||||
|
SYNC_TIMER => self.sync.write().maintain_sync(&mut io),
|
||||||
|
TX_TIMER => {
|
||||||
self.sync.write().propagate_new_transactions(&mut io);
|
self.sync.write().propagate_new_transactions(&mut io);
|
||||||
|
},
|
||||||
|
_ => warn!("Unknown timer {} triggered.", timer),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,18 +477,19 @@ impl BlockDownloader {
|
|||||||
for block_and_receipts in blocks {
|
for block_and_receipts in blocks {
|
||||||
let block = block_and_receipts.block;
|
let block = block_and_receipts.block;
|
||||||
let receipts = block_and_receipts.receipts;
|
let receipts = block_and_receipts.receipts;
|
||||||
|
|
||||||
|
// Perform basic block verification
|
||||||
|
if !Block::is_good(&block) {
|
||||||
|
debug!(target: "sync", "Bad block rlp: {:?}", block);
|
||||||
|
bad = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
let (h, number, parent) = {
|
let (h, number, parent) = {
|
||||||
let header = view!(BlockView, &block).header_view();
|
let header = view!(BlockView, &block).header_view();
|
||||||
(header.hash(), header.number(), header.parent_hash())
|
(header.hash(), header.number(), header.parent_hash())
|
||||||
};
|
};
|
||||||
|
|
||||||
// Perform basic block verification
|
|
||||||
if !Block::is_good(&block) {
|
|
||||||
debug!(target: "sync", "Bad block rlp {:?} : {:?}", h, block);
|
|
||||||
bad = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.target_hash.as_ref().map_or(false, |t| t == &h) {
|
if self.target_hash.as_ref().map_or(false, |t| t == &h) {
|
||||||
self.state = State::Complete;
|
self.state = State::Complete;
|
||||||
trace!(target: "sync", "Sync target reached");
|
trace!(target: "sync", "Sync target reached");
|
||||||
|
@ -149,6 +149,10 @@ const MAX_NEW_HASHES: usize = 64;
|
|||||||
const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
|
const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
|
||||||
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation).
|
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation).
|
||||||
const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
||||||
|
// Maximal number of transactions queried from miner to propagate.
|
||||||
|
// This set is used to diff with transactions known by the peer and
|
||||||
|
// we will send a difference of length up to `MAX_TRANSACTIONS_TO_PROPAGATE`.
|
||||||
|
const MAX_TRANSACTIONS_TO_QUERY: usize = 4096;
|
||||||
// Maximal number of transactions in sent in single packet.
|
// Maximal number of transactions in sent in single packet.
|
||||||
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
|
||||||
// Min number of blocks to be behind for a snapshot sync
|
// Min number of blocks to be behind for a snapshot sync
|
||||||
@ -1144,7 +1148,7 @@ pub mod tests {
|
|||||||
use super::{PeerInfo, PeerAsking};
|
use super::{PeerInfo, PeerAsking};
|
||||||
use ethcore::header::*;
|
use ethcore::header::*;
|
||||||
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient, ChainInfo, BlockInfo};
|
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient, ChainInfo, BlockInfo};
|
||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::{MinerService, PendingOrdering};
|
||||||
use private_tx::NoopPrivateTxHandler;
|
use private_tx::NoopPrivateTxHandler;
|
||||||
|
|
||||||
pub fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes {
|
pub fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes {
|
||||||
@ -1357,7 +1361,7 @@ pub mod tests {
|
|||||||
let mut io = TestIo::new(&mut client, &ss, &queue, None);
|
let mut io = TestIo::new(&mut client, &ss, &queue, None);
|
||||||
io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks, false);
|
io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks, false);
|
||||||
sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]);
|
sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]);
|
||||||
assert_eq!(io.chain.miner.ready_transactions(io.chain).len(), 1);
|
assert_eq!(io.chain.miner.ready_transactions(io.chain, 10, PendingOrdering::Priority).len(), 1);
|
||||||
}
|
}
|
||||||
// We need to update nonce status (because we say that the block has been imported)
|
// We need to update nonce status (because we say that the block has been imported)
|
||||||
for h in &[good_blocks[0]] {
|
for h in &[good_blocks[0]] {
|
||||||
@ -1373,7 +1377,7 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(client.miner.ready_transactions(&client).len(), 1);
|
assert_eq!(client.miner.ready_transactions(&client, 10, PendingOrdering::Priority).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -33,6 +33,7 @@ use super::{
|
|||||||
MAX_PEERS_PROPAGATION,
|
MAX_PEERS_PROPAGATION,
|
||||||
MAX_TRANSACTION_PACKET_SIZE,
|
MAX_TRANSACTION_PACKET_SIZE,
|
||||||
MAX_TRANSACTIONS_TO_PROPAGATE,
|
MAX_TRANSACTIONS_TO_PROPAGATE,
|
||||||
|
MAX_TRANSACTIONS_TO_QUERY,
|
||||||
MIN_PEERS_PROPAGATION,
|
MIN_PEERS_PROPAGATION,
|
||||||
CONSENSUS_DATA_PACKET,
|
CONSENSUS_DATA_PACKET,
|
||||||
NEW_BLOCK_HASHES_PACKET,
|
NEW_BLOCK_HASHES_PACKET,
|
||||||
@ -114,7 +115,7 @@ impl SyncPropagator {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let transactions = io.chain().ready_transactions();
|
let transactions = io.chain().ready_transactions(MAX_TRANSACTIONS_TO_QUERY);
|
||||||
if transactions.is_empty() {
|
if transactions.is_empty() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
use ethcore::snapshot::{ManifestData, SnapshotService};
|
use ethcore::snapshot::{ManifestData, SnapshotService};
|
||||||
use ethereum_types::H256;
|
use ethereum_types::H256;
|
||||||
use hash::keccak;
|
use hash::keccak;
|
||||||
use rand::{thread_rng, Rng};
|
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
@ -114,35 +113,32 @@ impl Snapshot {
|
|||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a random chunk to download
|
/// Find a chunk to download
|
||||||
pub fn needed_chunk(&mut self) -> Option<H256> {
|
pub fn needed_chunk(&mut self) -> Option<H256> {
|
||||||
// Find all random chunks: first blocks, then state
|
// Find next needed chunk: first block, then state chunks
|
||||||
let needed_chunks = {
|
let chunk = {
|
||||||
let chunk_filter = |h| !self.downloading_chunks.contains(h) && !self.completed_chunks.contains(h);
|
let chunk_filter = |h| !self.downloading_chunks.contains(h) && !self.completed_chunks.contains(h);
|
||||||
|
|
||||||
let needed_block_chunks = self.pending_block_chunks.iter()
|
let needed_block_chunk = self.pending_block_chunks.iter()
|
||||||
.filter(|&h| chunk_filter(h))
|
.filter(|&h| chunk_filter(h))
|
||||||
.map(|h| *h)
|
.map(|h| *h)
|
||||||
.collect::<Vec<H256>>();
|
.next();
|
||||||
|
|
||||||
// If no block chunks to download, get the state chunks
|
// If no block chunks to download, get the state chunks
|
||||||
if needed_block_chunks.len() == 0 {
|
if needed_block_chunk.is_none() {
|
||||||
self.pending_state_chunks.iter()
|
self.pending_state_chunks.iter()
|
||||||
.filter(|&h| chunk_filter(h))
|
.filter(|&h| chunk_filter(h))
|
||||||
.map(|h| *h)
|
.map(|h| *h)
|
||||||
.collect::<Vec<H256>>()
|
.next()
|
||||||
} else {
|
} else {
|
||||||
needed_block_chunks
|
needed_block_chunk
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get a random chunk
|
|
||||||
let chunk = thread_rng().choose(&needed_chunks);
|
|
||||||
|
|
||||||
if let Some(hash) = chunk {
|
if let Some(hash) = chunk {
|
||||||
self.downloading_chunks.insert(hash.clone());
|
self.downloading_chunks.insert(hash.clone());
|
||||||
}
|
}
|
||||||
chunk.map(|h| *h)
|
chunk
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_chunk_download(&mut self, hash: &H256) {
|
pub fn clear_chunk_download(&mut self, hash: &H256) {
|
||||||
|
@ -462,7 +462,7 @@
|
|||||||
<key>OVERWRITE_PERMISSIONS</key>
|
<key>OVERWRITE_PERMISSIONS</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>VERSION</key>
|
<key>VERSION</key>
|
||||||
<string>1.11.6</string>
|
<string>1.11.7</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>UUID</key>
|
<key>UUID</key>
|
||||||
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
<string>2DCD5B81-7BAF-4DA1-9251-6274B089FD36</string>
|
||||||
|
@ -35,9 +35,9 @@ extern crate transaction_pool as txpool;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate error_chain;
|
extern crate error_chain;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate trace_time;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate trace_time;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
//! Transaction Pool
|
//! Transaction Pool
|
||||||
|
|
||||||
use ethereum_types::{H256, Address};
|
use ethereum_types::{U256, H256, Address};
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use transaction;
|
use transaction;
|
||||||
use txpool;
|
use txpool;
|
||||||
@ -45,6 +45,43 @@ pub enum PrioritizationStrategy {
|
|||||||
GasPriceOnly,
|
GasPriceOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transaction ordering when requesting pending set.
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum PendingOrdering {
|
||||||
|
/// Get pending transactions ordered by their priority (potentially expensive)
|
||||||
|
Priority,
|
||||||
|
/// Get pending transactions without any care of particular ordering (cheaper).
|
||||||
|
Unordered,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pending set query settings
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PendingSettings {
|
||||||
|
/// Current block number (affects readiness of some transactions).
|
||||||
|
pub block_number: u64,
|
||||||
|
/// Current timestamp (affects readiness of some transactions).
|
||||||
|
pub current_timestamp: u64,
|
||||||
|
/// Nonce cap (for dust protection; EIP-168)
|
||||||
|
pub nonce_cap: Option<U256>,
|
||||||
|
/// Maximal number of transactions in pending the set.
|
||||||
|
pub max_len: usize,
|
||||||
|
/// Ordering of transactions.
|
||||||
|
pub ordering: PendingOrdering,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PendingSettings {
|
||||||
|
/// Get all transactions (no cap or len limit) prioritized.
|
||||||
|
pub fn all_prioritized(block_number: u64, current_timestamp: u64) -> Self {
|
||||||
|
PendingSettings {
|
||||||
|
block_number,
|
||||||
|
current_timestamp,
|
||||||
|
nonce_cap: None,
|
||||||
|
max_len: usize::max_value(),
|
||||||
|
ordering: PendingOrdering::Priority,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Transaction priority.
|
/// Transaction priority.
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Clone, Copy)]
|
||||||
pub(crate) enum Priority {
|
pub(crate) enum Priority {
|
||||||
|
@ -26,7 +26,10 @@ use parking_lot::RwLock;
|
|||||||
use transaction;
|
use transaction;
|
||||||
use txpool::{self, Verifier};
|
use txpool::{self, Verifier};
|
||||||
|
|
||||||
use pool::{self, scoring, verifier, client, ready, listener, PrioritizationStrategy};
|
use pool::{
|
||||||
|
self, scoring, verifier, client, ready, listener,
|
||||||
|
PrioritizationStrategy, PendingOrdering, PendingSettings,
|
||||||
|
};
|
||||||
use pool::local_transactions::LocalTransactionsList;
|
use pool::local_transactions::LocalTransactionsList;
|
||||||
|
|
||||||
type Listener = (LocalTransactionsList, (listener::Notifier, listener::Logger));
|
type Listener = (LocalTransactionsList, (listener::Notifier, listener::Logger));
|
||||||
@ -82,6 +85,7 @@ struct CachedPending {
|
|||||||
nonce_cap: Option<U256>,
|
nonce_cap: Option<U256>,
|
||||||
has_local_pending: bool,
|
has_local_pending: bool,
|
||||||
pending: Option<Vec<Arc<pool::VerifiedTransaction>>>,
|
pending: Option<Vec<Arc<pool::VerifiedTransaction>>>,
|
||||||
|
max_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedPending {
|
impl CachedPending {
|
||||||
@ -93,6 +97,7 @@ impl CachedPending {
|
|||||||
has_local_pending: false,
|
has_local_pending: false,
|
||||||
pending: None,
|
pending: None,
|
||||||
nonce_cap: None,
|
nonce_cap: None,
|
||||||
|
max_len: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +112,7 @@ impl CachedPending {
|
|||||||
block_number: u64,
|
block_number: u64,
|
||||||
current_timestamp: u64,
|
current_timestamp: u64,
|
||||||
nonce_cap: Option<&U256>,
|
nonce_cap: Option<&U256>,
|
||||||
|
max_len: usize,
|
||||||
) -> Option<Vec<Arc<pool::VerifiedTransaction>>> {
|
) -> Option<Vec<Arc<pool::VerifiedTransaction>>> {
|
||||||
// First check if we have anything in cache.
|
// First check if we have anything in cache.
|
||||||
let pending = self.pending.as_ref()?;
|
let pending = self.pending.as_ref()?;
|
||||||
@ -131,7 +137,12 @@ impl CachedPending {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(pending.clone())
|
// It's fine to just take a smaller subset, but not other way around.
|
||||||
|
if max_len > self.max_len {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(pending.iter().take(max_len).cloned().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +239,7 @@ impl TransactionQueue {
|
|||||||
transactions: Vec<verifier::Transaction>,
|
transactions: Vec<verifier::Transaction>,
|
||||||
) -> Vec<Result<(), transaction::Error>> {
|
) -> Vec<Result<(), transaction::Error>> {
|
||||||
// Run verification
|
// Run verification
|
||||||
let _timer = ::trace_time::PerfTimer::new("pool::verify_and_import");
|
trace_time!("pool::verify_and_import");
|
||||||
let options = self.options.read().clone();
|
let options = self.options.read().clone();
|
||||||
|
|
||||||
let transaction_to_replace = {
|
let transaction_to_replace = {
|
||||||
@ -287,10 +298,10 @@ impl TransactionQueue {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all transactions in the queue ordered by priority.
|
/// Returns all transactions in the queue without explicit ordering.
|
||||||
pub fn all_transactions(&self) -> Vec<Arc<pool::VerifiedTransaction>> {
|
pub fn all_transactions(&self) -> Vec<Arc<pool::VerifiedTransaction>> {
|
||||||
let ready = |_tx: &pool::VerifiedTransaction| txpool::Readiness::Ready;
|
let ready = |_tx: &pool::VerifiedTransaction| txpool::Readiness::Ready;
|
||||||
self.pool.read().pending(ready).collect()
|
self.pool.read().unordered_pending(ready).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes unordered set of pending hashes.
|
/// Computes unordered set of pending hashes.
|
||||||
@ -314,24 +325,31 @@ impl TransactionQueue {
|
|||||||
pub fn pending<C>(
|
pub fn pending<C>(
|
||||||
&self,
|
&self,
|
||||||
client: C,
|
client: C,
|
||||||
block_number: u64,
|
settings: PendingSettings,
|
||||||
current_timestamp: u64,
|
|
||||||
nonce_cap: Option<U256>,
|
|
||||||
) -> Vec<Arc<pool::VerifiedTransaction>> where
|
) -> Vec<Arc<pool::VerifiedTransaction>> where
|
||||||
C: client::NonceClient,
|
C: client::NonceClient,
|
||||||
{
|
{
|
||||||
|
let PendingSettings { block_number, current_timestamp, nonce_cap, max_len, ordering } = settings;
|
||||||
if let Some(pending) = self.cached_pending.read().pending(block_number, current_timestamp, nonce_cap.as_ref()) {
|
if let Some(pending) = self.cached_pending.read().pending(block_number, current_timestamp, nonce_cap.as_ref(), max_len) {
|
||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double check after acquiring write lock
|
// Double check after acquiring write lock
|
||||||
let mut cached_pending = self.cached_pending.write();
|
let mut cached_pending = self.cached_pending.write();
|
||||||
if let Some(pending) = cached_pending.pending(block_number, current_timestamp, nonce_cap.as_ref()) {
|
if let Some(pending) = cached_pending.pending(block_number, current_timestamp, nonce_cap.as_ref(), max_len) {
|
||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pending: Vec<_> = self.collect_pending(client, block_number, current_timestamp, nonce_cap, |i| i.collect());
|
// In case we don't have a cached set, but we don't care about order
|
||||||
|
// just return the unordered set.
|
||||||
|
if let PendingOrdering::Unordered = ordering {
|
||||||
|
let ready = Self::ready(client, block_number, current_timestamp, nonce_cap);
|
||||||
|
return self.pool.read().unordered_pending(ready).take(max_len).collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
let pending: Vec<_> = self.collect_pending(client, block_number, current_timestamp, nonce_cap, |i| {
|
||||||
|
i.take(max_len).collect()
|
||||||
|
});
|
||||||
|
|
||||||
*cached_pending = CachedPending {
|
*cached_pending = CachedPending {
|
||||||
block_number,
|
block_number,
|
||||||
@ -339,6 +357,7 @@ impl TransactionQueue {
|
|||||||
nonce_cap,
|
nonce_cap,
|
||||||
has_local_pending: self.has_local_pending_transactions(),
|
has_local_pending: self.has_local_pending_transactions(),
|
||||||
pending: Some(pending.clone()),
|
pending: Some(pending.clone()),
|
||||||
|
max_len,
|
||||||
};
|
};
|
||||||
|
|
||||||
pending
|
pending
|
||||||
@ -363,15 +382,27 @@ impl TransactionQueue {
|
|||||||
scoring::NonceAndGasPrice,
|
scoring::NonceAndGasPrice,
|
||||||
Listener,
|
Listener,
|
||||||
>) -> T,
|
>) -> T,
|
||||||
|
{
|
||||||
|
debug!(target: "txqueue", "Re-computing pending set for block: {}", block_number);
|
||||||
|
trace_time!("pool::collect_pending");
|
||||||
|
let ready = Self::ready(client, block_number, current_timestamp, nonce_cap);
|
||||||
|
collect(self.pool.read().pending(ready))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready<C>(
|
||||||
|
client: C,
|
||||||
|
block_number: u64,
|
||||||
|
current_timestamp: u64,
|
||||||
|
nonce_cap: Option<U256>,
|
||||||
|
) -> (ready::Condition, ready::State<C>) where
|
||||||
|
C: client::NonceClient,
|
||||||
{
|
{
|
||||||
let pending_readiness = ready::Condition::new(block_number, current_timestamp);
|
let pending_readiness = ready::Condition::new(block_number, current_timestamp);
|
||||||
// don't mark any transactions as stale at this point.
|
// don't mark any transactions as stale at this point.
|
||||||
let stale_id = None;
|
let stale_id = None;
|
||||||
let state_readiness = ready::State::new(client, stale_id, nonce_cap);
|
let state_readiness = ready::State::new(client, stale_id, nonce_cap);
|
||||||
|
|
||||||
let ready = (pending_readiness, state_readiness);
|
(pending_readiness, state_readiness)
|
||||||
|
|
||||||
collect(self.pool.read().pending(ready))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Culls all stalled transactions from the pool.
|
/// Culls all stalled transactions from the pool.
|
||||||
@ -523,6 +554,12 @@ impl TransactionQueue {
|
|||||||
let mut pool = self.pool.write();
|
let mut pool = self.pool.write();
|
||||||
(pool.listener_mut().1).0.add(f);
|
(pool.listener_mut().1).0.add(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if pending set is cached.
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn is_pending_cached(&self) -> bool {
|
||||||
|
self.cached_pending.read().pending.is_some()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -549,7 +586,7 @@ mod tests {
|
|||||||
fn should_get_pending_transactions() {
|
fn should_get_pending_transactions() {
|
||||||
let queue = TransactionQueue::new(txpool::Options::default(), verifier::Options::default(), PrioritizationStrategy::GasPriceOnly);
|
let queue = TransactionQueue::new(txpool::Options::default(), verifier::Options::default(), PrioritizationStrategy::GasPriceOnly);
|
||||||
|
|
||||||
let pending: Vec<_> = queue.pending(TestClient::default(), 0, 0, None);
|
let pending: Vec<_> = queue.pending(TestClient::default(), PendingSettings::all_prioritized(0, 0));
|
||||||
|
|
||||||
for tx in pending {
|
for tx in pending {
|
||||||
assert!(tx.signed().nonce > 0.into());
|
assert!(tx.signed().nonce > 0.into());
|
||||||
|
@ -18,7 +18,7 @@ use ethereum_types::U256;
|
|||||||
use transaction::{self, PendingTransaction};
|
use transaction::{self, PendingTransaction};
|
||||||
use txpool;
|
use txpool;
|
||||||
|
|
||||||
use pool::{verifier, TransactionQueue, PrioritizationStrategy};
|
use pool::{verifier, TransactionQueue, PrioritizationStrategy, PendingSettings, PendingOrdering};
|
||||||
|
|
||||||
pub mod tx;
|
pub mod tx;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
@ -158,7 +158,7 @@ fn should_handle_same_transaction_imported_twice_with_different_state_nonces() {
|
|||||||
// and then there should be only one transaction in current (the one with higher gas_price)
|
// and then there should be only one transaction in current (the one with higher gas_price)
|
||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 1);
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ fn should_move_all_transactions_from_future() {
|
|||||||
// then
|
// then
|
||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
assert_eq!(top[1].hash, hash2);
|
assert_eq!(top[1].hash, hash2);
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ fn should_import_txs_from_same_sender() {
|
|||||||
txq.import(TestClient::new(), txs.local().into_vec());
|
txq.import(TestClient::new(), txs.local().into_vec());
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let top = txq.pending(TestClient::new(), 0 ,0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0 ,0));
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
assert_eq!(top[1].hash, hash2);
|
assert_eq!(top[1].hash, hash2);
|
||||||
assert_eq!(top.len(), 2);
|
assert_eq!(top.len(), 2);
|
||||||
@ -279,7 +279,7 @@ fn should_prioritize_local_transactions_within_same_nonce_height() {
|
|||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let top = txq.pending(client, 0, 0, None);
|
let top = txq.pending(client, PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top[0].hash, hash); // local should be first
|
assert_eq!(top[0].hash, hash); // local should be first
|
||||||
assert_eq!(top[1].hash, hash2);
|
assert_eq!(top[1].hash, hash2);
|
||||||
assert_eq!(top.len(), 2);
|
assert_eq!(top.len(), 2);
|
||||||
@ -301,7 +301,7 @@ fn should_prioritize_reimported_transactions_within_same_nonce_height() {
|
|||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top[0].hash, hash); // retracted should be first
|
assert_eq!(top[0].hash, hash); // retracted should be first
|
||||||
assert_eq!(top[1].hash, hash2);
|
assert_eq!(top[1].hash, hash2);
|
||||||
assert_eq!(top.len(), 2);
|
assert_eq!(top.len(), 2);
|
||||||
@ -320,7 +320,7 @@ fn should_not_prioritize_local_transactions_with_different_nonce_height() {
|
|||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
assert_eq!(top[1].hash, hash2);
|
assert_eq!(top[1].hash, hash2);
|
||||||
assert_eq!(top.len(), 2);
|
assert_eq!(top.len(), 2);
|
||||||
@ -338,7 +338,7 @@ fn should_put_transaction_to_futures_if_gap_detected() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top.len(), 1);
|
assert_eq!(top.len(), 1);
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
}
|
}
|
||||||
@ -358,9 +358,9 @@ fn should_handle_min_block() {
|
|||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top.len(), 0);
|
assert_eq!(top.len(), 0);
|
||||||
let top = txq.pending(TestClient::new(), 1, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(1, 0));
|
||||||
assert_eq!(top.len(), 2);
|
assert_eq!(top.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,7 +391,7 @@ fn should_move_transactions_if_gap_filled() {
|
|||||||
let res = txq.import(TestClient::new(), vec![tx, tx2].local());
|
let res = txq.import(TestClient::new(), vec![tx, tx2].local());
|
||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = txq.import(TestClient::new(), vec![tx1.local()]);
|
let res = txq.import(TestClient::new(), vec![tx1.local()]);
|
||||||
@ -399,7 +399,7 @@ fn should_move_transactions_if_gap_filled() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.status().status.transaction_count, 3);
|
assert_eq!(txq.status().status.transaction_count, 3);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 3);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -411,12 +411,12 @@ fn should_remove_transaction() {
|
|||||||
let res = txq.import(TestClient::default(), vec![tx, tx2].local());
|
let res = txq.import(TestClient::default(), vec![tx, tx2].local());
|
||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.cull(TestClient::new().with_nonce(124));
|
txq.cull(TestClient::new().with_nonce(124));
|
||||||
assert_eq!(txq.status().status.transaction_count, 1);
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
assert_eq!(txq.pending(TestClient::new().with_nonce(125), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new().with_nonce(125), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
txq.cull(TestClient::new().with_nonce(126));
|
txq.cull(TestClient::new().with_nonce(126));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -434,19 +434,19 @@ fn should_move_transactions_to_future_if_gap_introduced() {
|
|||||||
let res = txq.import(TestClient::new(), vec![tx3, tx2].local());
|
let res = txq.import(TestClient::new(), vec![tx3, tx2].local());
|
||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
|
|
||||||
let res = txq.import(TestClient::new(), vec![tx].local());
|
let res = txq.import(TestClient::new(), vec![tx].local());
|
||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 3);
|
assert_eq!(txq.status().status.transaction_count, 3);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 3);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 3);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.remove(vec![&hash], true);
|
txq.remove(vec![&hash], true);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -497,7 +497,7 @@ fn should_prefer_current_transactions_when_hitting_the_limit() {
|
|||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 1);
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
|
|
||||||
let top = txq.pending(TestClient::new(), 0, 0, None);
|
let top = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
assert_eq!(top.len(), 1);
|
assert_eq!(top.len(), 1);
|
||||||
assert_eq!(top[0].hash, hash);
|
assert_eq!(top[0].hash, hash);
|
||||||
assert_eq!(txq.next_nonce(TestClient::new(), &sender), Some(124.into()));
|
assert_eq!(txq.next_nonce(TestClient::new(), &sender), Some(124.into()));
|
||||||
@ -545,19 +545,19 @@ fn should_accept_same_transaction_twice_if_removed() {
|
|||||||
let res = txq.import(TestClient::new(), txs.local().into_vec());
|
let res = txq.import(TestClient::new(), txs.local().into_vec());
|
||||||
assert_eq!(res, vec![Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 2);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.remove(vec![&hash], true);
|
txq.remove(vec![&hash], true);
|
||||||
assert_eq!(txq.status().status.transaction_count, 1);
|
assert_eq!(txq.status().status.transaction_count, 1);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 0);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 0);
|
||||||
|
|
||||||
let res = txq.import(TestClient::new(), vec![tx1].local());
|
let res = txq.import(TestClient::new(), vec![tx1].local());
|
||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 2);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -577,8 +577,8 @@ fn should_not_replace_same_transaction_if_the_fee_is_less_than_minimal_bump() {
|
|||||||
// then
|
// then
|
||||||
assert_eq!(res, vec![Err(transaction::Error::TooCheapToReplace), Ok(())]);
|
assert_eq!(res, vec![Err(transaction::Error::TooCheapToReplace), Ok(())]);
|
||||||
assert_eq!(txq.status().status.transaction_count, 2);
|
assert_eq!(txq.status().status.transaction_count, 2);
|
||||||
assert_eq!(txq.pending(client.clone(), 0, 0, None)[0].signed().gas_price, U256::from(20));
|
assert_eq!(txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[0].signed().gas_price, U256::from(20));
|
||||||
assert_eq!(txq.pending(client.clone(), 0, 0, None)[1].signed().gas_price, U256::from(2));
|
assert_eq!(txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0))[1].signed().gas_price, U256::from(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -620,7 +620,7 @@ fn should_return_valid_last_nonce_after_cull() {
|
|||||||
let client = TestClient::new().with_nonce(124);
|
let client = TestClient::new().with_nonce(124);
|
||||||
txq.cull(client.clone());
|
txq.cull(client.clone());
|
||||||
// tx2 should be not be promoted to current
|
// tx2 should be not be promoted to current
|
||||||
assert_eq!(txq.pending(client.clone(), 0, 0, None).len(), 0);
|
assert_eq!(txq.pending(client.clone(), PendingSettings::all_prioritized(0, 0)).len(), 0);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.next_nonce(client.clone(), &sender), None);
|
assert_eq!(txq.next_nonce(client.clone(), &sender), None);
|
||||||
@ -718,7 +718,7 @@ fn should_accept_local_transactions_below_min_gas_price() {
|
|||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -736,7 +736,7 @@ fn should_accept_local_service_transaction() {
|
|||||||
assert_eq!(res, vec![Ok(())]);
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 0, None).len(), 1);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0)).len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -777,9 +777,15 @@ fn should_not_return_transactions_over_nonce_cap() {
|
|||||||
assert_eq!(res, vec![Ok(()), Ok(()), Ok(())]);
|
assert_eq!(res, vec![Ok(()), Ok(()), Ok(())]);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let all = txq.pending(TestClient::new(), 0, 0, None);
|
let all = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
// This should invalidate the cache!
|
// This should invalidate the cache!
|
||||||
let limited = txq.pending(TestClient::new(), 0, 0, Some(123.into()));
|
let limited = txq.pending(TestClient::new(), PendingSettings {
|
||||||
|
block_number: 0,
|
||||||
|
current_timestamp: 0,
|
||||||
|
nonce_cap: Some(123.into()),
|
||||||
|
max_len: usize::max_value(),
|
||||||
|
ordering: PendingOrdering::Priority,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -787,6 +793,62 @@ fn should_not_return_transactions_over_nonce_cap() {
|
|||||||
assert_eq!(limited.len(), 1);
|
assert_eq!(limited.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_cached_pending_even_if_unordered_is_requested() {
|
||||||
|
// given
|
||||||
|
let txq = new_queue();
|
||||||
|
let tx1 = Tx::default().signed();
|
||||||
|
let (tx2_1, tx2_2)= Tx::default().signed_pair();
|
||||||
|
let tx2_1_hash = tx2_1.hash();
|
||||||
|
let res = txq.import(TestClient::new(), vec![tx1].unverified());
|
||||||
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
let res = txq.import(TestClient::new(), vec![tx2_1, tx2_2].local());
|
||||||
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
|
// when
|
||||||
|
let all = txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 0));
|
||||||
|
assert_eq!(all[0].hash, tx2_1_hash);
|
||||||
|
assert_eq!(all.len(), 3);
|
||||||
|
|
||||||
|
// This should not invalidate the cache!
|
||||||
|
let limited = txq.pending(TestClient::new(), PendingSettings {
|
||||||
|
block_number: 0,
|
||||||
|
current_timestamp: 0,
|
||||||
|
nonce_cap: None,
|
||||||
|
max_len: 3,
|
||||||
|
ordering: PendingOrdering::Unordered,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(all, limited);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_unordered_and_not_populate_the_cache() {
|
||||||
|
// given
|
||||||
|
let txq = new_queue();
|
||||||
|
let tx1 = Tx::default().signed();
|
||||||
|
let (tx2_1, tx2_2)= Tx::default().signed_pair();
|
||||||
|
let res = txq.import(TestClient::new(), vec![tx1].unverified());
|
||||||
|
assert_eq!(res, vec![Ok(())]);
|
||||||
|
let res = txq.import(TestClient::new(), vec![tx2_1, tx2_2].local());
|
||||||
|
assert_eq!(res, vec![Ok(()), Ok(())]);
|
||||||
|
|
||||||
|
// when
|
||||||
|
// This should not invalidate the cache!
|
||||||
|
let limited = txq.pending(TestClient::new(), PendingSettings {
|
||||||
|
block_number: 0,
|
||||||
|
current_timestamp: 0,
|
||||||
|
nonce_cap: None,
|
||||||
|
max_len: usize::max_value(),
|
||||||
|
ordering: PendingOrdering::Unordered,
|
||||||
|
});
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(limited.len(), 3);
|
||||||
|
assert!(!txq.is_pending_cached());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_clear_cache_after_timeout_for_local() {
|
fn should_clear_cache_after_timeout_for_local() {
|
||||||
// given
|
// given
|
||||||
@ -800,12 +862,12 @@ fn should_clear_cache_after_timeout_for_local() {
|
|||||||
|
|
||||||
// This should populate cache and set timestamp to 1
|
// This should populate cache and set timestamp to 1
|
||||||
// when
|
// when
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 1, None).len(), 0);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 1)).len(), 0);
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 1000, None).len(), 0);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 1000)).len(), 0);
|
||||||
|
|
||||||
// This should invalidate the cache and trigger transaction ready.
|
// This should invalidate the cache and trigger transaction ready.
|
||||||
// then
|
// then
|
||||||
assert_eq!(txq.pending(TestClient::new(), 0, 1002, None).len(), 2);
|
assert_eq!(txq.pending(TestClient::new(), PendingSettings::all_prioritized(0, 1002)).len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
!define DESCRIPTION "Fast, light, robust Ethereum implementation"
|
||||||
!define VERSIONMAJOR 1
|
!define VERSIONMAJOR 1
|
||||||
!define VERSIONMINOR 11
|
!define VERSIONMINOR 11
|
||||||
!define VERSIONBUILD 6
|
!define VERSIONBUILD 7
|
||||||
!define ARGS ""
|
!define ARGS ""
|
||||||
!define FIRST_START_ARGS "--mode=passive ui"
|
!define FIRST_START_ARGS "--mode=passive ui"
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ impl FullDependencies {
|
|||||||
let client = EthPubSubClient::new(self.client.clone(), self.remote.clone());
|
let client = EthPubSubClient::new(self.client.clone(), self.remote.clone());
|
||||||
let h = client.handler();
|
let h = client.handler();
|
||||||
self.miner.add_transactions_listener(Box::new(move |hashes| if let Some(h) = h.upgrade() {
|
self.miner.add_transactions_listener(Box::new(move |hashes| if let Some(h) = h.upgrade() {
|
||||||
h.new_transactions(hashes);
|
h.notify_new_transactions(hashes);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if let Some(h) = client.handler().upgrade() {
|
if let Some(h) = client.handler().upgrade() {
|
||||||
@ -527,7 +527,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
|||||||
let h = client.handler();
|
let h = client.handler();
|
||||||
self.transaction_queue.write().add_listener(Box::new(move |transactions| {
|
self.transaction_queue.write().add_listener(Box::new(move |transactions| {
|
||||||
if let Some(h) = h.upgrade() {
|
if let Some(h) = h.upgrade() {
|
||||||
h.new_transactions(transactions);
|
h.notify_new_transactions(transactions);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
handler.extend_with(EthPubSub::to_delegate(client));
|
handler.extend_with(EthPubSub::to_delegate(client));
|
||||||
|
@ -550,7 +550,8 @@ fn execute_impl<Cr, Rr>(cmd: RunCmd, logger: Arc<RotatingLogger>, on_client_rq:
|
|||||||
cmd.miner_options,
|
cmd.miner_options,
|
||||||
cmd.gas_pricer_conf.to_gas_pricer(fetch.clone(), cpu_pool.clone()),
|
cmd.gas_pricer_conf.to_gas_pricer(fetch.clone(), cpu_pool.clone()),
|
||||||
&spec,
|
&spec,
|
||||||
Some(account_provider.clone())
|
Some(account_provider.clone()),
|
||||||
|
|
||||||
));
|
));
|
||||||
miner.set_author(cmd.miner_extras.author, None).expect("Fails only if password is Some; password is None; qed");
|
miner.set_author(cmd.miner_extras.author, None).expect("Fails only if password is Some; password is None; qed");
|
||||||
miner.set_gas_range_target(cmd.miner_extras.gas_range_target);
|
miner.set_gas_range_target(cmd.miner_extras.gas_range_target);
|
||||||
|
@ -175,7 +175,7 @@ impl<C> ChainNotificationHandler<C> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Notify all subscribers about new transaction hashes.
|
/// Notify all subscribers about new transaction hashes.
|
||||||
pub fn new_transactions(&self, hashes: &[H256]) {
|
pub fn notify_new_transactions(&self, hashes: &[H256]) {
|
||||||
for subscriber in self.transactions_subscribers.read().values() {
|
for subscriber in self.transactions_subscribers.read().values() {
|
||||||
for hash in hashes {
|
for hash in hashes {
|
||||||
Self::notify(&self.remote, subscriber, pubsub::Result::TransactionHash((*hash).into()));
|
Self::notify(&self.remote, subscriber, pubsub::Result::TransactionHash((*hash).into()));
|
||||||
|
@ -264,12 +264,13 @@ impl Parity for ParityClient {
|
|||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transactions(&self) -> Result<Vec<Transaction>> {
|
fn pending_transactions(&self, limit: Trailing<usize>) -> Result<Vec<Transaction>> {
|
||||||
let txq = self.light_dispatch.transaction_queue.read();
|
let txq = self.light_dispatch.transaction_queue.read();
|
||||||
let chain_info = self.light_dispatch.client.chain_info();
|
let chain_info = self.light_dispatch.client.chain_info();
|
||||||
Ok(
|
Ok(
|
||||||
txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
|
txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.take(limit.unwrap_or_else(usize::max_value))
|
||||||
.map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition))
|
.map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
)
|
)
|
||||||
|
@ -313,9 +313,13 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
|||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transactions(&self) -> Result<Vec<Transaction>> {
|
fn pending_transactions(&self, limit: Trailing<usize>) -> Result<Vec<Transaction>> {
|
||||||
let block_number = self.client.chain_info().best_block_number;
|
let block_number = self.client.chain_info().best_block_number;
|
||||||
let ready_transactions = self.miner.ready_transactions(&*self.client);
|
let ready_transactions = self.miner.ready_transactions(
|
||||||
|
&*self.client,
|
||||||
|
limit.unwrap_or_else(usize::max_value),
|
||||||
|
miner::PendingOrdering::Priority,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(ready_transactions
|
Ok(ready_transactions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -27,7 +27,7 @@ use ethcore::engines::EthEngine;
|
|||||||
use ethcore::error::Error;
|
use ethcore::error::Error;
|
||||||
use ethcore::header::{BlockNumber, Header};
|
use ethcore::header::{BlockNumber, Header};
|
||||||
use ethcore::ids::BlockId;
|
use ethcore::ids::BlockId;
|
||||||
use ethcore::miner::{MinerService, AuthoringParams};
|
use ethcore::miner::{self, MinerService, AuthoringParams};
|
||||||
use ethcore::receipt::{Receipt, RichReceipt};
|
use ethcore::receipt::{Receipt, RichReceipt};
|
||||||
use ethereum_types::{H256, U256, Address};
|
use ethereum_types::{H256, U256, Address};
|
||||||
use miner::pool::local_transactions::Status as LocalTransactionStatus;
|
use miner::pool::local_transactions::Status as LocalTransactionStatus;
|
||||||
@ -215,7 +215,7 @@ impl MinerService for TestMinerService {
|
|||||||
self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect()
|
self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ready_transactions<C>(&self, _chain: &C) -> Vec<Arc<VerifiedTransaction>> {
|
fn ready_transactions<C>(&self, _chain: &C, _max_len: usize, _ordering: miner::PendingOrdering) -> Vec<Arc<VerifiedTransaction>> {
|
||||||
self.queued_transactions()
|
self.queued_transactions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ fn should_subscribe_to_pending_transactions() {
|
|||||||
assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()));
|
assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned()));
|
||||||
|
|
||||||
// Send new transactions
|
// Send new transactions
|
||||||
handler.new_transactions(&[5.into(), 7.into()]);
|
handler.notify_new_transactions(&[5.into(), 7.into()]);
|
||||||
|
|
||||||
let (res, receiver) = receiver.into_future().wait().unwrap();
|
let (res, receiver) = receiver.into_future().wait().unwrap();
|
||||||
let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000005","subscription":"0x416d77337e24399d"}}"#;
|
let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":"0x0000000000000000000000000000000000000000000000000000000000000005","subscription":"0x416d77337e24399d"}}"#;
|
||||||
|
@ -141,7 +141,7 @@ build_rpc_trait! {
|
|||||||
|
|
||||||
/// Returns all pending transactions from transaction queue.
|
/// Returns all pending transactions from transaction queue.
|
||||||
#[rpc(name = "parity_pendingTransactions")]
|
#[rpc(name = "parity_pendingTransactions")]
|
||||||
fn pending_transactions(&self) -> Result<Vec<Transaction>>;
|
fn pending_transactions(&self, Trailing<usize>) -> Result<Vec<Transaction>>;
|
||||||
|
|
||||||
/// Returns all transactions from transaction queue.
|
/// Returns all transactions from transaction queue.
|
||||||
///
|
///
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::{HashMap, BTreeSet};
|
use std::slice;
|
||||||
|
use std::collections::{hash_map, HashMap, BTreeSet};
|
||||||
|
|
||||||
use error;
|
use error;
|
||||||
use listener::{Listener, NoopListener};
|
use listener::{Listener, NoopListener};
|
||||||
@ -443,7 +444,16 @@ impl<T, S, L> Pool<T, S, L> where
|
|||||||
PendingIterator {
|
PendingIterator {
|
||||||
ready,
|
ready,
|
||||||
best_transactions,
|
best_transactions,
|
||||||
pool: self
|
pool: self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns unprioritized list of ready transactions.
|
||||||
|
pub fn unordered_pending<R: Ready<T>>(&self, ready: R) -> UnorderedIterator<T, R, S> {
|
||||||
|
UnorderedIterator {
|
||||||
|
ready,
|
||||||
|
senders: self.transactions.iter(),
|
||||||
|
transactions: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,6 +524,50 @@ impl<T, S, L> Pool<T, S, L> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over all pending (ready) transactions in unoredered fashion.
|
||||||
|
///
|
||||||
|
/// NOTE: Current implementation will iterate over all transactions from particular sender
|
||||||
|
/// ordered by nonce, but that might change in the future.
|
||||||
|
///
|
||||||
|
/// NOTE: the transactions are not removed from the queue.
|
||||||
|
/// You might remove them later by calling `cull`.
|
||||||
|
pub struct UnorderedIterator<'a, T, R, S> where
|
||||||
|
T: VerifiedTransaction + 'a,
|
||||||
|
S: Scoring<T> + 'a,
|
||||||
|
{
|
||||||
|
ready: R,
|
||||||
|
senders: hash_map::Iter<'a, T::Sender, Transactions<T, S>>,
|
||||||
|
transactions: Option<slice::Iter<'a, Transaction<T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T, R, S> Iterator for UnorderedIterator<'a, T, R, S> where
|
||||||
|
T: VerifiedTransaction,
|
||||||
|
R: Ready<T>,
|
||||||
|
S: Scoring<T>,
|
||||||
|
{
|
||||||
|
type Item = Arc<T>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if let Some(transactions) = self.transactions.as_mut() {
|
||||||
|
if let Some(tx) = transactions.next() {
|
||||||
|
match self.ready.is_ready(&tx) {
|
||||||
|
Readiness::Ready => {
|
||||||
|
return Some(tx.transaction.clone());
|
||||||
|
},
|
||||||
|
state => trace!("[{:?}] Ignoring {:?} transaction.", tx.hash(), state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise fallback and try next sender
|
||||||
|
let next_sender = self.senders.next()?;
|
||||||
|
self.transactions = Some(next_sender.1.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// An iterator over all pending (ready) transactions.
|
/// An iterator over all pending (ready) transactions.
|
||||||
/// NOTE: the transactions are not removed from the queue.
|
/// NOTE: the transactions are not removed from the queue.
|
||||||
/// You might remove them later by calling `cull`.
|
/// You might remove them later by calling `cull`.
|
||||||
|
@ -259,6 +259,66 @@ fn should_construct_pending() {
|
|||||||
assert_eq!(pending.next(), None);
|
assert_eq!(pending.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_unordered_iterator() {
|
||||||
|
// given
|
||||||
|
let b = TransactionBuilder::default();
|
||||||
|
let mut txq = TestPool::default();
|
||||||
|
|
||||||
|
let tx0 = txq.import(b.tx().nonce(0).gas_price(5).new()).unwrap();
|
||||||
|
let tx1 = txq.import(b.tx().nonce(1).gas_price(5).new()).unwrap();
|
||||||
|
let tx2 = txq.import(b.tx().nonce(2).new()).unwrap();
|
||||||
|
let tx3 = txq.import(b.tx().nonce(3).gas_price(4).new()).unwrap();
|
||||||
|
//gap
|
||||||
|
txq.import(b.tx().nonce(5).new()).unwrap();
|
||||||
|
|
||||||
|
let tx5 = txq.import(b.tx().sender(1).nonce(0).new()).unwrap();
|
||||||
|
let tx6 = txq.import(b.tx().sender(1).nonce(1).new()).unwrap();
|
||||||
|
let tx7 = txq.import(b.tx().sender(1).nonce(2).new()).unwrap();
|
||||||
|
let tx8 = txq.import(b.tx().sender(1).nonce(3).gas_price(4).new()).unwrap();
|
||||||
|
// gap
|
||||||
|
txq.import(b.tx().sender(1).nonce(5).new()).unwrap();
|
||||||
|
|
||||||
|
let tx9 = txq.import(b.tx().sender(2).nonce(0).new()).unwrap();
|
||||||
|
assert_eq!(txq.light_status().transaction_count, 11);
|
||||||
|
assert_eq!(txq.status(NonceReady::default()), Status {
|
||||||
|
stalled: 0,
|
||||||
|
pending: 9,
|
||||||
|
future: 2,
|
||||||
|
});
|
||||||
|
assert_eq!(txq.status(NonceReady::new(1)), Status {
|
||||||
|
stalled: 3,
|
||||||
|
pending: 6,
|
||||||
|
future: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
// when
|
||||||
|
let all: Vec<_> = txq.unordered_pending(NonceReady::default()).collect();
|
||||||
|
|
||||||
|
let chain1 = vec![tx0, tx1, tx2, tx3];
|
||||||
|
let chain2 = vec![tx5, tx6, tx7, tx8];
|
||||||
|
let chain3 = vec![tx9];
|
||||||
|
|
||||||
|
assert_eq!(all.len(), chain1.len() + chain2.len() + chain3.len());
|
||||||
|
|
||||||
|
let mut options = vec![
|
||||||
|
vec![chain1.clone(), chain2.clone(), chain3.clone()],
|
||||||
|
vec![chain2.clone(), chain1.clone(), chain3.clone()],
|
||||||
|
vec![chain2.clone(), chain3.clone(), chain1.clone()],
|
||||||
|
vec![chain3.clone(), chain2.clone(), chain1.clone()],
|
||||||
|
vec![chain3.clone(), chain1.clone(), chain2.clone()],
|
||||||
|
vec![chain1.clone(), chain3.clone(), chain2.clone()],
|
||||||
|
].into_iter().map(|mut v| {
|
||||||
|
let mut first = v.pop().unwrap();
|
||||||
|
for mut x in v {
|
||||||
|
first.append(&mut x);
|
||||||
|
}
|
||||||
|
first
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(options.any(|opt| all == opt));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_update_scoring_correctly() {
|
fn should_update_scoring_correctly() {
|
||||||
// given
|
// given
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "parity-version"
|
name = "parity-version"
|
||||||
# NOTE: this value is used for Parity version string (via env CARGO_PKG_VERSION)
|
# NOTE: this value is used for Parity version string (via env CARGO_PKG_VERSION)
|
||||||
version = "1.11.6"
|
version = "1.11.7"
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
# This versions track. Should be changed to `stable` or `beta` when on respective branches.
|
# This versions track. Should be changed to `stable` or `beta` when on respective branches.
|
||||||
# Used by auto-updater and for Parity version string.
|
# Used by auto-updater and for Parity version string.
|
||||||
track = "beta"
|
track = "stable"
|
||||||
|
|
||||||
# Network specific settings, used ONLY by auto-updater.
|
# Network specific settings, used ONLY by auto-updater.
|
||||||
# Latest supported fork blocks.
|
# Latest supported fork blocks.
|
||||||
|
Loading…
Reference in New Issue
Block a user