Merge branch 'master' into lightserv
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
"AuthorityRound": {
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"stepDuration": "1",
|
||||
"stepDuration": 1,
|
||||
"startStep": 2,
|
||||
"authorities" : [
|
||||
"0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e",
|
||||
"0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1"
|
||||
|
||||
@@ -255,6 +255,11 @@ impl Client {
|
||||
self.notify.write().push(Arc::downgrade(&target));
|
||||
}
|
||||
|
||||
/// Returns engine reference.
|
||||
pub fn engine(&self) -> &Engine {
|
||||
&*self.engine
|
||||
}
|
||||
|
||||
fn notify<F>(&self, f: F) where F: Fn(&ChainNotify) {
|
||||
for np in self.notify.read().iter() {
|
||||
if let Some(n) = np.upgrade() {
|
||||
@@ -563,6 +568,11 @@ impl Client {
|
||||
results.len()
|
||||
}
|
||||
|
||||
/// Get shared miner reference.
|
||||
pub fn miner(&self) -> Arc<Miner> {
|
||||
self.miner.clone()
|
||||
}
|
||||
|
||||
/// Used by PoA to try sealing on period change.
|
||||
pub fn update_sealing(&self) {
|
||||
self.miner.update_sealing(self)
|
||||
@@ -1060,6 +1070,10 @@ impl BlockChainClient for Client {
|
||||
self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address))
|
||||
}
|
||||
|
||||
fn transaction_block(&self, id: TransactionID) -> Option<H256> {
|
||||
self.transaction_address(id).map(|addr| addr.block_hash)
|
||||
}
|
||||
|
||||
fn uncle(&self, id: UncleID) -> Option<Bytes> {
|
||||
let index = id.position;
|
||||
self.block_body(id.block).and_then(|body| BodyView::new(&body).uncle_rlp_at(index))
|
||||
@@ -1433,4 +1447,4 @@ mod tests {
|
||||
|
||||
assert!(client.tree_route(&genesis, &new_hash).is_none());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ impl TestBlockChainClient {
|
||||
}
|
||||
|
||||
/// Make a bad block by setting invalid extra data.
|
||||
pub fn corrupt_block(&mut self, n: BlockNumber) {
|
||||
pub fn corrupt_block(&self, n: BlockNumber) {
|
||||
let hash = self.block_hash(BlockID::Number(n)).unwrap();
|
||||
let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap());
|
||||
header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec());
|
||||
@@ -267,7 +267,7 @@ impl TestBlockChainClient {
|
||||
}
|
||||
|
||||
/// Make a bad block by setting invalid parent hash.
|
||||
pub fn corrupt_block_parent(&mut self, n: BlockNumber) {
|
||||
pub fn corrupt_block_parent(&self, n: BlockNumber) {
|
||||
let hash = self.block_hash(BlockID::Number(n)).unwrap();
|
||||
let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap());
|
||||
header.set_parent_hash(H256::from(42));
|
||||
@@ -432,6 +432,10 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
fn transaction_block(&self, _id: TransactionID) -> Option<H256> {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
fn uncle(&self, _id: UncleID) -> Option<Bytes> {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
@@ -129,6 +129,9 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Get transaction with given hash.
|
||||
fn transaction(&self, id: TransactionID) -> Option<LocalizedTransaction>;
|
||||
|
||||
/// Get the hash of block that contains the transaction, if any.
|
||||
fn transaction_block(&self, id: TransactionID) -> Option<H256>;
|
||||
|
||||
/// Get uncle with given id.
|
||||
fn uncle(&self, id: UncleID) -> Option<Bytes>;
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ pub struct AuthorityRoundParams {
|
||||
pub authorities: Vec<Address>,
|
||||
/// Number of authorities.
|
||||
pub authority_n: usize,
|
||||
/// Starting step,
|
||||
pub start_step: Option<u64>,
|
||||
}
|
||||
|
||||
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
@@ -58,6 +60,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
step_duration: Duration::from_secs(p.step_duration.into()),
|
||||
authority_n: p.authorities.len(),
|
||||
authorities: p.authorities.into_iter().map(Into::into).collect::<Vec<_>>(),
|
||||
start_step: p.start_step.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +100,7 @@ impl AsMillis for Duration {
|
||||
impl AuthorityRound {
|
||||
/// Create a new instance of AuthorityRound engine.
|
||||
pub fn new(params: CommonParams, our_params: AuthorityRoundParams, builtins: BTreeMap<Address, Builtin>) -> Result<Arc<Self>, Error> {
|
||||
let initial_step = (unix_now().as_secs() / our_params.step_duration.as_secs()) as usize;
|
||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
|
||||
let engine = Arc::new(
|
||||
AuthorityRound {
|
||||
params: params,
|
||||
@@ -160,14 +163,7 @@ impl IoHandler<()> for TransitionHandler {
|
||||
fn timeout(&self, io: &IoContext<()>, timer: TimerToken) {
|
||||
if timer == ENGINE_TIMEOUT_TOKEN {
|
||||
if let Some(engine) = self.engine.upgrade() {
|
||||
engine.step.fetch_add(1, AtomicOrdering::SeqCst);
|
||||
engine.proposed.store(false, AtomicOrdering::SeqCst);
|
||||
if let Some(ref channel) = *engine.message_channel.lock() {
|
||||
match channel.send(ClientIoMessage::UpdateSealing) {
|
||||
Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", engine.step.load(AtomicOrdering::Relaxed)),
|
||||
Err(err) => trace!(target: "poa", "timeout: Could not send a sealing message {} for step {}.", err, engine.step.load(AtomicOrdering::Relaxed)),
|
||||
}
|
||||
}
|
||||
engine.step();
|
||||
io.register_timer_once(ENGINE_TIMEOUT_TOKEN, engine.remaining_step_duration().as_millis())
|
||||
.unwrap_or_else(|e| warn!(target: "poa", "Failed to restart consensus step timer: {}.", e))
|
||||
}
|
||||
@@ -184,6 +180,17 @@ impl Engine for AuthorityRound {
|
||||
fn params(&self) -> &CommonParams { &self.params }
|
||||
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }
|
||||
|
||||
fn step(&self) {
|
||||
self.step.fetch_add(1, AtomicOrdering::SeqCst);
|
||||
self.proposed.store(false, AtomicOrdering::SeqCst);
|
||||
if let Some(ref channel) = *self.message_channel.lock() {
|
||||
match channel.send(ClientIoMessage::UpdateSealing) {
|
||||
Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", self.step.load(AtomicOrdering::Relaxed)),
|
||||
Err(err) => trace!(target: "poa", "timeout: Could not send a sealing message {} for step {}.", err, self.step.load(AtomicOrdering::Relaxed)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional engine-specific information for the user/developer concerning `header`.
|
||||
fn extra_info(&self, header: &Header) -> BTreeMap<String, String> {
|
||||
map![
|
||||
@@ -235,6 +242,8 @@ impl Engine for AuthorityRound {
|
||||
} else {
|
||||
warn!(target: "poa", "generate_seal: FAIL: Accounts not provided.");
|
||||
}
|
||||
} else {
|
||||
trace!(target: "poa", "generate_seal: Not a proposer for step {}.", step);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -160,4 +160,6 @@ pub trait Engine : Sync + Send {
|
||||
|
||||
/// Add an account provider useful for Engines that sign stuff.
|
||||
fn register_account_provider(&self, _account_provider: Arc<AccountProvider>) {}
|
||||
/// Trigger next step of the consensus engine.
|
||||
fn step(&self) {}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use account_provider::{AccountProvider, Error as AccountError};
|
||||
use views::{BlockView, HeaderView};
|
||||
use header::Header;
|
||||
use state::{State, CleanupMode};
|
||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics, TransactionID};
|
||||
use client::TransactionImportResult;
|
||||
use executive::contract_address;
|
||||
use block::{ClosedBlock, SealedBlock, IsBlock, Block};
|
||||
@@ -357,6 +357,8 @@ impl Miner {
|
||||
let block_number = open_block.block().fields().header.number();
|
||||
|
||||
// TODO Push new uncles too.
|
||||
let mut tx_count: usize = 0;
|
||||
let tx_total = transactions.len();
|
||||
for tx in transactions {
|
||||
let hash = tx.hash();
|
||||
let start = Instant::now();
|
||||
@@ -378,7 +380,7 @@ impl Miner {
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
trace!(target: "miner", "Adding tx {:?} took {:?}", hash, took);
|
||||
match result {
|
||||
Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, gas })) => {
|
||||
debug!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?} (limit: {:?}, used: {:?}, gas: {:?})", hash, gas_limit, gas_used, gas);
|
||||
@@ -407,9 +409,12 @@ impl Miner {
|
||||
"Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}",
|
||||
block_number, hash, e);
|
||||
},
|
||||
_ => {} // imported ok
|
||||
_ => {
|
||||
tx_count += 1;
|
||||
} // imported ok
|
||||
}
|
||||
}
|
||||
trace!(target: "miner", "Pushed {}/{} transactions", tx_count, tx_total);
|
||||
|
||||
let block = open_block.close();
|
||||
|
||||
@@ -580,6 +585,10 @@ impl Miner {
|
||||
let best_block_header: Header = ::rlp::decode(&chain.best_block_header());
|
||||
transactions.into_iter()
|
||||
.map(|tx| {
|
||||
if chain.transaction_block(TransactionID::Hash(tx.hash())).is_some() {
|
||||
debug!(target: "miner", "Rejected tx {:?}: already in the blockchain", tx.hash());
|
||||
return Err(Error::Transaction(TransactionError::AlreadyImported));
|
||||
}
|
||||
match self.engine.verify_transaction_basic(&tx, &best_block_header) {
|
||||
Err(e) => {
|
||||
debug!(target: "miner", "Rejected tx {:?} with invalid signature: {:?}", tx.hash(), e);
|
||||
|
||||
@@ -273,7 +273,7 @@ impl Spec {
|
||||
pub fn new_instant() -> Spec { load_bundled!("instant_seal") }
|
||||
|
||||
/// Create a new Spec with AuthorityRound consensus which does internal sealing (not requiring work).
|
||||
/// Accounts with secrets "1".sha3() and "2".sha3() are the authorities.
|
||||
/// Accounts with secrets "0".sha3() and "1".sha3() are the authorities.
|
||||
pub fn new_test_round() -> Self { load_bundled!("authority_round") }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user