Add transactions from retracted blocks back to the pool (#3562)

* Add transactions from retracted blocks back to the pool

* Line width

* Reverse retracted
This commit is contained in:
Arkadiy Paronyan
2019-09-06 21:30:43 +02:00
committed by Gavin Wood
parent a381f033bd
commit 0df2be5760
7 changed files with 118 additions and 34 deletions
+10 -9
View File
@@ -35,6 +35,15 @@ pub type StorageCollection = Vec<(Vec<u8>, Option<Vec<u8>>)>;
/// In memory arrays of storage values for multiple child tries.
pub type ChildStorageCollection = Vec<(Vec<u8>, StorageCollection)>;
pub(crate) struct ImportSummary<Block: BlockT> {
pub(crate) hash: Block::Hash,
pub(crate) origin: BlockOrigin,
pub(crate) header: Block::Header,
pub(crate) is_new_best: bool,
pub(crate) storage_changes: Option<(StorageCollection, ChildStorageCollection)>,
pub(crate) retracted: Vec<Block::Hash>,
}
/// Import operation wrapper
pub struct ClientImportOperation<
Block: BlockT,
@@ -42,15 +51,7 @@ pub struct ClientImportOperation<
B: Backend<Block, H>,
> {
pub(crate) op: B::BlockImportOperation,
pub(crate) notify_imported: Option<(
Block::Hash,
BlockOrigin,
Block::Header,
bool,
Option<(
StorageCollection,
ChildStorageCollection,
)>)>,
pub(crate) notify_imported: Option<ImportSummary<Block>>,
pub(crate) notify_finalized: Vec<Block::Hash>,
}
+30 -19
View File
@@ -62,7 +62,7 @@ use crate::{
},
backend::{
self, BlockImportOperation, PrunableStateChangesTrieStorage,
ClientImportOperation, Finalizer,
ClientImportOperation, Finalizer, ImportSummary,
},
blockchain::{
self, Info as ChainInfo, Backend as ChainBackend,
@@ -199,6 +199,8 @@ pub struct BlockImportNotification<Block: BlockT> {
pub header: Block::Header,
/// Is this the new best block.
pub is_new_best: bool,
/// List of retracted blocks ordered by block number.
pub retracted: Vec<Block::Hash>,
}
/// Summary of a finalized block.
@@ -968,6 +970,17 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
crate::backend::NewBlockState::Normal
};
let retracted = if is_new_best {
let route_from_best = crate::blockchain::tree_route(
|id| self.header(&id)?.ok_or_else(|| Error::UnknownBlock(format!("{:?}", id))),
BlockId::Hash(info.best_hash),
BlockId::Hash(parent_hash),
)?;
route_from_best.retracted().iter().rev().map(|e| e.hash.clone()).collect()
} else {
Vec::default()
};
trace!("Imported {}, (#{}), best={}, origin={:?}", hash, import_headers.post().number(), is_new_best, origin);
operation.op.set_block_data(
@@ -995,7 +1008,14 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
operation.notify_finalized.push(hash);
}
operation.notify_imported = Some((hash, origin, import_headers.into_post(), is_new_best, storage_changes));
operation.notify_imported = Some(ImportSummary {
hash,
origin,
header: import_headers.into_post(),
is_new_best,
storage_changes,
retracted,
})
}
Ok(ImportResult::imported(is_new_best))
@@ -1167,33 +1187,24 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
fn notify_imported(
&self,
notify_import: (
Block::Hash, BlockOrigin,
Block::Header,
bool,
Option<(
Vec<(Vec<u8>, Option<Vec<u8>>)>,
Vec<(Vec<u8>, Vec<(Vec<u8>, Option<Vec<u8>>)>)>,
)
>),
notify_import: ImportSummary<Block>,
) -> error::Result<()> {
let (hash, origin, header, is_new_best, storage_changes) = notify_import;
if let Some(storage_changes) = storage_changes {
if let Some(storage_changes) = notify_import.storage_changes {
// TODO [ToDr] How to handle re-orgs? Should we re-emit all storage changes?
self.storage_notifications.lock()
.trigger(
&hash,
&notify_import.hash,
storage_changes.0.into_iter(),
storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())),
);
}
let notification = BlockImportNotification::<Block> {
hash,
origin,
header,
is_new_best,
hash: notify_import.hash,
origin: notify_import.origin,
header: notify_import.header,
is_new_best: notify_import.is_new_best,
retracted: notify_import.retracted,
};
self.import_notification_sinks.lock()