Don't remove invalid transactions when skipping. (#5121)

* Don't remove invalid transactions when skipping.

* Use a special kind of extrinsic instead of arbitrary limit.

* Fix txpool tests.

* Attempt to create more blocks.

* Bump lock

Co-authored-by: Gavin Wood <github@gavwood.com>
Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
Gavin Wood
2020-03-05 17:00:31 +01:00
committed by GitHub
parent 99ae5342eb
commit f5dc69b404
7 changed files with 133 additions and 22 deletions
@@ -26,15 +26,15 @@ use sp_inherents::InherentData;
use log::{error, info, debug, trace};
use sp_core::ExecutionContext;
use sp_runtime::{
traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256},
generic::BlockId,
traits::{Block as BlockT, Hash as HashT, Header as HeaderT, DigestFor, BlakeTwo256},
};
use sp_transaction_pool::{TransactionPool, InPoolTransaction};
use sc_telemetry::{telemetry, CONSENSUS_INFO};
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider};
use sp_api::{ProvideRuntimeApi, ApiExt};
use futures::prelude::*;
use sp_blockchain::HeaderBackend;
use sp_blockchain::{HeaderBackend, ApplyExtrinsicFailed};
use std::marker::PhantomData;
/// Proposer factory.
@@ -230,7 +230,7 @@ impl<A, B, Block, C> ProposerInner<B, Block, C, A>
Ok(()) => {
debug!("[{:?}] Pushed to the block.", pending_tx_hash);
}
Err(sp_blockchain::Error::ApplyExtrinsicFailed(sp_blockchain::ApplyExtrinsicFailed::Validity(e)))
Err(sp_blockchain::Error::ApplyExtrinsicFailed(ApplyExtrinsicFailed::Validity(e)))
if e.exhausted_resources() => {
if is_first {
debug!("[{:?}] Invalid transaction: FullBlock on empty block", pending_tx_hash);
@@ -246,6 +246,13 @@ impl<A, B, Block, C> ProposerInner<B, Block, C, A>
break;
}
}
Err(e) if skipped > 0 => {
trace!(
"[{:?}] Ignoring invalid transaction when skipping: {}",
pending_tx_hash,
e
);
}
Err(e) => {
debug!("[{:?}] Invalid transaction: {}", pending_tx_hash, e);
unqueue_invalid.push(pending_tx_hash);
@@ -292,10 +299,10 @@ mod tests {
use super::*;
use parking_lot::Mutex;
use sp_consensus::Proposer;
use sp_consensus::{BlockOrigin, Proposer};
use substrate_test_runtime_client::{
runtime::{Extrinsic, Transfer}, AccountKeyring, DefaultTestClientBuilderExt,
TestClientBuilderExt,
prelude::*,
runtime::{Extrinsic, Transfer},
};
use sc_transaction_pool::{BasicPool, FullChainApi};
use sp_api::Core;
@@ -395,4 +402,73 @@ mod tests {
storage_changes.transaction_storage_root,
);
}
#[test]
fn should_not_remove_invalid_transactions_when_skipping() {
// given
let mut client = Arc::new(substrate_test_runtime_client::new());
let txpool = Arc::new(
BasicPool::new(Default::default(), Arc::new(FullChainApi::new(client.clone()))).0
);
futures::executor::block_on(
txpool.submit_at(&BlockId::number(0), vec![
extrinsic(0),
extrinsic(1),
Transfer {
amount: Default::default(),
nonce: 2,
from: AccountKeyring::Alice.into(),
to: Default::default(),
}.into_resources_exhausting_tx(),
extrinsic(3),
Transfer {
amount: Default::default(),
nonce: 4,
from: AccountKeyring::Alice.into(),
to: Default::default(),
}.into_resources_exhausting_tx(),
extrinsic(5),
extrinsic(6),
])
).unwrap();
let mut proposer_factory = ProposerFactory::new(client.clone(), txpool.clone());
let mut propose_block = |
client: &TestClient,
number,
expected_block_extrinsics,
expected_pool_transactions,
| {
let mut proposer = proposer_factory.init_with_now(
&client.header(&BlockId::number(number)).unwrap().unwrap(),
Box::new(move || time::Instant::now()),
);
// when
let deadline = time::Duration::from_secs(9);
let block = futures::executor::block_on(
proposer.propose(Default::default(), Default::default(), deadline, RecordProof::No)
).map(|r| r.block).unwrap();
// then
// block should have some extrinsics although we have some more in the pool.
assert_eq!(block.extrinsics().len(), expected_block_extrinsics);
assert_eq!(txpool.ready().count(), expected_pool_transactions);
block
};
// let's create one block and import it
let block = propose_block(&client, 0, 2, 7);
client.import(BlockOrigin::Own, block).unwrap();
// now let's make sure that we can still make some progress
// This is most likely incorrect, and caused by #5139
let tx_remaining = 0;
let block = propose_block(&client, 1, 2, tx_remaining);
client.import(BlockOrigin::Own, block).unwrap();
}
}