Backports for stable 2.1.10 (#10046)

* bump stable to 2.1.10

* RPC: parity_getBlockReceipts (#9527)

* Block receipts RPC.

* Use lazy evaluation of block receipts (ecrecover).

* Optimize transaction_receipt to prevent performance regression.

* Fix RPC grumbles.

* Add block & transaction receipt tests.

* Fix conversion to block id.

* Update a few parity-common dependencies (#9663)

* Update a few parity-common dependencies

* cleanup

* cleanup

* revert update of ethereum/tests

* better reporting of network rlp errors

* Use rlp 0.3.0-beta.1

* fix util function get_dummy_blocks

* Already a Vec

* encode_list returns vec already

* Address grumble

* No need for betas

* Fix double spaces

* Fix empty steps (#9939)

* Don't send empty step twice or empty step then block.

* Perform basic validation of locally sealed blocks.

* Don't include empty step twice.

* Strict empty steps validation (#10041)

* Add two failings tests for strict empty steps.

* Implement strict validation of empty steps.

* ethcore: enable constantinople on ethereum (#10031)

* ethcore: change blockreward to 2e18 for foundation after constantinople

* ethcore: delay diff bomb by 2e6 blocks for foundation after constantinople

* ethcore: enable eip-{145,1014,1052,1283} for foundation after constantinople

* Change test miner max memory to malloc reports. (#10024)

* Bump crossbeam. (#10048)

* Revert "Bump crossbeam. (#10048)"

This reverts commit ed1db0c2d3d3b8e6bfde3124fb03b093a264e241.
This commit is contained in:
Thibaut Sardan
2018-12-13 17:53:36 +01:00
committed by GitHub
parent af1169d2ff
commit b47e064f8e
98 changed files with 862 additions and 646 deletions

View File

@@ -58,7 +58,7 @@ impl Default for Factory {
impl Factory {
/// Create a read-only accountdb.
/// This will panic when write operations are called.
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
pub fn readonly<'db>(&self, db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
match *self {
Factory::Mangled => Box::new(AccountDB::from_hash(db, address_hash)),
Factory::Plain => Box::new(Wrapping(db)),
@@ -66,7 +66,7 @@ impl Factory {
}
/// Create a new mutable hashdb.
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Box<HashDB<KeccakHasher> + 'db> {
pub fn create<'db>(&self, db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Box<HashDB<KeccakHasher, DBValue> + 'db> {
match *self {
Factory::Mangled => Box::new(AccountDBMut::from_hash(db, address_hash)),
Factory::Plain => Box::new(WrappingMut(db)),
@@ -78,19 +78,19 @@ impl Factory {
/// DB backend wrapper for Account trie
/// Transforms trie node keys for the database
pub struct AccountDB<'db> {
db: &'db HashDB<KeccakHasher>,
db: &'db HashDB<KeccakHasher, DBValue>,
address_hash: H256,
}
impl<'db> AccountDB<'db> {
/// Create a new AccountDB from an address.
#[cfg(test)]
pub fn new(db: &'db HashDB<KeccakHasher>, address: &Address) -> Self {
pub fn new(db: &'db HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
Self::from_hash(db, keccak(address))
}
/// Create a new AcountDB from an address' hash.
pub fn from_hash(db: &'db HashDB<KeccakHasher>, address_hash: H256) -> Self {
pub fn from_hash(db: &'db HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
AccountDB {
db: db,
address_hash: address_hash,
@@ -98,12 +98,12 @@ impl<'db> AccountDB<'db> {
}
}
impl<'db> AsHashDB<KeccakHasher> for AccountDB<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDB<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -137,19 +137,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDB<'db> {
/// DB backend wrapper for Account trie
pub struct AccountDBMut<'db> {
db: &'db mut HashDB<KeccakHasher>,
db: &'db mut HashDB<KeccakHasher, DBValue>,
address_hash: H256,
}
impl<'db> AccountDBMut<'db> {
/// Create a new AccountDB from an address.
#[cfg(test)]
pub fn new(db: &'db mut HashDB<KeccakHasher>, address: &Address) -> Self {
pub fn new(db: &'db mut HashDB<KeccakHasher, DBValue>, address: &Address) -> Self {
Self::from_hash(db, keccak(address))
}
/// Create a new AcountDB from an address' hash.
pub fn from_hash(db: &'db mut HashDB<KeccakHasher>, address_hash: H256) -> Self {
pub fn from_hash(db: &'db mut HashDB<KeccakHasher, DBValue>, address_hash: H256) -> Self {
AccountDBMut {
db: db,
address_hash: address_hash,
@@ -162,7 +162,7 @@ impl<'db> AccountDBMut<'db> {
}
}
impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
impl<'db> HashDB<KeccakHasher, DBValue> for AccountDBMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -208,19 +208,19 @@ impl<'db> HashDB<KeccakHasher> for AccountDBMut<'db>{
}
}
impl<'db> AsHashDB<KeccakHasher> for AccountDBMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for AccountDBMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
struct Wrapping<'db>(&'db HashDB<KeccakHasher>);
struct Wrapping<'db>(&'db HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher> for Wrapping<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<'db> AsHashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
impl<'db> HashDB<KeccakHasher, DBValue> for Wrapping<'db> {
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}
@@ -252,13 +252,13 @@ impl<'db> HashDB<KeccakHasher> for Wrapping<'db> {
}
}
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher>);
impl<'db> AsHashDB<KeccakHasher> for WrappingMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
struct WrappingMut<'db>(&'db mut HashDB<KeccakHasher, DBValue>);
impl<'db> AsHashDB<KeccakHasher, DBValue> for WrappingMut<'db> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<'db> HashDB<KeccakHasher> for WrappingMut<'db>{
impl<'db> HashDB<KeccakHasher, DBValue> for WrappingMut<'db>{
fn keys(&self) -> HashMap<H256, i32> {
unimplemented!()
}

View File

@@ -160,11 +160,6 @@ pub trait BlockProvider {
.and_then(|n| body.view().localized_transaction_at(&address.block_hash, n, address.index)))
}
/// Get transaction receipt.
fn transaction_receipt(&self, address: &TransactionAddress) -> Option<Receipt> {
self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index))
}
/// Get a list of transactions for a given block.
/// Returns None if block does not exist.
fn transactions(&self, hash: &H256) -> Option<Vec<LocalizedTransaction>> {

View File

@@ -51,7 +51,7 @@ impl Block {
#[inline]
pub fn encoded(&self) -> encoded::Block {
encoded::Block::new(encode(self).into_vec())
encoded::Block::new(encode(self))
}
#[inline]

View File

@@ -1795,26 +1795,49 @@ impl BlockChainClient for Client {
}
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt> {
// NOTE Don't use block_receipts here for performance reasons
let address = self.transaction_address(id)?;
let hash = address.block_hash;
let chain = self.chain.read();
self.transaction_address(id)
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| {
let transaction = chain.block_body(&address.block_hash)
.and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index));
let number = chain.block_number(&hash)?;
let body = chain.block_body(&hash)?;
let mut receipts = chain.block_receipts(&hash)?.receipts;
receipts.truncate(address.index + 1);
let previous_receipts = (0..address.index + 1)
.map(|index| {
let mut address = address.clone();
address.index = index;
chain.transaction_receipt(&address)
})
.collect();
match (transaction, previous_receipts) {
(Some(transaction), Some(previous_receipts)) => {
Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts))
},
_ => None,
}
}))
let transaction = body.view().localized_transaction_at(&hash, number, address.index)?;
let receipt = receipts.pop()?;
let gas_used = receipts.last().map_or_else(|| 0.into(), |r| r.gas_used);
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
let receipt = transaction_receipt(self.engine().machine(), transaction, receipt, gas_used, no_of_logs);
Some(receipt)
}
fn block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>> {
let hash = self.block_hash(id)?;
let chain = self.chain.read();
let receipts = chain.block_receipts(&hash)?;
let number = chain.block_number(&hash)?;
let body = chain.block_body(&hash)?;
let engine = self.engine.clone();
let mut gas_used = 0.into();
let mut no_of_logs = 0;
Some(body
.view()
.localized_transactions(&hash, number)
.into_iter()
.zip(receipts.receipts)
.map(move |(transaction, receipt)| {
let result = transaction_receipt(engine.machine(), transaction, receipt, gas_used, no_of_logs);
gas_used = result.cumulative_gas_used;
no_of_logs += result.logs.len();
result
})
.collect()
)
}
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
@@ -1833,8 +1856,8 @@ impl BlockChainClient for Client {
self.state_db.read().journal_db().state(hash)
}
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).into_vec())
fn encoded_block_receipts(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts))
}
fn queue_info(&self) -> BlockQueueInfo {
@@ -2249,8 +2272,7 @@ impl ScheduleInfo for Client {
}
impl ImportSealedBlock for Client {
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult {
let h = block.header().hash();
fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult<H256> {
let start = Instant::now();
let header = block.header().clone();
let route = {
@@ -2396,16 +2418,14 @@ impl Drop for Client {
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
/// and a vector of receipts from given block up to transaction index.
fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
fn transaction_receipt(
machine: &::machine::EthereumMachine,
mut tx: LocalizedTransaction,
receipt: Receipt,
prior_gas_used: U256,
prior_no_of_logs: usize,
) -> LocalizedReceipt {
let sender = tx.sender();
let receipt = receipts.pop().expect("Current receipt is provided; qed");
let prior_gas_used = match tx.transaction_index {
0 => 0.into(),
i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used,
};
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>();
let transaction_hash = tx.hash();
let block_hash = tx.block_hash;
let block_number = tx.block_number;
@@ -2434,7 +2454,7 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr
transaction_hash: transaction_hash,
transaction_index: transaction_index,
transaction_log_index: i,
log_index: no_of_logs + i,
log_index: prior_no_of_logs + i,
}).collect(),
log_bloom: receipt.log_bloom,
outcome: receipt.outcome,
@@ -2482,6 +2502,33 @@ mod tests {
assert!(client.tree_route(&genesis, &new_hash).is_none());
}
#[test]
fn should_return_block_receipts() {
use client::{BlockChainClient, BlockId, TransactionId};
use test_helpers::{generate_dummy_client_with_data};
let client = generate_dummy_client_with_data(2, 2, &[1.into(), 1.into()]);
let receipts = client.block_receipts(BlockId::Latest).unwrap();
assert_eq!(receipts.len(), 2);
assert_eq!(receipts[0].transaction_index, 0);
assert_eq!(receipts[0].block_number, 2);
assert_eq!(receipts[0].cumulative_gas_used, 53_000.into());
assert_eq!(receipts[0].gas_used, 53_000.into());
assert_eq!(receipts[1].transaction_index, 1);
assert_eq!(receipts[1].block_number, 2);
assert_eq!(receipts[1].cumulative_gas_used, 106_000.into());
assert_eq!(receipts[1].gas_used, 53_000.into());
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[0].transaction_hash));
assert_eq!(receipt, Some(receipts[0].clone()));
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[1].transaction_hash));
assert_eq!(receipt, Some(receipts[1].clone()));
}
#[test]
fn should_return_correct_log_index() {
use hash::keccak;
@@ -2525,20 +2572,15 @@ mod tests {
topics: vec![],
data: vec![],
}];
let receipts = vec![Receipt {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: 5.into(),
log_bloom: Default::default(),
logs: vec![logs[0].clone()],
}, Receipt {
let receipt = Receipt {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: gas_used,
log_bloom: Default::default(),
logs: logs.clone(),
}];
};
// when
let receipt = transaction_receipt(&machine, transaction, receipts);
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1);
// then
assert_eq!(receipt, LocalizedReceipt {

View File

@@ -686,6 +686,10 @@ impl BlockChainClient for TestBlockChainClient {
self.receipts.read().get(&id).cloned()
}
fn block_receipts(&self, _id: BlockId) -> Option<Vec<LocalizedReceipt>> {
Some(self.receipts.read().values().cloned().collect())
}
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
match self.error_on_logs.read().as_ref() {
Some(id) => return Err(id.clone()),
@@ -785,7 +789,7 @@ impl BlockChainClient for TestBlockChainClient {
None
}
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
fn encoded_block_receipts(&self, hash: &H256) -> Option<Bytes> {
// starts with 'f' ?
if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") {
let receipt = BlockReceipts::new(vec![Receipt::new(

View File

@@ -42,7 +42,7 @@ use engines::EthEngine;
use ethereum_types::{H256, U256, Address};
use ethcore_miner::pool::VerifiedTransaction;
use bytes::Bytes;
use hashdb::DBValue;
use kvdb::DBValue;
use types::ids::*;
use types::basic_account::BasicAccount;
@@ -281,6 +281,9 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get transaction receipt with given hash.
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt>;
/// Get localized receipts for all transaction in given block.
fn block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>>;
/// Get a tree route between `from` and `to`.
/// See `BlockChain::tree_route`.
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute>;
@@ -292,7 +295,7 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
fn state_data(&self, hash: &H256) -> Option<Bytes>;
/// Get raw block receipts data by block header hash.
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
fn encoded_block_receipts(&self, hash: &H256) -> Option<Bytes>;
/// Get block queue information.
fn queue_info(&self) -> BlockQueueInfo;

View File

@@ -80,6 +80,8 @@ pub struct AuthorityRoundParams {
pub empty_steps_transition: u64,
/// Number of accepted empty steps.
pub maximum_empty_steps: usize,
/// Transition block to strict empty steps validation.
pub strict_empty_steps_transition: u64,
}
const U16_MAX: usize = ::std::u16::MAX as usize;
@@ -109,6 +111,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
empty_steps_transition: p.empty_steps_transition.map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)),
maximum_empty_steps: p.maximum_empty_steps.map_or(0, Into::into),
strict_empty_steps_transition: p.strict_empty_steps_transition.map_or(0, Into::into),
}
}
}
@@ -420,6 +423,7 @@ pub struct AuthorityRound {
maximum_uncle_count_transition: u64,
maximum_uncle_count: usize,
empty_steps_transition: u64,
strict_empty_steps_transition: u64,
maximum_empty_steps: usize,
machine: EthereumMachine,
}
@@ -673,6 +677,7 @@ impl AuthorityRound {
maximum_uncle_count: our_params.maximum_uncle_count,
empty_steps_transition: our_params.empty_steps_transition,
maximum_empty_steps: our_params.maximum_empty_steps,
strict_empty_steps_transition: our_params.strict_empty_steps_transition,
machine: machine,
});
@@ -1011,7 +1016,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
let empty_steps_rlp = if header.number() >= self.empty_steps_transition {
let empty_steps: Vec<_> = empty_steps.iter().map(|e| e.sealed()).collect();
Some(::rlp::encode_list(&empty_steps).into_vec())
Some(::rlp::encode_list(&empty_steps))
} else {
None
};
@@ -1033,8 +1038,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
let mut fields = vec![
encode(&step).into_vec(),
encode(&(&H520::from(signature) as &[u8])).into_vec(),
encode(&step),
encode(&(&H520::from(signature) as &[u8])),
];
if let Some(empty_steps_rlp) = empty_steps_rlp {
@@ -1186,8 +1191,11 @@ impl Engine<EthereumMachine> for AuthorityRound {
// reported as there's no way to tell whether the empty step message was never sent or simply not included.
let empty_steps_len = if header.number() >= self.empty_steps_transition {
let validate_empty_steps = || -> Result<usize, Error> {
let strict_empty_steps = header.number() >= self.strict_empty_steps_transition;
let empty_steps = header_empty_steps(header)?;
let empty_steps_len = empty_steps.len();
let mut prev_empty_step = 0;
for empty_step in empty_steps {
if empty_step.step <= parent_step || empty_step.step >= step {
Err(EngineError::InsufficientProof(
@@ -1203,7 +1211,20 @@ impl Engine<EthereumMachine> for AuthorityRound {
Err(EngineError::InsufficientProof(
format!("invalid empty step proof: {:?}", empty_step)))?;
}
if strict_empty_steps {
if empty_step.step <= prev_empty_step {
Err(EngineError::InsufficientProof(format!(
"{} empty step: {:?}",
if empty_step.step == prev_empty_step { "duplicate" } else { "unordered" },
empty_step
)))?;
}
prev_empty_step = empty_step.step;
}
}
Ok(empty_steps_len)
};
@@ -1459,10 +1480,40 @@ mod tests {
use spec::Spec;
use transaction::{Action, Transaction};
use engines::{Seal, Engine, EngineError, EthEngine};
use engines::validator_set::TestSet;
use engines::validator_set::{TestSet, SimpleList};
use error::{Error, ErrorKind};
use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep, calculate_score};
fn aura<F>(f: F) -> Arc<AuthorityRound> where
F: FnOnce(&mut AuthorityRoundParams),
{
let mut params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::default()),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
strict_empty_steps_transition: 0,
};
// mutate aura params
f(&mut params);
// create engine
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
}
#[test]
fn has_valid_metadata() {
let engine = Spec::new_test_round().engine;
@@ -1481,7 +1532,7 @@ mod tests {
fn can_do_signature_verification_fail() {
let engine = Spec::new_test_round().engine;
let mut header: Header = Header::default();
header.set_seal(vec![encode(&H520::default()).into_vec()]);
header.set_seal(vec![encode(&H520::default())]);
let verify_result = engine.verify_block_external(&header);
assert!(verify_result.is_err());
@@ -1558,7 +1609,7 @@ mod tests {
let tap = AccountProvider::transient_provider();
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1571,12 +1622,12 @@ mod tests {
// Spec starts with step 2.
header.set_difficulty(calculate_score(0, 2, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&2usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&2usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_err());
header.set_difficulty(calculate_score(0, 1, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&1usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_ok());
}
@@ -1587,7 +1638,7 @@ mod tests {
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1600,10 +1651,10 @@ mod tests {
// Spec starts with step 2.
header.set_difficulty(calculate_score(0, 1, 0));
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&1usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
assert!(engine.verify_block_external(&header).is_ok());
header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&5usize), encode(&(&*signature as &[u8]))]);
assert!(engine.verify_block_basic(&header).is_err());
}
@@ -1613,7 +1664,7 @@ mod tests {
let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap();
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&4usize).into_vec()]);
parent_header.set_seal(vec![encode(&4usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_number(1);
@@ -1625,10 +1676,10 @@ mod tests {
let signature = tap.sign(addr, Some("0".into()), header.bare_hash()).unwrap();
// Two validators.
// Spec starts with step 2.
header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&5usize), encode(&(&*signature as &[u8]))]);
header.set_difficulty(calculate_score(4, 5, 0));
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
header.set_seal(vec![encode(&3usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]);
header.set_seal(vec![encode(&3usize), encode(&(&*signature as &[u8]))]);
header.set_difficulty(calculate_score(4, 3, 0));
assert!(engine.verify_block_family(&header, &parent_header).is_err());
}
@@ -1636,36 +1687,17 @@ mod tests {
#[test]
fn reports_skipped() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let aura = {
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
};
let aura = aura(|p| {
p.validators = Box::new(TestSet::new(Default::default(), last_benign.clone()));
});
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&1usize).into_vec()]);
parent_header.set_seal(vec![encode(&1usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
header.set_difficulty(calculate_score(1, 3, 0));
header.set_gas_limit("222222".parse::<U256>().unwrap());
header.set_seal(vec![encode(&3usize).into_vec()]);
header.set_seal(vec![encode(&3usize)]);
// Do not report when signer not present.
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
@@ -1686,29 +1718,9 @@ mod tests {
#[test]
fn test_uncles_transition() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 1,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 1,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let aura = {
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap()
};
let aura = aura(|params| {
params.maximum_uncle_count_transition = 1;
});
assert_eq!(aura.maximum_uncle_count(0), 2);
assert_eq!(aura.maximum_uncle_count(1), 0);
@@ -1742,27 +1754,9 @@ mod tests {
#[test]
#[should_panic(expected="authority_round: step duration can't be zero")]
fn test_step_duration_zero() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 0,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: u64::max_value(),
maximum_empty_steps: 0,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
AuthorityRound::new(params, machine).unwrap();
aura(|params| {
params.step_duration = 0;
});
}
fn setup_empty_steps() -> (Spec, Arc<AccountProvider>, Vec<Address>) {
@@ -1790,6 +1784,23 @@ mod tests {
SealedEmptyStep { signature, step }
}
fn set_empty_steps_seal(header: &mut Header, step: u64, block_signature: &ethkey::Signature, empty_steps: &[SealedEmptyStep]) {
header.set_seal(vec![
encode(&(step as usize)),
encode(&(&**block_signature as &[u8])),
::rlp::encode_list(&empty_steps),
]);
}
fn assert_insufficient_proof<T: ::std::fmt::Debug>(result: Result<T, Error>, contains: &str) {
match result {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _)) =>{
assert!(s.contains(contains), "Expected {:?} to contain {:?}", s, contains);
},
e => assert!(false, "Unexpected result: {:?}", e),
}
}
#[test]
fn broadcast_empty_step_message() {
let (spec, tap, accounts) = setup_empty_steps();
@@ -1816,7 +1827,7 @@ mod tests {
assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None);
// spec starts with step 2
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash())).into_vec();
let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash()));
// we've received the message
assert!(notify.messages.read().contains(&empty_step_rlp));
@@ -1874,8 +1885,8 @@ mod tests {
let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash());
let empty_steps = ::rlp::encode_list(&vec![empty_step2]);
assert_eq!(seal[0], encode(&3usize).into_vec());
assert_eq!(seal[2], empty_steps.into_vec());
assert_eq!(seal[0], encode(&3usize));
assert_eq!(seal[2], empty_steps);
}
}
@@ -1928,8 +1939,8 @@ mod tests {
let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]);
assert_eq!(seal[0], encode(&4usize).into_vec());
assert_eq!(seal[2], empty_steps.into_vec());
assert_eq!(seal[0], encode(&4usize));
assert_eq!(seal[2], empty_steps);
}
}
@@ -1978,7 +1989,7 @@ mod tests {
let engine = &*spec.engine;
let mut parent_header: Header = Header::default();
parent_header.set_seal(vec![encode(&0usize).into_vec()]);
parent_header.set_seal(vec![encode(&0usize)]);
parent_header.set_gas_limit("222222".parse::<U256>().unwrap());
let mut header: Header = Header::default();
@@ -1991,46 +2002,31 @@ mod tests {
// empty step with invalid step
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 2 }];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid step") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid step"
);
// empty step with invalid signature
let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 1 }];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid empty step proof") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid empty step proof"
);
// empty step with valid signature from incorrect proposer for step
engine.set_signer(tap.clone(), addr1, "1".into());
let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())];
header.set_seal(vec![
encode(&2usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
]);
set_empty_steps_seal(&mut header, 2, &signature, &empty_steps);
assert!(match engine.verify_block_family(&header, &parent_header) {
Err(Error(ErrorKind::Engine(EngineError::InsufficientProof(ref s)), _))
if s.contains("invalid empty step proof") => true,
_ => false,
});
assert_insufficient_proof(
engine.verify_block_family(&header, &parent_header),
"invalid empty step proof"
);
// valid empty steps
engine.set_signer(tap.clone(), addr1, "1".into());
@@ -2041,11 +2037,7 @@ mod tests {
let empty_steps = vec![empty_step2, empty_step3];
header.set_difficulty(calculate_score(0, 4, 2));
let signature = tap.sign(addr1, Some("1".into()), header.bare_hash()).unwrap();
header.set_seal(vec![
encode(&4usize).into_vec(),
encode(&(&*signature as &[u8])).into_vec(),
::rlp::encode_list(&empty_steps).into_vec(),
]);
set_empty_steps_seal(&mut header, 4, &signature, &empty_steps);
assert!(engine.verify_block_family(&header, &parent_header).is_ok());
}
@@ -2157,28 +2149,11 @@ mod tests {
#[test]
fn test_empty_steps() {
let last_benign = Arc::new(AtomicUsize::new(0));
let params = AuthorityRoundParams {
step_duration: 4,
start_step: Some(1),
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
validate_score_transition: 0,
validate_step_transition: 0,
immediate_transitions: true,
maximum_uncle_count_transition: 0,
maximum_uncle_count: 0,
empty_steps_transition: 0,
maximum_empty_steps: 10,
block_reward: Default::default(),
block_reward_contract_transition: 0,
block_reward_contract: Default::default(),
};
let mut c_params = ::spec::CommonParams::default();
c_params.gas_limit_bound_divisor = 5.into();
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
let engine = AuthorityRound::new(params, machine).unwrap();
let engine = aura(|p| {
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let parent_hash: H256 = 1.into();
let signature = H520::default();
@@ -2202,4 +2177,85 @@ mod tests {
assert_eq!(engine.empty_steps(0, 3, parent_hash), vec![]);
assert_eq!(engine.empty_steps(0, 4, parent_hash), vec![step(3)]);
}
#[test]
fn should_reject_duplicate_empty_steps() {
// given
let (_spec, tap, accounts) = setup_empty_steps();
let engine = aura(|p| {
p.validators = Box::new(SimpleList::new(accounts.clone()));
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let mut parent = Header::default();
parent.set_seal(vec![encode(&0usize)]);
let mut header = Header::default();
header.set_number(parent.number() + 1);
header.set_parent_hash(parent.hash());
header.set_author(accounts[0]);
// when
engine.set_signer(tap.clone(), accounts[1], "0".into());
let empty_steps = vec![
sealed_empty_step(&*engine, 1, &parent.hash()),
sealed_empty_step(&*engine, 1, &parent.hash()),
];
let step = 2;
let signature = tap.sign(accounts[0], Some("1".into()), header.bare_hash()).unwrap();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
header.set_difficulty(calculate_score(0, step, empty_steps.len()));
// then
assert_insufficient_proof(
engine.verify_block_family(&header, &parent),
"duplicate empty step"
);
}
#[test]
fn should_reject_empty_steps_out_of_order() {
// given
let (_spec, tap, accounts) = setup_empty_steps();
let engine = aura(|p| {
p.validators = Box::new(SimpleList::new(accounts.clone()));
p.step_duration = 4;
p.empty_steps_transition = 0;
p.maximum_empty_steps = 0;
});
let mut parent = Header::default();
parent.set_seal(vec![encode(&0usize)]);
let mut header = Header::default();
header.set_number(parent.number() + 1);
header.set_parent_hash(parent.hash());
header.set_author(accounts[0]);
// when
engine.set_signer(tap.clone(), accounts[1], "0".into());
let es1 = sealed_empty_step(&*engine, 1, &parent.hash());
engine.set_signer(tap.clone(), accounts[0], "1".into());
let es2 = sealed_empty_step(&*engine, 2, &parent.hash());
let mut empty_steps = vec![es2, es1];
let step = 3;
let signature = tap.sign(accounts[1], Some("0".into()), header.bare_hash()).unwrap();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
header.set_difficulty(calculate_score(0, step, empty_steps.len()));
// then make sure it's rejected because of the order
assert_insufficient_proof(
engine.verify_block_family(&header, &parent),
"unordered empty step"
);
// now try to fix the order
empty_steps.reverse();
set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
assert_eq!(engine.verify_block_family(&header, &parent).unwrap(), ());
}
}

View File

@@ -110,7 +110,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
if self.validators.contains(header.parent_hash(), author) {
// account should be pernamently unlocked, otherwise sealing will fail
if let Ok(signature) = self.sign(header.bare_hash()) {
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).into_vec()]);
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8]))]);
} else {
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
}
@@ -234,7 +234,7 @@ mod tests {
fn can_do_signature_verification_fail() {
let engine = new_test_authority().engine;
let mut header: Header = Header::default();
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
header.set_seal(vec![::rlp::encode(&H520::default())]);
let verify_result = engine.verify_block_external(&header);
assert!(verify_result.is_err());

View File

@@ -120,7 +120,7 @@ mod tests {
assert!(engine.verify_block_basic(&header).is_ok());
header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]);
header.set_seal(vec![::rlp::encode(&H520::default())]);
assert!(engine.verify_block_unordered(&header).is_ok());
}

