Backporting to stable (#6060)

* --reseal-on-uncle (#5940)

* --reseal-on-uncle

* Optimized uncle check

* Additional uncle check

* Updated comment

* v1.6.9

* CLI: Export error message and less verbose peer counter. (#5870)

* Removed numbed of active connections from informant

* Print error message when fatdb is required

* Remove peers from UI
This commit is contained in:
Arkadiy Paronyan
2017-07-14 17:42:36 +02:00
committed by GitHub
parent 823f207d25
commit 1f176c7798
19 changed files with 109 additions and 44 deletions

View File

@@ -1532,6 +1532,33 @@ impl MiningBlockChainClient for Client {
open_block
}
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
let engine = &*self.engine;
let mut block = block.reopen(engine);
let max_uncles = engine.maximum_uncle_count();
if block.uncles().len() < max_uncles {
let chain = self.chain.read();
let h = chain.best_block_hash();
// Add new uncles
let uncles = chain
.find_uncle_hashes(&h, engine.maximum_uncle_age())
.unwrap_or_else(Vec::new);
for h in uncles {
if !block.uncles().iter().any(|header| header.hash() == h) {
let uncle = chain.block_header(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed");
block.push_uncle(uncle).expect("pushing up to maximum_uncle_count;
push_uncle is not ok only if more than maximum_uncle_count is pushed;
so all push_uncle are Ok;
qed");
if block.uncles().len() >= max_uncles { break }
}
}
}
block
}
fn vm_factory(&self) -> &EvmFactory {
&self.factories.vm
}

View File

@@ -42,7 +42,7 @@ use types::mode::Mode;
use types::pruning_info::PruningInfo;
use verification::queue::QueueInfo;
use block::{OpenBlock, SealedBlock};
use block::{OpenBlock, SealedBlock, ClosedBlock};
use executive::Executed;
use error::CallError;
use trace::LocalizedTrace;
@@ -378,6 +378,10 @@ impl MiningBlockChainClient for TestBlockChainClient {
open_block
}
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
block.reopen(&*self.spec.engine)
}
fn vm_factory(&self) -> &EvmFactory {
&self.vm_factory
}

View File

@@ -18,7 +18,7 @@ use std::collections::BTreeMap;
use util::{U256, Address, H256, H2048, Bytes, Itertools};
use blockchain::TreeRoute;
use verification::queue::QueueInfo as BlockQueueInfo;
use block::{OpenBlock, SealedBlock};
use block::{OpenBlock, SealedBlock, ClosedBlock};
use header::{BlockNumber};
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction};
use transaction_import::TransactionImportResult;
@@ -277,6 +277,9 @@ pub trait MiningBlockChainClient: BlockChainClient {
extra_data: Bytes
) -> OpenBlock;
/// Reopens an OpenBlock and updates uncles.
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
/// Returns EvmFactory.
fn vm_factory(&self) -> &EvmFactory;

View File

@@ -129,6 +129,8 @@ pub enum BlockError {
UncleIsBrother(OutOfBounds<BlockNumber>),
/// An uncle is already in the chain.
UncleInChain(H256),
/// An uncle is included twice.
DuplicateUncle(H256),
/// An uncle has a parent not in the chain.
UncleParentNotInChain(H256),
/// State root header field is invalid.
@@ -184,6 +186,7 @@ impl fmt::Display for BlockError {
UncleTooOld(ref oob) => format!("Uncle block is too old. {}", oob),
UncleIsBrother(ref oob) => format!("Uncle from same generation as block. {}", oob),
UncleInChain(ref hash) => format!("Uncle {} already in chain", hash),
DuplicateUncle(ref hash) => format!("Uncle {} already in the header", hash),
UncleParentNotInChain(ref hash) => format!("Uncle {} has a parent not in the chain", hash),
InvalidStateRoot(ref mis) => format!("Invalid state root in header: {}", mis),
InvalidGasUsed(ref mis) => format!("Invalid gas used in header: {}", mis),

View File

@@ -88,6 +88,8 @@ pub struct MinerOptions {
pub reseal_on_external_tx: bool,
/// Reseal on receipt of new local transactions.
pub reseal_on_own_tx: bool,
/// Reseal when new uncle block has been imported.
pub reseal_on_uncle: bool,
/// Minimum period between transaction-inspired reseals.
pub reseal_min_period: Duration,
/// Maximum amount of gas to bother considering for block insertion.
@@ -117,6 +119,7 @@ impl Default for MinerOptions {
force_sealing: false,
reseal_on_external_tx: false,
reseal_on_own_tx: true,
reseal_on_uncle: false,
tx_gas_limit: !U256::zero(),
tx_queue_size: 1024,
tx_queue_gas_limit: GasLimit::Auto,
@@ -339,7 +342,7 @@ impl Miner {
Some(old_block) => {
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
// add transactions to old_block
old_block.reopen(&*self.engine)
chain.reopen_block(old_block)
}
None => {
// block not found - create it.
@@ -358,7 +361,6 @@ impl Miner {
let mut transactions_to_penalize = HashSet::new();
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 {
@@ -1142,11 +1144,10 @@ impl MinerService for Miner {
})
}
fn chain_new_blocks(&self, chain: &MiningBlockChainClient, _imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) {
fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) {
trace!(target: "miner", "chain_new_blocks");
// 1. We ignore blocks that were `imported` (because it means that they are not in canon-chain, and transactions
// should be still available in the queue.
// 1. We ignore blocks that were `imported` unless resealing on new uncles is enabled.
// 2. We ignore blocks that are `invalid` because it doesn't have any meaning in terms of the transactions that
// are in those blocks
@@ -1181,7 +1182,7 @@ impl MinerService for Miner {
transaction_queue.remove_old(&fetch_account, time);
}
if enacted.len() > 0 {
if enacted.len() > 0 || (imported.len() > 0 && self.options.reseal_on_uncle) {
// --------------------------------------------------------------------------
// | NOTE Code below requires transaction_queue and sealing_work locks. |
// | Make sure to release the locks before calling that method. |
@@ -1300,6 +1301,7 @@ mod tests {
force_sealing: false,
reseal_on_external_tx: false,
reseal_on_own_tx: true,
reseal_on_uncle: false,
reseal_min_period: Duration::from_secs(5),
tx_gas_limit: !U256::zero(),
tx_queue_size: 1024,

View File

@@ -124,12 +124,17 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
}
}
let mut verified = HashSet::new();
for uncle in UntrustedRlp::new(bytes).at(2)?.iter().map(|rlp| rlp.as_val::<Header>()) {
let uncle = uncle?;
if excluded.contains(&uncle.hash()) {
return Err(From::from(BlockError::UncleInChain(uncle.hash())))
}
if verified.contains(&uncle.hash()) {
return Err(From::from(BlockError::DuplicateUncle(uncle.hash())))
}
// m_currentBlock.number() - uncle.number() m_cB.n - uP.n()
// 1 2
// 2
@@ -172,6 +177,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
verify_parent(&uncle, &uncle_parent)?;
engine.verify_block_family(&uncle, &uncle_parent, Some(bytes))?;
verified.insert(uncle.hash());
}
}
Ok(())
@@ -555,6 +561,11 @@ mod tests {
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &bad_uncles), engine, &bc),
TooManyUncles(OutOfBounds { max: Some(engine.maximum_uncle_count()), min: None, found: bad_uncles.len() }));
header = good.clone();
bad_uncles = vec![ good_uncle1.clone(), good_uncle1.clone() ];
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &bad_uncles), engine, &bc),
DuplicateUncle(good_uncle1.hash()));
// TODO: some additional uncle checks
}
}