mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 20:01:03 +00:00
BlockId removal: tx-pool refactor (#1678)
It changes following APIs: - trait `ChainApi` -- `validate_transaction` - trait `TransactionPool` --`submit_at` --`submit_one` --`submit_and_watch` and some implementation details, in particular: - impl `Pool` --`submit_at` --`resubmit_at` --`submit_one` --`submit_and_watch` --`prune_known` --`prune` --`prune_tags` --`resolve_block_number` --`verify` --`verify_one` - revalidation queue All tests are also adjusted. --------- Co-authored-by: command-bot <> Co-authored-by: Bastian Köcher <git@kchr.de>
This commit is contained in:
committed by
GitHub
parent
a846b74604
commit
ab3a3bc278
@@ -21,7 +21,7 @@ use cumulus_test_runtime::{AccountId, BalancesCall, ExistentialDeposit, SudoCall
|
|||||||
use futures::{future, StreamExt};
|
use futures::{future, StreamExt};
|
||||||
use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus};
|
use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus};
|
||||||
use sp_core::{crypto::Pair, sr25519};
|
use sp_core::{crypto::Pair, sr25519};
|
||||||
use sp_runtime::{generic::BlockId, OpaqueExtrinsic};
|
use sp_runtime::OpaqueExtrinsic;
|
||||||
|
|
||||||
use cumulus_primitives_core::ParaId;
|
use cumulus_primitives_core::ParaId;
|
||||||
use cumulus_test_service::{
|
use cumulus_test_service::{
|
||||||
@@ -117,7 +117,7 @@ async fn submit_tx_and_wait_for_inclusion(
|
|||||||
let best_hash = client.chain_info().best_hash;
|
let best_hash = client.chain_info().best_hash;
|
||||||
|
|
||||||
let mut watch = tx_pool
|
let mut watch = tx_pool
|
||||||
.submit_and_watch(&BlockId::Hash(best_hash), TransactionSource::External, tx.clone())
|
.submit_and_watch(best_hash, TransactionSource::External, tx.clone())
|
||||||
.await
|
.await
|
||||||
.expect("Submits tx to pool")
|
.expect("Submits tx to pool")
|
||||||
.fuse();
|
.fuse();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ use sc_transaction_pool_api::{
|
|||||||
};
|
};
|
||||||
use sp_consensus::{Environment, Proposer};
|
use sp_consensus::{Environment, Proposer};
|
||||||
use sp_inherents::InherentDataProvider;
|
use sp_inherents::InherentDataProvider;
|
||||||
use sp_runtime::{generic::BlockId, traits::NumberFor, OpaqueExtrinsic};
|
use sp_runtime::{traits::NumberFor, OpaqueExtrinsic};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::SizeType,
|
common::SizeType,
|
||||||
@@ -233,7 +233,7 @@ impl sc_transaction_pool_api::TransactionPool for Transactions {
|
|||||||
/// Returns a future that imports a bunch of unverified transactions to the pool.
|
/// Returns a future that imports a bunch of unverified transactions to the pool.
|
||||||
fn submit_at(
|
fn submit_at(
|
||||||
&self,
|
&self,
|
||||||
_at: &BlockId<Self::Block>,
|
_at: Self::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
_xts: Vec<TransactionFor<Self>>,
|
_xts: Vec<TransactionFor<Self>>,
|
||||||
) -> PoolFuture<Vec<Result<node_primitives::Hash, Self::Error>>, Self::Error> {
|
) -> PoolFuture<Vec<Result<node_primitives::Hash, Self::Error>>, Self::Error> {
|
||||||
@@ -243,7 +243,7 @@ impl sc_transaction_pool_api::TransactionPool for Transactions {
|
|||||||
/// Returns a future that imports one unverified transaction to the pool.
|
/// Returns a future that imports one unverified transaction to the pool.
|
||||||
fn submit_one(
|
fn submit_one(
|
||||||
&self,
|
&self,
|
||||||
_at: &BlockId<Self::Block>,
|
_at: Self::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
_xt: TransactionFor<Self>,
|
_xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<TxHash<Self>, Self::Error> {
|
) -> PoolFuture<TxHash<Self>, Self::Error> {
|
||||||
@@ -252,7 +252,7 @@ impl sc_transaction_pool_api::TransactionPool for Transactions {
|
|||||||
|
|
||||||
fn submit_and_watch(
|
fn submit_and_watch(
|
||||||
&self,
|
&self,
|
||||||
_at: &BlockId<Self::Block>,
|
_at: Self::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
_xt: TransactionFor<Self>,
|
_xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> {
|
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ use node_testing::bench::{BenchDb, BlockType, DatabaseType, KeyTypes};
|
|||||||
|
|
||||||
use sc_transaction_pool::BasicPool;
|
use sc_transaction_pool::BasicPool;
|
||||||
use sc_transaction_pool_api::{TransactionPool, TransactionSource};
|
use sc_transaction_pool_api::{TransactionPool, TransactionSource};
|
||||||
use sp_runtime::generic::BlockId;
|
|
||||||
|
|
||||||
use crate::core::{self, Mode, Path};
|
use crate::core::{self, Mode, Path};
|
||||||
|
|
||||||
@@ -58,10 +57,11 @@ impl core::BenchmarkDescription for PoolBenchmarkDescription {
|
|||||||
impl core::Benchmark for PoolBenchmark {
|
impl core::Benchmark for PoolBenchmark {
|
||||||
fn run(&mut self, mode: Mode) -> std::time::Duration {
|
fn run(&mut self, mode: Mode) -> std::time::Duration {
|
||||||
let context = self.database.create_context();
|
let context = self.database.create_context();
|
||||||
|
let genesis_hash = context.client.chain_info().genesis_hash;
|
||||||
|
|
||||||
let _ = context
|
let _ = context
|
||||||
.client
|
.client
|
||||||
.runtime_version_at(context.client.chain_info().genesis_hash)
|
.runtime_version_at(genesis_hash)
|
||||||
.expect("Failed to get runtime version")
|
.expect("Failed to get runtime version")
|
||||||
.spec_version;
|
.spec_version;
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ impl core::Benchmark for PoolBenchmark {
|
|||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
let submissions = generated_transactions
|
let submissions = generated_transactions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|tx| txpool.submit_one(&BlockId::Number(0), TransactionSource::External, tx));
|
.map(|tx| txpool.submit_one(genesis_hash, TransactionSource::External, tx));
|
||||||
futures::executor::block_on(futures::future::join_all(submissions));
|
futures::executor::block_on(futures::future::join_all(submissions));
|
||||||
let elapsed = start.elapsed();
|
let elapsed = start.elapsed();
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use sc_transaction_pool::PoolLimit;
|
|||||||
use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus};
|
use sc_transaction_pool_api::{TransactionPool as _, TransactionSource, TransactionStatus};
|
||||||
use sp_core::{crypto::Pair, sr25519};
|
use sp_core::{crypto::Pair, sr25519};
|
||||||
use sp_keyring::Sr25519Keyring;
|
use sp_keyring::Sr25519Keyring;
|
||||||
use sp_runtime::{generic::BlockId, OpaqueExtrinsic};
|
use sp_runtime::OpaqueExtrinsic;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
|
||||||
fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
|
fn new_node(tokio_handle: Handle) -> node_cli::service::NewFullBase {
|
||||||
@@ -191,7 +191,7 @@ async fn submit_tx_and_wait_for_inclusion(
|
|||||||
let best_hash = client.chain_info().best_hash;
|
let best_hash = client.chain_info().best_hash;
|
||||||
|
|
||||||
let mut watch = tx_pool
|
let mut watch = tx_pool
|
||||||
.submit_and_watch(&BlockId::Hash(best_hash), TransactionSource::External, tx.clone())
|
.submit_and_watch(best_hash, TransactionSource::External, tx.clone())
|
||||||
.await
|
.await
|
||||||
.expect("Submits tx to pool")
|
.expect("Submits tx to pool")
|
||||||
.fuse();
|
.fuse();
|
||||||
|
|||||||
@@ -642,8 +642,8 @@ mod tests {
|
|||||||
client.clone(),
|
client.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
block_on(txpool.submit_at(&BlockId::number(0), SOURCE, vec![extrinsic(0), extrinsic(1)]))
|
let hashof0 = client.info().genesis_hash;
|
||||||
.unwrap();
|
block_on(txpool.submit_at(hashof0, SOURCE, vec![extrinsic(0), extrinsic(1)])).unwrap();
|
||||||
|
|
||||||
block_on(
|
block_on(
|
||||||
txpool.maintain(chain_event(
|
txpool.maintain(chain_event(
|
||||||
@@ -658,7 +658,7 @@ mod tests {
|
|||||||
|
|
||||||
let cell = Mutex::new((false, time::Instant::now()));
|
let cell = Mutex::new((false, time::Instant::now()));
|
||||||
let proposer = proposer_factory.init_with_now(
|
let proposer = proposer_factory.init_with_now(
|
||||||
&client.expect_header(client.info().genesis_hash).unwrap(),
|
&client.expect_header(hashof0).unwrap(),
|
||||||
Box::new(move || {
|
Box::new(move || {
|
||||||
let mut value = cell.lock();
|
let mut value = cell.lock();
|
||||||
if !value.0 {
|
if !value.0 {
|
||||||
@@ -736,7 +736,7 @@ mod tests {
|
|||||||
|
|
||||||
let genesis_hash = client.info().best_hash;
|
let genesis_hash = client.info().best_hash;
|
||||||
|
|
||||||
block_on(txpool.submit_at(&BlockId::number(0), SOURCE, vec![extrinsic(0)])).unwrap();
|
block_on(txpool.submit_at(genesis_hash, SOURCE, vec![extrinsic(0)])).unwrap();
|
||||||
|
|
||||||
block_on(
|
block_on(
|
||||||
txpool.maintain(chain_event(
|
txpool.maintain(chain_event(
|
||||||
@@ -800,7 +800,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
block_on(txpool.submit_at(
|
block_on(txpool.submit_at(
|
||||||
&BlockId::number(0),
|
client.info().genesis_hash,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
vec![medium(0), medium(1), huge(2), medium(3), huge(4), medium(5), medium(6)],
|
vec![medium(0), medium(1), huge(2), medium(3), huge(4), medium(5), medium(6)],
|
||||||
))
|
))
|
||||||
@@ -897,9 +897,8 @@ mod tests {
|
|||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
client.clone(),
|
client.clone(),
|
||||||
);
|
);
|
||||||
let genesis_header = client
|
let genesis_hash = client.info().genesis_hash;
|
||||||
.expect_header(client.info().genesis_hash)
|
let genesis_header = client.expect_header(genesis_hash).expect("there should be header");
|
||||||
.expect("there should be header");
|
|
||||||
|
|
||||||
let extrinsics_num = 5;
|
let extrinsics_num = 5;
|
||||||
let extrinsics = std::iter::once(
|
let extrinsics = std::iter::once(
|
||||||
@@ -922,7 +921,7 @@ mod tests {
|
|||||||
.sum::<usize>() +
|
.sum::<usize>() +
|
||||||
Vec::<Extrinsic>::new().encoded_size();
|
Vec::<Extrinsic>::new().encoded_size();
|
||||||
|
|
||||||
block_on(txpool.submit_at(&BlockId::number(0), SOURCE, extrinsics.clone())).unwrap();
|
block_on(txpool.submit_at(genesis_hash, SOURCE, extrinsics.clone())).unwrap();
|
||||||
|
|
||||||
block_on(txpool.maintain(chain_event(genesis_header.clone())));
|
block_on(txpool.maintain(chain_event(genesis_header.clone())));
|
||||||
|
|
||||||
@@ -999,6 +998,7 @@ mod tests {
|
|||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
client.clone(),
|
client.clone(),
|
||||||
);
|
);
|
||||||
|
let genesis_hash = client.info().genesis_hash;
|
||||||
|
|
||||||
let tiny = |nonce| {
|
let tiny = |nonce| {
|
||||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
|
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
|
||||||
@@ -1011,7 +1011,7 @@ mod tests {
|
|||||||
|
|
||||||
block_on(
|
block_on(
|
||||||
txpool.submit_at(
|
txpool.submit_at(
|
||||||
&BlockId::number(0),
|
genesis_hash,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
// add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources
|
// add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources
|
||||||
(0..MAX_SKIPPED_TRANSACTIONS * 2)
|
(0..MAX_SKIPPED_TRANSACTIONS * 2)
|
||||||
@@ -1024,13 +1024,9 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
block_on(
|
block_on(txpool.maintain(chain_event(
|
||||||
txpool.maintain(chain_event(
|
client.expect_header(genesis_hash).expect("there should be header"),
|
||||||
client
|
)));
|
||||||
.expect_header(client.info().genesis_hash)
|
|
||||||
.expect("there should be header"),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 3);
|
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 3);
|
||||||
|
|
||||||
let mut proposer_factory =
|
let mut proposer_factory =
|
||||||
@@ -1038,7 +1034,7 @@ mod tests {
|
|||||||
|
|
||||||
let cell = Mutex::new(time::Instant::now());
|
let cell = Mutex::new(time::Instant::now());
|
||||||
let proposer = proposer_factory.init_with_now(
|
let proposer = proposer_factory.init_with_now(
|
||||||
&client.expect_header(client.info().genesis_hash).unwrap(),
|
&client.expect_header(genesis_hash).unwrap(),
|
||||||
Box::new(move || {
|
Box::new(move || {
|
||||||
let mut value = cell.lock();
|
let mut value = cell.lock();
|
||||||
let old = *value;
|
let old = *value;
|
||||||
@@ -1071,6 +1067,7 @@ mod tests {
|
|||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
client.clone(),
|
client.clone(),
|
||||||
);
|
);
|
||||||
|
let genesis_hash = client.info().genesis_hash;
|
||||||
|
|
||||||
let tiny = |who| {
|
let tiny = |who| {
|
||||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY))
|
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY))
|
||||||
@@ -1086,7 +1083,7 @@ mod tests {
|
|||||||
|
|
||||||
block_on(
|
block_on(
|
||||||
txpool.submit_at(
|
txpool.submit_at(
|
||||||
&BlockId::number(0),
|
genesis_hash,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
(0..MAX_SKIPPED_TRANSACTIONS + 2)
|
(0..MAX_SKIPPED_TRANSACTIONS + 2)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -1098,13 +1095,9 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
block_on(
|
block_on(txpool.maintain(chain_event(
|
||||||
txpool.maintain(chain_event(
|
client.expect_header(genesis_hash).expect("there should be header"),
|
||||||
client
|
)));
|
||||||
.expect_header(client.info().genesis_hash)
|
|
||||||
.expect("there should be header"),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 4);
|
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 4);
|
||||||
|
|
||||||
let mut proposer_factory =
|
let mut proposer_factory =
|
||||||
@@ -1114,7 +1107,7 @@ mod tests {
|
|||||||
let cell = Arc::new(Mutex::new((0, time::Instant::now())));
|
let cell = Arc::new(Mutex::new((0, time::Instant::now())));
|
||||||
let cell2 = cell.clone();
|
let cell2 = cell.clone();
|
||||||
let proposer = proposer_factory.init_with_now(
|
let proposer = proposer_factory.init_with_now(
|
||||||
&client.expect_header(client.info().genesis_hash).unwrap(),
|
&client.expect_header(genesis_hash).unwrap(),
|
||||||
Box::new(move || {
|
Box::new(move || {
|
||||||
let mut value = cell.lock();
|
let mut value = cell.lock();
|
||||||
let (called, old) = *value;
|
let (called, old) = *value;
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ mod tests {
|
|||||||
use sc_transaction_pool::{BasicPool, FullChainApi, Options, RevalidationType};
|
use sc_transaction_pool::{BasicPool, FullChainApi, Options, RevalidationType};
|
||||||
use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool, TransactionSource};
|
use sc_transaction_pool_api::{MaintainedTransactionPool, TransactionPool, TransactionSource};
|
||||||
use sp_inherents::InherentData;
|
use sp_inherents::InherentData;
|
||||||
use sp_runtime::generic::{BlockId, Digest, DigestItem};
|
use sp_runtime::generic::{Digest, DigestItem};
|
||||||
use substrate_test_runtime_client::{
|
use substrate_test_runtime_client::{
|
||||||
AccountKeyring::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
|
AccountKeyring::*, DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
|
||||||
};
|
};
|
||||||
@@ -400,10 +400,11 @@ mod tests {
|
|||||||
let client = Arc::new(client);
|
let client = Arc::new(client);
|
||||||
let spawner = sp_core::testing::TaskExecutor::new();
|
let spawner = sp_core::testing::TaskExecutor::new();
|
||||||
let genesis_hash = client.info().genesis_hash;
|
let genesis_hash = client.info().genesis_hash;
|
||||||
|
let pool_api = Arc::new(FullChainApi::new(client.clone(), None, &spawner.clone()));
|
||||||
let pool = Arc::new(BasicPool::with_revalidation_type(
|
let pool = Arc::new(BasicPool::with_revalidation_type(
|
||||||
Options::default(),
|
Options::default(),
|
||||||
true.into(),
|
true.into(),
|
||||||
api(),
|
pool_api,
|
||||||
None,
|
None,
|
||||||
RevalidationType::Full,
|
RevalidationType::Full,
|
||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
@@ -444,7 +445,7 @@ mod tests {
|
|||||||
rt.block_on(future);
|
rt.block_on(future);
|
||||||
});
|
});
|
||||||
// submit a transaction to pool.
|
// submit a transaction to pool.
|
||||||
let result = pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Alice, 0)).await;
|
let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await;
|
||||||
// assert that it was successfully imported
|
// assert that it was successfully imported
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
// assert that the background task returns ok
|
// assert that the background task returns ok
|
||||||
@@ -475,10 +476,11 @@ mod tests {
|
|||||||
let client = Arc::new(client);
|
let client = Arc::new(client);
|
||||||
let spawner = sp_core::testing::TaskExecutor::new();
|
let spawner = sp_core::testing::TaskExecutor::new();
|
||||||
let genesis_hash = client.info().genesis_hash;
|
let genesis_hash = client.info().genesis_hash;
|
||||||
|
let pool_api = Arc::new(FullChainApi::new(client.clone(), None, &spawner.clone()));
|
||||||
let pool = Arc::new(BasicPool::with_revalidation_type(
|
let pool = Arc::new(BasicPool::with_revalidation_type(
|
||||||
Options::default(),
|
Options::default(),
|
||||||
true.into(),
|
true.into(),
|
||||||
api(),
|
pool_api,
|
||||||
None,
|
None,
|
||||||
RevalidationType::Full,
|
RevalidationType::Full,
|
||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
@@ -535,7 +537,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut finality_stream = client.finality_notification_stream();
|
let mut finality_stream = client.finality_notification_stream();
|
||||||
// submit a transaction to pool.
|
// submit a transaction to pool.
|
||||||
let result = pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Alice, 0)).await;
|
let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await;
|
||||||
// assert that it was successfully imported
|
// assert that it was successfully imported
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
// assert that the background task returns ok
|
// assert that the background task returns ok
|
||||||
@@ -571,10 +573,11 @@ mod tests {
|
|||||||
let client = Arc::new(client);
|
let client = Arc::new(client);
|
||||||
let spawner = sp_core::testing::TaskExecutor::new();
|
let spawner = sp_core::testing::TaskExecutor::new();
|
||||||
let genesis_hash = client.info().genesis_hash;
|
let genesis_hash = client.info().genesis_hash;
|
||||||
|
let pool_api = Arc::new(FullChainApi::new(client.clone(), None, &spawner.clone()));
|
||||||
let pool = Arc::new(BasicPool::with_revalidation_type(
|
let pool = Arc::new(BasicPool::with_revalidation_type(
|
||||||
Options::default(),
|
Options::default(),
|
||||||
true.into(),
|
true.into(),
|
||||||
api(),
|
pool_api,
|
||||||
None,
|
None,
|
||||||
RevalidationType::Full,
|
RevalidationType::Full,
|
||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
@@ -602,7 +605,7 @@ mod tests {
|
|||||||
rt.block_on(future);
|
rt.block_on(future);
|
||||||
});
|
});
|
||||||
// submit a transaction to pool.
|
// submit a transaction to pool.
|
||||||
let result = pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Alice, 0)).await;
|
let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await;
|
||||||
// assert that it was successfully imported
|
// assert that it was successfully imported
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let (tx, rx) = futures::channel::oneshot::channel();
|
let (tx, rx) = futures::channel::oneshot::channel();
|
||||||
@@ -688,7 +691,7 @@ mod tests {
|
|||||||
rt.block_on(future);
|
rt.block_on(future);
|
||||||
});
|
});
|
||||||
// submit a transaction to pool.
|
// submit a transaction to pool.
|
||||||
let result = pool.submit_one(&BlockId::Number(0), SOURCE, uxt(Alice, 0)).await;
|
let result = pool.submit_one(genesis_hash, SOURCE, uxt(Alice, 0)).await;
|
||||||
// assert that it was successfully imported
|
// assert that it was successfully imported
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
@@ -719,7 +722,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(pool.submit_one(&BlockId::Number(1), SOURCE, uxt(Alice, 1)).await.is_ok());
|
assert!(pool.submit_one(created_block.hash, SOURCE, uxt(Alice, 1)).await.is_ok());
|
||||||
|
|
||||||
let header = client.header(created_block.hash).expect("db error").expect("imported above");
|
let header = client.header(created_block.hash).expect("db error").expect("imported above");
|
||||||
assert_eq!(header.number, 1);
|
assert_eq!(header.number, 1);
|
||||||
@@ -741,7 +744,7 @@ mod tests {
|
|||||||
.is_ok());
|
.is_ok());
|
||||||
assert_matches::assert_matches!(rx1.await.expect("should be no error receiving"), Ok(_));
|
assert_matches::assert_matches!(rx1.await.expect("should be no error receiving"), Ok(_));
|
||||||
|
|
||||||
assert!(pool.submit_one(&BlockId::Number(1), SOURCE, uxt(Bob, 0)).await.is_ok());
|
assert!(pool.submit_one(created_block.hash, SOURCE, uxt(Bob, 0)).await.is_ok());
|
||||||
let (tx2, rx2) = futures::channel::oneshot::channel();
|
let (tx2, rx2) = futures::channel::oneshot::channel();
|
||||||
assert!(sink
|
assert!(sink
|
||||||
.send(EngineCommand::SealNewBlock {
|
.send(EngineCommand::SealNewBlock {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ use std::sync::Arc;
|
|||||||
use sp_api::ProvideRuntimeApi;
|
use sp_api::ProvideRuntimeApi;
|
||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
use sp_runtime::{generic, traits::Block as BlockT};
|
use sp_runtime::traits::Block as BlockT;
|
||||||
|
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
use futures::{FutureExt, StreamExt, TryFutureExt};
|
use futures::{FutureExt, StreamExt, TryFutureExt};
|
||||||
@@ -110,11 +110,7 @@ where
|
|||||||
|
|
||||||
let submit = self
|
let submit = self
|
||||||
.pool
|
.pool
|
||||||
.submit_and_watch(
|
.submit_and_watch(best_block_hash, TX_SOURCE, decoded_extrinsic)
|
||||||
&generic::BlockId::hash(best_block_hash),
|
|
||||||
TX_SOURCE,
|
|
||||||
decoded_extrinsic,
|
|
||||||
)
|
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
e.into_pool_error()
|
e.into_pool_error()
|
||||||
.map(Error::from)
|
.map(Error::from)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ use sp_api::{ApiExt, ProvideRuntimeApi};
|
|||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
use sp_keystore::{KeystoreExt, KeystorePtr};
|
use sp_keystore::{KeystoreExt, KeystorePtr};
|
||||||
use sp_runtime::{generic, traits::Block as BlockT};
|
use sp_runtime::traits::Block as BlockT;
|
||||||
use sp_session::SessionKeys;
|
use sp_session::SessionKeys;
|
||||||
|
|
||||||
use self::error::{Error, Result};
|
use self::error::{Error, Result};
|
||||||
@@ -97,15 +97,12 @@ where
|
|||||||
Err(err) => return Err(Error::Client(Box::new(err)).into()),
|
Err(err) => return Err(Error::Client(Box::new(err)).into()),
|
||||||
};
|
};
|
||||||
let best_block_hash = self.client.info().best_hash;
|
let best_block_hash = self.client.info().best_hash;
|
||||||
self.pool
|
self.pool.submit_one(best_block_hash, TX_SOURCE, xt).await.map_err(|e| {
|
||||||
.submit_one(&generic::BlockId::hash(best_block_hash), TX_SOURCE, xt)
|
e.into_pool_error()
|
||||||
.await
|
.map(|e| Error::Pool(e))
|
||||||
.map_err(|e| {
|
.unwrap_or_else(|e| Error::Verification(Box::new(e)))
|
||||||
e.into_pool_error()
|
.into()
|
||||||
.map(|e| Error::Pool(e))
|
})
|
||||||
.unwrap_or_else(|e| Error::Verification(Box::new(e)))
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> RpcResult<()> {
|
fn insert_key(&self, key_type: String, suri: String, public: Bytes) -> RpcResult<()> {
|
||||||
@@ -191,14 +188,11 @@ where
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let submit = self
|
let submit = self.pool.submit_and_watch(best_block_hash, TX_SOURCE, dxt).map_err(|e| {
|
||||||
.pool
|
e.into_pool_error()
|
||||||
.submit_and_watch(&generic::BlockId::hash(best_block_hash), TX_SOURCE, dxt)
|
.map(error::Error::from)
|
||||||
.map_err(|e| {
|
.unwrap_or_else(|e| error::Error::Verification(Box::new(e)))
|
||||||
e.into_pool_error()
|
});
|
||||||
.map(error::Error::from)
|
|
||||||
.unwrap_or_else(|e| error::Error::Verification(Box::new(e)))
|
|
||||||
});
|
|
||||||
|
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
let stream = match submit.await {
|
let stream = match submit.await {
|
||||||
|
|||||||
@@ -48,10 +48,7 @@ use sc_network_sync::SyncingService;
|
|||||||
use sc_utils::mpsc::TracingUnboundedReceiver;
|
use sc_utils::mpsc::TracingUnboundedReceiver;
|
||||||
use sp_blockchain::HeaderMetadata;
|
use sp_blockchain::HeaderMetadata;
|
||||||
use sp_consensus::SyncOracle;
|
use sp_consensus::SyncOracle;
|
||||||
use sp_runtime::{
|
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
|
||||||
generic::BlockId,
|
|
||||||
traits::{Block as BlockT, Header as HeaderT},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
builder::{
|
builder::{
|
||||||
@@ -481,10 +478,8 @@ where
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let best_block_id = BlockId::hash(self.client.info().best_hash);
|
|
||||||
|
|
||||||
let import_future = self.pool.submit_one(
|
let import_future = self.pool.submit_one(
|
||||||
&best_block_id,
|
self.client.info().best_hash,
|
||||||
sc_transaction_pool_api::TransactionSource::External,
|
sc_transaction_pool_api::TransactionSource::External,
|
||||||
uxt,
|
uxt,
|
||||||
);
|
);
|
||||||
@@ -549,10 +544,9 @@ mod tests {
|
|||||||
to: AccountKeyring::Bob.into(),
|
to: AccountKeyring::Bob.into(),
|
||||||
}
|
}
|
||||||
.into_unchecked_extrinsic();
|
.into_unchecked_extrinsic();
|
||||||
block_on(pool.submit_one(&BlockId::hash(best.hash()), source, transaction.clone()))
|
block_on(pool.submit_one(best.hash(), source, transaction.clone())).unwrap();
|
||||||
.unwrap();
|
|
||||||
block_on(pool.submit_one(
|
block_on(pool.submit_one(
|
||||||
&BlockId::hash(best.hash()),
|
best.hash(),
|
||||||
source,
|
source,
|
||||||
ExtrinsicBuilder::new_call_do_not_propagate().nonce(1).build(),
|
ExtrinsicBuilder::new_call_do_not_propagate().nonce(1).build(),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ use sc_service::{
|
|||||||
RuntimeGenesis, SpawnTaskHandle, TaskManager,
|
RuntimeGenesis, SpawnTaskHandle, TaskManager,
|
||||||
};
|
};
|
||||||
use sc_transaction_pool_api::TransactionPool;
|
use sc_transaction_pool_api::TransactionPool;
|
||||||
use sp_api::BlockId;
|
|
||||||
use sp_blockchain::HeaderBackend;
|
use sp_blockchain::HeaderBackend;
|
||||||
use sp_runtime::traits::Block as BlockT;
|
use sp_runtime::traits::Block as BlockT;
|
||||||
use std::{iter, net::Ipv4Addr, pin::Pin, sync::Arc, task::Context, time::Duration};
|
use std::{iter, net::Ipv4Addr, pin::Pin, sync::Arc, task::Context, time::Duration};
|
||||||
@@ -501,15 +500,13 @@ pub fn sync<G, E, Fb, F, B, ExF, U>(
|
|||||||
info!("Checking extrinsic propagation");
|
info!("Checking extrinsic propagation");
|
||||||
let first_service = network.full_nodes[0].1.clone();
|
let first_service = network.full_nodes[0].1.clone();
|
||||||
let first_user_data = &network.full_nodes[0].2;
|
let first_user_data = &network.full_nodes[0].2;
|
||||||
let best_block = BlockId::number(first_service.client().info().best_number);
|
let best_block = first_service.client().info().best_hash;
|
||||||
let extrinsic = extrinsic_factory(&first_service, first_user_data);
|
let extrinsic = extrinsic_factory(&first_service, first_user_data);
|
||||||
let source = sc_transaction_pool_api::TransactionSource::External;
|
let source = sc_transaction_pool_api::TransactionSource::External;
|
||||||
|
|
||||||
futures::executor::block_on(first_service.transaction_pool().submit_one(
|
futures::executor::block_on(
|
||||||
&best_block,
|
first_service.transaction_pool().submit_one(best_block, source, extrinsic),
|
||||||
source,
|
)
|
||||||
extrinsic,
|
|
||||||
))
|
|
||||||
.expect("failed to submit extrinsic");
|
.expect("failed to submit extrinsic");
|
||||||
|
|
||||||
network.run_until_all_full(|_index, service| service.transaction_pool().ready().count() == 1);
|
network.run_until_all_full(|_index, service| service.transaction_pool().ready().count() == 1);
|
||||||
|
|||||||
@@ -26,10 +26,7 @@ use codec::Codec;
|
|||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use sp_core::offchain::TransactionPoolExt;
|
use sp_core::offchain::TransactionPoolExt;
|
||||||
use sp_runtime::{
|
use sp_runtime::traits::{Block as BlockT, Member, NumberFor};
|
||||||
generic::BlockId,
|
|
||||||
traits::{Block as BlockT, Member, NumberFor},
|
|
||||||
};
|
|
||||||
use std::{collections::HashMap, hash::Hash, marker::PhantomData, pin::Pin, sync::Arc};
|
use std::{collections::HashMap, hash::Hash, marker::PhantomData, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
const LOG_TARGET: &str = "txpool::api";
|
const LOG_TARGET: &str = "txpool::api";
|
||||||
@@ -202,7 +199,7 @@ pub trait TransactionPool: Send + Sync {
|
|||||||
/// Returns a future that imports a bunch of unverified transactions to the pool.
|
/// Returns a future that imports a bunch of unverified transactions to the pool.
|
||||||
fn submit_at(
|
fn submit_at(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xts: Vec<TransactionFor<Self>>,
|
xts: Vec<TransactionFor<Self>>,
|
||||||
) -> PoolFuture<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error>;
|
) -> PoolFuture<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error>;
|
||||||
@@ -210,7 +207,7 @@ pub trait TransactionPool: Send + Sync {
|
|||||||
/// Returns a future that imports one unverified transaction to the pool.
|
/// Returns a future that imports one unverified transaction to the pool.
|
||||||
fn submit_one(
|
fn submit_one(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: TransactionFor<Self>,
|
xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<TxHash<Self>, Self::Error>;
|
) -> PoolFuture<TxHash<Self>, Self::Error>;
|
||||||
@@ -219,7 +216,7 @@ pub trait TransactionPool: Send + Sync {
|
|||||||
/// pool.
|
/// pool.
|
||||||
fn submit_and_watch(
|
fn submit_and_watch(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: TransactionFor<Self>,
|
xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error>;
|
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error>;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ use sp_runtime::{
|
|||||||
ValidTransaction,
|
ValidTransaction,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
use substrate_test_runtime::{AccountId, Block, Extrinsic, ExtrinsicBuilder, TransferData, H256};
|
use substrate_test_runtime::{AccountId, Block, Extrinsic, ExtrinsicBuilder, TransferData, H256};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
@@ -61,7 +62,7 @@ impl ChainApi for TestApi {
|
|||||||
|
|
||||||
fn validate_transaction(
|
fn validate_transaction(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
uxt: <Self::Block as BlockT>::Extrinsic,
|
uxt: <Self::Block as BlockT>::Extrinsic,
|
||||||
) -> Self::ValidationFuture {
|
) -> Self::ValidationFuture {
|
||||||
@@ -70,7 +71,7 @@ impl ChainApi for TestApi {
|
|||||||
let nonce = transfer.nonce;
|
let nonce = transfer.nonce;
|
||||||
let from = transfer.from;
|
let from = transfer.from;
|
||||||
|
|
||||||
match self.block_id_to_number(at) {
|
match self.block_id_to_number(&BlockId::Hash(at)) {
|
||||||
Ok(Some(num)) if num > 5 => return ready(Ok(Err(InvalidTransaction::Stale.into()))),
|
Ok(Some(num)) if num > 5 => return ready(Ok(Err(InvalidTransaction::Stale.into()))),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
@@ -94,6 +95,8 @@ impl ChainApi for TestApi {
|
|||||||
) -> Result<Option<NumberFor<Self::Block>>, Self::Error> {
|
) -> Result<Option<NumberFor<Self::Block>>, Self::Error> {
|
||||||
Ok(match at {
|
Ok(match at {
|
||||||
BlockId::Number(num) => Some(*num),
|
BlockId::Number(num) => Some(*num),
|
||||||
|
BlockId::Hash(hash) if *hash == H256::from_low_u64_be(hash.to_low_u64_be()) =>
|
||||||
|
Some(hash.to_low_u64_be()),
|
||||||
BlockId::Hash(_) => None,
|
BlockId::Hash(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -104,7 +107,7 @@ impl ChainApi for TestApi {
|
|||||||
) -> Result<Option<<Self::Block as BlockT>::Hash>, Self::Error> {
|
) -> Result<Option<<Self::Block as BlockT>::Hash>, Self::Error> {
|
||||||
Ok(match at {
|
Ok(match at {
|
||||||
BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(),
|
BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(),
|
||||||
BlockId::Hash(_) => None,
|
BlockId::Hash(hash) => Some(*hash),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +140,7 @@ fn uxt(transfer: TransferData) -> Extrinsic {
|
|||||||
ExtrinsicBuilder::new_bench_call(transfer).build()
|
ExtrinsicBuilder::new_bench_call(transfer).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
fn bench_configured(pool: Pool<TestApi>, number: u64, api: Arc<TestApi>) {
|
||||||
let source = TransactionSource::External;
|
let source = TransactionSource::External;
|
||||||
let mut futures = Vec::new();
|
let mut futures = Vec::new();
|
||||||
let mut tags = Vec::new();
|
let mut tags = Vec::new();
|
||||||
@@ -151,7 +154,12 @@ fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
tags.push(to_tag(nonce, AccountId::from_h256(H256::from_low_u64_be(1))));
|
tags.push(to_tag(nonce, AccountId::from_h256(H256::from_low_u64_be(1))));
|
||||||
futures.push(pool.submit_one(&BlockId::Number(1), source, xt));
|
|
||||||
|
futures.push(pool.submit_one(
|
||||||
|
api.block_id_to_hash(&BlockId::Number(1)).unwrap().unwrap(),
|
||||||
|
source,
|
||||||
|
xt,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = block_on(futures::future::join_all(futures.into_iter()));
|
let res = block_on(futures::future::join_all(futures.into_iter()));
|
||||||
@@ -162,7 +170,12 @@ fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
|||||||
|
|
||||||
// Prune all transactions.
|
// Prune all transactions.
|
||||||
let block_num = 6;
|
let block_num = 6;
|
||||||
block_on(pool.prune_tags(&BlockId::Number(block_num), tags, vec![])).expect("Prune failed");
|
block_on(pool.prune_tags(
|
||||||
|
api.block_id_to_hash(&BlockId::Number(block_num)).unwrap().unwrap(),
|
||||||
|
tags,
|
||||||
|
vec![],
|
||||||
|
))
|
||||||
|
.expect("Prune failed");
|
||||||
|
|
||||||
// pool is empty
|
// pool is empty
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
@@ -172,19 +185,15 @@ fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
|||||||
fn benchmark_main(c: &mut Criterion) {
|
fn benchmark_main(c: &mut Criterion) {
|
||||||
c.bench_function("sequential 50 tx", |b| {
|
c.bench_function("sequential 50 tx", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
bench_configured(
|
let api = Arc::from(TestApi::new_dependant());
|
||||||
Pool::new(Default::default(), true.into(), TestApi::new_dependant().into()),
|
bench_configured(Pool::new(Default::default(), true.into(), api.clone()), 50, api);
|
||||||
50,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
c.bench_function("random 100 tx", |b| {
|
c.bench_function("random 100 tx", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
bench_configured(
|
let api = Arc::from(TestApi::default());
|
||||||
Pool::new(Default::default(), true.into(), TestApi::default().into()),
|
bench_configured(Pool::new(Default::default(), true.into(), api.clone()), 100, api);
|
||||||
100,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,13 +133,12 @@ where
|
|||||||
|
|
||||||
fn validate_transaction(
|
fn validate_transaction(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
uxt: graph::ExtrinsicFor<Self>,
|
uxt: graph::ExtrinsicFor<Self>,
|
||||||
) -> Self::ValidationFuture {
|
) -> Self::ValidationFuture {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
let at = *at;
|
|
||||||
let validation_pool = self.validation_pool.clone();
|
let validation_pool = self.validation_pool.clone();
|
||||||
let metrics = self.metrics.clone();
|
let metrics = self.metrics.clone();
|
||||||
|
|
||||||
@@ -151,7 +150,7 @@ where
|
|||||||
.await
|
.await
|
||||||
.send(
|
.send(
|
||||||
async move {
|
async move {
|
||||||
let res = validate_transaction_blocking(&*client, &at, source, uxt);
|
let res = validate_transaction_blocking(&*client, at, source, uxt);
|
||||||
let _ = tx.send(res);
|
let _ = tx.send(res);
|
||||||
metrics.report(|m| m.validations_finished.inc());
|
metrics.report(|m| m.validations_finished.inc());
|
||||||
}
|
}
|
||||||
@@ -209,7 +208,7 @@ where
|
|||||||
/// This method will call into the runtime to perform the validation.
|
/// This method will call into the runtime to perform the validation.
|
||||||
fn validate_transaction_blocking<Client, Block>(
|
fn validate_transaction_blocking<Client, Block>(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
at: &BlockId<Block>,
|
at: Block::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
uxt: graph::ExtrinsicFor<FullChainApi<Client, Block>>,
|
uxt: graph::ExtrinsicFor<FullChainApi<Client, Block>>,
|
||||||
) -> error::Result<TransactionValidity>
|
) -> error::Result<TransactionValidity>
|
||||||
@@ -225,14 +224,10 @@ where
|
|||||||
{
|
{
|
||||||
sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction";
|
sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction";
|
||||||
{
|
{
|
||||||
let block_hash = client.to_hash(at)
|
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))?
|
|
||||||
.ok_or_else(|| Error::RuntimeApi(format!("Could not get hash for block `{:?}`.", at)))?;
|
|
||||||
|
|
||||||
let runtime_api = client.runtime_api();
|
let runtime_api = client.runtime_api();
|
||||||
let api_version = sp_tracing::within_span! { sp_tracing::Level::TRACE, "check_version";
|
let api_version = sp_tracing::within_span! { sp_tracing::Level::TRACE, "check_version";
|
||||||
runtime_api
|
runtime_api
|
||||||
.api_version::<dyn TaggedTransactionQueue<Block>>(block_hash)
|
.api_version::<dyn TaggedTransactionQueue<Block>>(at)
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))?
|
.map_err(|e| Error::RuntimeApi(e.to_string()))?
|
||||||
.ok_or_else(|| Error::RuntimeApi(
|
.ok_or_else(|| Error::RuntimeApi(
|
||||||
format!("Could not find `TaggedTransactionQueue` api for block `{:?}`.", at)
|
format!("Could not find `TaggedTransactionQueue` api for block `{:?}`.", at)
|
||||||
@@ -245,31 +240,31 @@ where
|
|||||||
sp_tracing::Level::TRACE, "runtime::validate_transaction";
|
sp_tracing::Level::TRACE, "runtime::validate_transaction";
|
||||||
{
|
{
|
||||||
if api_version >= 3 {
|
if api_version >= 3 {
|
||||||
runtime_api.validate_transaction(block_hash, source, uxt, block_hash)
|
runtime_api.validate_transaction(at, source, uxt, at)
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
||||||
} else {
|
} else {
|
||||||
let block_number = client.to_number(at)
|
let block_number = client.to_number(&BlockId::Hash(at))
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))?
|
.map_err(|e| Error::RuntimeApi(e.to_string()))?
|
||||||
.ok_or_else(||
|
.ok_or_else(||
|
||||||
Error::RuntimeApi(format!("Could not get number for block `{:?}`.", at))
|
Error::RuntimeApi(format!("Could not get number for block `{:?}`.", at))
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// The old versions require us to call `initialize_block` before.
|
// The old versions require us to call `initialize_block` before.
|
||||||
runtime_api.initialize_block(block_hash, &sp_runtime::traits::Header::new(
|
runtime_api.initialize_block(at, &sp_runtime::traits::Header::new(
|
||||||
block_number + sp_runtime::traits::One::one(),
|
block_number + sp_runtime::traits::One::one(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
block_hash,
|
at,
|
||||||
Default::default()),
|
Default::default()),
|
||||||
).map_err(|e| Error::RuntimeApi(e.to_string()))?;
|
).map_err(|e| Error::RuntimeApi(e.to_string()))?;
|
||||||
|
|
||||||
if api_version == 2 {
|
if api_version == 2 {
|
||||||
#[allow(deprecated)] // old validate_transaction
|
#[allow(deprecated)] // old validate_transaction
|
||||||
runtime_api.validate_transaction_before_version_3(block_hash, source, uxt)
|
runtime_api.validate_transaction_before_version_3(at, source, uxt)
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
||||||
} else {
|
} else {
|
||||||
#[allow(deprecated)] // old validate_transaction
|
#[allow(deprecated)] // old validate_transaction
|
||||||
runtime_api.validate_transaction_before_version_2(block_hash, uxt)
|
runtime_api.validate_transaction_before_version_2(at, uxt)
|
||||||
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
.map_err(|e| Error::RuntimeApi(e.to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +289,7 @@ where
|
|||||||
/// the runtime locally.
|
/// the runtime locally.
|
||||||
pub fn validate_transaction_blocking(
|
pub fn validate_transaction_blocking(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Block>,
|
at: Block::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
uxt: graph::ExtrinsicFor<Self>,
|
uxt: graph::ExtrinsicFor<Self>,
|
||||||
) -> error::Result<TransactionValidity> {
|
) -> error::Result<TransactionValidity> {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ pub trait ChainApi: Send + Sync {
|
|||||||
/// Verify extrinsic at given block.
|
/// Verify extrinsic at given block.
|
||||||
fn validate_transaction(
|
fn validate_transaction(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
uxt: ExtrinsicFor<Self>,
|
uxt: ExtrinsicFor<Self>,
|
||||||
) -> Self::ValidationFuture;
|
) -> Self::ValidationFuture;
|
||||||
@@ -154,7 +154,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// Imports a bunch of unverified extrinsics to the pool
|
/// Imports a bunch of unverified extrinsics to the pool
|
||||||
pub async fn submit_at(
|
pub async fn submit_at(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xts: impl IntoIterator<Item = ExtrinsicFor<B>>,
|
xts: impl IntoIterator<Item = ExtrinsicFor<B>>,
|
||||||
) -> Result<Vec<Result<ExtrinsicHash<B>, B::Error>>, B::Error> {
|
) -> Result<Vec<Result<ExtrinsicHash<B>, B::Error>>, B::Error> {
|
||||||
@@ -168,7 +168,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// This does not check if a transaction is banned, before we verify it again.
|
/// This does not check if a transaction is banned, before we verify it again.
|
||||||
pub async fn resubmit_at(
|
pub async fn resubmit_at(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xts: impl IntoIterator<Item = ExtrinsicFor<B>>,
|
xts: impl IntoIterator<Item = ExtrinsicFor<B>>,
|
||||||
) -> Result<Vec<Result<ExtrinsicHash<B>, B::Error>>, B::Error> {
|
) -> Result<Vec<Result<ExtrinsicHash<B>, B::Error>>, B::Error> {
|
||||||
@@ -180,7 +180,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// Imports one unverified extrinsic to the pool
|
/// Imports one unverified extrinsic to the pool
|
||||||
pub async fn submit_one(
|
pub async fn submit_one(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: ExtrinsicFor<B>,
|
xt: ExtrinsicFor<B>,
|
||||||
) -> Result<ExtrinsicHash<B>, B::Error> {
|
) -> Result<ExtrinsicHash<B>, B::Error> {
|
||||||
@@ -191,11 +191,11 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// Import a single extrinsic and starts to watch its progress in the pool.
|
/// Import a single extrinsic and starts to watch its progress in the pool.
|
||||||
pub async fn submit_and_watch(
|
pub async fn submit_and_watch(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: ExtrinsicFor<B>,
|
xt: ExtrinsicFor<B>,
|
||||||
) -> Result<Watcher<ExtrinsicHash<B>, ExtrinsicHash<B>>, B::Error> {
|
) -> Result<Watcher<ExtrinsicHash<B>, ExtrinsicHash<B>>, B::Error> {
|
||||||
let block_number = self.resolve_block_number(at)?;
|
let block_number = self.resolve_block_number(&BlockId::Hash(at))?;
|
||||||
let (_, tx) = self
|
let (_, tx) = self
|
||||||
.verify_one(at, block_number, source, xt, CheckBannedBeforeVerify::Yes)
|
.verify_one(at, block_number, source, xt, CheckBannedBeforeVerify::Yes)
|
||||||
.await;
|
.await;
|
||||||
@@ -246,8 +246,8 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// their provided tags from there. Otherwise we query the runtime at the `parent` block.
|
/// their provided tags from there. Otherwise we query the runtime at the `parent` block.
|
||||||
pub async fn prune(
|
pub async fn prune(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
parent: &BlockId<B::Block>,
|
parent: <B::Block as BlockT>::Hash,
|
||||||
extrinsics: &[ExtrinsicFor<B>],
|
extrinsics: &[ExtrinsicFor<B>],
|
||||||
) -> Result<(), B::Error> {
|
) -> Result<(), B::Error> {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
@@ -324,7 +324,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// prevent importing them in the (near) future.
|
/// prevent importing them in the (near) future.
|
||||||
pub async fn prune_tags(
|
pub async fn prune_tags(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
tags: impl IntoIterator<Item = Tag>,
|
tags: impl IntoIterator<Item = Tag>,
|
||||||
known_imported_hashes: impl IntoIterator<Item = ExtrinsicHash<B>> + Clone,
|
known_imported_hashes: impl IntoIterator<Item = ExtrinsicHash<B>> + Clone,
|
||||||
) -> Result<(), B::Error> {
|
) -> Result<(), B::Error> {
|
||||||
@@ -351,7 +351,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
// And finally - submit reverified transactions back to the pool
|
// And finally - submit reverified transactions back to the pool
|
||||||
|
|
||||||
self.validated_pool.resubmit_pruned(
|
self.validated_pool.resubmit_pruned(
|
||||||
at,
|
&BlockId::Hash(at),
|
||||||
known_imported_hashes,
|
known_imported_hashes,
|
||||||
pruned_hashes,
|
pruned_hashes,
|
||||||
reverified_transactions.into_values().collect(),
|
reverified_transactions.into_values().collect(),
|
||||||
@@ -373,12 +373,12 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// Returns future that validates a bunch of transactions at given block.
|
/// Returns future that validates a bunch of transactions at given block.
|
||||||
async fn verify(
|
async fn verify(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<B::Block>,
|
at: <B::Block as BlockT>::Hash,
|
||||||
xts: impl IntoIterator<Item = (TransactionSource, ExtrinsicFor<B>)>,
|
xts: impl IntoIterator<Item = (TransactionSource, ExtrinsicFor<B>)>,
|
||||||
check: CheckBannedBeforeVerify,
|
check: CheckBannedBeforeVerify,
|
||||||
) -> Result<HashMap<ExtrinsicHash<B>, ValidatedTransactionFor<B>>, B::Error> {
|
) -> Result<HashMap<ExtrinsicHash<B>, ValidatedTransactionFor<B>>, B::Error> {
|
||||||
// we need a block number to compute tx validity
|
// we need a block number to compute tx validity
|
||||||
let block_number = self.resolve_block_number(at)?;
|
let block_number = self.resolve_block_number(&BlockId::Hash(at))?;
|
||||||
|
|
||||||
let res = futures::future::join_all(
|
let res = futures::future::join_all(
|
||||||
xts.into_iter()
|
xts.into_iter()
|
||||||
@@ -394,7 +394,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
/// Returns future that validates single transaction at given block.
|
/// Returns future that validates single transaction at given block.
|
||||||
async fn verify_one(
|
async fn verify_one(
|
||||||
&self,
|
&self,
|
||||||
block_id: &BlockId<B::Block>,
|
block_hash: <B::Block as BlockT>::Hash,
|
||||||
block_number: NumberFor<B>,
|
block_number: NumberFor<B>,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: ExtrinsicFor<B>,
|
xt: ExtrinsicFor<B>,
|
||||||
@@ -410,7 +410,7 @@ impl<B: ChainApi> Pool<B> {
|
|||||||
let validation_result = self
|
let validation_result = self
|
||||||
.validated_pool
|
.validated_pool
|
||||||
.api()
|
.api()
|
||||||
.validate_transaction(block_id, source, xt.clone())
|
.validate_transaction(block_hash, source, xt.clone())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let status = match validation_result {
|
let status = match validation_result {
|
||||||
@@ -458,6 +458,7 @@ mod tests {
|
|||||||
use super::{super::base_pool::Limit, *};
|
use super::{super::base_pool::Limit, *};
|
||||||
use crate::tests::{pool, uxt, TestApi, INVALID_NONCE};
|
use crate::tests::{pool, uxt, TestApi, INVALID_NONCE};
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
|
use codec::Encode;
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use sc_transaction_pool_api::TransactionStatus;
|
use sc_transaction_pool_api::TransactionStatus;
|
||||||
@@ -471,11 +472,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_validate_and_import_transaction() {
|
fn should_validate_and_import_transaction() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let hash = block_on(pool.submit_one(
|
let hash = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -493,7 +494,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_reject_if_temporarily_banned() {
|
fn should_reject_if_temporarily_banned() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let uxt = uxt(Transfer {
|
let uxt = uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||||
@@ -503,7 +504,7 @@ mod tests {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
pool.validated_pool.ban(&Instant::now(), vec![pool.hash_of(&uxt)]);
|
pool.validated_pool.ban(&Instant::now(), vec![pool.hash_of(&uxt)]);
|
||||||
let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt));
|
let res = block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt));
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
assert_eq!(pool.validated_pool().status().future, 0);
|
assert_eq!(pool.validated_pool().status().future, 0);
|
||||||
|
|
||||||
@@ -514,18 +515,19 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_reject_unactionable_transactions() {
|
fn should_reject_unactionable_transactions() {
|
||||||
// given
|
// given
|
||||||
|
let api = Arc::new(TestApi::default());
|
||||||
let pool = Pool::new(
|
let pool = Pool::new(
|
||||||
Default::default(),
|
Default::default(),
|
||||||
// the node does not author blocks
|
// the node does not author blocks
|
||||||
false.into(),
|
false.into(),
|
||||||
TestApi::default().into(),
|
api.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// after validation `IncludeData` will be set to non-propagable (validate_transaction mock)
|
// after validation `IncludeData` will be set to non-propagable (validate_transaction mock)
|
||||||
let uxt = ExtrinsicBuilder::new_include_data(vec![42]).build();
|
let uxt = ExtrinsicBuilder::new_include_data(vec![42]).build();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt));
|
let res = block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt));
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_matches!(res.unwrap_err(), error::Error::Unactionable);
|
assert_matches!(res.unwrap_err(), error::Error::Unactionable);
|
||||||
@@ -535,12 +537,13 @@ mod tests {
|
|||||||
fn should_notify_about_pool_events() {
|
fn should_notify_about_pool_events() {
|
||||||
let (stream, hash0, hash1) = {
|
let (stream, hash0, hash1) = {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
let stream = pool.validated_pool().import_notification_stream();
|
let stream = pool.validated_pool().import_notification_stream();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let hash0 = block_on(pool.submit_one(
|
let hash0 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -551,7 +554,7 @@ mod tests {
|
|||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hash1 = block_on(pool.submit_one(
|
let hash1 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -563,7 +566,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
// future doesn't count
|
// future doesn't count
|
||||||
let _hash = block_on(pool.submit_one(
|
let _hash = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -590,9 +593,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_clear_stale_transactions() {
|
fn should_clear_stale_transactions() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
let hash1 = block_on(pool.submit_one(
|
let hash1 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -603,7 +607,7 @@ mod tests {
|
|||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hash2 = block_on(pool.submit_one(
|
let hash2 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -614,7 +618,7 @@ mod tests {
|
|||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let hash3 = block_on(pool.submit_one(
|
let hash3 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -641,9 +645,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_ban_mined_transactions() {
|
fn should_ban_mined_transactions() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let hash1 = block_on(pool.submit_one(
|
let hash1 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -655,12 +659,12 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1])).unwrap();
|
block_on(pool.prune_tags(api.expect_hash_from_number(1), vec![vec![0]], vec![hash1]))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert!(pool.validated_pool.is_banned(&hash1));
|
assert!(pool.validated_pool.is_banned(&hash1));
|
||||||
}
|
}
|
||||||
use codec::Encode;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_limit_futures() {
|
fn should_limit_futures() {
|
||||||
@@ -678,14 +682,15 @@ mod tests {
|
|||||||
|
|
||||||
let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||||
|
|
||||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Pool::new(options, true.into(), api.clone());
|
||||||
|
|
||||||
let hash1 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
let hash1 = block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().future, 1);
|
assert_eq!(pool.validated_pool().status().future, 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let hash2 = block_on(pool.submit_one(
|
let hash2 = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Bob.into(),
|
from: Bob.into(),
|
||||||
@@ -709,11 +714,12 @@ mod tests {
|
|||||||
|
|
||||||
let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||||
|
|
||||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Pool::new(options, true.into(), api.clone());
|
||||||
|
|
||||||
// when
|
// when
|
||||||
block_on(pool.submit_one(
|
block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -732,11 +738,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_reject_transactions_with_no_provides() {
|
fn should_reject_transactions_with_no_provides() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let err = block_on(pool.submit_one(
|
let err = block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -759,9 +765,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_trigger_ready_and_finalized() {
|
fn should_trigger_ready_and_finalized() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let watcher = block_on(pool.submit_and_watch(
|
let watcher = block_on(pool.submit_and_watch(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -774,26 +780,25 @@ mod tests {
|
|||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
assert_eq!(pool.validated_pool().status().future, 0);
|
assert_eq!(pool.validated_pool().status().future, 0);
|
||||||
|
|
||||||
|
let hash_of_block2 = api.expect_hash_from_number(2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![])).unwrap();
|
block_on(pool.prune_tags(hash_of_block2, vec![vec![0u8]], vec![])).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
assert_eq!(pool.validated_pool().status().future, 0);
|
assert_eq!(pool.validated_pool().status().future, 0);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let mut stream = futures::executor::block_on_stream(watcher.into_stream());
|
let mut stream = futures::executor::block_on_stream(watcher.into_stream());
|
||||||
assert_eq!(stream.next(), Some(TransactionStatus::Ready));
|
assert_eq!(stream.next(), Some(TransactionStatus::Ready));
|
||||||
assert_eq!(
|
assert_eq!(stream.next(), Some(TransactionStatus::InBlock((hash_of_block2.into(), 0))),);
|
||||||
stream.next(),
|
|
||||||
Some(TransactionStatus::InBlock((H256::from_low_u64_be(2).into(), 0))),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_trigger_ready_and_finalized_when_pruning_via_hash() {
|
fn should_trigger_ready_and_finalized_when_pruning_via_hash() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let watcher = block_on(pool.submit_and_watch(
|
let watcher = block_on(pool.submit_and_watch(
|
||||||
&BlockId::Number(0),
|
api.expect_hash_from_number(0),
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -806,8 +811,10 @@ mod tests {
|
|||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
assert_eq!(pool.validated_pool().status().future, 0);
|
assert_eq!(pool.validated_pool().status().future, 0);
|
||||||
|
|
||||||
|
let hash_of_block2 = api.expect_hash_from_number(2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
block_on(pool.prune_tags(&BlockId::Number(2), vec![vec![0u8]], vec![*watcher.hash()]))
|
block_on(pool.prune_tags(hash_of_block2, vec![vec![0u8]], vec![*watcher.hash()]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
assert_eq!(pool.validated_pool().status().future, 0);
|
assert_eq!(pool.validated_pool().status().future, 0);
|
||||||
@@ -815,18 +822,17 @@ mod tests {
|
|||||||
// then
|
// then
|
||||||
let mut stream = futures::executor::block_on_stream(watcher.into_stream());
|
let mut stream = futures::executor::block_on_stream(watcher.into_stream());
|
||||||
assert_eq!(stream.next(), Some(TransactionStatus::Ready));
|
assert_eq!(stream.next(), Some(TransactionStatus::Ready));
|
||||||
assert_eq!(
|
assert_eq!(stream.next(), Some(TransactionStatus::InBlock((hash_of_block2.into(), 0))),);
|
||||||
stream.next(),
|
|
||||||
Some(TransactionStatus::InBlock((H256::from_low_u64_be(2).into(), 0))),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_trigger_future_and_ready_after_promoted() {
|
fn should_trigger_future_and_ready_after_promoted() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
|
|
||||||
let watcher = block_on(pool.submit_and_watch(
|
let watcher = block_on(pool.submit_and_watch(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -841,7 +847,7 @@ mod tests {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
block_on(pool.submit_one(
|
block_on(pool.submit_one(
|
||||||
&BlockId::Number(0),
|
hash_of_block0,
|
||||||
SOURCE,
|
SOURCE,
|
||||||
uxt(Transfer {
|
uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -862,7 +868,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_trigger_invalid_and_ban() {
|
fn should_trigger_invalid_and_ban() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let uxt = uxt(Transfer {
|
let uxt = uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||||
@@ -870,7 +876,8 @@ mod tests {
|
|||||||
nonce: 0,
|
nonce: 0,
|
||||||
});
|
});
|
||||||
let watcher =
|
let watcher =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, uxt)).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, uxt))
|
||||||
|
.unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -886,7 +893,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_trigger_broadcasted() {
|
fn should_trigger_broadcasted() {
|
||||||
// given
|
// given
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let uxt = uxt(Transfer {
|
let uxt = uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||||
@@ -894,7 +901,8 @@ mod tests {
|
|||||||
nonce: 0,
|
nonce: 0,
|
||||||
});
|
});
|
||||||
let watcher =
|
let watcher =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, uxt)).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, uxt))
|
||||||
|
.unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -916,7 +924,8 @@ mod tests {
|
|||||||
let options =
|
let options =
|
||||||
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||||
|
|
||||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Pool::new(options, true.into(), api.clone());
|
||||||
|
|
||||||
let xt = uxt(Transfer {
|
let xt = uxt(Transfer {
|
||||||
from: Alice.into(),
|
from: Alice.into(),
|
||||||
@@ -924,7 +933,9 @@ mod tests {
|
|||||||
amount: 5,
|
amount: 5,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
});
|
});
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
let watcher =
|
||||||
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt))
|
||||||
|
.unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -934,7 +945,7 @@ mod tests {
|
|||||||
amount: 4,
|
amount: 4,
|
||||||
nonce: 1,
|
nonce: 1,
|
||||||
});
|
});
|
||||||
block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -951,12 +962,13 @@ mod tests {
|
|||||||
let options =
|
let options =
|
||||||
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||||
|
|
||||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Pool::new(options, true.into(), api.clone());
|
||||||
|
|
||||||
// after validation `IncludeData` will have priority set to 9001
|
// after validation `IncludeData` will have priority set to 9001
|
||||||
// (validate_transaction mock)
|
// (validate_transaction mock)
|
||||||
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||||
block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -968,7 +980,7 @@ mod tests {
|
|||||||
amount: 4,
|
amount: 4,
|
||||||
nonce: 1,
|
nonce: 1,
|
||||||
});
|
});
|
||||||
let result = block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt));
|
let result = block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt));
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
result,
|
result,
|
||||||
Err(sc_transaction_pool_api::error::Error::ImmediatelyDropped)
|
Err(sc_transaction_pool_api::error::Error::ImmediatelyDropped)
|
||||||
@@ -980,12 +992,15 @@ mod tests {
|
|||||||
let options =
|
let options =
|
||||||
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||||
|
|
||||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Pool::new(options, true.into(), api.clone());
|
||||||
|
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
|
|
||||||
// after validation `IncludeData` will have priority set to 9001
|
// after validation `IncludeData` will have priority set to 9001
|
||||||
// (validate_transaction mock)
|
// (validate_transaction mock)
|
||||||
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
block_on(pool.submit_and_watch(hash_of_block0, SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// after validation `Transfer` will have priority set to 4 (validate_transaction
|
// after validation `Transfer` will have priority set to 4 (validate_transaction
|
||||||
@@ -996,15 +1011,14 @@ mod tests {
|
|||||||
amount: 5,
|
amount: 5,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
});
|
});
|
||||||
let watcher =
|
let watcher = block_on(pool.submit_and_watch(hash_of_block0, SOURCE, xt)).unwrap();
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
|
||||||
assert_eq!(pool.validated_pool().status().ready, 2);
|
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// after validation `Store` will have priority set to 9001 (validate_transaction
|
// after validation `Store` will have priority set to 9001 (validate_transaction
|
||||||
// mock)
|
// mock)
|
||||||
let xt = ExtrinsicBuilder::new_indexed_call(Vec::new()).build();
|
let xt = ExtrinsicBuilder::new_indexed_call(Vec::new()).build();
|
||||||
block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 2);
|
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@@ -1021,7 +1035,10 @@ mod tests {
|
|||||||
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||||
let mut api = TestApi::default();
|
let mut api = TestApi::default();
|
||||||
api.delay = Arc::new(Mutex::new(rx.into()));
|
api.delay = Arc::new(Mutex::new(rx.into()));
|
||||||
let pool = Arc::new(Pool::new(Default::default(), true.into(), api.into()));
|
let api = Arc::new(api);
|
||||||
|
let pool = Arc::new(Pool::new(Default::default(), true.into(), api.clone()));
|
||||||
|
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let xt = uxt(Transfer {
|
let xt = uxt(Transfer {
|
||||||
@@ -1034,7 +1051,7 @@ mod tests {
|
|||||||
// This transaction should go to future, since we use `nonce: 1`
|
// This transaction should go to future, since we use `nonce: 1`
|
||||||
let pool2 = pool.clone();
|
let pool2 = pool.clone();
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
block_on(pool2.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
block_on(pool2.submit_one(hash_of_block0, SOURCE, xt)).unwrap();
|
||||||
ready.send(()).unwrap();
|
ready.send(()).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1048,12 +1065,13 @@ mod tests {
|
|||||||
});
|
});
|
||||||
// The tag the above transaction provides (TestApi is using just nonce as u8)
|
// The tag the above transaction provides (TestApi is using just nonce as u8)
|
||||||
let provides = vec![0_u8];
|
let provides = vec![0_u8];
|
||||||
block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
block_on(pool.submit_one(hash_of_block0, SOURCE, xt)).unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// Now block import happens before the second transaction is able to finish
|
// Now block import happens before the second transaction is able to finish
|
||||||
// verification.
|
// verification.
|
||||||
block_on(pool.prune_tags(&BlockId::Number(1), vec![provides], vec![])).unwrap();
|
block_on(pool.prune_tags(api.expect_hash_from_number(1), vec![provides], vec![]))
|
||||||
|
.unwrap();
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
|
|
||||||
// so when we release the verification of the previous one it will have
|
// so when we release the verification of the previous one it will have
|
||||||
|
|||||||
@@ -166,8 +166,11 @@ where
|
|||||||
finalized_hash: Block::Hash,
|
finalized_hash: Block::Hash,
|
||||||
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
||||||
let pool = Arc::new(graph::Pool::new(Default::default(), true.into(), pool_api.clone()));
|
let pool = Arc::new(graph::Pool::new(Default::default(), true.into(), pool_api.clone()));
|
||||||
let (revalidation_queue, background_task) =
|
let (revalidation_queue, background_task) = revalidation::RevalidationQueue::new_background(
|
||||||
revalidation::RevalidationQueue::new_background(pool_api.clone(), pool.clone());
|
pool_api.clone(),
|
||||||
|
pool.clone(),
|
||||||
|
finalized_hash,
|
||||||
|
);
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
api: pool_api,
|
api: pool_api,
|
||||||
@@ -203,8 +206,11 @@ where
|
|||||||
RevalidationType::Light =>
|
RevalidationType::Light =>
|
||||||
(revalidation::RevalidationQueue::new(pool_api.clone(), pool.clone()), None),
|
(revalidation::RevalidationQueue::new(pool_api.clone(), pool.clone()), None),
|
||||||
RevalidationType::Full => {
|
RevalidationType::Full => {
|
||||||
let (queue, background) =
|
let (queue, background) = revalidation::RevalidationQueue::new_background(
|
||||||
revalidation::RevalidationQueue::new_background(pool_api.clone(), pool.clone());
|
pool_api.clone(),
|
||||||
|
pool.clone(),
|
||||||
|
finalized_hash,
|
||||||
|
);
|
||||||
(queue, Some(background))
|
(queue, Some(background))
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -254,46 +260,43 @@ where
|
|||||||
|
|
||||||
fn submit_at(
|
fn submit_at(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xts: Vec<TransactionFor<Self>>,
|
xts: Vec<TransactionFor<Self>>,
|
||||||
) -> PoolFuture<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error> {
|
) -> PoolFuture<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error> {
|
||||||
let pool = self.pool.clone();
|
let pool = self.pool.clone();
|
||||||
let at = *at;
|
|
||||||
|
|
||||||
self.metrics
|
self.metrics
|
||||||
.report(|metrics| metrics.submitted_transactions.inc_by(xts.len() as u64));
|
.report(|metrics| metrics.submitted_transactions.inc_by(xts.len() as u64));
|
||||||
|
|
||||||
async move { pool.submit_at(&at, source, xts).await }.boxed()
|
async move { pool.submit_at(at, source, xts).await }.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit_one(
|
fn submit_one(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: TransactionFor<Self>,
|
xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<TxHash<Self>, Self::Error> {
|
) -> PoolFuture<TxHash<Self>, Self::Error> {
|
||||||
let pool = self.pool.clone();
|
let pool = self.pool.clone();
|
||||||
let at = *at;
|
|
||||||
|
|
||||||
self.metrics.report(|metrics| metrics.submitted_transactions.inc());
|
self.metrics.report(|metrics| metrics.submitted_transactions.inc());
|
||||||
|
|
||||||
async move { pool.submit_one(&at, source, xt).await }.boxed()
|
async move { pool.submit_one(at, source, xt).await }.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submit_and_watch(
|
fn submit_and_watch(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
source: TransactionSource,
|
source: TransactionSource,
|
||||||
xt: TransactionFor<Self>,
|
xt: TransactionFor<Self>,
|
||||||
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> {
|
) -> PoolFuture<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> {
|
||||||
let at = *at;
|
|
||||||
let pool = self.pool.clone();
|
let pool = self.pool.clone();
|
||||||
|
|
||||||
self.metrics.report(|metrics| metrics.submitted_transactions.inc());
|
self.metrics.report(|metrics| metrics.submitted_transactions.inc());
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let watcher = pool.submit_and_watch(&at, source, xt).await?;
|
let watcher = pool.submit_and_watch(at, source, xt).await?;
|
||||||
|
|
||||||
Ok(watcher.into_stream().boxed())
|
Ok(watcher.into_stream().boxed())
|
||||||
}
|
}
|
||||||
@@ -433,11 +436,7 @@ where
|
|||||||
|
|
||||||
let validity = self
|
let validity = self
|
||||||
.api
|
.api
|
||||||
.validate_transaction_blocking(
|
.validate_transaction_blocking(at, TransactionSource::Local, xt.clone())?
|
||||||
&BlockId::hash(at),
|
|
||||||
TransactionSource::Local,
|
|
||||||
xt.clone(),
|
|
||||||
)?
|
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Self::Error::Pool(match e {
|
Self::Error::Pool(match e {
|
||||||
TransactionValidityError::Invalid(i) => TxPoolError::InvalidTransaction(i),
|
TransactionValidityError::Invalid(i) => TxPoolError::InvalidTransaction(i),
|
||||||
@@ -577,10 +576,7 @@ async fn prune_known_txs_for_block<Block: BlockT, Api: graph::ChainApi<Block = B
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = pool
|
if let Err(e) = pool.prune(block_hash, *header.parent_hash(), &extrinsics).await {
|
||||||
.prune(&BlockId::Hash(block_hash), &BlockId::hash(*header.parent_hash()), &extrinsics)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
log::error!("Cannot prune known in the pool: {}", e);
|
log::error!("Cannot prune known in the pool: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,7 +687,7 @@ where
|
|||||||
|
|
||||||
if let Err(e) = pool
|
if let Err(e) = pool
|
||||||
.resubmit_at(
|
.resubmit_at(
|
||||||
&BlockId::Hash(*hash),
|
*hash,
|
||||||
// These transactions are coming from retracted blocks, we should
|
// These transactions are coming from retracted blocks, we should
|
||||||
// simply consider them external.
|
// simply consider them external.
|
||||||
TransactionSource::External,
|
TransactionSource::External,
|
||||||
@@ -717,7 +713,7 @@ where
|
|||||||
|
|
||||||
if next_action.revalidate {
|
if next_action.revalidate {
|
||||||
let hashes = pool.validated_pool().ready().map(|tx| tx.hash).collect();
|
let hashes = pool.validated_pool().ready().map(|tx| tx.hash).collect();
|
||||||
self.revalidation_queue.revalidate_later(*block_number, hashes).await;
|
self.revalidation_queue.revalidate_later(*hash, hashes).await;
|
||||||
|
|
||||||
self.revalidation_strategy.lock().clear();
|
self.revalidation_strategy.lock().clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,14 +25,12 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::{ChainApi, ExtrinsicHash, NumberFor, Pool, ValidatedTransaction},
|
graph::{BlockHash, ChainApi, ExtrinsicHash, Pool, ValidatedTransaction},
|
||||||
LOG_TARGET,
|
LOG_TARGET,
|
||||||
};
|
};
|
||||||
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::BlockId,
|
generic::BlockId, traits::SaturatedConversion, transaction_validity::TransactionValidityError,
|
||||||
traits::{SaturatedConversion, Zero},
|
|
||||||
transaction_validity::TransactionValidityError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
@@ -44,7 +42,7 @@ const MIN_BACKGROUND_REVALIDATION_BATCH_SIZE: usize = 20;
|
|||||||
|
|
||||||
/// Payload from queue to worker.
|
/// Payload from queue to worker.
|
||||||
struct WorkerPayload<Api: ChainApi> {
|
struct WorkerPayload<Api: ChainApi> {
|
||||||
at: NumberFor<Api>,
|
at: BlockHash<Api>,
|
||||||
transactions: Vec<ExtrinsicHash<Api>>,
|
transactions: Vec<ExtrinsicHash<Api>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +52,9 @@ struct WorkerPayload<Api: ChainApi> {
|
|||||||
struct RevalidationWorker<Api: ChainApi> {
|
struct RevalidationWorker<Api: ChainApi> {
|
||||||
api: Arc<Api>,
|
api: Arc<Api>,
|
||||||
pool: Arc<Pool<Api>>,
|
pool: Arc<Pool<Api>>,
|
||||||
best_block: NumberFor<Api>,
|
best_block: BlockHash<Api>,
|
||||||
block_ordered: BTreeMap<NumberFor<Api>, HashSet<ExtrinsicHash<Api>>>,
|
block_ordered: BTreeMap<BlockHash<Api>, HashSet<ExtrinsicHash<Api>>>,
|
||||||
members: HashMap<ExtrinsicHash<Api>, NumberFor<Api>>,
|
members: HashMap<ExtrinsicHash<Api>, BlockHash<Api>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Api: ChainApi> Unpin for RevalidationWorker<Api> {}
|
impl<Api: ChainApi> Unpin for RevalidationWorker<Api> {}
|
||||||
@@ -68,15 +66,30 @@ impl<Api: ChainApi> Unpin for RevalidationWorker<Api> {}
|
|||||||
async fn batch_revalidate<Api: ChainApi>(
|
async fn batch_revalidate<Api: ChainApi>(
|
||||||
pool: Arc<Pool<Api>>,
|
pool: Arc<Pool<Api>>,
|
||||||
api: Arc<Api>,
|
api: Arc<Api>,
|
||||||
at: NumberFor<Api>,
|
at: BlockHash<Api>,
|
||||||
batch: impl IntoIterator<Item = ExtrinsicHash<Api>>,
|
batch: impl IntoIterator<Item = ExtrinsicHash<Api>>,
|
||||||
) {
|
) {
|
||||||
|
// This conversion should work. Otherwise, for unknown block the revalidation shall be skipped,
|
||||||
|
// all the transactions will be kept in the validated pool, and can be scheduled for
|
||||||
|
// revalidation with the next request.
|
||||||
|
let block_number = match api.block_id_to_number(&BlockId::Hash(at)) {
|
||||||
|
Ok(Some(n)) => n,
|
||||||
|
Ok(None) => {
|
||||||
|
log::debug!(target: LOG_TARGET, "revalidation skipped at block {at:?}, could not get block number.");
|
||||||
|
return
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::debug!(target: LOG_TARGET, "revalidation skipped at block {at:?}: {e:?}.");
|
||||||
|
return
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
let mut invalid_hashes = Vec::new();
|
let mut invalid_hashes = Vec::new();
|
||||||
let mut revalidated = HashMap::new();
|
let mut revalidated = HashMap::new();
|
||||||
|
|
||||||
let validation_results = futures::future::join_all(batch.into_iter().filter_map(|ext_hash| {
|
let validation_results = futures::future::join_all(batch.into_iter().filter_map(|ext_hash| {
|
||||||
pool.validated_pool().ready_by_hash(&ext_hash).map(|ext| {
|
pool.validated_pool().ready_by_hash(&ext_hash).map(|ext| {
|
||||||
api.validate_transaction(&BlockId::Number(at), ext.source, ext.data.clone())
|
api.validate_transaction(at, ext.source, ext.data.clone())
|
||||||
.map(move |validation_result| (validation_result, ext_hash, ext))
|
.map(move |validation_result| (validation_result, ext_hash, ext))
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
@@ -107,7 +120,7 @@ async fn batch_revalidate<Api: ChainApi>(
|
|||||||
revalidated.insert(
|
revalidated.insert(
|
||||||
ext_hash,
|
ext_hash,
|
||||||
ValidatedTransaction::valid_at(
|
ValidatedTransaction::valid_at(
|
||||||
at.saturated_into::<u64>(),
|
block_number.saturated_into::<u64>(),
|
||||||
ext_hash,
|
ext_hash,
|
||||||
ext.source,
|
ext.source,
|
||||||
ext.data.clone(),
|
ext.data.clone(),
|
||||||
@@ -135,13 +148,13 @@ async fn batch_revalidate<Api: ChainApi>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Api: ChainApi> RevalidationWorker<Api> {
|
impl<Api: ChainApi> RevalidationWorker<Api> {
|
||||||
fn new(api: Arc<Api>, pool: Arc<Pool<Api>>) -> Self {
|
fn new(api: Arc<Api>, pool: Arc<Pool<Api>>, best_block: BlockHash<Api>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
api,
|
api,
|
||||||
pool,
|
pool,
|
||||||
|
best_block,
|
||||||
block_ordered: Default::default(),
|
block_ordered: Default::default(),
|
||||||
members: Default::default(),
|
members: Default::default(),
|
||||||
best_block: Zero::zero(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,10 +316,11 @@ where
|
|||||||
api: Arc<Api>,
|
api: Arc<Api>,
|
||||||
pool: Arc<Pool<Api>>,
|
pool: Arc<Pool<Api>>,
|
||||||
interval: Duration,
|
interval: Duration,
|
||||||
|
best_block: BlockHash<Api>,
|
||||||
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
||||||
let (to_worker, from_queue) = tracing_unbounded("mpsc_revalidation_queue", 100_000);
|
let (to_worker, from_queue) = tracing_unbounded("mpsc_revalidation_queue", 100_000);
|
||||||
|
|
||||||
let worker = RevalidationWorker::new(api.clone(), pool.clone());
|
let worker = RevalidationWorker::new(api.clone(), pool.clone(), best_block);
|
||||||
|
|
||||||
let queue = Self { api, pool, background: Some(to_worker) };
|
let queue = Self { api, pool, background: Some(to_worker) };
|
||||||
|
|
||||||
@@ -317,8 +331,9 @@ where
|
|||||||
pub fn new_background(
|
pub fn new_background(
|
||||||
api: Arc<Api>,
|
api: Arc<Api>,
|
||||||
pool: Arc<Pool<Api>>,
|
pool: Arc<Pool<Api>>,
|
||||||
|
best_block: BlockHash<Api>,
|
||||||
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
) -> (Self, Pin<Box<dyn Future<Output = ()> + Send>>) {
|
||||||
Self::new_with_interval(api, pool, BACKGROUND_REVALIDATION_INTERVAL)
|
Self::new_with_interval(api, pool, BACKGROUND_REVALIDATION_INTERVAL, best_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queue some transaction for later revalidation.
|
/// Queue some transaction for later revalidation.
|
||||||
@@ -328,7 +343,7 @@ where
|
|||||||
/// revalidation is actually done.
|
/// revalidation is actually done.
|
||||||
pub async fn revalidate_later(
|
pub async fn revalidate_later(
|
||||||
&self,
|
&self,
|
||||||
at: NumberFor<Api>,
|
at: BlockHash<Api>,
|
||||||
transactions: Vec<ExtrinsicHash<Api>>,
|
transactions: Vec<ExtrinsicHash<Api>>,
|
||||||
) {
|
) {
|
||||||
if transactions.len() > 0 {
|
if transactions.len() > 0 {
|
||||||
@@ -360,9 +375,8 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use sc_transaction_pool_api::TransactionSource;
|
use sc_transaction_pool_api::TransactionSource;
|
||||||
use sp_runtime::generic::BlockId;
|
|
||||||
use substrate_test_runtime::{AccountId, Transfer, H256};
|
use substrate_test_runtime::{AccountId, Transfer, H256};
|
||||||
use substrate_test_runtime_client::AccountKeyring::Alice;
|
use substrate_test_runtime_client::AccountKeyring::{Alice, Bob};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn revalidation_queue_works() {
|
fn revalidation_queue_works() {
|
||||||
@@ -376,18 +390,63 @@ mod tests {
|
|||||||
amount: 5,
|
amount: 5,
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
});
|
});
|
||||||
let uxt_hash = block_on(pool.submit_one(
|
|
||||||
&BlockId::number(0),
|
|
||||||
TransactionSource::External,
|
|
||||||
uxt.clone(),
|
|
||||||
))
|
|
||||||
.expect("Should be valid");
|
|
||||||
|
|
||||||
block_on(queue.revalidate_later(0, vec![uxt_hash]));
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
|
|
||||||
|
let uxt_hash =
|
||||||
|
block_on(pool.submit_one(hash_of_block0, TransactionSource::External, uxt.clone()))
|
||||||
|
.expect("Should be valid");
|
||||||
|
|
||||||
|
block_on(queue.revalidate_later(hash_of_block0, vec![uxt_hash]));
|
||||||
|
|
||||||
// revalidated in sync offload 2nd time
|
// revalidated in sync offload 2nd time
|
||||||
assert_eq!(api.validation_requests().len(), 2);
|
assert_eq!(api.validation_requests().len(), 2);
|
||||||
// number of ready
|
// number of ready
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn revalidation_queue_skips_revalidation_for_unknown_block_hash() {
|
||||||
|
let api = Arc::new(TestApi::default());
|
||||||
|
let pool = Arc::new(Pool::new(Default::default(), true.into(), api.clone()));
|
||||||
|
let queue = Arc::new(RevalidationQueue::new(api.clone(), pool.clone()));
|
||||||
|
|
||||||
|
let uxt0 = uxt(Transfer {
|
||||||
|
from: Alice.into(),
|
||||||
|
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||||
|
amount: 5,
|
||||||
|
nonce: 0,
|
||||||
|
});
|
||||||
|
let uxt1 = uxt(Transfer {
|
||||||
|
from: Bob.into(),
|
||||||
|
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||||
|
amount: 4,
|
||||||
|
nonce: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
let hash_of_block0 = api.expect_hash_from_number(0);
|
||||||
|
let unknown_block = H256::repeat_byte(0x13);
|
||||||
|
|
||||||
|
let uxt_hashes =
|
||||||
|
block_on(pool.submit_at(hash_of_block0, TransactionSource::External, vec![uxt0, uxt1]))
|
||||||
|
.expect("Should be valid")
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| r.expect("Should be valid"))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(api.validation_requests().len(), 2);
|
||||||
|
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||||
|
|
||||||
|
// revalidation works fine for block 0:
|
||||||
|
block_on(queue.revalidate_later(hash_of_block0, uxt_hashes.clone()));
|
||||||
|
assert_eq!(api.validation_requests().len(), 4);
|
||||||
|
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||||
|
|
||||||
|
// revalidation shall be skipped for unknown block:
|
||||||
|
block_on(queue.revalidate_later(unknown_block, uxt_hashes));
|
||||||
|
// no revalidation shall be done
|
||||||
|
assert_eq!(api.validation_requests().len(), 4);
|
||||||
|
// number of ready shall not change
|
||||||
|
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ use sp_runtime::{
|
|||||||
};
|
};
|
||||||
use std::{collections::HashSet, sync::Arc};
|
use std::{collections::HashSet, sync::Arc};
|
||||||
use substrate_test_runtime::{
|
use substrate_test_runtime::{
|
||||||
substrate_test_pallet::pallet::Call as PalletCall, BalancesCall, Block, Extrinsic,
|
substrate_test_pallet::pallet::Call as PalletCall, BalancesCall, Block, BlockNumber, Extrinsic,
|
||||||
ExtrinsicBuilder, Hashing, RuntimeCall, Transfer, TransferData, H256,
|
ExtrinsicBuilder, Hashing, RuntimeCall, Transfer, TransferData, H256,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,6 +53,11 @@ impl TestApi {
|
|||||||
pub fn validation_requests(&self) -> Vec<Extrinsic> {
|
pub fn validation_requests(&self) -> Vec<Extrinsic> {
|
||||||
self.validation_requests.lock().clone()
|
self.validation_requests.lock().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for mapping block number to hash. Use if mapping shall not fail.
|
||||||
|
pub fn expect_hash_from_number(&self, n: BlockNumber) -> H256 {
|
||||||
|
self.block_id_to_hash(&BlockId::Number(n)).unwrap().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChainApi for TestApi {
|
impl ChainApi for TestApi {
|
||||||
@@ -64,13 +69,13 @@ impl ChainApi for TestApi {
|
|||||||
/// Verify extrinsic at given block.
|
/// Verify extrinsic at given block.
|
||||||
fn validate_transaction(
|
fn validate_transaction(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
uxt: ExtrinsicFor<Self>,
|
uxt: ExtrinsicFor<Self>,
|
||||||
) -> Self::ValidationFuture {
|
) -> Self::ValidationFuture {
|
||||||
self.validation_requests.lock().push(uxt.clone());
|
self.validation_requests.lock().push(uxt.clone());
|
||||||
let hash = self.hash_and_length(&uxt).0;
|
let hash = self.hash_and_length(&uxt).0;
|
||||||
let block_number = self.block_id_to_number(at).unwrap().unwrap();
|
let block_number = self.block_id_to_number(&BlockId::Hash(at)).unwrap().unwrap();
|
||||||
|
|
||||||
let res = match uxt {
|
let res = match uxt {
|
||||||
Extrinsic {
|
Extrinsic {
|
||||||
@@ -153,6 +158,8 @@ impl ChainApi for TestApi {
|
|||||||
) -> Result<Option<NumberFor<Self>>, Self::Error> {
|
) -> Result<Option<NumberFor<Self>>, Self::Error> {
|
||||||
Ok(match at {
|
Ok(match at {
|
||||||
BlockId::Number(num) => Some(*num),
|
BlockId::Number(num) => Some(*num),
|
||||||
|
BlockId::Hash(hash) if *hash == H256::from_low_u64_be(hash.to_low_u64_be()) =>
|
||||||
|
Some(hash.to_low_u64_be()),
|
||||||
BlockId::Hash(_) => None,
|
BlockId::Hash(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -164,7 +171,7 @@ impl ChainApi for TestApi {
|
|||||||
) -> Result<Option<<Self::Block as BlockT>::Hash>, Self::Error> {
|
) -> Result<Option<<Self::Block as BlockT>::Hash>, Self::Error> {
|
||||||
Ok(match at {
|
Ok(match at {
|
||||||
BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(),
|
BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(),
|
||||||
BlockId::Hash(_) => None,
|
BlockId::Hash(hash) => Some(*hash),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +206,7 @@ pub(crate) fn uxt(transfer: Transfer) -> Extrinsic {
|
|||||||
ExtrinsicBuilder::new_transfer(transfer).build()
|
ExtrinsicBuilder::new_transfer(transfer).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pool() -> Pool<TestApi> {
|
pub(crate) fn pool() -> (Pool<TestApi>, Arc<TestApi>) {
|
||||||
Pool::new(Default::default(), true.into(), TestApi::default().into())
|
let api = Arc::new(TestApi::default());
|
||||||
|
(Pool::new(Default::default(), true.into(), api.clone()), api)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,9 @@ use substrate_test_runtime_transaction_pool::{uxt, TestApi};
|
|||||||
|
|
||||||
const LOG_TARGET: &str = "txpool";
|
const LOG_TARGET: &str = "txpool";
|
||||||
|
|
||||||
fn pool() -> Pool<TestApi> {
|
fn pool() -> (Pool<TestApi>, Arc<TestApi>) {
|
||||||
Pool::new(Default::default(), true.into(), TestApi::with_alice_nonce(209).into())
|
let api = Arc::new(TestApi::with_alice_nonce(209));
|
||||||
|
(Pool::new(Default::default(), true.into(), api.clone()), api)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maintained_pool() -> (BasicPool<TestApi, Block>, Arc<TestApi>, futures::executor::ThreadPool) {
|
fn maintained_pool() -> (BasicPool<TestApi, Block>, Arc<TestApi>, futures::executor::ThreadPool) {
|
||||||
@@ -83,8 +84,8 @@ const SOURCE: TransactionSource = TransactionSource::External;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn submission_should_work() {
|
fn submission_should_work() {
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||||
|
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
@@ -96,9 +97,9 @@ fn submission_should_work() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiple_submission_should_work() {
|
fn multiple_submission_should_work() {
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||||
|
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
@@ -111,8 +112,8 @@ fn multiple_submission_should_work() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn early_nonce_should_be_culled() {
|
fn early_nonce_should_be_culled() {
|
||||||
sp_tracing::try_init_simple();
|
sp_tracing::try_init_simple();
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 208))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 208))).unwrap();
|
||||||
|
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
@@ -124,9 +125,9 @@ fn early_nonce_should_be_culled() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn late_nonce_should_be_queued() {
|
fn late_nonce_should_be_queued() {
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
.ready()
|
.ready()
|
||||||
@@ -134,7 +135,7 @@ fn late_nonce_should_be_queued() {
|
|||||||
.collect();
|
.collect();
|
||||||
assert_eq!(pending, Vec::<Nonce>::new());
|
assert_eq!(pending, Vec::<Nonce>::new());
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
.ready()
|
.ready()
|
||||||
@@ -145,9 +146,10 @@ fn late_nonce_should_be_queued() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prune_tags_should_work() {
|
fn prune_tags_should_work() {
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let hash209 = block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
let hash209 =
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||||
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||||
|
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
.validated_pool()
|
.validated_pool()
|
||||||
@@ -157,7 +159,7 @@ fn prune_tags_should_work() {
|
|||||||
assert_eq!(pending, vec![209, 210]);
|
assert_eq!(pending, vec![209, 210]);
|
||||||
|
|
||||||
pool.validated_pool().api().push_block(1, Vec::new(), true);
|
pool.validated_pool().api().push_block(1, Vec::new(), true);
|
||||||
block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![hash209]))
|
block_on(pool.prune_tags(api.expect_hash_from_number(1), vec![vec![209]], vec![hash209]))
|
||||||
.expect("Prune tags");
|
.expect("Prune tags");
|
||||||
|
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
@@ -170,11 +172,12 @@ fn prune_tags_should_work() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_ban_invalid_transactions() {
|
fn should_ban_invalid_transactions() {
|
||||||
let pool = pool();
|
let (pool, api) = pool();
|
||||||
let uxt = uxt(Alice, 209);
|
let uxt = uxt(Alice, 209);
|
||||||
let hash = block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap();
|
let hash =
|
||||||
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt.clone())).unwrap();
|
||||||
pool.validated_pool().remove_invalid(&[hash]);
|
pool.validated_pool().remove_invalid(&[hash]);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap_err();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt.clone())).unwrap_err();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
@@ -185,7 +188,7 @@ fn should_ban_invalid_transactions() {
|
|||||||
assert_eq!(pending, Vec::<Nonce>::new());
|
assert_eq!(pending, Vec::<Nonce>::new());
|
||||||
|
|
||||||
// then
|
// then
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap_err();
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, uxt.clone())).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -193,9 +196,9 @@ fn only_prune_on_new_best() {
|
|||||||
let (pool, api, _) = maintained_pool();
|
let (pool, api, _) = maintained_pool();
|
||||||
let uxt = uxt(Alice, 209);
|
let uxt = uxt(Alice, 209);
|
||||||
|
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, uxt.clone()))
|
let _ = block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, uxt.clone()))
|
||||||
.expect("1. Imported");
|
.expect("1. Imported");
|
||||||
pool.api().push_block(1, vec![uxt.clone()], true);
|
api.push_block(1, vec![uxt.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(2, vec![uxt], true);
|
let header = api.push_block(2, vec![uxt], true);
|
||||||
@@ -212,13 +215,15 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() {
|
|||||||
}));
|
}));
|
||||||
let pool = Pool::new(Default::default(), true.into(), api.clone());
|
let pool = Pool::new(Default::default(), true.into(), api.clone());
|
||||||
let xt = uxt(Alice, 209);
|
let xt = uxt(Alice, 209);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
|
|
||||||
// remove the transaction that just got imported.
|
// remove the transaction that just got imported.
|
||||||
api.increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
api.push_block(1, Vec::new(), true);
|
api.push_block(1, Vec::new(), true);
|
||||||
block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![])).expect("1. Pruned");
|
block_on(pool.prune_tags(api.expect_hash_from_number(1), vec![vec![209]], vec![]))
|
||||||
|
.expect("1. Pruned");
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
// it's re-imported to future
|
// it's re-imported to future
|
||||||
assert_eq!(pool.validated_pool().status().future, 1);
|
assert_eq!(pool.validated_pool().status().future, 1);
|
||||||
@@ -227,7 +232,8 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() {
|
|||||||
api.increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
api.push_block(2, Vec::new(), true);
|
api.push_block(2, Vec::new(), true);
|
||||||
let xt = uxt(Alice, 211);
|
let xt = uxt(Alice, 211);
|
||||||
block_on(pool.submit_one(&BlockId::number(2), SOURCE, xt.clone())).expect("2. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(2), SOURCE, xt.clone()))
|
||||||
|
.expect("2. Imported");
|
||||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||||
assert_eq!(pool.validated_pool().status().future, 1);
|
assert_eq!(pool.validated_pool().status().future, 1);
|
||||||
let pending: Vec<_> = pool
|
let pending: Vec<_> = pool
|
||||||
@@ -240,7 +246,8 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() {
|
|||||||
// prune it and make sure the pool is empty
|
// prune it and make sure the pool is empty
|
||||||
api.increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
api.push_block(3, Vec::new(), true);
|
api.push_block(3, Vec::new(), true);
|
||||||
block_on(pool.prune_tags(&BlockId::number(3), vec![vec![155]], vec![])).expect("2. Pruned");
|
block_on(pool.prune_tags(api.expect_hash_from_number(3), vec![vec![155]], vec![]))
|
||||||
|
.expect("2. Pruned");
|
||||||
assert_eq!(pool.validated_pool().status().ready, 0);
|
assert_eq!(pool.validated_pool().status().ready, 0);
|
||||||
assert_eq!(pool.validated_pool().status().future, 2);
|
assert_eq!(pool.validated_pool().status().future, 2);
|
||||||
}
|
}
|
||||||
@@ -270,7 +277,8 @@ fn should_prune_old_during_maintenance() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![xt.clone()], true);
|
let header = api.push_block(1, vec![xt.clone()], true);
|
||||||
@@ -285,9 +293,11 @@ fn should_revalidate_during_maintenance() {
|
|||||||
let xt2 = uxt(Alice, 210);
|
let xt2 = uxt(Alice, 210);
|
||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt1.clone()))
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt2.clone()))
|
.expect("1. Imported");
|
||||||
.expect("2. Imported");
|
let watcher =
|
||||||
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt2.clone()))
|
||||||
|
.expect("2. Imported");
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
assert_eq!(api.validation_requests().len(), 2);
|
assert_eq!(api.validation_requests().len(), 2);
|
||||||
|
|
||||||
@@ -311,7 +321,8 @@ fn should_resubmit_from_retracted_during_maintenance() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![], true);
|
let header = api.push_block(1, vec![], true);
|
||||||
@@ -329,7 +340,8 @@ fn should_not_resubmit_from_retracted_during_maintenance_if_tx_is_also_in_enacte
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![xt.clone()], true);
|
let header = api.push_block(1, vec![xt.clone()], true);
|
||||||
@@ -347,8 +359,9 @@ fn should_not_retain_invalid_hashes_from_retracted() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt.clone()))
|
let watcher =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![], true);
|
let header = api.push_block(1, vec![], true);
|
||||||
@@ -374,15 +387,18 @@ fn should_revalidate_across_many_blocks() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
let watcher1 = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt1.clone()))
|
let watcher1 =
|
||||||
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt1.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt2.clone()))
|
||||||
.expect("1. Imported");
|
.expect("1. Imported");
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt2.clone())).expect("1. Imported");
|
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![], true);
|
let header = api.push_block(1, vec![], true);
|
||||||
block_on(pool.maintain(block_event(header)));
|
block_on(pool.maintain(block_event(header)));
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt3.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt3.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 3);
|
assert_eq!(pool.status().ready, 3);
|
||||||
|
|
||||||
let header = api.push_block(2, vec![xt1.clone()], true);
|
let header = api.push_block(2, vec![xt1.clone()], true);
|
||||||
@@ -409,19 +425,24 @@ fn should_push_watchers_during_maintenance() {
|
|||||||
|
|
||||||
let tx0 = alice_uxt(0);
|
let tx0 = alice_uxt(0);
|
||||||
let watcher0 =
|
let watcher0 =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, tx0.clone())).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, tx0.clone()))
|
||||||
|
.unwrap();
|
||||||
let tx1 = alice_uxt(1);
|
let tx1 = alice_uxt(1);
|
||||||
let watcher1 =
|
let watcher1 =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, tx1.clone())).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, tx1.clone()))
|
||||||
|
.unwrap();
|
||||||
let tx2 = alice_uxt(2);
|
let tx2 = alice_uxt(2);
|
||||||
let watcher2 =
|
let watcher2 =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, tx2.clone())).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, tx2.clone()))
|
||||||
|
.unwrap();
|
||||||
let tx3 = alice_uxt(3);
|
let tx3 = alice_uxt(3);
|
||||||
let watcher3 =
|
let watcher3 =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, tx3.clone())).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, tx3.clone()))
|
||||||
|
.unwrap();
|
||||||
let tx4 = alice_uxt(4);
|
let tx4 = alice_uxt(4);
|
||||||
let watcher4 =
|
let watcher4 =
|
||||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, tx4.clone())).unwrap();
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, tx4.clone()))
|
||||||
|
.unwrap();
|
||||||
assert_eq!(pool.status().ready, 5);
|
assert_eq!(pool.status().ready, 5);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@@ -489,11 +510,13 @@ fn finalization() {
|
|||||||
let api = TestApi::with_alice_nonce(209);
|
let api = TestApi::with_alice_nonce(209);
|
||||||
api.push_block(1, vec![], true);
|
api.push_block(1, vec![], true);
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, xt.clone()))
|
let api = pool.api();
|
||||||
.expect("1. Imported");
|
let watcher =
|
||||||
pool.api().push_block(2, vec![xt.clone()], true);
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
|
api.push_block(2, vec![xt.clone()], true);
|
||||||
|
|
||||||
let header = pool.api().chain().read().block_by_number.get(&2).unwrap()[0].0.header().clone();
|
let header = api.chain().read().block_by_number.get(&2).unwrap()[0].0.header().clone();
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
|
|
||||||
@@ -515,16 +538,17 @@ fn fork_aware_finalization() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
let mut canon_watchers = vec![];
|
let mut canon_watchers = vec![];
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_dave = uxt(Dave, 2);
|
let from_dave = uxt(Dave, 2);
|
||||||
let from_bob = uxt(Bob, 1);
|
let from_bob = uxt(Bob, 1);
|
||||||
let from_charlie = uxt(Charlie, 1);
|
let from_charlie = uxt(Charlie, 1);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Dave.into());
|
api.increment_nonce(Dave.into());
|
||||||
pool.api().increment_nonce(Charlie.into());
|
api.increment_nonce(Charlie.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
|
|
||||||
let from_dave_watcher;
|
let from_dave_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -538,10 +562,13 @@ fn fork_aware_finalization() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
let watcher =
|
let watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header = pool.api().push_block(2, vec![from_alice.clone()], true);
|
from_alice.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(2, vec![from_alice.clone()], true);
|
||||||
canon_watchers.push((watcher, header.hash()));
|
canon_watchers.push((watcher, header.hash()));
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
@@ -556,10 +583,13 @@ fn fork_aware_finalization() {
|
|||||||
|
|
||||||
// block C2
|
// block C2
|
||||||
{
|
{
|
||||||
let header = pool.api().push_block_with_parent(b1, vec![from_dave.clone()], true);
|
let header = api.push_block_with_parent(b1, vec![from_dave.clone()], true);
|
||||||
from_dave_watcher =
|
from_dave_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_dave.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
|
from_dave.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
log::trace!(target: LOG_TARGET, ">> C2: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> C2: {:?} {:?}", header.hash(), header);
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
@@ -570,11 +600,14 @@ fn fork_aware_finalization() {
|
|||||||
|
|
||||||
// block D2
|
// block D2
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
|
from_bob.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
let header = pool.api().push_block_with_parent(c2, vec![from_bob.clone()], true);
|
let header = api.push_block_with_parent(c2, vec![from_bob.clone()], true);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> D2: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> D2: {:?} {:?}", header.hash(), header);
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
@@ -585,15 +618,18 @@ fn fork_aware_finalization() {
|
|||||||
|
|
||||||
// block C1
|
// block C1
|
||||||
{
|
{
|
||||||
let watcher =
|
let watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_charlie.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1.Imported");
|
SOURCE,
|
||||||
|
from_charlie.clone(),
|
||||||
|
))
|
||||||
|
.expect("1.Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
let header = pool.api().push_block_with_parent(b1, vec![from_charlie.clone()], true);
|
let header = api.push_block_with_parent(b1, vec![from_charlie.clone()], true);
|
||||||
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
||||||
c1 = header.hash();
|
c1 = header.hash();
|
||||||
canon_watchers.push((watcher, header.hash()));
|
canon_watchers.push((watcher, header.hash()));
|
||||||
let event = block_event_with_retracted(header.clone(), d2, pool.api());
|
let event = block_event_with_retracted(header.clone(), d2, api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
|
|
||||||
@@ -604,10 +640,10 @@ fn fork_aware_finalization() {
|
|||||||
// block D1
|
// block D1
|
||||||
{
|
{
|
||||||
let xt = uxt(Eve, 0);
|
let xt = uxt(Eve, 0);
|
||||||
let w = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, xt.clone()))
|
let w = block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, xt.clone()))
|
||||||
.expect("1. Imported");
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 3);
|
assert_eq!(pool.status().ready, 3);
|
||||||
let header = pool.api().push_block_with_parent(c1, vec![xt.clone()], true);
|
let header = api.push_block_with_parent(c1, vec![xt.clone()], true);
|
||||||
log::trace!(target: LOG_TARGET, ">> D1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> D1: {:?} {:?}", header.hash(), header);
|
||||||
d1 = header.hash();
|
d1 = header.hash();
|
||||||
canon_watchers.push((w, header.hash()));
|
canon_watchers.push((w, header.hash()));
|
||||||
@@ -623,7 +659,7 @@ fn fork_aware_finalization() {
|
|||||||
|
|
||||||
// block E1
|
// block E1
|
||||||
{
|
{
|
||||||
let header = pool.api().push_block_with_parent(d1, vec![from_dave, from_bob], true);
|
let header = api.push_block_with_parent(d1, vec![from_dave, from_bob], true);
|
||||||
log::trace!(target: LOG_TARGET, ">> E1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> E1: {:?} {:?}", header.hash(), header);
|
||||||
e1 = header.hash();
|
e1 = header.hash();
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
@@ -673,16 +709,18 @@ fn prune_and_retract_tx_at_same_time() {
|
|||||||
api.push_block(1, vec![], true);
|
api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
|
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
let watcher =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, from_alice.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
|
|
||||||
// Block B1
|
// Block B1
|
||||||
let b1 = {
|
let b1 = {
|
||||||
let header = pool.api().push_block(2, vec![from_alice.clone()], true);
|
let header = api.push_block(2, vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
@@ -693,10 +731,10 @@ fn prune_and_retract_tx_at_same_time() {
|
|||||||
|
|
||||||
// Block B2
|
// Block B2
|
||||||
let b2 = {
|
let b2 = {
|
||||||
let header = pool.api().push_block(2, vec![from_alice.clone()], true);
|
let header = api.push_block(2, vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
|
|
||||||
let event = block_event_with_retracted(header.clone(), b1, pool.api());
|
let event = block_event_with_retracted(header.clone(), b1, api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
|
|
||||||
@@ -739,19 +777,21 @@ fn resubmit_tx_of_fork_that_is_not_part_of_retracted() {
|
|||||||
api.push_block(1, vec![], true);
|
api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let tx0 = uxt(Alice, 1);
|
let tx0 = uxt(Alice, 1);
|
||||||
let tx1 = uxt(Dave, 2);
|
let tx1 = uxt(Dave, 2);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Dave.into());
|
api.increment_nonce(Dave.into());
|
||||||
|
|
||||||
let d0;
|
let d0;
|
||||||
|
|
||||||
// Block D0
|
// Block D0
|
||||||
{
|
{
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx0.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx0.clone()))
|
||||||
let header = pool.api().push_block(2, vec![tx0.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(2, vec![tx0.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
let event = ChainEvent::NewBestBlock { hash: header.hash(), tree_route: None };
|
||||||
@@ -762,17 +802,18 @@ fn resubmit_tx_of_fork_that_is_not_part_of_retracted() {
|
|||||||
|
|
||||||
// Block D1
|
// Block D1
|
||||||
{
|
{
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx1.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx1.clone()))
|
||||||
pool.api().push_block(2, vec![tx1.clone()], false);
|
.expect("1. Imported");
|
||||||
|
api.push_block(2, vec![tx1.clone()], false);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block D2
|
// Block D2
|
||||||
{
|
{
|
||||||
//push new best block
|
//push new best block
|
||||||
let header = pool.api().push_block(2, vec![], true);
|
let header = api.push_block(2, vec![], true);
|
||||||
let event = block_event_with_retracted(header, d0, pool.api());
|
let event = block_event_with_retracted(header, d0, api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
}
|
}
|
||||||
@@ -786,6 +827,8 @@ fn resubmit_from_retracted_fork() {
|
|||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let tx0 = uxt(Alice, 1);
|
let tx0 = uxt(Alice, 1);
|
||||||
let tx1 = uxt(Dave, 2);
|
let tx1 = uxt(Dave, 2);
|
||||||
let tx2 = uxt(Bob, 3);
|
let tx2 = uxt(Bob, 3);
|
||||||
@@ -795,18 +838,19 @@ fn resubmit_from_retracted_fork() {
|
|||||||
let tx4 = uxt(Ferdie, 2);
|
let tx4 = uxt(Ferdie, 2);
|
||||||
let tx5 = uxt(One, 3);
|
let tx5 = uxt(One, 3);
|
||||||
|
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Dave.into());
|
api.increment_nonce(Dave.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
pool.api().increment_nonce(Eve.into());
|
api.increment_nonce(Eve.into());
|
||||||
pool.api().increment_nonce(Ferdie.into());
|
api.increment_nonce(Ferdie.into());
|
||||||
pool.api().increment_nonce(One.into());
|
api.increment_nonce(One.into());
|
||||||
|
|
||||||
// Block D0
|
// Block D0
|
||||||
{
|
{
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx0.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx0.clone()))
|
||||||
let header = pool.api().push_block(2, vec![tx0.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(2, vec![tx0.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
block_on(pool.maintain(block_event(header)));
|
block_on(pool.maintain(block_event(header)));
|
||||||
@@ -815,18 +859,20 @@ fn resubmit_from_retracted_fork() {
|
|||||||
|
|
||||||
// Block E0
|
// Block E0
|
||||||
{
|
{
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx1.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx1.clone()))
|
||||||
let header = pool.api().push_block(3, vec![tx1.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(3, vec![tx1.clone()], true);
|
||||||
block_on(pool.maintain(block_event(header)));
|
block_on(pool.maintain(block_event(header)));
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block F0
|
// Block F0
|
||||||
let f0 = {
|
let f0 = {
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx2.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx2.clone()))
|
||||||
let header = pool.api().push_block(4, vec![tx2.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(4, vec![tx2.clone()], true);
|
||||||
block_on(pool.maintain(block_event(header.clone())));
|
block_on(pool.maintain(block_event(header.clone())));
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
header.hash()
|
header.hash()
|
||||||
@@ -834,27 +880,30 @@ fn resubmit_from_retracted_fork() {
|
|||||||
|
|
||||||
// Block D1
|
// Block D1
|
||||||
let d1 = {
|
let d1 = {
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx3.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx3.clone()))
|
||||||
let header = pool.api().push_block(2, vec![tx3.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block(2, vec![tx3.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
header.hash()
|
header.hash()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Block E1
|
// Block E1
|
||||||
let e1 = {
|
let e1 = {
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx4.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx4.clone()))
|
||||||
let header = pool.api().push_block_with_parent(d1, vec![tx4.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(d1, vec![tx4.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
header.hash()
|
header.hash()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Block F1
|
// Block F1
|
||||||
let f1_header = {
|
let f1_header = {
|
||||||
let _ = block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, tx5.clone()))
|
let _ =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(1), SOURCE, tx5.clone()))
|
||||||
let header = pool.api().push_block_with_parent(e1, vec![tx5.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(e1, vec![tx5.clone()], true);
|
||||||
// Don't announce the block event to the pool directly, because we will
|
// Don't announce the block event to the pool directly, because we will
|
||||||
// re-org to this block.
|
// re-org to this block.
|
||||||
assert_eq!(pool.status().ready, 3);
|
assert_eq!(pool.status().ready, 3);
|
||||||
@@ -865,7 +914,7 @@ fn resubmit_from_retracted_fork() {
|
|||||||
let expected_ready = vec![tx3, tx4, tx5].iter().map(Encode::encode).collect::<BTreeSet<_>>();
|
let expected_ready = vec![tx3, tx4, tx5].iter().map(Encode::encode).collect::<BTreeSet<_>>();
|
||||||
assert_eq!(expected_ready, ready);
|
assert_eq!(expected_ready, ready);
|
||||||
|
|
||||||
let event = block_event_with_retracted(f1_header, f0, pool.api());
|
let event = block_event_with_retracted(f1_header, f0, api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
|
|
||||||
assert_eq!(pool.status().ready, 3);
|
assert_eq!(pool.status().ready, 3);
|
||||||
@@ -876,9 +925,10 @@ fn resubmit_from_retracted_fork() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ready_set_should_not_resolve_before_block_update() {
|
fn ready_set_should_not_resolve_before_block_update() {
|
||||||
let (pool, _api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
let xt1 = uxt(Alice, 209);
|
let xt1 = uxt(Alice, 209);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt1.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
|
|
||||||
assert!(pool.ready_at(1).now_or_never().is_none());
|
assert!(pool.ready_at(1).now_or_never().is_none());
|
||||||
}
|
}
|
||||||
@@ -890,7 +940,8 @@ fn ready_set_should_resolve_after_block_update() {
|
|||||||
|
|
||||||
let xt1 = uxt(Alice, 209);
|
let xt1 = uxt(Alice, 209);
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt1.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt1.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
block_on(pool.maintain(block_event(header)));
|
block_on(pool.maintain(block_event(header)));
|
||||||
|
|
||||||
assert!(pool.ready_at(1).now_or_never().is_some());
|
assert!(pool.ready_at(1).now_or_never().is_some());
|
||||||
@@ -903,7 +954,8 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() {
|
|||||||
|
|
||||||
let xt1 = uxt(Alice, 209);
|
let xt1 = uxt(Alice, 209);
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(1), SOURCE, xt1.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(1), SOURCE, xt1.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
|
|
||||||
let noop_waker = futures::task::noop_waker();
|
let noop_waker = futures::task::noop_waker();
|
||||||
let mut context = futures::task::Context::from_waker(&noop_waker);
|
let mut context = futures::task::Context::from_waker(&noop_waker);
|
||||||
@@ -948,7 +1000,12 @@ fn import_notification_to_pool_maintain_works() {
|
|||||||
|
|
||||||
// Prepare the extrisic, push it to the pool and check that it was added.
|
// Prepare the extrisic, push it to the pool and check that it was added.
|
||||||
let xt = uxt(Alice, 0);
|
let xt = uxt(Alice, 0);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())).expect("1. Imported");
|
block_on(pool.submit_one(
|
||||||
|
pool.api().block_id_to_hash(&BlockId::Number(0)).unwrap().unwrap(),
|
||||||
|
SOURCE,
|
||||||
|
xt.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let mut import_stream = block_on_stream(client.import_notification_stream());
|
let mut import_stream = block_on_stream(client.import_notification_stream());
|
||||||
@@ -973,7 +1030,8 @@ fn pruning_a_transaction_should_remove_it_from_best_transaction() {
|
|||||||
|
|
||||||
let xt1 = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
let xt1 = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||||
|
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported");
|
block_on(pool.submit_one(api.expect_hash_from_number(0), SOURCE, xt1.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
let header = api.push_block(1, vec![xt1.clone()], true);
|
let header = api.push_block(1, vec![xt1.clone()], true);
|
||||||
|
|
||||||
@@ -997,8 +1055,12 @@ fn stale_transactions_are_pruned() {
|
|||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
xts.into_iter().for_each(|xt| {
|
xts.into_iter().for_each(|xt| {
|
||||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_unchecked_extrinsic()))
|
block_on(pool.submit_one(
|
||||||
.expect("1. Imported");
|
api.expect_hash_from_number(0),
|
||||||
|
SOURCE,
|
||||||
|
xt.into_unchecked_extrinsic(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
});
|
});
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
assert_eq!(pool.status().future, 3);
|
assert_eq!(pool.status().future, 3);
|
||||||
@@ -1038,8 +1100,9 @@ fn finalized_only_handled_correctly() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt.clone()))
|
let watcher =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![xt], true);
|
let header = api.push_block(1, vec![xt], true);
|
||||||
@@ -1066,8 +1129,9 @@ fn best_block_after_finalized_handled_correctly() {
|
|||||||
|
|
||||||
let (pool, api, _guard) = maintained_pool();
|
let (pool, api, _guard) = maintained_pool();
|
||||||
|
|
||||||
let watcher = block_on(pool.submit_and_watch(&BlockId::number(0), SOURCE, xt.clone()))
|
let watcher =
|
||||||
.expect("1. Imported");
|
block_on(pool.submit_and_watch(api.expect_hash_from_number(0), SOURCE, xt.clone()))
|
||||||
|
.expect("1. Imported");
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
let header = api.push_block(1, vec![xt], true);
|
let header = api.push_block(1, vec![xt], true);
|
||||||
@@ -1096,11 +1160,12 @@ fn switching_fork_with_finalized_works() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_bob = uxt(Bob, 2);
|
let from_bob = uxt(Bob, 2);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
|
|
||||||
let from_alice_watcher;
|
let from_alice_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -1109,12 +1174,13 @@ fn switching_fork_with_finalized_works() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
from_alice_watcher =
|
from_alice_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_alice.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
||||||
b1_header = header;
|
b1_header = header;
|
||||||
@@ -1122,10 +1188,13 @@ fn switching_fork_with_finalized_works() {
|
|||||||
|
|
||||||
// block B2
|
// block B2
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header = pool.api().push_block_with_parent(
|
from_bob.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(
|
||||||
a_header.hash(),
|
a_header.hash(),
|
||||||
vec![from_alice.clone(), from_bob.clone()],
|
vec![from_alice.clone(), from_bob.clone()],
|
||||||
true,
|
true,
|
||||||
@@ -1174,11 +1243,12 @@ fn switching_fork_multiple_times_works() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_bob = uxt(Bob, 2);
|
let from_bob = uxt(Bob, 2);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
|
|
||||||
let from_alice_watcher;
|
let from_alice_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -1187,12 +1257,13 @@ fn switching_fork_multiple_times_works() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
from_alice_watcher =
|
from_alice_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_alice.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
||||||
b1_header = header;
|
b1_header = header;
|
||||||
@@ -1200,10 +1271,13 @@ fn switching_fork_multiple_times_works() {
|
|||||||
|
|
||||||
// block B2
|
// block B2
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header = pool.api().push_block_with_parent(
|
from_bob.clone(),
|
||||||
|
))
|
||||||
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(
|
||||||
a_header.hash(),
|
a_header.hash(),
|
||||||
vec![from_alice.clone(), from_bob.clone()],
|
vec![from_alice.clone(), from_bob.clone()],
|
||||||
true,
|
true,
|
||||||
@@ -1223,14 +1297,14 @@ fn switching_fork_multiple_times_works() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
// phase-1
|
// phase-1
|
||||||
let event = block_event_with_retracted(b2_header.clone(), b1_header.hash(), pool.api());
|
let event = block_event_with_retracted(b2_header.clone(), b1_header.hash(), api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
assert_eq!(pool.status().ready, 0);
|
assert_eq!(pool.status().ready, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// phase-2
|
// phase-2
|
||||||
let event = block_event_with_retracted(b1_header.clone(), b2_header.hash(), pool.api());
|
let event = block_event_with_retracted(b1_header.clone(), b2_header.hash(), api);
|
||||||
block_on(pool.maintain(event));
|
block_on(pool.maintain(event));
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
}
|
}
|
||||||
@@ -1282,13 +1356,14 @@ fn two_blocks_delayed_finalization_works() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_bob = uxt(Bob, 2);
|
let from_bob = uxt(Bob, 2);
|
||||||
let from_charlie = uxt(Charlie, 3);
|
let from_charlie = uxt(Charlie, 3);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
pool.api().increment_nonce(Charlie.into());
|
api.increment_nonce(Charlie.into());
|
||||||
|
|
||||||
let from_alice_watcher;
|
let from_alice_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -1299,12 +1374,13 @@ fn two_blocks_delayed_finalization_works() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
from_alice_watcher =
|
from_alice_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_alice.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1313,12 +1389,13 @@ fn two_blocks_delayed_finalization_works() {
|
|||||||
|
|
||||||
// block C1
|
// block C1
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_bob.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1327,12 +1404,13 @@ fn two_blocks_delayed_finalization_works() {
|
|||||||
|
|
||||||
// block D1
|
// block D1
|
||||||
{
|
{
|
||||||
from_charlie_watcher =
|
from_charlie_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_charlie.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_charlie.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(c1_header.hash(), vec![from_charlie.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(c1_header.hash(), vec![from_charlie.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 3);
|
assert_eq!(pool.status().ready, 3);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> D1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> D1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1398,11 +1476,12 @@ fn delayed_finalization_does_not_retract() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_bob = uxt(Bob, 2);
|
let from_bob = uxt(Bob, 2);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
|
|
||||||
let from_alice_watcher;
|
let from_alice_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -1411,12 +1490,13 @@ fn delayed_finalization_does_not_retract() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
from_alice_watcher =
|
from_alice_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_alice.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1425,12 +1505,13 @@ fn delayed_finalization_does_not_retract() {
|
|||||||
|
|
||||||
// block C1
|
// block C1
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_bob.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1493,11 +1574,12 @@ fn best_block_after_finalization_does_not_retract() {
|
|||||||
let a_header = api.push_block(1, vec![], true);
|
let a_header = api.push_block(1, vec![], true);
|
||||||
|
|
||||||
let pool = create_basic_pool(api);
|
let pool = create_basic_pool(api);
|
||||||
|
let api = pool.api();
|
||||||
|
|
||||||
let from_alice = uxt(Alice, 1);
|
let from_alice = uxt(Alice, 1);
|
||||||
let from_bob = uxt(Bob, 2);
|
let from_bob = uxt(Bob, 2);
|
||||||
pool.api().increment_nonce(Alice.into());
|
api.increment_nonce(Alice.into());
|
||||||
pool.api().increment_nonce(Bob.into());
|
api.increment_nonce(Bob.into());
|
||||||
|
|
||||||
let from_alice_watcher;
|
let from_alice_watcher;
|
||||||
let from_bob_watcher;
|
let from_bob_watcher;
|
||||||
@@ -1506,12 +1588,13 @@ fn best_block_after_finalization_does_not_retract() {
|
|||||||
|
|
||||||
// block B1
|
// block B1
|
||||||
{
|
{
|
||||||
from_alice_watcher =
|
from_alice_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_alice.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_alice.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(a_header.hash(), vec![from_alice.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 1);
|
assert_eq!(pool.status().ready, 1);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> B1: {:?} {:?}", header.hash(), header);
|
||||||
@@ -1520,12 +1603,13 @@ fn best_block_after_finalization_does_not_retract() {
|
|||||||
|
|
||||||
// block C1
|
// block C1
|
||||||
{
|
{
|
||||||
from_bob_watcher =
|
from_bob_watcher = block_on(pool.submit_and_watch(
|
||||||
block_on(pool.submit_and_watch(&BlockId::number(1), SOURCE, from_bob.clone()))
|
api.expect_hash_from_number(1),
|
||||||
.expect("1. Imported");
|
SOURCE,
|
||||||
let header =
|
from_bob.clone(),
|
||||||
pool.api()
|
))
|
||||||
.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
.expect("1. Imported");
|
||||||
|
let header = api.push_block_with_parent(b1_header.hash(), vec![from_bob.clone()], true);
|
||||||
assert_eq!(pool.status().ready, 2);
|
assert_eq!(pool.status().ready, 2);
|
||||||
|
|
||||||
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
log::trace!(target: LOG_TARGET, ">> C1: {:?} {:?}", header.hash(), header);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use sc_transaction_pool::ChainApi;
|
||||||
use sp_blockchain::{CachedHeaderMetadata, TreeRoute};
|
use sp_blockchain::{CachedHeaderMetadata, TreeRoute};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::{self, BlockId},
|
generic::{self, BlockId},
|
||||||
@@ -237,9 +238,14 @@ impl TestApi {
|
|||||||
) -> Result<sp_blockchain::TreeRoute<Block>, Error> {
|
) -> Result<sp_blockchain::TreeRoute<Block>, Error> {
|
||||||
sp_blockchain::tree_route(self, from, to)
|
sp_blockchain::tree_route(self, from, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for mapping block number to hash. Use if mapping shall not fail.
|
||||||
|
pub fn expect_hash_from_number(&self, n: BlockNumber) -> Hash {
|
||||||
|
self.block_id_to_hash(&BlockId::Number(n)).unwrap().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sc_transaction_pool::ChainApi for TestApi {
|
impl ChainApi for TestApi {
|
||||||
type Block = Block;
|
type Block = Block;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type ValidationFuture = futures::future::Ready<Result<TransactionValidity, Error>>;
|
type ValidationFuture = futures::future::Ready<Result<TransactionValidity, Error>>;
|
||||||
@@ -247,13 +253,13 @@ impl sc_transaction_pool::ChainApi for TestApi {
|
|||||||
|
|
||||||
fn validate_transaction(
|
fn validate_transaction(
|
||||||
&self,
|
&self,
|
||||||
at: &BlockId<Self::Block>,
|
at: <Self::Block as BlockT>::Hash,
|
||||||
_source: TransactionSource,
|
_source: TransactionSource,
|
||||||
uxt: <Self::Block as BlockT>::Extrinsic,
|
uxt: <Self::Block as BlockT>::Extrinsic,
|
||||||
) -> Self::ValidationFuture {
|
) -> Self::ValidationFuture {
|
||||||
self.validation_requests.write().push(uxt.clone());
|
self.validation_requests.write().push(uxt.clone());
|
||||||
|
|
||||||
match self.block_id_to_number(at) {
|
match self.block_id_to_number(&BlockId::Hash(at)) {
|
||||||
Ok(Some(number)) => {
|
Ok(Some(number)) => {
|
||||||
let found_best = self
|
let found_best = self
|
||||||
.chain
|
.chain
|
||||||
|
|||||||
@@ -219,7 +219,6 @@ mod tests {
|
|||||||
use jsonrpsee::{core::Error as JsonRpseeError, types::error::CallError};
|
use jsonrpsee::{core::Error as JsonRpseeError, types::error::CallError};
|
||||||
use sc_transaction_pool::BasicPool;
|
use sc_transaction_pool::BasicPool;
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::BlockId,
|
|
||||||
transaction_validity::{InvalidTransaction, TransactionValidityError},
|
transaction_validity::{InvalidTransaction, TransactionValidityError},
|
||||||
ApplyExtrinsicResult,
|
ApplyExtrinsicResult,
|
||||||
};
|
};
|
||||||
@@ -245,11 +244,12 @@ mod tests {
|
|||||||
};
|
};
|
||||||
t.into_unchecked_extrinsic()
|
t.into_unchecked_extrinsic()
|
||||||
};
|
};
|
||||||
|
let hash_of_block0 = client.info().genesis_hash;
|
||||||
// Populate the pool
|
// Populate the pool
|
||||||
let ext0 = new_transaction(0);
|
let ext0 = new_transaction(0);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), source, ext0)).unwrap();
|
block_on(pool.submit_one(hash_of_block0, source, ext0)).unwrap();
|
||||||
let ext1 = new_transaction(1);
|
let ext1 = new_transaction(1);
|
||||||
block_on(pool.submit_one(&BlockId::number(0), source, ext1)).unwrap();
|
block_on(pool.submit_one(hash_of_block0, source, ext1)).unwrap();
|
||||||
|
|
||||||
let accounts = System::new(client, pool, DenyUnsafe::Yes);
|
let accounts = System::new(client, pool, DenyUnsafe::Yes);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user