View File

@@ -231,7 +231,7 @@ mod tests {
},
block_hash: Some(keccak("1")),
};
let raw_rlp = ::rlp::encode(&message).into_vec();
let raw_rlp = ::rlp::encode(&message);
let rlp = Rlp::new(&raw_rlp);
assert_eq!(Ok(message), rlp.as_val());
@@ -268,8 +268,8 @@ mod tests {
fn proposal_message() {
let mut header = Header::default();
let seal = vec![
::rlp::encode(&0u8).into_vec(),
::rlp::encode(&H520::default()).into_vec(),
::rlp::encode(&0u8),
::rlp::encode(&H520::default()),
Vec::new()
];

View File

@@ -407,9 +407,9 @@ impl Tendermint {
let precommits = self.votes.round_signatures(vote_step, &bh);
trace!(target: "engine", "Collected seal: {:?}", precommits);
let seal = vec![
::rlp::encode(&vote_step.view).into_vec(),
::rlp::encode(&vote_step.view),
::rlp::NULL_RLP.to_vec(),
::rlp::encode_list(&precommits).into_vec()
::rlp::encode_list(&precommits)
];
self.submit_seal(bh, seal);
self.votes.throw_out_old(&vote_step);
@@ -491,8 +491,8 @@ impl Engine<EthereumMachine> for Tendermint {
*self.proposal.write() = bh;
*self.proposal_parent.write() = header.parent_hash().clone();
Seal::Proposal(vec![
::rlp::encode(&view).into_vec(),
::rlp::encode(&signature).into_vec(),
::rlp::encode(&view),
::rlp::encode(&signature),
::rlp::EMPTY_LIST_RLP.to_vec()
])
} else {
@@ -520,7 +520,7 @@ impl Engine<EthereumMachine> for Tendermint {
self.broadcast_message(rlp.as_raw().to_vec());
if let Some(double) = self.votes.vote(message.clone(), sender) {
let height = message.vote_step.height as BlockNumber;
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double).into_vec());
self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double));
return Err(EngineError::DoubleVote(sender));
}
trace!(target: "engine", "Handling a valid {:?} from {}.", message, sender);
@@ -823,8 +823,8 @@ mod tests {
let vote_info = message_info_rlp(&VoteStep::new(header.number() as Height, view, Step::Propose), Some(header.bare_hash()));
let signature = tap.sign(*author, None, keccak(vote_info)).unwrap();
vec![
::rlp::encode(&view).into_vec(),
::rlp::encode(&H520::from(signature)).into_vec(),
::rlp::encode(&view),
::rlp::encode(&H520::from(signature)),
::rlp::EMPTY_LIST_RLP.to_vec()
]
}
@@ -928,7 +928,7 @@ mod tests {
let signature1 = tap.sign(proposer, None, keccak(&vote_info)).unwrap();
seal[1] = ::rlp::NULL_RLP.to_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
header.set_seal(seal.clone());
// One good signature is not enough.
@@ -940,7 +940,7 @@ mod tests {
let voter = insert_and_unlock(&tap, "0");
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
header.set_seal(seal.clone());
assert!(engine.verify_block_external(&header).is_ok());
@@ -948,7 +948,7 @@ mod tests {
let bad_voter = insert_and_unlock(&tap, "101");
let bad_signature = tap.sign(bad_voter, None, keccak(vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
header.set_seal(seal);
// One good and one bad signature.
@@ -1084,7 +1084,7 @@ mod tests {
let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap();
seal[1] = ::rlp::NULL_RLP.to_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]);
header.set_seal(seal.clone());
let epoch_verifier = super::EpochVerifier {
@@ -1112,7 +1112,7 @@ mod tests {
_ => panic!(),
}
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]);
header.set_seal(seal.clone());
assert!(epoch_verifier.verify_light(&header).is_ok());
@@ -1120,7 +1120,7 @@ mod tests {
let bad_voter = insert_and_unlock(&tap, "101");
let bad_signature = tap.sign(bad_voter, None, keccak(&vote_info)).unwrap();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec();
seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]);
header.set_seal(seal);
// One good and one bad signature.

View File

@@ -174,7 +174,7 @@ mod tests {
// Check a block that is a bit in future, reject it but don't report the validator.
let mut header = Header::default();
let seal = vec![encode(&4u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
let seal = vec![encode(&4u8), encode(&(&H520::default() as &[u8]))];
header.set_seal(seal);
header.set_author(v1);
header.set_number(2);
@@ -185,7 +185,7 @@ mod tests {
// Now create one that is more in future. That one should be rejected and validator should be reported.
let mut header = Header::default();
let seal = vec![encode(&8u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()];
let seal = vec![encode(&8u8), encode(&(&H520::default() as &[u8]))];
header.set_seal(seal);
header.set_author(v1);
header.set_number(2);

View File

@@ -158,7 +158,7 @@ fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Erro
fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes {
let mut stream = RlpStream::new_list(2);
stream.append(header).append_list(receipts);
stream.drain().into_vec()
stream.drain()
}
fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {

View File

@@ -34,12 +34,18 @@ pub struct TestSet {
last_benign: Arc<AtomicUsize>,
}
impl Default for TestSet {
fn default() -> Self {
TestSet::new(Default::default(), Default::default())
}
}
impl TestSet {
pub fn new(last_malicious: Arc<AtomicUsize>, last_benign: Arc<AtomicUsize>) -> Self {
TestSet {
validator: SimpleList::new(vec![Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap()]),
last_malicious: last_malicious,
last_benign: last_benign,
last_malicious,
last_benign,
}
}
}

View File

@@ -681,7 +681,7 @@ mod tests {
fn can_do_difficulty_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
let verify_result = engine.verify_block_basic(&header);
@@ -696,7 +696,7 @@ mod tests {
fn can_do_proof_of_work_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
let verify_result = engine.verify_block_basic(&header);
@@ -737,7 +737,7 @@ mod tests {
fn can_do_seal256_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::zero()), rlp::encode(&H64::zero())]);
let verify_result = engine.verify_block_unordered(&header);
match verify_result {
@@ -751,7 +751,7 @@ mod tests {
fn can_do_proof_of_work_unordered_verification_fail() {
let engine = test_spec().engine;
let mut header: Header = Header::default();
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap());
let verify_result = engine.verify_block_unordered(&header);
@@ -944,7 +944,7 @@ mod tests {
let tempdir = TempDir::new("").unwrap();
let ethash = Ethash::new(tempdir.path(), ethparams, machine, None);
let mut header = Header::default();
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]);
header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")), rlp::encode(&H64::zero())]);
let info = ethash.extra_info(&header);
assert_eq!(info["nonce"], "0x0000000000000000");
assert_eq!(info["mixHash"], "0xb251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d");

View File

@@ -449,7 +449,7 @@ mod tests {
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
let encoded_header = rlp::encode(&header).into_vec();
let encoded_header = rlp::encode(&header);
assert_eq!(header_rlp, encoded_header);
}

View File

@@ -20,6 +20,7 @@ use ethtrie::RlpCodec;
use ethereum_types::H256;
use memorydb::MemoryDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use super::HookType;
@@ -36,7 +37,7 @@ fn test_trie<H: FnMut(&str, HookType)>(json: &[u8], trie: TrieSpec, start_stop_h
for (name, test) in tests.into_iter() {
start_stop_hook(&name, HookType::OnStart);
let mut memdb = MemoryDB::<KeccakHasher>::new();
let mut memdb = MemoryDB::<KeccakHasher, DBValue>::new();
let mut root = H256::default();
let mut t = factory.create(&mut memdb, &mut root);

View File

@@ -50,7 +50,7 @@ use executive::contract_address;
use header::{Header, BlockNumber};
use miner;
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
use receipt::{Receipt, RichReceipt};
use receipt::RichReceipt;
use spec::Spec;
use state::State;
use ethkey::Password;
@@ -1039,19 +1039,17 @@ impl miner::MinerService for Miner {
self.transaction_queue.status()
}
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>> {
self.map_existing_pending_block(|pending| {
let txs = pending.transactions();
txs.iter()
.map(|t| t.hash())
.position(|t| t == *hash)
.map(|index| {
let receipts = pending.receipts();
let receipts = pending.receipts();
pending.transactions()
.into_iter()
.enumerate()
.map(|(index, tx)| {
let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used };
let tx = &txs[index];
let receipt = &receipts[index];
RichReceipt {
transaction_hash: hash.clone(),
transaction_hash: tx.hash(),
transaction_index: index,
cumulative_gas_used: receipt.gas_used,
gas_used: receipt.gas_used - prev_gas,
@@ -1067,15 +1065,7 @@ impl miner::MinerService for Miner {
outcome: receipt.outcome.clone(),
}
})
}, best_block).and_then(|x| x)
}
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>> {
self.map_existing_pending_block(|pending| {
let hashes = pending.transactions().iter().map(|t| t.hash());
let receipts = pending.receipts().iter().cloned();
hashes.zip(receipts).collect()
.collect()
}, best_block)
}

View File

@@ -44,7 +44,7 @@ use client::{
};
use error::Error;
use header::{BlockNumber, Header};
use receipt::{RichReceipt, Receipt};
use receipt::RichReceipt;
use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction};
use state::StateInfo;
use ethkey::Password;
@@ -95,10 +95,13 @@ pub trait MinerService : Send + Sync {
// Pending block
/// Get a list of all pending receipts from pending block.
fn pending_receipts(&self, best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>>;
fn pending_receipts(&self, best_block: BlockNumber) -> Option<Vec<RichReceipt>>;
/// Get a particular receipt from pending block.
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt>;
fn pending_receipt(&self, best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
let receipts = self.pending_receipts(best_block)?;
receipts.into_iter().find(|r| &r.transaction_hash == hash)
}
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
fn pending_state(&self, latest_block_number: BlockNumber) -> Option<Self::State>;

View File

@@ -138,7 +138,7 @@ impl JobDispatcher for StratumJobDispatcher {
);
self.with_core_result(|client, miner| {
let seal = vec![encode(&payload.mix_hash).into_vec(), encode(&payload.nonce).into_vec()];
let seal = vec![encode(&payload.mix_hash), encode(&payload.nonce)];
let import = miner.submit_seal(payload.pow_hash, seal)
.and_then(|block| client.import_sealed_block(block));

View File

@@ -20,6 +20,7 @@ use itertools::Itertools;
use hash::{keccak};
use ethereum_types::{H256, U256};
use hashdb::HashDB;
use kvdb::DBValue;
use keccak_hasher::KeccakHasher;
use triehash::sec_trie_root;
use bytes::Bytes;
@@ -67,7 +68,7 @@ impl PodAccount {
}
/// Place additional data into given hash DB.
pub fn insert_additional(&self, db: &mut HashDB<KeccakHasher>, factory: &TrieFactory<KeccakHasher, RlpCodec>) {
pub fn insert_additional(&self, db: &mut HashDB<KeccakHasher, DBValue>, factory: &TrieFactory<KeccakHasher, RlpCodec>) {
match self.code {
Some(ref c) if !c.is_empty() => { db.insert(c); }
_ => {}

View File

@@ -123,7 +123,7 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB,
let stream = ::std::mem::replace(&mut account_stream, RlpStream::new_list(2));
chunks.push(stream.out());
target_chunk_size = max_chunk_size;
leftover = Some(pair.into_vec());
leftover = Some(pair);
break;
}
},

View File

@@ -34,12 +34,11 @@ use ids::BlockId;
use ethereum_types::{H256, U256};
use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use kvdb::DBValue;
use snappy;
use bytes::Bytes;
use parking_lot::Mutex;
use journaldb::{self, Algorithm, JournalDB};
use kvdb::KeyValueDB;
use kvdb::{KeyValueDB, DBValue};
use trie::{Trie, TrieMut};
use ethtrie::{TrieDB, TrieDBMut};
use rlp::{RlpStream, Rlp};
@@ -152,7 +151,7 @@ pub fn take_snapshot<W: SnapshotWriter + Send>(
engine: &EthEngine,
chain: &BlockChain,
block_at: H256,
state_db: &HashDB<KeccakHasher>,
state_db: &HashDB<KeccakHasher, DBValue>,
writer: W,
p: &Progress,
processing_threads: usize,
@@ -322,7 +321,7 @@ impl<'a> StateChunker<'a> {
///
/// Returns a list of hashes of chunks created, or any error it may
/// have encountered.
pub fn chunk_state<'a>(db: &HashDB<KeccakHasher>, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress, part: Option<usize>) -> Result<Vec<H256>, Error> {
pub fn chunk_state<'a>(db: &HashDB<KeccakHasher, DBValue>, root: &H256, writer: &Mutex<SnapshotWriter + 'a>, progress: &'a Progress, part: Option<usize>) -> Result<Vec<H256>, Error> {
let account_trie = TrieDB::new(db, &root)?;
let mut chunker = StateChunker {
@@ -494,7 +493,7 @@ struct RebuiltStatus {
// rebuild a set of accounts and their storage.
// returns a status detailing newly-loaded code and accounts missing code.
fn rebuild_accounts(
db: &mut HashDB<KeccakHasher>,
db: &mut HashDB<KeccakHasher, DBValue>,
account_fat_rlps: Rlp,
out_chunk: &mut [(H256, Bytes)],
known_code: &HashMap<H256, H256>,
@@ -541,7 +540,7 @@ fn rebuild_accounts(
}
}
::rlp::encode(&acc).into_vec()
::rlp::encode(&acc)
};
*out = (hash, thin_rlp);

View File

@@ -62,7 +62,7 @@ impl StateProducer {
/// Tick the state producer. This alters the state, writing new data into
/// the database.
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB<KeccakHasher>) {
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB<KeccakHasher, DBValue>) {
// modify existing accounts.
let mut accounts_to_modify: Vec<_> = {
let trie = TrieDB::new(&*db, &self.state_root).unwrap();
@@ -80,7 +80,7 @@ impl StateProducer {
let mut account: BasicAccount = ::rlp::decode(&*account_data).expect("error decoding basic account");
let acct_db = AccountDBMut::from_hash(db, *address_hash);
fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed);
*account_data = DBValue::from_vec(::rlp::encode(&account).into_vec());
*account_data = DBValue::from_vec(::rlp::encode(&account));
}
// sweep again to alter account trie.
@@ -131,7 +131,7 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) {
}
/// Compare two state dbs.
pub fn compare_dbs(one: &HashDB<KeccakHasher>, two: &HashDB<KeccakHasher>) {
pub fn compare_dbs(one: &HashDB<KeccakHasher, DBValue>, two: &HashDB<KeccakHasher, DBValue>) {
let keys = one.keys();
for key in keys.keys() {

View File

@@ -213,7 +213,7 @@ impl Account {
/// Get (and cache) the contents of the trie's storage at `key`.
/// Takes modified storage into account.
pub fn storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
pub fn storage_at(&self, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
if let Some(value) = self.cached_storage_at(key) {
return Ok(value);
}
@@ -226,7 +226,7 @@ impl Account {
/// Get (and cache) the contents of the trie's storage at `key`.
/// Does not take modified storage into account.
pub fn original_storage_at(&self, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
pub fn original_storage_at(&self, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
if let Some(value) = self.cached_original_storage_at(key) {
return Ok(value);
}
@@ -248,7 +248,7 @@ impl Account {
}
}
fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache<H256, H256>, db: &HashDB<KeccakHasher>, key: &H256) -> TrieResult<H256> {
fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache<H256, H256>, db: &HashDB<KeccakHasher, DBValue>, key: &H256) -> TrieResult<H256> {
let db = SecTrieDB::new(db, storage_root)?;
let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed");
let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero);
@@ -354,7 +354,7 @@ impl Account {
/// Provide a database to get `code_hash`. Should not be called if it is a contract without code. Returns the cached code, if successful.
#[must_use]
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher>) -> Option<Arc<Bytes>> {
pub fn cache_code(&mut self, db: &HashDB<KeccakHasher, DBValue>) -> Option<Arc<Bytes>> {
// TODO: fill out self.code_cache;
trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
@@ -384,7 +384,7 @@ impl Account {
/// Provide a database to get `code_size`. Should not be called if it is a contract without code. Returns whether
/// the cache succeeds.
#[must_use]
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher>) -> bool {
pub fn cache_code_size(&mut self, db: &HashDB<KeccakHasher, DBValue>) -> bool {
// TODO: fill out self.code_cache;
trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty());
self.code_size.is_some() ||
@@ -473,7 +473,7 @@ impl Account {
}
/// Commit the `storage_changes` to the backing DB and update `storage_root`.
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB<KeccakHasher>) -> TrieResult<()> {
pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB<KeccakHasher, DBValue>) -> TrieResult<()> {
let mut t = trie_factory.from_existing(db, &mut self.storage_root)?;
for (k, v) in self.storage_changes.drain() {
// cast key and value to trait type,
@@ -490,7 +490,7 @@ impl Account {
}
/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
pub fn commit_code(&mut self, db: &mut HashDB<KeccakHasher>) {
pub fn commit_code(&mut self, db: &mut HashDB<KeccakHasher, DBValue>) {
trace!("Commiting code of {:?} - {:?}, {:?}", self, self.code_filth == Filth::Dirty, self.code_cache.is_empty());
match (self.code_filth == Filth::Dirty, self.code_cache.is_empty()) {
(true, true) => {
@@ -579,7 +579,7 @@ impl Account {
/// trie.
/// `storage_key` is the hash of the desired storage key, meaning
/// this will only work correctly under a secure trie.
pub fn prove_storage(&self, db: &HashDB<KeccakHasher>, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
pub fn prove_storage(&self, db: &HashDB<KeccakHasher, DBValue>, storage_key: H256) -> TrieResult<(Vec<Bytes>, H256)> {
let mut recorder = Recorder::new();
let trie = TrieDB::new(db, &self.storage_root)?;

View File

@@ -28,16 +28,17 @@ use state::Account;
use parking_lot::Mutex;
use ethereum_types::{Address, H256};
use memorydb::MemoryDB;
use hashdb::{AsHashDB, HashDB, DBValue};
use hashdb::{AsHashDB, HashDB};
use kvdb::DBValue;
use keccak_hasher::KeccakHasher;
/// State backend. See module docs for more details.
pub trait Backend: Send {
/// Treat the backend as a read-only hashdb.
fn as_hashdb(&self) -> &HashDB<KeccakHasher>;
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue>;
/// Treat the backend as a writeable hashdb.
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher>;
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue>;
/// Add an account entry to the cache.
fn add_to_account_cache(&mut self, addr: Address, data: Option<Account>, modified: bool);
@@ -76,18 +77,18 @@ pub trait Backend: Send {
// TODO: when account lookup moved into backends, this won't rely as tenuously on intended
// usage.
#[derive(Clone, PartialEq)]
pub struct ProofCheck(MemoryDB<KeccakHasher>);
pub struct ProofCheck(MemoryDB<KeccakHasher, DBValue>);
impl ProofCheck {
/// Create a new `ProofCheck` backend from the given state items.
pub fn new(proof: &[DBValue]) -> Self {
let mut db = MemoryDB::<KeccakHasher>::new();
let mut db = MemoryDB::<KeccakHasher, DBValue>::new();
for item in proof { db.insert(item); }
ProofCheck(db)
}
}
impl HashDB<KeccakHasher> for ProofCheck {
impl HashDB<KeccakHasher, DBValue> for ProofCheck {
fn keys(&self) -> HashMap<H256, i32> { self.0.keys() }
fn get(&self, key: &H256) -> Option<DBValue> {
self.0.get(key)
@@ -108,14 +109,14 @@ impl HashDB<KeccakHasher> for ProofCheck {
fn remove(&mut self, _key: &H256) { }
}
impl AsHashDB<KeccakHasher> for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl AsHashDB<KeccakHasher, DBValue> for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl Backend for ProofCheck {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn add_to_account_cache(&mut self, _addr: Address, _data: Option<Account>, _modified: bool) {}
fn cache_code(&self, _hash: H256, _code: Arc<Vec<u8>>) {}
fn get_cached_account(&self, _addr: &Address) -> Option<Option<Account>> { None }
@@ -134,18 +135,18 @@ impl Backend for ProofCheck {
/// The proof-of-execution can be extracted with `extract_proof`.
///
/// This doesn't cache anything or rely on the canonical state caches.
pub struct Proving<H: AsHashDB<KeccakHasher>> {
pub struct Proving<H: AsHashDB<KeccakHasher, DBValue>> {
base: H, // state we're proving values from.
changed: MemoryDB<KeccakHasher>, // changed state via insertions.
changed: MemoryDB<KeccakHasher, DBValue>, // changed state via insertions.
proof: Mutex<HashSet<DBValue>>,
}
impl<AH: AsHashDB<KeccakHasher> + Send + Sync> AsHashDB<KeccakHasher> for Proving<AH> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
impl<AH: AsHashDB<KeccakHasher, DBValue> + Send + Sync> AsHashDB<KeccakHasher, DBValue> for Proving<AH> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
}
impl<H: AsHashDB<KeccakHasher> + Send + Sync> HashDB<KeccakHasher> for Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> HashDB<KeccakHasher, DBValue> for Proving<H> {
fn keys(&self) -> HashMap<H256, i32> {
let mut keys = self.base.as_hashdb().keys();
keys.extend(self.changed.keys());
@@ -182,10 +183,10 @@ impl<H: AsHashDB<KeccakHasher> + Send + Sync> HashDB<KeccakHasher> for Proving<H
}
}
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Proving<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self }
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> Backend for Proving<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> { self }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> { self }
fn add_to_account_cache(&mut self, _: Address, _: Option<Account>, _: bool) { }
@@ -204,13 +205,13 @@ impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Proving<H> {
fn is_known_null(&self, _: &Address) -> bool { false }
}
impl<H: AsHashDB<KeccakHasher>> Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue>> Proving<H> {
/// Create a new `Proving` over a base database.
/// This will store all values ever fetched from that base.
pub fn new(base: H) -> Self {
Proving {
base: base,
changed: MemoryDB::<KeccakHasher>::new(),
changed: MemoryDB::<KeccakHasher, DBValue>::new(),
proof: Mutex::new(HashSet::new()),
}
}
@@ -222,7 +223,7 @@ impl<H: AsHashDB<KeccakHasher>> Proving<H> {
}
}
impl<H: AsHashDB<KeccakHasher> + Clone> Clone for Proving<H> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Clone> Clone for Proving<H> {
fn clone(&self) -> Self {
Proving {
base: self.base.clone(),
@@ -236,12 +237,12 @@ impl<H: AsHashDB<KeccakHasher> + Clone> Clone for Proving<H> {
/// it. Doesn't cache anything.
pub struct Basic<H>(pub H);
impl<H: AsHashDB<KeccakHasher> + Send + Sync> Backend for Basic<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
impl<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync> Backend for Basic<H> {
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> {
self.0.as_hashdb()
}
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.0.as_hashdb_mut()
}

View File

@@ -227,7 +227,7 @@ pub fn check_proof(
/// Prove a `virtual` transaction on the given state.
/// Returns `None` when the transacion could not be proved,
/// and a proof otherwise.
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher> + Send + Sync>(
pub fn prove_transaction_virtual<H: AsHashDB<KeccakHasher, DBValue> + Send + Sync>(
db: H,
root: H256,
transaction: &SignedTransaction,
@@ -618,7 +618,7 @@ impl<B: Backend> State<B> {
&self, address: &Address, key: &H256, f_cached_at: FCachedStorageAt, f_at: FStorageAt,
) -> TrieResult<H256> where
FCachedStorageAt: Fn(&Account, &H256) -> Option<H256>,
FStorageAt: Fn(&Account, &HashDB<KeccakHasher>, &H256) -> TrieResult<H256>
FStorageAt: Fn(&Account, &HashDB<KeccakHasher, DBValue>, &H256) -> TrieResult<H256>
{
// Storage key search and update works like this:
// 1. If there's an entry for the account in the local cache check for the key and return it if found.
@@ -1014,7 +1014,7 @@ impl<B: Backend> State<B> {
/// Load required account data from the databases. Returns whether the cache succeeds.
#[must_use]
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher>) -> bool {
fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB<KeccakHasher, DBValue>) -> bool {
if let RequireCache::None = require {
return true;
}

View File

@@ -29,7 +29,7 @@ use hashdb::HashDB;
use keccak_hasher::KeccakHasher;
use header::BlockNumber;
use journaldb::JournalDB;
use kvdb::{KeyValueDB, DBTransaction};
use kvdb::{KeyValueDB, DBTransaction, DBValue};
use lru_cache::LruCache;
use memory_cache::MemoryLruCache;
use parking_lot::Mutex;
@@ -312,12 +312,12 @@ impl StateDB {
}
/// Conversion method to interpret self as `HashDB` reference
pub fn as_hashdb(&self) -> &HashDB<KeccakHasher> {
pub fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb()
}
/// Conversion method to interpret self as mutable `HashDB` reference
pub fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
pub fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb_mut()
}
@@ -412,9 +412,9 @@ impl StateDB {
}
impl state::Backend for StateDB {
fn as_hashdb(&self) -> &HashDB<KeccakHasher> { self.db.as_hashdb() }
fn as_hashdb(&self) -> &HashDB<KeccakHasher, DBValue> { self.db.as_hashdb() }
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher> {
fn as_hashdb_mut(&mut self) -> &mut HashDB<KeccakHasher, DBValue> {
self.db.as_hashdb_mut()
}

View File

@@ -90,7 +90,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransa
rlp.append(header);
rlp.begin_list(transactions.len());
for t in transactions {
rlp.append_raw(&rlp::encode(t).into_vec(), 1);
rlp.append_raw(&rlp::encode(t), 1);
}
rlp.append_list(&uncles);
rlp.out()

View File

@@ -38,9 +38,9 @@ impl<'a> BodyView<'a> {
/// ```
/// #[macro_use]
/// extern crate ethcore;
///
///
/// use ethcore::views::{BodyView};
///
///
/// fn main() {
/// let bytes : &[u8] = &[];
/// let body_view = view!(BodyView, bytes);