Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into refactor/hashdb-generic
Browse files Browse the repository at this point in the history
* master:
  Fix subcrate test compile (#8862)
  network-devp2p: downgrade logging to debug, add target (#8784)
  Clearing up a comment about the prefix for signing (#8828)
  Disable parallel verification and skip verifiying already imported txs. (#8834)
  devp2p: Move UDP socket handling from Discovery to Host. (#8790)
  Fixed AuthorityRound deadlock on shutdown, closes #8088 (#8803)
  Specify critical release flag per network (#8821)
  Fix `deadlock_detection` feature branch compilation (#8824)
  Use system allocator when profiling memory (#8831)
  added from and to to Receipt (#8756)
  • Loading branch information
dvdplm committed Jun 11, 2018
2 parents 494e58f + 09ee6e1 commit 6f48370
Show file tree
Hide file tree
Showing 26 changed files with 301 additions and 166 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ slow-blocks = ["ethcore/slow-blocks"]
secretstore = ["ethcore-secretstore"]
final = ["parity-version/final"]
deadlock_detection = ["parking_lot/deadlock_detection"]
# to create a memory profile (requires nightly rust), use e.g.
# `heaptrack /path/to/parity <parity params>`,
# to visualize a memory profile, use `heaptrack_gui`
# or
# `valgrind --tool=massif /path/to/parity <parity params>`
# and `massif-visualizer` for visualization
memory_profiling = []

[lib]
path = "parity/lib.rs"
Expand Down
1 change: 1 addition & 0 deletions ethcore/light/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ memory-cache = { path = "../../util/memory_cache" }
error-chain = { version = "0.11", default-features = false }

[dev-dependencies]
ethcore = { path = "..", features = ["test-helpers"] }
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
tempdir = "0.3"

Expand Down
1 change: 1 addition & 0 deletions ethcore/node_filter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ethabi-contract = "5.0"
lru-cache = "0.1"

[dev-dependencies]
ethcore = { path = "..", features = ["test-helpers"] }
kvdb-memorydb = { path = "../../util/kvdb-memorydb" }
ethcore-io = { path = "../../util/io" }
tempdir = "0.3"
1 change: 1 addition & 0 deletions ethcore/service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ stop-guard = { path = "../../util/stop-guard" }
trace-time = { path = "../../util/trace-time" }

[dev-dependencies]
ethcore = { path = "..", features = ["test-helpers"] }
tempdir = "0.3"
kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" }
10 changes: 10 additions & 0 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,11 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr
let transaction_index = tx.transaction_index;

LocalizedReceipt {
from: sender,
to: match tx.action {
Action::Create => None,
Action::Call(ref address) => Some(address.clone().into())
},
transaction_hash: transaction_hash,
transaction_index: transaction_index,
block_hash: block_hash,
Expand Down Expand Up @@ -2464,6 +2469,11 @@ mod tests {

// then
assert_eq!(receipt, LocalizedReceipt {
from: tx1.sender().into(),
to: match tx1.action {
Action::Create => None,
Action::Call(ref address) => Some(address.clone().into())
},
transaction_hash: tx1.hash(),
transaction_index: 1,
block_hash: block_hash,
Expand Down
90 changes: 51 additions & 39 deletions ethcore/src/engines/authority_round/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,12 +382,16 @@ impl Decodable for SealedEmptyStep {
}
}

struct PermissionedStep {
inner: Step,
can_propose: AtomicBool,
}

/// Engine using `AuthorityRound` proof-of-authority BFT consensus.
pub struct AuthorityRound {
transition_service: IoService<()>,
step: Arc<Step>,
can_propose: AtomicBool,
client: RwLock<Option<Weak<EngineClient>>>,
step: Arc<PermissionedStep>,
client: Arc<RwLock<Option<Weak<EngineClient>>>>,
signer: RwLock<EngineSigner>,
validators: Box<ValidatorSet>,
validate_score_transition: u64,
Expand All @@ -407,15 +411,15 @@ pub struct AuthorityRound {

// header-chain validator.
struct EpochVerifier {
step: Arc<Step>,
step: Arc<PermissionedStep>,
subchain_validators: SimpleList,
empty_steps_transition: u64,
}

impl super::EpochVerifier<EthereumMachine> for EpochVerifier {
fn verify_light(&self, header: &Header) -> Result<(), Error> {
// Validate the timestamp
verify_timestamp(&*self.step, header_step(header, self.empty_steps_transition)?)?;
verify_timestamp(&self.step.inner, header_step(header, self.empty_steps_transition)?)?;
// always check the seal since it's fast.
// nothing heavier to do.
verify_external(header, &self.subchain_validators, self.empty_steps_transition)
Expand Down Expand Up @@ -615,13 +619,15 @@ impl AuthorityRound {
let engine = Arc::new(
AuthorityRound {
transition_service: IoService::<()>::start()?,
step: Arc::new(Step {
inner: AtomicUsize::new(initial_step),
calibrate: our_params.start_step.is_none(),
duration: our_params.step_duration,
step: Arc::new(PermissionedStep {
inner: Step {
inner: AtomicUsize::new(initial_step),
calibrate: our_params.start_step.is_none(),
duration: our_params.step_duration,
},
can_propose: AtomicBool::new(true),
}),
can_propose: AtomicBool::new(true),
client: RwLock::new(None),
client: Arc::new(RwLock::new(None)),
signer: Default::default(),
validators: our_params.validators,
validate_score_transition: our_params.validate_score_transition,
Expand All @@ -641,7 +647,10 @@ impl AuthorityRound {

// Do not initialize timeouts for tests.
if should_timeout {
let handler = TransitionHandler { engine: Arc::downgrade(&engine) };
let handler = TransitionHandler {
step: engine.step.clone(),
client: engine.client.clone(),
};
engine.transition_service.register_handler(Arc::new(handler))?;
}
Ok(engine)
Expand All @@ -666,7 +675,7 @@ impl AuthorityRound {
}

fn generate_empty_step(&self, parent_hash: &H256) {
let step = self.step.load();
let step = self.step.inner.load();
let empty_step_rlp = empty_step_rlp(step, parent_hash);

if let Ok(signature) = self.sign(keccak(&empty_step_rlp)).map(Into::into) {
Expand Down Expand Up @@ -698,34 +707,37 @@ fn unix_now() -> Duration {
}

struct TransitionHandler {
engine: Weak<AuthorityRound>,
step: Arc<PermissionedStep>,
client: Arc<RwLock<Option<Weak<EngineClient>>>>,
}

const ENGINE_TIMEOUT_TOKEN: TimerToken = 23;

impl IoHandler<()> for TransitionHandler {
fn initialize(&self, io: &IoContext<()>) {
if let Some(engine) = self.engine.upgrade() {
let remaining = engine.step.duration_remaining().as_millis();
io.register_timer_once(ENGINE_TIMEOUT_TOKEN, Duration::from_millis(remaining))
.unwrap_or_else(|e| warn!(target: "engine", "Failed to start consensus step timer: {}.", e))
}
let remaining = self.step.inner.duration_remaining().as_millis();
io.register_timer_once(ENGINE_TIMEOUT_TOKEN, Duration::from_millis(remaining))
.unwrap_or_else(|e| warn!(target: "engine", "Failed to start consensus step timer: {}.", e))
}

fn timeout(&self, io: &IoContext<()>, timer: TimerToken) {
if timer == ENGINE_TIMEOUT_TOKEN {
if let Some(engine) = self.engine.upgrade() {
// NOTE we might be lagging by couple of steps in case the timeout
// has not been called fast enough.
// Make sure to advance up to the actual step.
while engine.step.duration_remaining().as_millis() == 0 {
engine.step();
// NOTE we might be lagging by couple of steps in case the timeout
// has not been called fast enough.
// Make sure to advance up to the actual step.
while self.step.inner.duration_remaining().as_millis() == 0 {
self.step.inner.increment();
self.step.can_propose.store(true, AtomicOrdering::SeqCst);
if let Some(ref weak) = *self.client.read() {
if let Some(c) = weak.upgrade() {
c.update_sealing();
}
}

let next_run_at = engine.step.duration_remaining().as_millis() >> 2;
io.register_timer_once(ENGINE_TIMEOUT_TOKEN, Duration::from_millis(next_run_at))
.unwrap_or_else(|e| warn!(target: "engine", "Failed to restart consensus step timer: {}.", e))
}

let next_run_at = self.step.inner.duration_remaining().as_millis() >> 2;
io.register_timer_once(ENGINE_TIMEOUT_TOKEN, Duration::from_millis(next_run_at))
.unwrap_or_else(|e| warn!(target: "engine", "Failed to restart consensus step timer: {}.", e))
}
}
}
Expand All @@ -742,8 +754,8 @@ impl Engine<EthereumMachine> for AuthorityRound {
}

fn step(&self) {
self.step.increment();
self.can_propose.store(true, AtomicOrdering::SeqCst);
self.step.inner.increment();
self.step.can_propose.store(true, AtomicOrdering::SeqCst);
if let Some(ref weak) = *self.client.read() {
if let Some(c) = weak.upgrade() {
c.update_sealing();
Expand Down Expand Up @@ -790,7 +802,7 @@ impl Engine<EthereumMachine> for AuthorityRound {

fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
let parent_step = header_step(parent, self.empty_steps_transition).expect("Header has been verified; qed");
let current_step = self.step.load();
let current_step = self.step.inner.load();

let current_empty_steps_len = if header.number() >= self.empty_steps_transition {
self.empty_steps(parent_step.into(), current_step.into(), parent.hash()).len()
Expand All @@ -816,7 +828,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
let empty_step: EmptyStep = rlp.as_val().map_err(fmt_err)?;;

if empty_step.verify(&*self.validators).unwrap_or(false) {
if self.step.check_future(empty_step.step).is_ok() {
if self.step.inner.check_future(empty_step.step).is_ok() {
trace!(target: "engine", "handle_message: received empty step message {:?}", empty_step);
self.handle_empty_step_message(empty_step);
} else {
Expand All @@ -836,7 +848,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal {
// first check to avoid generating signature most of the time
// (but there's still a race to the `compare_and_swap`)
if !self.can_propose.load(AtomicOrdering::SeqCst) {
if !self.step.can_propose.load(AtomicOrdering::SeqCst) {
trace!(target: "engine", "Aborting seal generation. Can't propose.");
return Seal::None;
}
Expand All @@ -845,7 +857,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
let parent_step: U256 = header_step(parent, self.empty_steps_transition)
.expect("Header has been verified; qed").into();

let step = self.step.load();
let step = self.step.inner.load();

// filter messages from old and future steps and different parents
let empty_steps = if header.number() >= self.empty_steps_transition {
Expand Down Expand Up @@ -922,7 +934,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step);

// only issue the seal if we were the first to reach the compare_and_swap.
if self.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {

self.clear_empty_steps(parent_step);

Expand Down Expand Up @@ -999,7 +1011,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
.decode()?;

let parent_step = header_step(&parent, self.empty_steps_transition)?;
let current_step = self.step.load();
let current_step = self.step.inner.load();
self.empty_steps(parent_step.into(), current_step.into(), parent.hash())
} else {
// we're verifying a block, extract empty steps from the seal
Expand Down Expand Up @@ -1052,7 +1064,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
// If yes then probably benign reporting needs to be moved further in the verification.
let set_number = header.number();

match verify_timestamp(&*self.step, header_step(header, self.empty_steps_transition)?) {
match verify_timestamp(&self.step.inner, header_step(header, self.empty_steps_transition)?) {
Err(BlockError::InvalidSeal) => {
self.validators.report_benign(header.author(), set_number, header.number());
Err(BlockError::InvalidSeal.into())
Expand Down Expand Up @@ -1294,7 +1306,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
// This way, upon encountering an epoch change, the proposer from the
// new set will be forced to wait until the next step to avoid sealing a
// block that breaks the invariant that the parent's step < the block's step.
self.can_propose.store(false, AtomicOrdering::SeqCst);
self.step.can_propose.store(false, AtomicOrdering::SeqCst);
return Some(combine_proofs(signal_number, &pending.proof, &*finality_proof));
}
}
Expand Down
6 changes: 5 additions & 1 deletion ethcore/types/src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Receipt

use ethereum_types::{H256, U256, Address, Bloom};
use ethereum_types::{H160, H256, U256, Address, Bloom};
use heapsize::HeapSizeOf;
use rlp::{Rlp, RlpStream, Encodable, Decodable, DecoderError};

Expand Down Expand Up @@ -157,6 +157,10 @@ pub struct LocalizedReceipt {
pub log_bloom: Bloom,
/// Transaction outcome.
pub outcome: TransactionOutcome,
/// Receiver address
pub to: Option<H160>,
/// Sender
pub from: H160
}

#[cfg(test)]
Expand Down
3 changes: 3 additions & 0 deletions ipfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ rlp = { path = "../util/rlp" }
cid = "0.2"
multihash = "0.7"
unicase = "2.0"

[dev-dependencies]
ethcore = { path = "../ethcore", features = ["test-helpers"] }
1 change: 1 addition & 0 deletions local-store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ serde_derive = "1.0"
serde_json = "1.0"

[dev-dependencies]
ethcore = { path = "../ethcore", features = ["test-helpers"] }
ethkey = { path = "../ethkey" }
kvdb-memorydb = { path = "../util/kvdb-memorydb" }
1 change: 0 additions & 1 deletion miner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ linked-hash-map = "0.5"
log = "0.3"
parking_lot = "0.5"
price-info = { path = "../price-info" }
rayon = "1.0"
rlp = { path = "../util/rlp" }
trace-time = { path = "../util/trace-time" }
transaction-pool = { path = "../transaction-pool" }
Expand Down
1 change: 0 additions & 1 deletion miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ extern crate keccak_hash as hash;
extern crate linked_hash_map;
extern crate parking_lot;
extern crate price_info;
extern crate rayon;
extern crate rlp;
extern crate trace_time;
extern crate transaction_pool as txpool;
Expand Down
11 changes: 8 additions & 3 deletions miner/src/pool/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use std::collections::BTreeMap;

use ethereum_types::{H256, U256, Address};
use parking_lot::RwLock;
use rayon::prelude::*;
use transaction;
use txpool::{self, Verifier};

Expand Down Expand Up @@ -179,8 +178,14 @@ impl TransactionQueue {

let verifier = verifier::Verifier::new(client, options, self.insertion_id.clone());
let results = transactions
.into_par_iter()
.map(|transaction| verifier.verify_transaction(transaction))
.into_iter()
.map(|transaction| {
if self.pool.read().find(&transaction.hash()).is_some() {
bail!(transaction::Error::AlreadyImported)
}

verifier.verify_transaction(transaction)
})
.map(|result| result.and_then(|verified| {
self.pool.write().import(verified)
.map(|_imported| ())
Expand Down
Loading

0 comments on commit 6f48370

Please sign in to comment.