Merge with master

This commit is contained in:
arkpar 2016-06-28 20:04:00 +02:00
commit 09e1970bbf
44 changed files with 927 additions and 575 deletions

14
Cargo.lock generated
View File

@ -20,7 +20,7 @@ dependencies = [
"ethsync 1.2.0",
"fdlimit 0.1.0",
"hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)",
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -344,7 +344,7 @@ dependencies = [
"ethcore-util 1.2.0",
"ethjson 0.1.0",
"ethsync 1.2.0",
"json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)",
"json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)",
"jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -594,8 +594,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "json-ipc-server"
version = "0.2.3"
source = "git+https://github.com/ethcore/json-ipc-server.git#bfe16b66b2e9412d153b1ea53bc078d74037da7f"
version = "0.2.4"
source = "git+https://github.com/ethcore/json-ipc-server.git#902b031b8f50a59ecb4f389cbec1d264a98556bc"
dependencies = [
"bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1077,7 +1077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rocksdb"
version = "0.4.5"
source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541"
source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6"
dependencies = [
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
@ -1086,7 +1086,7 @@ dependencies = [
[[package]]
name = "rocksdb-sys"
version = "0.3.0"
source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541"
source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6"
dependencies = [
"gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1446,7 +1446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ws"
version = "0.5.0"
source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#e2452450c830618aed30db02e63f3a68710cc40e"
source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#a876fc115c3ef50a17c8822c9bd2f6e94473e005"
dependencies = [
"httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -31,7 +31,7 @@ In a near-future release, it will be easy to install Dapps and use them through
If you run into an issue while using parity, feel free to file one in this repository
or hop on our [gitter chat room]([gitter-url]) to ask a question. We are glad to help!
Parity's current release is 1.1. You can download it at https://ethcore.io/parity.html or follow the instructions
Parity's current release is 1.2. You can download it at https://ethcore.io/parity.html or follow the instructions
below to build from source.
----

View File

@ -2,24 +2,26 @@ FROM centos:latest
WORKDIR /build
# install tools and dependencies
RUN yum -y update&& \
yum install -y git make gcc-c++ gcc file
yum install -y git make gcc-c++ gcc file binutils
# install rustup
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
ls&&\
sh rustup.sh -s -- --disable-sudo
# show backtraces
ENV RUST_BACKTRACE 1
# set compiler
ENV CXX g++
ENV CC gcc
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# git clone parity
# build parity
RUN git clone https://github.com/ethcore/parity && \
cd parity&&\
ls -a&&\
cargo build --release --verbose && \
ls /build/parity/target/release/parity && \
file /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
RUN file /build/parity/target/release/parity

View File

@ -0,0 +1,47 @@
FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get -y update && \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \
binutils-aarch64-linux-gnu \
&& \
apt-get clean
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
# rustup directory
ENV PATH /root/.cargo/bin:$PATH
ENV RUST_TARGETS="aarch64-unknown-linux-gnu"
# multirust add arm--linux-gnuabhf toolchain
RUN rustup target add aarch64-unknown-linux-gnu
# show backtraces
ENV RUST_BACKTRACE 1
# set compilers
ENV CXX aarch64-linux-gnu-g++
ENV CC aarch64-linux-gnu-gcc
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
RUN git clone https://github.com/ethcore/parity && \
cd parity && \
mkdir -p .cargo && \
echo '[target.aarch64-unknown-linux-gnu]\n\
linker = "aarch64-linux-gnu-gcc"\n'\
>>.cargo/config && \
cat .cargo/config && \
cargo build --target aarch64-unknown-linux-gnu --release --verbose && \
ls /build/parity/target/aarch64-unknown-linux-gnu/release/parity && \
/usr/bin/aarch64-linux-gnu-strip /build/parity/target/aarch64-unknown-linux-gnu/release/parity
RUN file /build/parity/target/aarch64-unknown-linux-gnu/release/parity

View File

@ -2,11 +2,11 @@ FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get -y update && \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross wget file ca-certificates \
binutils-arm-linux-gnueabihf \
&& \
apt-get install -y --force-yes --no-install-recommends \
curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
libc6-dev-armhf-cross wget file ca-certificates \
binutils-arm-linux-gnueabihf \
&& \
apt-get clean
# install rustup
@ -18,33 +18,30 @@ ENV PATH /root/.cargo/bin:$PATH
ENV RUST_TARGETS="arm-unknown-linux-gnueabihf"
# multirust add arm--linux-gnuabhf toolchain
RUN rustup target add stable arm-unknown-linux-gnueabihf
RUN rustup target add armv7-unknown-linux-gnueabihf
# show backtraces
ENV RUST_BACKTRACE 1
# set compilers
ENV CXX arm-linux-gnueabihf-g++
ENV CC arm-linux-gnueabihf-gcc
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
RUN git clone https://github.com/ethcore/parity && \
cd parity && \
git checkout master && \
wget https://github.com/nix-rust/nix/archive/v0.5.0.tar.gz && \
tar -xf v0.5.0.tar.gz && \
rm -rf v0.5.0.tar.gz && \
wget https://github.com/thkaw/mio/archive/v0.5.x.tar.gz && \
tar -xf v0.5.x.tar.gz && \
rm -rf v0.5.x.tar.gz && \
mkdir -p .cargo && \
echo 'paths = ["nix-0.5.0","mio-0.5.x"]\n\
[target.arm-unknown-linux-gnueabihf]\n\
linker = "arm-linux-gnueabihf-gcc"\n'\
>>.cargo/config && \
cat .cargo/config && \
rustc -vV && \
cargo -V && \
cargo build --target arm-unknown-linux-gnueabihf --release --verbose && \
ls /build/parity/target/arm-unknown-linux-gnueabihf/release/parity && \
file /build/parity/target/arm-unknown-linux-gnueabihf/release/parity && \
/usr/bin/arm-linux-gnueabihf-strip /build/parity/target/arm-unknown-linux-gnueabihf/release/parity
RUN file /build/parity/target/arm-unknown-linux-gnueabihf/release/parity
cd parity && \
mkdir -p .cargo && \
echo '[target.armv7-unknown-linux-gnueabihf]\n\
linker = "arm-linux-gnueabihf-gcc"\n'\
>>.cargo/config && \
cat .cargo/config && \
cargo build --target armv7-unknown-linux-gnueabihf --release --verbose && \
ls /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity && \
/usr/bin/arm-linux-gnueabihf-strip /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity
RUN file /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity

View File

@ -1,31 +1,33 @@
FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get update && \
apt-get install -y \
# make
build-essential \
# add-apt-repository
software-properties-common \
curl \
wget \
git \
g++ \
# evmjit dependencies
zlib1g-dev \
libedit-dev
apt-get install -y \
# make
build-essential \
# add-apt-repository
software-properties-common \
curl \
wget \
git \
g++ \
binutils \
file \
# evmjit dependencies
zlib1g-dev \
libedit-dev
# cmake, llvm and rocksdb ppas. then update ppas
# cmake and llvm ppas. then update ppas
RUN add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
apt-get update && \
apt-get install -y --force-yes cmake llvm-3.7-dev
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
apt-get update && \
apt-get install -y --force-yes cmake llvm-3.7-dev
# install evmjit
RUN git clone https://github.com/debris/evmjit && \
cd evmjit && \
mkdir build && cd build && \
cmake .. && make && make install && cd
cd evmjit && \
mkdir build && cd build && \
cmake .. && make && make install && cd
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
@ -36,7 +38,16 @@ ENV PATH /root/.cargo/bin:$PATH
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
RUN git clone https://github.com/ethcore/parity && \
cd parity && \
cargo build --release --features ethcore/jit
cd parity && \
cargo build --release --features ethcore/jit --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
RUN file /build/parity/target/release/parity

View File

@ -1,12 +1,13 @@
FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get update && \
apt-get install -y \
g++ \
curl \
git \
make
apt-get install -y \
g++ \
curl \
git \
file \
binutils
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
@ -17,7 +18,16 @@ ENV PATH /root/.cargo/bin:$PATH
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
RUN git clone https://github.com/ethcore/parity && \
cd parity && \
cargo build --release
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

View File

@ -16,7 +16,6 @@
//! Blockchain database client.
use std::marker::PhantomData;
use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use util::*;
@ -30,7 +29,8 @@ use engine::Engine;
use views::HeaderView;
use service::{NetSyncMessage, SyncMessage};
use env_info::LastHashes;
use verification::*;
use verification;
use verification::{PreverifiedBlock, Verifier};
use block::*;
use transaction::{LocalizedTransaction, SignedTransaction, Action};
use blockchain::extras::TransactionAddress;
@ -83,7 +83,7 @@ impl ClientReport {
/// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue.
/// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue.
pub struct Client<V = CanonVerifier> where V: Verifier {
pub struct Client {
chain: Arc<BlockChain>,
tracedb: Arc<TraceDB<BlockChain>>,
engine: Arc<Box<Engine>>,
@ -92,7 +92,7 @@ pub struct Client<V = CanonVerifier> where V: Verifier {
report: RwLock<ClientReport>,
import_lock: Mutex<()>,
panic_handler: Arc<PanicHandler>,
verifier: PhantomData<V>,
verifier: Box<Verifier>,
vm_factory: Arc<EvmFactory>,
miner: Arc<Miner>,
io_channel: IoChannel<NetSyncMessage>,
@ -107,13 +107,6 @@ const HISTORY: u64 = 1200;
// of which you actually want force an upgrade.
const CLIENT_DB_VER_STR: &'static str = "5.3";
impl Client<CanonVerifier> {
/// Create a new client with given spec and DB path.
pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc<Miner>, message_channel: IoChannel<NetSyncMessage> ) -> Result<Arc<Client>, ClientError> {
Client::<CanonVerifier>::new_with_verifier(config, spec, path, miner, message_channel)
}
}
/// Get the path for the databases given the root path and information on the databases.
pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf {
let mut dir = path.to_path_buf();
@ -131,15 +124,15 @@ pub fn append_path(path: &Path, item: &str) -> String {
p.to_str().unwrap().to_owned()
}
impl<V> Client<V> where V: Verifier {
impl Client {
/// Create a new client with given spec and DB path and custom verifier.
pub fn new_with_verifier(
pub fn new(
config: ClientConfig,
spec: Spec,
path: &Path,
miner: Arc<Miner>,
message_channel: IoChannel<NetSyncMessage>)
-> Result<Arc<Client<V>>, ClientError>
-> Result<Arc<Client>, ClientError>
{
let path = get_db_path(path, config.pruning, spec.genesis_header().hash());
let gb = spec.genesis_block();
@ -158,7 +151,8 @@ impl<V> Client<V> where V: Verifier {
let mut state_db = journaldb::new(
&append_path(&path, "state"),
config.pruning,
state_db_config);
state_db_config
);
if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) {
state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB");
@ -179,7 +173,7 @@ impl<V> Client<V> where V: Verifier {
report: RwLock::new(Default::default()),
import_lock: Mutex::new(()),
panic_handler: panic_handler,
verifier: PhantomData,
verifier: verification::new(config.verifier_type),
vm_factory: Arc::new(EvmFactory::new(config.vm_type)),
miner: miner,
io_channel: message_channel,
@ -221,7 +215,7 @@ impl<V> Client<V> where V: Verifier {
}
// Verify Block Family
let verify_family_result = V::verify_block_family(&header, &block.bytes, engine, self.chain.deref());
let verify_family_result = self.verifier.verify_block_family(&header, &block.bytes, engine, self.chain.deref());
if let Err(e) = verify_family_result {
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
return Err(());
@ -247,7 +241,7 @@ impl<V> Client<V> where V: Verifier {
// Final Verification
let locked_block = enact_result.unwrap();
if let Err(e) = V::verify_block_final(&header, locked_block.block().header()) {
if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) {
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
return Err(());
}
@ -482,7 +476,7 @@ impl<V> Client<V> where V: Verifier {
}
}
impl<V> BlockChainClient for Client<V> where V: Verifier {
impl BlockChainClient for Client {
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
let header = self.block_header(BlockID::Latest).unwrap();
let view = HeaderView::new(&header);
@ -800,12 +794,12 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
}
}
fn all_transactions(&self) -> Vec<SignedTransaction> {
self.miner.all_transactions()
fn pending_transactions(&self) -> Vec<SignedTransaction> {
self.miner.pending_transactions()
}
}
impl<V> MiningBlockChainClient for Client<V> where V: Verifier {
impl MiningBlockChainClient for Client {
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
let engine = self.engine.deref().deref();
let h = self.chain.best_block_hash();

View File

@ -18,6 +18,7 @@ pub use block_queue::BlockQueueConfig;
pub use blockchain::Config as BlockChainConfig;
pub use trace::{Config as TraceConfig, Switch};
pub use evm::VMType;
pub use verification::VerifierType;
use util::journaldb;
/// Client state db compaction profile
@ -52,4 +53,6 @@ pub struct ClientConfig {
pub db_cache_size: Option<usize>,
/// State db compaction profile
pub db_compaction: DatabaseCompactionProfile,
/// Type of block verifier used by client.
pub verifier_type: VerifierType,
}

View File

@ -197,7 +197,7 @@ pub trait BlockChainClient : Sync + Send {
fn queue_transactions(&self, transactions: Vec<Bytes>);
/// list all transactions
fn all_transactions(&self) -> Vec<SignedTransaction>;
fn pending_transactions(&self) -> Vec<SignedTransaction>;
/// Get the gas price distribution.
fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result<Vec<U256>, ()> {

View File

@ -29,6 +29,7 @@ use blockchain::extras::BlockReceipts;
use error::{ImportResult};
use evm::Factory as EvmFactory;
use miner::{Miner, MinerService};
use spec::Spec;
use block_queue::BlockQueueInfo;
use block::OpenBlock;
@ -105,7 +106,7 @@ impl TestBlockChainClient {
execution_result: RwLock::new(None),
receipts: RwLock::new(HashMap::new()),
queue_size: AtomicUsize::new(0),
miner: Arc::new(Miner::default()),
miner: Arc::new(Miner::with_spec(Spec::new_test())),
};
client.add_blocks(1, EachBlockWith::Nothing); // add genesis block
client.genesis_hash = client.last_hash.read().unwrap().clone();
@ -499,7 +500,7 @@ impl BlockChainClient for TestBlockChainClient {
self.import_transactions(tx);
}
fn all_transactions(&self) -> Vec<SignedTransaction> {
self.miner.all_transactions()
fn pending_transactions(&self) -> Vec<SignedTransaction> {
self.miner.pending_transactions()
}
}

View File

@ -22,6 +22,7 @@ use tests::helpers::*;
use devtools::*;
use spec::Genesis;
use ethjson;
use ethjson::blockchain::BlockChain;
use miner::Miner;
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
@ -41,20 +42,28 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
flush!(" - {}...", name);
let mut spec = match era {
ChainEra::Frontier => ethereum::new_frontier_test(),
ChainEra::Homestead => ethereum::new_homestead_test(),
let spec = |blockchain: &BlockChain| {
let genesis = Genesis::from(blockchain.genesis());
let state = From::from(blockchain.pre_state.clone());
let mut spec = match era {
ChainEra::Frontier => ethereum::new_frontier_test(),
ChainEra::Homestead => ethereum::new_homestead_test(),
};
spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis);
assert!(spec.is_state_root_valid());
spec
};
let genesis = Genesis::from(blockchain.genesis());
let state = From::from(blockchain.pre_state.clone());
spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis);
assert!(spec.is_state_root_valid());
let temp = RandomTempPath::new();
{
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(
ClientConfig::default(),
spec(&blockchain),
temp.as_path(),
Arc::new(Miner::with_spec(spec(&blockchain))),
IoChannel::disconnected()
).unwrap();
for b in &blockchain.blocks_rlp() {
if Block::is_good(&b) {
let _ = client.import_block(b.clone());

View File

@ -29,6 +29,48 @@ use spec::Spec;
use engine::Engine;
use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
/// Different possible definitions for pending transaction set.
#[derive(Debug)]
pub enum PendingSet {
/// Always just the transactions in the queue. These have had only cheap checks.
AlwaysQueue,
/// Always just the transactions in the sealing block. These have had full checks but
/// may be empty if the node is not actively mining or has force_sealing enabled.
AlwaysSealing,
/// Try the sealing block, but if it is not currently sealing, fallback to the queue.
SealingOrElseQueue,
}
/// Configures the behaviour of the miner.
#[derive(Debug)]
pub struct MinerOptions {
/// Force the miner to reseal, even when nobody has asked for work.
pub force_sealing: bool,
/// Reseal on receipt of new external transactions.
pub reseal_on_external_tx: bool,
/// Reseal on receipt of new local transactions.
pub reseal_on_own_tx: bool,
/// Maximum amount of gas to bother considering for block insertion.
pub tx_gas_limit: U256,
/// Maximum size of the transaction queue.
pub tx_queue_size: usize,
/// Whether we should fallback to providing all the queue's transactions or just pending.
pub pending_set: PendingSet,
}
impl Default for MinerOptions {
fn default() -> Self {
MinerOptions {
force_sealing: false,
reseal_on_external_tx: true,
reseal_on_own_tx: true,
tx_gas_limit: !U256::zero(),
tx_queue_size: 1024,
pending_set: PendingSet::AlwaysQueue,
}
}
}
/// Keeps track of transactions using priority queue and holds currently mined block.
pub struct Miner {
// NOTE [ToDr] When locking always lock in this order!
@ -36,7 +78,7 @@ pub struct Miner {
sealing_work: Mutex<UsingQueue<ClosedBlock>>,
// for sealing...
force_sealing: bool,
options: MinerOptions,
sealing_enabled: AtomicBool,
sealing_block_last_request: Mutex<u64>,
gas_range_target: RwLock<(U256, U256)>,
@ -47,11 +89,12 @@ pub struct Miner {
accounts: Option<Arc<AccountProvider>>,
}
impl Default for Miner {
fn default() -> Miner {
impl Miner {
/// Creates new instance of miner without accounts, but with given spec.
pub fn with_spec(spec: Spec) -> Miner {
Miner {
transaction_queue: Mutex::new(TransactionQueue::new()),
force_sealing: false,
options: Default::default(),
sealing_enabled: AtomicBool::new(false),
sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(UsingQueue::new(5)),
@ -59,40 +102,22 @@ impl Default for Miner {
author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()),
accounts: None,
spec: Spec::new_test(),
spec: spec,
}
}
}
impl Miner {
/// Creates new instance of miner
pub fn new(force_sealing: bool, spec: Spec) -> Arc<Miner> {
pub fn new(options: MinerOptions, spec: Spec, accounts: Option<Arc<AccountProvider>>) -> Arc<Miner> {
Arc::new(Miner {
transaction_queue: Mutex::new(TransactionQueue::new()),
force_sealing: force_sealing,
sealing_enabled: AtomicBool::new(force_sealing),
transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)),
sealing_enabled: AtomicBool::new(options.force_sealing),
options: options,
sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(UsingQueue::new(5)),
gas_range_target: RwLock::new((U256::zero(), U256::zero())),
author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()),
accounts: None,
spec: spec,
})
}
/// Creates new instance of miner
pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
Arc::new(Miner {
transaction_queue: Mutex::new(TransactionQueue::new()),
force_sealing: force_sealing,
sealing_enabled: AtomicBool::new(force_sealing),
sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(UsingQueue::new(5)),
gas_range_target: RwLock::new((U256::zero(), U256::zero())),
author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()),
accounts: Some(accounts),
accounts: accounts,
spec: spec,
})
}
@ -373,6 +398,10 @@ impl MinerService for Miner {
self.transaction_queue.lock().unwrap().set_limit(limit)
}
fn set_tx_gas_limit(&self, limit: U256) {
self.transaction_queue.lock().unwrap().set_tx_gas_limit(limit)
}
/// Get the author that we will seal blocks as.
fn author(&self) -> Address {
*self.author.read().unwrap()
@ -402,7 +431,7 @@ impl MinerService for Miner {
.map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
.collect()
};
if !results.is_empty() {
if !results.is_empty() && self.options.reseal_on_external_tx {
self.update_sealing(chain);
}
results
@ -437,7 +466,7 @@ impl MinerService for Miner {
import
};
if imported.is_ok() {
if imported.is_ok() && self.options.reseal_on_own_tx {
// Make sure to do it after transaction is imported and lock is droped.
// We need to create pending block and enable sealing
let prepared = self.enable_and_prepare_sealing(chain);
@ -451,26 +480,6 @@ impl MinerService for Miner {
imported
}
fn pending_transactions_hashes(&self) -> Vec<H256> {
let queue = self.transaction_queue.lock().unwrap();
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
(true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(),
_ => {
queue.pending_hashes()
}
}
}
fn transaction(&self, hash: &H256) -> Option<SignedTransaction> {
let queue = self.transaction_queue.lock().unwrap();
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
(true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(),
_ => {
queue.find(hash)
}
}
}
fn all_transactions(&self) -> Vec<SignedTransaction> {
let queue = self.transaction_queue.lock().unwrap();
queue.top_transactions()
@ -478,12 +487,41 @@ impl MinerService for Miner {
fn pending_transactions(&self) -> Vec<SignedTransaction> {
let queue = self.transaction_queue.lock().unwrap();
let sw = self.sealing_work.lock().unwrap();
// TODO: should only use the sealing_work when it's current (it could be an old block)
match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) {
(true, Some(pending)) => pending.transactions().clone(),
_ => {
queue.top_transactions()
}
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
true => sw.peek_last_ref(),
false => None,
};
match (&self.options.pending_set, sealing_set) {
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(),
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().clone()),
}
}
fn pending_transactions_hashes(&self) -> Vec<H256> {
let queue = self.transaction_queue.lock().unwrap();
let sw = self.sealing_work.lock().unwrap();
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
true => sw.peek_last_ref(),
false => None,
};
match (&self.options.pending_set, sealing_set) {
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.pending_hashes(),
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().iter().map(|t| t.hash()).collect()),
}
}
fn transaction(&self, hash: &H256) -> Option<SignedTransaction> {
let queue = self.transaction_queue.lock().unwrap();
let sw = self.sealing_work.lock().unwrap();
let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) {
true => sw.peek_last_ref(),
false => None,
};
match (&self.options.pending_set, sealing_set) {
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.find(hash),
(_, sealing) => sealing.and_then(|s| s.transactions().iter().find(|t| &t.hash() == hash).cloned()),
}
}
@ -511,7 +549,7 @@ impl MinerService for Miner {
let current_no = chain.chain_info().best_block_number;
let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions();
let last_request = *self.sealing_block_last_request.lock().unwrap();
let should_disable_sealing = !self.force_sealing
let should_disable_sealing = !self.options.force_sealing
&& !has_local_transactions
&& current_no > last_request
&& current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS;
@ -626,6 +664,7 @@ mod tests {
use util::*;
use client::{TestBlockChainClient, EachBlockWith};
use block::*;
use spec::Spec;
// TODO [ToDr] To uncomment` when TestBlockChainClient can actually return a ClosedBlock.
#[ignore]
@ -633,7 +672,7 @@ mod tests {
fn should_prepare_block_to_seal() {
// given
let client = TestBlockChainClient::default();
let miner = Miner::default();
let miner = Miner::with_spec(Spec::new_test());
// when
let sealing_work = miner.map_sealing_work(&client, |_| ());
@ -645,7 +684,7 @@ mod tests {
fn should_still_work_after_a_couple_of_blocks() {
// given
let client = TestBlockChainClient::default();
let miner = Miner::default();
let miner = Miner::with_spec(Spec::new_test());
let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash());
assert!(res.is_some());

View File

@ -28,11 +28,12 @@
//! extern crate ethcore;
//! use std::env;
//! use util::network::{NetworkService, NetworkConfiguration};
//! use ethcore::ethereum;
//! use ethcore::client::{Client, ClientConfig};
//! use ethcore::miner::{Miner, MinerService};
//!
//! fn main() {
//! let miner: Miner = Miner::default();
//! let miner: Miner = Miner::with_spec(ethereum::new_frontier(true));
//! // get status
//! assert_eq!(miner.status().transactions_in_pending_queue, 0);
//!
@ -46,7 +47,7 @@ mod external;
mod transaction_queue;
pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin};
pub use self::miner::{Miner};
pub use self::miner::{Miner, MinerOptions, PendingSet};
pub use self::external::{ExternalMiner, ExternalMinerService};
use std::collections::BTreeMap;
@ -100,6 +101,9 @@ pub trait MinerService : Send + Sync {
/// Set maximal number of transactions kept in the queue (both current and future).
fn set_transactions_limit(&self, limit: usize);
/// Set maximum amount of gas allowed for any single transaction to mine.
fn set_tx_gas_limit(&self, limit: U256);
/// Imports transactions to transaction queue.
fn import_transactions<T>(&self, chain: &MiningBlockChainClient, transactions: Vec<SignedTransaction>, fetch_account: T) ->
Vec<Result<TransactionImportResult, Error>>

View File

@ -334,6 +334,8 @@ const GAS_LIMIT_HYSTERESIS: usize = 10; // %
pub struct TransactionQueue {
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
minimal_gas_price: U256,
/// The maximum amount of gas any individual transaction may use.
tx_gas_limit: U256,
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
gas_limit: U256,
/// Priority queue for transactions that can go to block
@ -355,11 +357,11 @@ impl Default for TransactionQueue {
impl TransactionQueue {
/// Creates new instance of this Queue
pub fn new() -> Self {
Self::with_limit(1024)
Self::with_limits(1024, !U256::zero())
}
/// Create new instance of this Queue with specified limits
pub fn with_limit(limit: usize) -> Self {
pub fn with_limits(limit: usize, tx_gas_limit: U256) -> Self {
let current = TransactionSet {
by_priority: BTreeSet::new(),
by_address: Table::new(),
@ -374,6 +376,7 @@ impl TransactionQueue {
TransactionQueue {
minimal_gas_price: U256::zero(),
tx_gas_limit: tx_gas_limit,
gas_limit: !U256::zero(),
current: current,
future: future,
@ -418,6 +421,12 @@ impl TransactionQueue {
};
}
/// Set the new limit for the amount of gas any individual transaction may have.
/// Any transaction already imported to the queue is not affected.
pub fn set_tx_gas_limit(&mut self, limit: U256) {
self.tx_gas_limit = limit;
}
/// Returns current status for this queue
pub fn status(&self) -> TransactionQueueStatus {
TransactionQueueStatus {
@ -435,7 +444,9 @@ impl TransactionQueue {
if tx.gas_price < self.minimal_gas_price {
trace!(target: "miner",
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
tx.hash(), tx.gas_price, self.minimal_gas_price
tx.hash(),
tx.gas_price,
self.minimal_gas_price
);
return Err(Error::Transaction(TransactionError::InsufficientGasPrice {
@ -446,10 +457,13 @@ impl TransactionQueue {
try!(tx.check_low_s());
if tx.gas > self.gas_limit {
if tx.gas > self.gas_limit || tx.gas > self.tx_gas_limit {
trace!(target: "miner",
"Dropping transaction above gas limit: {:?} ({} > {})",
tx.hash(), tx.gas, self.gas_limit
"Dropping transaction above gas limit: {:?} ({} > min({}, {}))",
tx.hash(),
tx.gas,
self.gas_limit,
self.tx_gas_limit
);
return Err(Error::Transaction(TransactionError::GasLimitExceeded {
@ -463,8 +477,13 @@ impl TransactionQueue {
let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas;
if client_account.balance < cost {
trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})",
vtx.hash(), client_account.balance, cost);
trace!(target: "miner",
"Dropping transaction without sufficient balance: {:?} ({} < {})",
vtx.hash(),
client_account.balance,
cost
);
return Err(Error::Transaction(TransactionError::InsufficientBalance {
cost: cost,
balance: client_account.balance
@ -1288,7 +1307,7 @@ mod test {
#[test]
fn should_drop_old_transactions_when_hitting_the_limit() {
// given
let mut txq = TransactionQueue::with_limit(1);
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
let (tx, tx2) = new_txs(U256::one());
let sender = tx.sender().unwrap();
let nonce = tx.nonce;
@ -1310,7 +1329,7 @@ mod test {
#[test]
fn should_return_correct_nonces_when_dropped_because_of_limit() {
// given
let mut txq = TransactionQueue::with_limit(2);
let mut txq = TransactionQueue::with_limits(2, !U256::zero());
let tx = new_tx();
let (tx1, tx2) = new_txs(U256::one());
let sender = tx1.sender().unwrap();
@ -1331,7 +1350,7 @@ mod test {
#[test]
fn should_limit_future_transactions() {
let mut txq = TransactionQueue::with_limit(1);
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
txq.current.set_limit(10);
let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1));
let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2));
@ -1591,7 +1610,7 @@ mod test {
#[test]
fn should_keep_right_order_in_future() {
// given
let mut txq = TransactionQueue::with_limit(1);
let mut txq = TransactionQueue::with_limits(1, !U256::zero());
let (tx1, tx2) = new_txs(U256::from(1));
let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance:
default_nonce(a).balance };

View File

@ -159,9 +159,15 @@ mod tests {
#[test]
fn it_can_be_started() {
let spec = get_test_spec();
let temp_path = RandomTempPath::new();
let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default()), false);
let service = ClientService::start(
ClientConfig::default(),
get_test_spec(),
NetworkConfiguration::new_local(),
&temp_path.as_path(),
Arc::new(Miner::with_spec(get_test_spec())),
false
);
assert!(service.is_ok());
}
}

View File

@ -24,7 +24,7 @@ use miner::Miner;
#[test]
fn imports_from_empty() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap();
client.import_verified_blocks(&IoChannel::disconnected());
client.flush_queue();
}
@ -42,7 +42,7 @@ fn returns_state_root_basic() {
#[test]
fn imports_good_block() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap();
let good_block = get_good_dummy_block();
if let Err(_) = client.import_block(good_block) {
panic!("error importing block being good by definition");
@ -57,7 +57,7 @@ fn imports_good_block() {
#[test]
fn query_none_block() {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap();
let non_existant = client.block_header(BlockID::Number(188));
assert!(non_existant.is_none());

View File

@ -151,7 +151,7 @@ pub fn generate_dummy_client_with_spec_and_data<F>(get_test_spec: F, block_numbe
let dir = RandomTempPath::new();
let test_spec = get_test_spec();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap();
let test_engine = &test_spec.engine;
let mut db_result = get_temp_journal_db();
@ -250,7 +250,7 @@ pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting
pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> GuardedTempResult<Arc<Client>> {
let dir = RandomTempPath::new();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap();
let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap();
for block in &blocks {
if let Err(_) = client.import_block(block.clone()) {
panic!("panic importing block which is well-formed");

View File

@ -24,11 +24,11 @@ use super::verification;
pub struct CanonVerifier;
impl Verifier for CanonVerifier {
fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> {
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> {
verification::verify_block_family(header, bytes, engine, bc)
}
fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> {
verification::verify_block_final(expected, got)
}
}

View File

@ -17,11 +17,32 @@
pub mod verification;
pub mod verifier;
mod canon_verifier;
#[cfg(test)]
mod noop_verifier;
pub use self::verification::*;
pub use self::verifier::Verifier;
pub use self::canon_verifier::CanonVerifier;
#[cfg(test)]
pub use self::noop_verifier::NoopVerifier;
/// Verifier type.
#[derive(Debug)]
pub enum VerifierType {
/// Verifies block normally.
Canon,
/// Does not verify block at all.
/// Used in tests.
Noop,
}
impl Default for VerifierType {
fn default() -> Self {
VerifierType::Canon
}
}
pub fn new(v: VerifierType) -> Box<Verifier> {
match v {
VerifierType::Canon => Box::new(CanonVerifier),
VerifierType::Noop => Box::new(NoopVerifier),
}
}

View File

@ -24,11 +24,11 @@ use super::Verifier;
pub struct NoopVerifier;
impl Verifier for NoopVerifier {
fn verify_block_family(_header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> {
fn verify_block_family(&self, _header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> {
Ok(())
}
fn verify_block_final(_expected: &Header, _got: &Header) -> Result<(), Error> {
fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> {
Ok(())
}
}

View File

@ -21,6 +21,6 @@ use header::Header;
/// Should be used to verify blocks.
pub trait Verifier: Send + Sync {
fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>;
fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
}

View File

@ -1,339 +0,0 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Block oriented views onto rlp.
use util::*;
use header::*;
use transaction::*;
/// View onto transaction rlp.
pub struct TransactionView<'a> {
rlp: Rlp<'a>
}
impl<'a> TransactionView<'a> {
/// Creates new view onto block from raw bytes.
pub fn new(bytes: &'a [u8]) -> TransactionView<'a> {
TransactionView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto block from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> TransactionView<'a> {
TransactionView {
rlp: rlp
}
}
/// Return reference to underlaying rlp.
pub fn rlp(&self) -> &Rlp<'a> {
&self.rlp
}
/// Get the nonce field of the transaction.
pub fn nonce(&self) -> U256 { self.rlp.val_at(0) }
/// Get the gas_price field of the transaction.
pub fn gas_price(&self) -> U256 { self.rlp.val_at(1) }
/// Get the gas field of the transaction.
pub fn gas(&self) -> U256 { self.rlp.val_at(2) }
/// Get the value field of the transaction.
pub fn value(&self) -> U256 { self.rlp.val_at(4) }
/// Get the data field of the transaction.
pub fn data(&self) -> Bytes { self.rlp.val_at(5) }
/// Get the v field of the transaction.
pub fn v(&self) -> u8 { let r: u16 = self.rlp.val_at(6); r as u8 }
/// Get the r field of the transaction.
pub fn r(&self) -> U256 { self.rlp.val_at(7) }
/// Get the s field of the transaction.
pub fn s(&self) -> U256 { self.rlp.val_at(8) }
// TODO: something like pub fn action(&self) -> Action { self.rlp.val_at(3) }
}
impl<'a> Hashable for TransactionView<'a> {
fn sha3(&self) -> H256 {
self.rlp.as_raw().sha3()
}
}
/// View onto transaction rlp.
pub struct AccountView<'a> {
rlp: Rlp<'a>
}
impl<'a> AccountView<'a> {
/// Creates new view onto block from raw bytes.
pub fn new(bytes: &'a [u8]) -> AccountView<'a> {
AccountView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto block from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> AccountView<'a> {
AccountView {
rlp: rlp
}
}
/// Return reference to underlaying rlp.
pub fn rlp(&self) -> &Rlp<'a> {
&self.rlp
}
/// Get the nonce field of the transaction.
pub fn nonce(&self) -> U256 { self.rlp.val_at(0) }
/// Get the gas_price field of the transaction.
pub fn balance(&self) -> U256 { self.rlp.val_at(1) }
/// Get the gas field of the transaction.
pub fn storage_root(&self) -> H256 { self.rlp.val_at(2) }
/// Get the value field of the transaction.
pub fn code_hash(&self) -> H256 { self.rlp.val_at(3) }
}
/// View onto block rlp.
pub struct BlockView<'a> {
rlp: Rlp<'a>
}
impl<'a> BlockView<'a> {
/// Creates new view onto block from raw bytes.
pub fn new(bytes: &'a [u8]) -> BlockView<'a> {
BlockView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto block from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> BlockView<'a> {
BlockView {
rlp: rlp
}
}
/// Return reference to underlaying rlp.
pub fn rlp(&self) -> &Rlp<'a> {
&self.rlp
}
/// Create new Header object from header rlp.
pub fn header(&self) -> Header {
self.rlp.val_at(0)
}
/// Create new header view obto block head rlp.
pub fn header_view(&self) -> HeaderView<'a> {
HeaderView::new_from_rlp(self.rlp.at(0))
}
/// Return List of transactions in given block.
pub fn transactions(&self) -> Vec<SignedTransaction> {
self.rlp.val_at(1)
}
/// Return List of transactions with additional localization info.
pub fn localized_transactions(&self) -> Vec<LocalizedTransaction> {
let header = self.header_view();
let block_hash = header.sha3();
let block_number = header.number();
self.transactions()
.into_iter()
.enumerate()
.map(|(i, t)| LocalizedTransaction {
signed: t,
block_hash: block_hash.clone(),
block_number: block_number,
transaction_index: i
}).collect()
}
/// Return number of transactions in given block, without deserializing them.
pub fn transactions_count(&self) -> usize {
self.rlp.at(1).iter().count()
}
/// Return List of transactions in given block.
pub fn transaction_views(&self) -> Vec<TransactionView> {
self.rlp.at(1).iter().map(TransactionView::new_from_rlp).collect()
}
/// Return transaction hashes.
pub fn transaction_hashes(&self) -> Vec<H256> {
self.rlp.at(1).iter().map(|rlp| rlp.as_raw().sha3()).collect()
}
/// Returns transaction at given index without deserializing unnecessary data.
pub fn transaction_at(&self, index: usize) -> Option<SignedTransaction> {
self.rlp.at(1).iter().nth(index).map(|rlp| rlp.as_val())
}
/// Returns localized transaction at given index.
pub fn localized_transaction_at(&self, index: usize) -> Option<LocalizedTransaction> {
let header = self.header_view();
let block_hash = header.sha3();
let block_number = header.number();
self.transaction_at(index).map(|t| LocalizedTransaction {
signed: t,
block_hash: block_hash,
block_number: block_number,
transaction_index: index
})
}
/// Return list of uncles of given block.
pub fn uncles(&self) -> Vec<Header> {
self.rlp.val_at(2)
}
/// Return number of uncles in given block, without deserializing them.
pub fn uncles_count(&self) -> usize {
self.rlp.at(2).iter().count()
}
/// Return List of transactions in given block.
pub fn uncle_views(&self) -> Vec<HeaderView> {
self.rlp.at(2).iter().map(HeaderView::new_from_rlp).collect()
}
/// Return list of uncle hashes of given block.
pub fn uncle_hashes(&self) -> Vec<H256> {
self.rlp.at(2).iter().map(|rlp| rlp.as_raw().sha3()).collect()
}
/// Return nth uncle.
pub fn uncle_at(&self, index: usize) -> Option<Header> {
self.rlp.at(2).iter().nth(index).map(|rlp| rlp.as_val())
}
}
impl<'a> Hashable for BlockView<'a> {
fn sha3(&self) -> H256 {
self.header_view().sha3()
}
}
/// View onto block header rlp.
pub struct HeaderView<'a> {
rlp: Rlp<'a>
}
impl<'a> HeaderView<'a> {
/// Creates new view onto header from raw bytes.
pub fn new(bytes: &'a [u8]) -> HeaderView<'a> {
HeaderView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto header from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> HeaderView<'a> {
HeaderView {
rlp: rlp
}
}
/// Returns header hash.
pub fn hash(&self) -> H256 { self.sha3() }
/// Returns raw rlp.
pub fn rlp(&self) -> &Rlp<'a> { &self.rlp }
/// Returns parent hash.
pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) }
/// Returns uncles hash.
pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) }
/// Returns author.
pub fn author(&self) -> Address { self.rlp.val_at(2) }
/// Returns state root.
pub fn state_root(&self) -> H256 { self.rlp.val_at(3) }
/// Returns transactions root.
pub fn transactions_root(&self) -> H256 { self.rlp.val_at(4) }
/// Returns block receipts root.
pub fn receipts_root(&self) -> H256 { self.rlp.val_at(5) }
/// Returns block log bloom.
pub fn log_bloom(&self) -> H2048 { self.rlp.val_at(6) }
/// Returns block difficulty.
pub fn difficulty(&self) -> U256 { self.rlp.val_at(7) }
/// Returns block number.
pub fn number(&self) -> BlockNumber { self.rlp.val_at(8) }
/// Returns block gas limit.
pub fn gas_limit(&self) -> U256 { self.rlp.val_at(9) }
/// Returns block gas used.
pub fn gas_used(&self) -> U256 { self.rlp.val_at(10) }
/// Returns timestamp.
pub fn timestamp(&self) -> u64 { self.rlp.val_at(11) }
/// Returns block extra data.
pub fn extra_data(&self) -> Bytes { self.rlp.val_at(12) }
/// Returns a vector of post-RLP-encoded seal fields.
pub fn seal(&self) -> Vec<Bytes> {
let mut seal = vec![];
for i in 13..self.rlp.item_count() {
seal.push(self.rlp.at(i).as_raw().to_vec());
}
seal
}
}
impl<'a> Hashable for HeaderView<'a> {
fn sha3(&self) -> H256 {
self.rlp.as_raw().sha3()
}
}
#[cfg(test)]
mod tests {
use rustc_serialize::hex::FromHex;
use super::BlockView;
#[test]
fn test_header_view_seal_fields() {
// that's rlp of block created with ethash engine.
let block_rlp = "f90261f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba03a347e72953c860f32b1eb2c78a680d8734b2ea08085d949d729479796f218d5a047ea6239d9e31ccac8af3366f5ca37184d26e7646e3191a3aeb81c4cf74de500c0".from_hex().unwrap();
let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
let block_view = BlockView::new(&block_rlp);
let header_view = block_view.header_view();
let seal_fields = header_view.seal();
assert_eq!(seal_fields.len(), 2);
assert_eq!(seal_fields[0], mix_hash);
assert_eq!(seal_fields[1], nonce);
}
}

167
ethcore/src/views/block.rs Normal file
View File

@ -0,0 +1,167 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! View onto block rlp.
use util::*;
use header::*;
use transaction::*;
use super::{TransactionView, HeaderView};
/// View onto block rlp.
pub struct BlockView<'a> {
rlp: Rlp<'a>
}
impl<'a> BlockView<'a> {
/// Creates new view onto block from raw bytes.
pub fn new(bytes: &'a [u8]) -> BlockView<'a> {
BlockView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto block from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> BlockView<'a> {
BlockView {
rlp: rlp
}
}
/// Block header hash.
pub fn hash(&self) -> H256 {
self.sha3()
}
/// Return reference to underlaying rlp.
pub fn rlp(&self) -> &Rlp<'a> {
&self.rlp
}
/// Create new Header object from header rlp.
pub fn header(&self) -> Header {
self.rlp.val_at(0)
}
/// Create new header view obto block head rlp.
pub fn header_view(&self) -> HeaderView<'a> {
HeaderView::new_from_rlp(self.rlp.at(0))
}
/// Return List of transactions in given block.
pub fn transactions(&self) -> Vec<SignedTransaction> {
self.rlp.val_at(1)
}
/// Return List of transactions with additional localization info.
pub fn localized_transactions(&self) -> Vec<LocalizedTransaction> {
let header = self.header_view();
let block_hash = header.sha3();
let block_number = header.number();
self.transactions()
.into_iter()
.enumerate()
.map(|(i, t)| LocalizedTransaction {
signed: t,
block_hash: block_hash.clone(),
block_number: block_number,
transaction_index: i
}).collect()
}
/// Return number of transactions in given block, without deserializing them.
pub fn transactions_count(&self) -> usize {
self.rlp.at(1).iter().count()
}
/// Return List of transactions in given block.
pub fn transaction_views(&self) -> Vec<TransactionView> {
self.rlp.at(1).iter().map(TransactionView::new_from_rlp).collect()
}
/// Return transaction hashes.
pub fn transaction_hashes(&self) -> Vec<H256> {
self.rlp.at(1).iter().map(|rlp| rlp.as_raw().sha3()).collect()
}
/// Returns transaction at given index without deserializing unnecessary data.
pub fn transaction_at(&self, index: usize) -> Option<SignedTransaction> {
self.rlp.at(1).iter().nth(index).map(|rlp| rlp.as_val())
}
/// Returns localized transaction at given index.
pub fn localized_transaction_at(&self, index: usize) -> Option<LocalizedTransaction> {
let header = self.header_view();
let block_hash = header.sha3();
let block_number = header.number();
self.transaction_at(index).map(|t| LocalizedTransaction {
signed: t,
block_hash: block_hash,
block_number: block_number,
transaction_index: index
})
}
/// Return list of uncles of given block.
pub fn uncles(&self) -> Vec<Header> {
self.rlp.val_at(2)
}
/// Return number of uncles in given block, without deserializing them.
pub fn uncles_count(&self) -> usize {
self.rlp.at(2).iter().count()
}
/// Return List of transactions in given block.
pub fn uncle_views(&self) -> Vec<HeaderView> {
self.rlp.at(2).iter().map(HeaderView::new_from_rlp).collect()
}
/// Return list of uncle hashes of given block.
pub fn uncle_hashes(&self) -> Vec<H256> {
self.rlp.at(2).iter().map(|rlp| rlp.as_raw().sha3()).collect()
}
/// Return nth uncle.
pub fn uncle_at(&self, index: usize) -> Option<Header> {
self.rlp.at(2).iter().nth(index).map(|rlp| rlp.as_val())
}
}
impl<'a> Hashable for BlockView<'a> {
fn sha3(&self) -> H256 {
self.header_view().sha3()
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use rustc_serialize::hex::FromHex;
use util::H256;
use super::BlockView;
#[test]
fn test_block_view() {
// that's rlp of block created with ethash engine.
let rlp = "f90261f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba03a347e72953c860f32b1eb2c78a680d8734b2ea08085d949d729479796f218d5a047ea6239d9e31ccac8af3366f5ca37184d26e7646e3191a3aeb81c4cf74de500c0".from_hex().unwrap();
let view = BlockView::new(&rlp);
assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap());
assert_eq!(view.transactions_count(), 1);
assert_eq!(view.uncles_count(), 0);
}
}

134
ethcore/src/views/header.rs Normal file
View File

@ -0,0 +1,134 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! View onto block header rlp
use util::{Rlp, U256, Bytes, Hashable, H256, Address, H2048, View};
use header::BlockNumber;
/// View onto block header rlp.
pub struct HeaderView<'a> {
rlp: Rlp<'a>
}
impl<'a> HeaderView<'a> {
/// Creates new view onto header from raw bytes.
pub fn new(bytes: &'a [u8]) -> HeaderView<'a> {
HeaderView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto header from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> HeaderView<'a> {
HeaderView {
rlp: rlp
}
}
/// Returns header hash.
pub fn hash(&self) -> H256 { self.sha3() }
/// Returns raw rlp.
pub fn rlp(&self) -> &Rlp<'a> { &self.rlp }
/// Returns parent hash.
pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) }
/// Returns uncles hash.
pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) }
/// Returns author.
pub fn author(&self) -> Address { self.rlp.val_at(2) }
/// Returns state root.
pub fn state_root(&self) -> H256 { self.rlp.val_at(3) }
/// Returns transactions root.
pub fn transactions_root(&self) -> H256 { self.rlp.val_at(4) }
/// Returns block receipts root.
pub fn receipts_root(&self) -> H256 { self.rlp.val_at(5) }
/// Returns block log bloom.
pub fn log_bloom(&self) -> H2048 { self.rlp.val_at(6) }
/// Returns block difficulty.
pub fn difficulty(&self) -> U256 { self.rlp.val_at(7) }
/// Returns block number.
pub fn number(&self) -> BlockNumber { self.rlp.val_at(8) }
/// Returns block gas limit.
pub fn gas_limit(&self) -> U256 { self.rlp.val_at(9) }
/// Returns block gas used.
pub fn gas_used(&self) -> U256 { self.rlp.val_at(10) }
/// Returns timestamp.
pub fn timestamp(&self) -> u64 { self.rlp.val_at(11) }
/// Returns block extra data.
pub fn extra_data(&self) -> Bytes { self.rlp.val_at(12) }
/// Returns a vector of post-RLP-encoded seal fields.
pub fn seal(&self) -> Vec<Bytes> {
let mut seal = vec![];
for i in 13..self.rlp.item_count() {
seal.push(self.rlp.at(i).as_raw().to_vec());
}
seal
}
}
impl<'a> Hashable for HeaderView<'a> {
fn sha3(&self) -> H256 {
self.rlp.as_raw().sha3()
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use rustc_serialize::hex::FromHex;
use util::{H256, Address, H2048, U256};
use super::HeaderView;
#[test]
fn test_header_view() {
// that's rlp of block header created with ethash engine.
let rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
let view = HeaderView::new(&rlp);
assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap());
assert_eq!(view.parent_hash(), H256::from_str("d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7").unwrap());
assert_eq!(view.uncles_hash(), H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap());
assert_eq!(view.author(), Address::from_str("8888f1f195afa192cfee860698584c030f4c9db1").unwrap());
assert_eq!(view.state_root(), H256::from_str("5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25").unwrap());
assert_eq!(view.transactions_root(), H256::from_str("88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158").unwrap());
assert_eq!(view.receipts_root(), H256::from_str("07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1").unwrap());
assert_eq!(view.log_bloom(), H2048::default());
assert_eq!(view.difficulty(), U256::from(0x02_00_80));
assert_eq!(view.number(), 3);
assert_eq!(view.gas_limit(), U256::from(0x2f_ef_ba));
assert_eq!(view.gas_used(), U256::from(0x52_4d));
assert_eq!(view.timestamp(), 0x56_8e_93_2a);
assert_eq!(view.extra_data(), vec![] as Vec<u8>);
assert_eq!(view.seal(), vec![mix_hash, nonce]);
}
}

25
ethcore/src/views/mod.rs Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Block oriented views onto rlp.
mod block;
mod header;
mod transaction;
pub use self::block::BlockView;
pub use self::header::HeaderView;
pub use self::transaction::TransactionView;

View File

@ -0,0 +1,97 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! View onto transaction rlp
use util::{Rlp, U256, Bytes, Hashable, H256, View};
/// View onto transaction rlp.
pub struct TransactionView<'a> {
rlp: Rlp<'a>
}
impl<'a> TransactionView<'a> {
/// Creates new view onto block from raw bytes.
pub fn new(bytes: &'a [u8]) -> TransactionView<'a> {
TransactionView {
rlp: Rlp::new(bytes)
}
}
/// Creates new view onto block from rlp.
pub fn new_from_rlp(rlp: Rlp<'a>) -> TransactionView<'a> {
TransactionView {
rlp: rlp
}
}
/// Return reference to underlaying rlp.
pub fn rlp(&self) -> &Rlp<'a> {
&self.rlp
}
/// Get the nonce field of the transaction.
pub fn nonce(&self) -> U256 { self.rlp.val_at(0) }
/// Get the gas_price field of the transaction.
pub fn gas_price(&self) -> U256 { self.rlp.val_at(1) }
/// Get the gas field of the transaction.
pub fn gas(&self) -> U256 { self.rlp.val_at(2) }
/// Get the value field of the transaction.
pub fn value(&self) -> U256 { self.rlp.val_at(4) }
/// Get the data field of the transaction.
pub fn data(&self) -> Bytes { self.rlp.val_at(5) }
/// Get the v field of the transaction.
pub fn v(&self) -> u8 { let r: u16 = self.rlp.val_at(6); r as u8 }
/// Get the r field of the transaction.
pub fn r(&self) -> U256 { self.rlp.val_at(7) }
/// Get the s field of the transaction.
pub fn s(&self) -> U256 { self.rlp.val_at(8) }
}
impl<'a> Hashable for TransactionView<'a> {
fn sha3(&self) -> H256 {
self.rlp.as_raw().sha3()
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use rustc_serialize::hex::FromHex;
use util::U256;
use super::TransactionView;
#[test]
fn test_transaction_view() {
let rlp = "f87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".from_hex().unwrap();
let view = TransactionView::new(&rlp);
assert_eq!(view.nonce(), U256::from(0));
assert_eq!(view.gas_price(), U256::from(1));
assert_eq!(view.gas(), U256::from(0x61a8));
assert_eq!(view.value(), U256::from(0xa));
assert_eq!(view.data(), "0000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
assert_eq!(view.r(), U256::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353").unwrap());
assert_eq!(view.s(), U256::from_str("efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
assert_eq!(view.v(), 0x1b);
}
}

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.1.0/parity_linux_1.1.0-0_amd64.deb
PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.2.0/parity_linux_1.2.0-0_amd64.deb
function run_installer()

View File

@ -133,6 +133,22 @@ Sealing/Mining Options:
NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.
--force-sealing Force the node to author new blocks as if it were
always sealing/mining.
--reseal-on-txs SET Specify which transactions should force the node
to reseal a block. SET is one of:
none - never reseal on new transactions;
own - reseal only on a new local transaction;
ext - reseal only on a new external transaction;
all - reseal on all new transactions [default: all].
--tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas
a single transaction may have for it to be mined.
--relay-set SET Set of transactions to relay. SET may be:
cheap - Relay any transaction in the queue (this
may include invalid transactions);
strict - Relay only executed transactions (this
guarantees we don't relay invalid transactions, but
means we relay nothing if not mining);
lenient - Same as strict when mining, and cheap
when not [default: cheap].
--usd-per-tx USD Amount of USD to be paid for a basic transaction
[default: 0.005]. The minimum gas price is set
accordingly.
@ -146,8 +162,8 @@ Sealing/Mining Options:
block due to transaction volume [default: 3141592].
--extra-data STRING Specify a custom extra-data for authored blocks, no
more than 32 characters.
--tx-limit LIMIT Limit of transactions kept in the queue (waiting to
be included in next block) [default: 1024].
--tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting
to be included in next block) [default: 1024].
Footprint Options:
--tracing BOOL Indicates if full transaction tracing should be
@ -288,13 +304,16 @@ pub struct Args {
pub flag_signer_path: String,
pub flag_no_token: bool,
pub flag_force_sealing: bool,
pub flag_reseal_on_txs: String,
pub flag_tx_gas_limit: Option<String>,
pub flag_relay_set: String,
pub flag_author: Option<String>,
pub flag_usd_per_tx: String,
pub flag_usd_per_eth: String,
pub flag_gas_floor_target: String,
pub flag_gas_cap: String,
pub flag_extra_data: Option<String>,
pub flag_tx_limit: usize,
pub flag_tx_queue_size: usize,
pub flag_logging: Option<String>,
pub flag_version: bool,
pub flag_from: String,

View File

@ -27,6 +27,7 @@ use util::*;
use ethcore::account_provider::AccountProvider;
use util::network_settings::NetworkSettings;
use ethcore::client::{append_path, get_db_path, ClientConfig, DatabaseCompactionProfile, Switch, VMType};
use ethcore::miner::{MinerOptions, PendingSet};
use ethcore::ethereum;
use ethcore::spec::Spec;
use ethsync::SyncConfig;
@ -67,6 +68,37 @@ impl Configuration {
self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32
}
fn decode_u256(d: &str, argument: &str) -> U256 {
U256::from_dec_str(d).unwrap_or_else(|_|
U256::from_str(clean_0x(d)).unwrap_or_else(|_|
die!("{}: Invalid numeric value for {}. Must be either a decimal or a hex number.", d, argument)
)
)
}
pub fn miner_options(&self) -> MinerOptions {
let (own, ext) = match self.args.flag_reseal_on_txs.as_str() {
"none" => (false, false),
"own" => (true, false),
"ext" => (false, true),
"all" => (true, true),
x => die!("{}: Invalid value for --reseal option. Use --help for more information.", x)
};
MinerOptions {
force_sealing: self.args.flag_force_sealing,
reseal_on_external_tx: ext,
reseal_on_own_tx: own,
tx_gas_limit: self.args.flag_tx_gas_limit.as_ref().map_or(!U256::zero(), |d| Self::decode_u256(d, "--tx-gas-limit")),
tx_queue_size: self.args.flag_tx_queue_size,
pending_set: match self.args.flag_relay_set.as_str() {
"cheap" => PendingSet::AlwaysQueue,
"strict" => PendingSet::AlwaysSealing,
"lenient" => PendingSet::SealingOrElseQueue,
x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x)
},
}
}
pub fn author(&self) -> Option<Address> {
self.args.flag_etherbase.as_ref()
.or(self.args.flag_author.as_ref())

View File

@ -208,13 +208,13 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
let account_service = Arc::new(conf.account_service());
// Miner
let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone());
miner.set_author(conf.author().unwrap_or(Default::default()));
let miner = Miner::new(conf.miner_options(), conf.spec(), Some(account_service.clone()));
miner.set_author(conf.author().unwrap_or_default());
miner.set_gas_floor_target(conf.gas_floor_target());
miner.set_gas_ceil_target(conf.gas_ceil_target());
miner.set_extra_data(conf.extra_data());
miner.set_minimal_gas_price(conf.gas_price());
miner.set_transactions_limit(conf.args.flag_tx_limit);
miner.set_transactions_limit(conf.args.flag_tx_queue_size);
// Build client
let mut service = ClientService::start(
@ -341,7 +341,7 @@ fn execute_export(conf: Configuration) {
// Build client
let service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);
@ -413,7 +413,7 @@ fn execute_import(conf: Configuration) {
// Build client
let service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);

View File

@ -18,6 +18,8 @@
extern crate ethash;
use std::thread;
use std::time::{Instant, Duration};
use std::sync::{Arc, Weak, Mutex};
use std::ops::Deref;
use ethsync::{SyncProvider, SyncState};
@ -479,6 +481,12 @@ impl<C, S, M, EM> Eth for EthClient<C, S, M, EM> where
trace!(target: "miner", "Syncing. Cannot give any work.");
return Err(no_work_err());
}
// Otherwise spin until our submitted block has been included.
let timeout = Instant::now() + Duration::from_millis(1000);
while Instant::now() < timeout && client.queue_info().total_queue_size() > 0 {
thread::sleep(Duration::from_millis(1));
}
}
let miner = take_weak!(self.miner);

View File

@ -29,6 +29,9 @@ use v1::impls::{default_gas_price, sign_and_dispatch};
fn fill_optional_fields<C, M>(request: &mut TransactionRequest, client: &C, miner: &M)
where C: MiningBlockChainClient, M: MinerService {
if request.value.is_none() {
request.value = Some(U256::zero());
}
if request.gas.is_none() {
request.gas = Some(miner.sensible_gas_limit());
}

View File

@ -22,7 +22,7 @@ use jsonrpc_core::*;
use ethcore::miner::MinerService;
use ethcore::service::SyncMessage;
use v1::traits::EthcoreSet;
use v1::types::{Bytes};
use v1::types::Bytes;
/// Ethcore-specific rpc interface for operations altering the settings.
pub struct EthcoreSetClient<M> where
@ -86,6 +86,13 @@ impl<M> EthcoreSet for EthcoreSetClient<M> where M: MinerService + 'static {
})
}
fn set_tx_gas_limit(&self, params: Params) -> Result<Value, Error> {
from_params::<(U256,)>(params).and_then(|(limit,)| {
take_weak!(self.miner).set_tx_gas_limit(limit.into());
to_value(&true)
})
}
fn add_reserved_peer(&self, params: Params) -> Result<Value, Error> {
from_params::<(String,)>(params).and_then(|(peer,)| {
match take_weak!(self.net).add_reserved_peer(&peer) {

View File

@ -24,12 +24,12 @@ use ethcore::spec::{Genesis, Spec};
use ethcore::block::Block;
use ethcore::views::BlockView;
use ethcore::ethereum;
use ethcore::miner::{MinerService, ExternalMiner, Miner};
use ethcore::miner::{MinerOptions, MinerService, ExternalMiner, Miner, PendingSet};
use ethcore::account_provider::AccountProvider;
use devtools::RandomTempPath;
use util::Hashable;
use util::io::IoChannel;
use util::{U256, H256};
use util::{U256, H256, Uint};
use jsonrpc_core::IoHandler;
use ethjson::blockchain::BlockChain;
@ -49,7 +49,18 @@ fn sync_provider() -> Arc<TestSyncProvider> {
}
fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
Miner::with_accounts(true, spec, accounts)
Miner::new(
MinerOptions {
force_sealing: true,
reseal_on_external_tx: true,
reseal_on_own_tx: true,
tx_queue_size: 1024,
tx_gas_limit: !U256::zero(),
pending_set: PendingSet::SealingOrElseQueue,
},
spec,
Some(accounts)
)
}
fn make_spec(chain: &BlockChain) -> Spec {

View File

@ -43,6 +43,7 @@ pub struct TestMinerService {
author: RwLock<Address>,
extra_data: RwLock<Bytes>,
limit: RwLock<usize>,
tx_gas_limit: RwLock<U256>,
}
impl Default for TestMinerService {
@ -58,6 +59,7 @@ impl Default for TestMinerService {
author: RwLock::new(Address::zero()),
extra_data: RwLock::new(vec![1, 2, 3, 4]),
limit: RwLock::new(1024),
tx_gas_limit: RwLock::new(!U256::zero()),
}
}
}
@ -99,6 +101,10 @@ impl MinerService for TestMinerService {
*self.limit.write().unwrap() = limit;
}
fn set_tx_gas_limit(&self, limit: U256) {
*self.tx_gas_limit.write().unwrap() = limit;
}
fn transactions_limit(&self) -> usize {
*self.limit.read().unwrap()
}

View File

@ -40,6 +40,9 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static {
/// Sets the limits for transaction queue.
fn set_transactions_limit(&self, _: Params) -> Result<Value, Error>;
/// Sets the maximum amount of gas a single transaction may consume.
fn set_tx_gas_limit(&self, _: Params) -> Result<Value, Error>;
/// Add a reserved peer.
fn add_reserved_peer(&self, _: Params) -> Result<Value, Error>;
@ -60,6 +63,7 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static {
delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target);
delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data);
delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author);
delegate.add_method("ethcore_setMaxTransactionGas", EthcoreSet::set_tx_gas_limit);
delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit);
delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer);
delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer);

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use serde::{Serialize, Serializer};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde_json::Value;
/// Optional value
@ -26,13 +26,22 @@ pub enum OptionalValue<T> where T: Serialize {
Null
}
impl<T> Default for OptionalValue<T> where T: Serialize {
impl<T> Default for OptionalValue<T> where T: Serialize + Deserialize {
fn default() -> Self {
OptionalValue::Null
}
}
impl<T> Serialize for OptionalValue<T> where T: Serialize {
impl<T> Into<Option<T>> for OptionalValue<T> where T: Serialize + Deserialize {
fn into(self) -> Option<T> {
match self {
OptionalValue::Null => None,
OptionalValue::Value(t) => Some(t),
}
}
}
impl<T> Serialize for OptionalValue<T> where T: Serialize + Deserialize {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer {
match *self {
@ -42,6 +51,17 @@ impl<T> Serialize for OptionalValue<T> where T: Serialize {
}
}
impl<T> Deserialize for OptionalValue<T> where T: Serialize + Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<OptionalValue<T>, D::Error>
where D: Deserializer {
let deser_result: Result<T, D::Error> = Deserialize::deserialize(deserializer);
match deser_result {
Ok(t) => Ok(OptionalValue::Value(t)),
Err(_) => Ok(OptionalValue::Null),
}
}
}
#[cfg(test)]
mod tests {
use serde_json;

View File

@ -1314,7 +1314,7 @@ impl ChainSync {
return 0;
}
let mut transactions = io.chain().all_transactions();
let mut transactions = io.chain().pending_transactions();
if transactions.is_empty() {
return 0;
}

View File

@ -44,8 +44,14 @@
//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap();
//! service.start().unwrap();
//! let dir = env::temp_dir();
//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(true), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap();
//! let miner = Miner::new(false, ethereum::new_frontier(true));
//! let miner = Miner::new(Default::default(), ethereum::new_frontier(true), None);
//! let client = Client::new(
//! ClientConfig::default(),
//! ethereum::new_frontier(true),
//! &dir,
//! miner,
//! service.io().channel()
//! ).unwrap();
//! let sync = EthSync::new(SyncConfig::default(), client);
//! EthSync::register(&mut service, sync);
//! }

View File

@ -557,7 +557,7 @@ macro_rules! construct_uint {
($name:ident, $n_words:expr) => (
/// Little-endian large integer type
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct $name(pub [u64; $n_words]);
impl Uint for $name {
@ -1126,14 +1126,6 @@ macro_rules! construct_uint {
Ok(())
}
}
#[cfg_attr(feature="dev", allow(derive_hash_xor_eq))] // We are pretty sure it's ok.
impl Hash for $name {
fn hash<H>(&self, state: &mut H) where H: Hasher {
unsafe { state.write(::std::slice::from_raw_parts(self.0.as_ptr() as *mut u8, self.0.len() * 8)); }
state.finish();
}
}
);
}

View File

@ -132,15 +132,10 @@ macro_rules! impl_hash {
$size
}
// TODO: remove once slice::clone_from_slice is stable
#[inline]
fn clone_from_slice(&mut self, src: &[u8]) -> usize {
let min = ::std::cmp::min($size, src.len());
let dst = &mut self.deref_mut()[.. min];
let src = &src[.. min];
for i in 0..min {
dst[i] = src[i];
}
let min = cmp::min($size, src.len());
self.0[..min].copy_from_slice(&src[..min]);
min
}
@ -151,7 +146,7 @@ macro_rules! impl_hash {
}
fn copy_to(&self, dest: &mut[u8]) {
let min = ::std::cmp::min($size, dest.len());
let min = cmp::min($size, dest.len());
dest[..min].copy_from_slice(&self.0[..min]);
}

View File

@ -199,7 +199,16 @@ impl Database {
opts.set_block_based_table_factory(&block_opts);
opts.set_prefix_extractor_fixed_size(size);
}
let db = try!(DB::open(&opts, path));
let db = match DB::open(&opts, path) {
Ok(db) => db,
Err(ref s) if s.starts_with("Corruption:") => {
info!("{}", s);
info!("Attempting DB repair for {}", path);
try!(DB::repair(&opts, path));
try!(DB::open(&opts, path))
},
Err(s) => { return Err(s); }
};
Ok(Database { db: db })
}

View File

@ -258,14 +258,7 @@ impl <T>FromBytes for T where T: FixedHash {
Ordering::Equal => ()
};
unsafe {
use std::{mem, ptr};
let mut res: T = mem::uninitialized();
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::len());
Ok(res)
}
Ok(T::from_slice(bytes))
}
}