decode block rlp less often (#9252)
in total: - removed 4 redundant rlp deserializations - avoid 1 redundant block data copy
This commit is contained in:
committed by
André Silva
parent
f442665c46
commit
b4ae1b6528
@@ -73,6 +73,8 @@ use types::filter::Filter;
|
||||
use types::ancestry_action::AncestryAction;
|
||||
use verification;
|
||||
use verification::{PreverifiedBlock, Verifier, BlockQueue};
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
use verification::queue::kind::BlockLike;
|
||||
|
||||
// re-export
|
||||
pub use types::blockchain_info::BlockChainInfo;
|
||||
@@ -208,7 +210,7 @@ pub struct Client {
|
||||
/// Queued ancient blocks, make sure they are imported in order.
|
||||
queued_ancient_blocks: Arc<RwLock<(
|
||||
HashSet<H256>,
|
||||
VecDeque<(Header, encoded::Block, Bytes)>
|
||||
VecDeque<(Unverified, Bytes)>
|
||||
)>>,
|
||||
ancient_blocks_import_lock: Arc<Mutex<()>>,
|
||||
/// Consensus messages import queue
|
||||
@@ -428,7 +430,7 @@ impl Importer {
|
||||
///
|
||||
/// The block is guaranteed to be the next best blocks in the
|
||||
/// first block sequence. Does no sealing or transaction validation.
|
||||
fn import_old_block(&self, header: &Header, block: encoded::Block, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> Result<(), ::error::Error> {
|
||||
fn import_old_block(&self, unverified: Unverified, receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> Result<(), ::error::Error> {
|
||||
let receipts = ::rlp::decode_list(receipts_bytes);
|
||||
let _import_lock = self.import_lock.lock();
|
||||
|
||||
@@ -436,11 +438,11 @@ impl Importer {
|
||||
trace_time!("import_old_block");
|
||||
// verify the block, passing the chain for updating the epoch verifier.
|
||||
let mut rng = OsRng::new()?;
|
||||
self.ancient_verifier.verify(&mut rng, &header, &chain)?;
|
||||
self.ancient_verifier.verify(&mut rng, &unverified.header, &chain)?;
|
||||
|
||||
// Commit results
|
||||
let mut batch = DBTransaction::new();
|
||||
chain.insert_unordered_block(&mut batch, block, receipts, None, false, true);
|
||||
chain.insert_unordered_block(&mut batch, encoded::Block::new(unverified.bytes), receipts, None, false, true);
|
||||
// Final commit to the DB
|
||||
db.write_buffered(batch);
|
||||
chain.commit();
|
||||
@@ -1381,22 +1383,15 @@ impl CallContract for Client {
|
||||
}
|
||||
|
||||
impl ImportBlock for Client {
|
||||
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError> {
|
||||
use verification::queue::kind::BlockLike;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
// create unverified block here so the `keccak` calculation can be cached.
|
||||
let unverified = Unverified::from_rlp(bytes)?;
|
||||
|
||||
{
|
||||
if self.chain.read().is_known(&unverified.hash()) {
|
||||
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
}
|
||||
let status = self.block_status(BlockId::Hash(unverified.parent_hash()));
|
||||
if status == BlockStatus::Unknown || status == BlockStatus::Pending {
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
|
||||
}
|
||||
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
|
||||
if self.chain.read().is_known(&unverified.hash()) {
|
||||
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
}
|
||||
let status = self.block_status(BlockId::Hash(unverified.parent_hash()));
|
||||
if status == BlockStatus::Unknown || status == BlockStatus::Pending {
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(unverified.parent_hash())));
|
||||
}
|
||||
|
||||
Ok(self.importer.block_queue.import(unverified)?)
|
||||
}
|
||||
}
|
||||
@@ -2027,24 +2022,23 @@ impl IoClient for Client {
|
||||
});
|
||||
}
|
||||
|
||||
fn queue_ancient_block(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError> {
|
||||
fn queue_ancient_block(&self, unverified: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError> {
|
||||
trace_time!("queue_ancient_block");
|
||||
let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?;
|
||||
let hash = header.hash();
|
||||
|
||||
let hash = unverified.hash();
|
||||
{
|
||||
// check block order
|
||||
if self.chain.read().is_known(&hash) {
|
||||
bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain));
|
||||
}
|
||||
let parent_hash = header.parent_hash();
|
||||
let parent_hash = unverified.parent_hash();
|
||||
// NOTE To prevent race condition with import, make sure to check queued blocks first
|
||||
// (and attempt to acquire lock)
|
||||
let is_parent_pending = self.queued_ancient_blocks.read().0.contains(parent_hash);
|
||||
let is_parent_pending = self.queued_ancient_blocks.read().0.contains(&parent_hash);
|
||||
if !is_parent_pending {
|
||||
let status = self.block_status(BlockId::Hash(*parent_hash));
|
||||
let status = self.block_status(BlockId::Hash(parent_hash));
|
||||
if status == BlockStatus::Unknown || status == BlockStatus::Pending {
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(*parent_hash)));
|
||||
bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(parent_hash)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2053,7 +2047,7 @@ impl IoClient for Client {
|
||||
{
|
||||
let mut queued = self.queued_ancient_blocks.write();
|
||||
queued.0.insert(hash);
|
||||
queued.1.push_back((header, encoded::Block::new(block_bytes), receipts_bytes));
|
||||
queued.1.push_back((unverified, receipts_bytes));
|
||||
}
|
||||
|
||||
let queued = self.queued_ancient_blocks.clone();
|
||||
@@ -2065,11 +2059,10 @@ impl IoClient for Client {
|
||||
let _lock = lock.lock();
|
||||
for _i in 0..MAX_ANCIENT_BLOCKS_TO_IMPORT {
|
||||
let first = queued.write().1.pop_front();
|
||||
if let Some((header, block_bytes, receipts_bytes)) = first {
|
||||
let hash = header.hash();
|
||||
if let Some((unverified, receipts_bytes)) = first {
|
||||
let hash = unverified.hash();
|
||||
let result = client.importer.import_old_block(
|
||||
&header,
|
||||
block_bytes,
|
||||
unverified,
|
||||
&receipts_bytes,
|
||||
&**client.db.read().key_value(),
|
||||
&*client.chain.read(),
|
||||
|
||||
@@ -53,6 +53,7 @@ use spec::Spec;
|
||||
use types::basic_account::BasicAccount;
|
||||
use types::pruning_info::PruningInfo;
|
||||
use verification::queue::QueueInfo;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
use block::{OpenBlock, SealedBlock, ClosedBlock};
|
||||
use executive::Executed;
|
||||
use error::CallError;
|
||||
@@ -280,7 +281,8 @@ impl TestBlockChainClient {
|
||||
rlp.append(&header);
|
||||
rlp.append_raw(&txs, 1);
|
||||
rlp.append_raw(uncles.as_raw(), 1);
|
||||
self.import_block(rlp.as_raw().to_vec()).unwrap();
|
||||
let unverified = Unverified::from_rlp(rlp.out()).unwrap();
|
||||
self.import_block(unverified).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,8 +514,8 @@ impl RegistryInfo for TestBlockChainClient {
|
||||
}
|
||||
|
||||
impl ImportBlock for TestBlockChainClient {
|
||||
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
|
||||
let header = view!(BlockView, &b).header();
|
||||
fn import_block(&self, unverified: Unverified) -> Result<H256, BlockImportError> {
|
||||
let header = unverified.header;
|
||||
let h = header.hash();
|
||||
let number: usize = header.number() as usize;
|
||||
if number > self.blocks.read().len() {
|
||||
@@ -539,7 +541,7 @@ impl ImportBlock for TestBlockChainClient {
|
||||
*difficulty = *difficulty + header.difficulty().clone();
|
||||
}
|
||||
mem::replace(&mut *self.last_hash.write(), h.clone());
|
||||
self.blocks.write().insert(h.clone(), b);
|
||||
self.blocks.write().insert(h.clone(), unverified.bytes);
|
||||
self.numbers.write().insert(number, h.clone());
|
||||
let mut parent_hash = header.parent_hash().clone();
|
||||
if number > 0 {
|
||||
@@ -552,7 +554,7 @@ impl ImportBlock for TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.blocks.write().insert(h.clone(), b.to_vec());
|
||||
self.blocks.write().insert(h.clone(), unverified.bytes);
|
||||
}
|
||||
Ok(h)
|
||||
}
|
||||
@@ -856,8 +858,8 @@ impl IoClient for TestBlockChainClient {
|
||||
self.miner.import_external_transactions(self, txs);
|
||||
}
|
||||
|
||||
fn queue_ancient_block(&self, b: Bytes, _r: Bytes) -> Result<H256, BlockImportError> {
|
||||
self.import_block(b)
|
||||
fn queue_ancient_block(&self, unverified: Unverified, _r: Bytes) -> Result<H256, BlockImportError> {
|
||||
self.import_block(unverified)
|
||||
}
|
||||
|
||||
fn queue_consensus_message(&self, message: Bytes) {
|
||||
|
||||
@@ -34,6 +34,7 @@ use receipt::LocalizedReceipt;
|
||||
use trace::LocalizedTrace;
|
||||
use transaction::{self, LocalizedTransaction, SignedTransaction};
|
||||
use verification::queue::QueueInfo as BlockQueueInfo;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
use state::StateInfo;
|
||||
use header::Header;
|
||||
use engines::EthEngine;
|
||||
@@ -167,7 +168,7 @@ pub trait RegistryInfo {
|
||||
/// Provides methods to import block into blockchain
|
||||
pub trait ImportBlock {
|
||||
/// Import a block into the blockchain.
|
||||
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
fn import_block(&self, block: Unverified) -> Result<H256, BlockImportError>;
|
||||
}
|
||||
|
||||
/// Provides `call_contract` method
|
||||
@@ -204,7 +205,7 @@ pub trait IoClient: Sync + Send {
|
||||
fn queue_transactions(&self, transactions: Vec<Bytes>, peer_id: usize);
|
||||
|
||||
/// Queue block import with transaction receipts. Does no sealing and transaction validation.
|
||||
fn queue_ancient_block(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
fn queue_ancient_block(&self, block_bytes: Unverified, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
|
||||
/// Queue conensus engine message.
|
||||
fn queue_consensus_message(&self, message: Bytes);
|
||||
|
||||
Reference in New Issue
Block a user