mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 07:11:03 +00:00
substrate-test-runtime migrated to "pure" frame runtime (#13737)
* substrate-test-runtime migrated to pure-frame based * test block builder: helpers added * simple renaming * basic_authorship test adjusted * block_building storage_proof test adjusted * babe: tests: should_panic expected added * babe: tests adjusted ConsensusLog::NextEpochData is now added by pallet_babe as pallet_babe::SameAuthoritiesForever trigger is used in runtime config. * beefy: tests adjusted test-substrate-runtime is now using frame::executive to finalize the block. during finalization the digests stored during block execution are checked against header digests: https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591 It makes impossible to directly manipulate header's digets, w/o depositing logs into system pallet storage `Digest<T: Config>`. Instead of this dedicated extrinsic allowing to store logs items (MmrRoot / AuthoritiesChange) is used. * grandpa: tests adjusted test-substrate-runtime is now using frame::executive to finalize the block. during finalization the digest logs stored during block execution are checked against header digest logs: https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591 It makes impossible to directly manipulate header's digets, w/o depositing logs into system pallet storage `Digest<T: Config>`. Instead of this dedicated extrinsic allowing to store logs items (ScheduledChange / ForcedChange and DigestItem::Other) is used. * network:bitswap: test adjusted The size of unchecked extrinsic was increased. The pattern used in test will be placed at the end of scale-encoded buffer. * runtime apis versions adjusted * storage keys used in runtime adjusted * wasm vs native tests removed * rpc tests: adjusted Transfer transaction processing was slightly improved, test was adjusted. * tests: sizes adjusted Runtime extrinsic size was increased. Size of data read during block execution was also increased due to usage of new pallets in runtime. Sizes were adjusted in tests. * cargo.lock update cargo update -p substrate-test-runtime -p substrate-test-runtime-client * warnings fixed * builders cleanup: includes / std * extrinsic validation cleanup * txpool: benches performance fixed * fmt * spelling * Apply suggestions from code review Co-authored-by: Davide Galassi <davxy@datawok.net> * Apply code review suggestions * Apply code review suggestions * get rid of 1063 const * renaming: UncheckedExtrinsic -> Extrinsic * test-utils-runtime: further step to pure-frame * basic-authorship: tests OK * CheckSubstrateCall added + tests fixes * test::Transfer call removed * priority / propagate / no sudo+root-testing * fixing warnings + format * cleanup: build2/nonce + format * final tests fixes all tests are passing * logs/comments removal * should_not_accept_old_signatures test removed * make txpool benches work again * Cargo.lock reset * format * sudo hack removed * txpool benches fix+cleanup * .gitignore reverted * rebase fixing + unsigned cleanup * Cargo.toml/Cargo.lock cleanup * force-debug feature removed * mmr tests fixed * make cargo-clippy happy * network sync test uses unsigned extrinsic * cleanup * ".git/.scripts/commands/fmt/fmt.sh" * push_storage_change signed call remove * GenesisConfig cleanup * fix * fix * GenesisConfig simplified * storage_keys_works: reworked * storage_keys_works: expected keys in vec * storage keys list moved to substrate-test-runtime * substrate-test: some sanity tests + GenesisConfigBuilder rework * Apply suggestions from code review Co-authored-by: Bastian Köcher <git@kchr.de> * Apply suggestions from code review * Review suggestions * fix * fix * beefy: generate_blocks_and_sync block_num sync with actaul value * Apply suggestions from code review Co-authored-by: Davide Galassi <davxy@datawok.net> * Update test-utils/runtime/src/genesismap.rs Co-authored-by: Davide Galassi <davxy@datawok.net> * cargo update -p sc-rpc -p sc-transaction-pool * Review suggestions * fix * doc added * slot_duration adjusted for Babe::slot_duration * small doc fixes * array_bytes::hex used instead of hex * tiny -> medium name fix * Apply suggestions from code review Co-authored-by: Sebastian Kunert <skunert49@gmail.com> * TransferData::try_from_unchecked_extrinsic -> try_from * Update Cargo.lock --------- Co-authored-by: parity-processbot <> Co-authored-by: Davide Galassi <davxy@datawok.net> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
This commit is contained in:
committed by
GitHub
parent
3a90728de0
commit
6a295e7c28
@@ -547,37 +547,29 @@ mod tests {
|
||||
use sp_api::Core;
|
||||
use sp_blockchain::HeaderBackend;
|
||||
use sp_consensus::{BlockOrigin, Environment, Proposer};
|
||||
use sp_core::Pair;
|
||||
use sp_runtime::{generic::BlockId, traits::NumberFor};
|
||||
use sp_runtime::{generic::BlockId, traits::NumberFor, Perbill};
|
||||
use substrate_test_runtime_client::{
|
||||
prelude::*,
|
||||
runtime::{Extrinsic, Transfer},
|
||||
runtime::{Block as TestBlock, Extrinsic, ExtrinsicBuilder, Transfer},
|
||||
TestClientBuilder, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
const SOURCE: TransactionSource = TransactionSource::External;
|
||||
|
||||
fn extrinsic(nonce: u64) -> Extrinsic {
|
||||
Transfer {
|
||||
amount: Default::default(),
|
||||
nonce,
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
}
|
||||
.into_signed_tx()
|
||||
}
|
||||
// Note:
|
||||
// Maximum normal extrinsic size for `substrate_test_runtime` is ~65% of max_block (refer to
|
||||
// `substrate_test_runtime::RuntimeBlockWeights` for details).
|
||||
// This extrinsic sizing allows for:
|
||||
// - one huge xts + a lot of tiny dust
|
||||
// - one huge, no medium,
|
||||
// - two medium xts
|
||||
// This is widely exploited in following tests.
|
||||
const HUGE: u32 = 649000000;
|
||||
const MEDIUM: u32 = 250000000;
|
||||
const TINY: u32 = 1000;
|
||||
|
||||
fn exhausts_resources_extrinsic_from(who: usize) -> Extrinsic {
|
||||
let pair = AccountKeyring::numeric(who);
|
||||
let transfer = Transfer {
|
||||
// increase the amount to bump priority
|
||||
amount: 1,
|
||||
nonce: 0,
|
||||
from: pair.public(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
};
|
||||
let signature = pair.sign(&transfer.encode()).into();
|
||||
Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true }
|
||||
fn extrinsic(nonce: u64) -> Extrinsic {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
|
||||
}
|
||||
|
||||
fn chain_event<B: BlockT>(header: B::Header) -> ChainEvent<B>
|
||||
@@ -738,7 +730,7 @@ mod tests {
|
||||
#[test]
|
||||
fn should_not_remove_invalid_transactions_from_the_same_sender_after_one_was_invalid() {
|
||||
// given
|
||||
let mut client = Arc::new(substrate_test_runtime_client::new());
|
||||
let client = Arc::new(substrate_test_runtime_client::new());
|
||||
let spawner = sp_core::testing::TaskExecutor::new();
|
||||
let txpool = BasicPool::new_full(
|
||||
Default::default(),
|
||||
@@ -748,38 +740,29 @@ mod tests {
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let medium = |nonce| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(MEDIUM))
|
||||
.nonce(nonce)
|
||||
.build()
|
||||
};
|
||||
let huge = |nonce| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE)).nonce(nonce).build()
|
||||
};
|
||||
|
||||
block_on(txpool.submit_at(
|
||||
&BlockId::number(0),
|
||||
SOURCE,
|
||||
vec![
|
||||
extrinsic(0),
|
||||
extrinsic(1),
|
||||
Transfer {
|
||||
amount: Default::default(),
|
||||
nonce: 2,
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
}.into_resources_exhausting_tx(),
|
||||
extrinsic(3),
|
||||
Transfer {
|
||||
amount: Default::default(),
|
||||
nonce: 4,
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
}.into_resources_exhausting_tx(),
|
||||
extrinsic(5),
|
||||
extrinsic(6),
|
||||
],
|
||||
vec![medium(0), medium(1), huge(2), medium(3), huge(4), medium(5), medium(6)],
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
let mut proposer_factory =
|
||||
ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None);
|
||||
let mut propose_block = |client: &TestClient,
|
||||
number,
|
||||
parent_number,
|
||||
expected_block_extrinsics,
|
||||
expected_pool_transactions| {
|
||||
let hash = client.expect_block_hash_from_id(&BlockId::Number(number)).unwrap();
|
||||
let hash = client.expect_block_hash_from_id(&BlockId::Number(parent_number)).unwrap();
|
||||
let proposer = proposer_factory.init_with_now(
|
||||
&client.expect_header(hash).unwrap(),
|
||||
Box::new(move || time::Instant::now()),
|
||||
@@ -794,12 +777,30 @@ mod tests {
|
||||
|
||||
// then
|
||||
// block should have some extrinsics although we have some more in the pool.
|
||||
assert_eq!(txpool.ready().count(), expected_pool_transactions);
|
||||
assert_eq!(block.extrinsics().len(), expected_block_extrinsics);
|
||||
assert_eq!(
|
||||
txpool.ready().count(),
|
||||
expected_pool_transactions,
|
||||
"at block: {}",
|
||||
block.header.number
|
||||
);
|
||||
assert_eq!(
|
||||
block.extrinsics().len(),
|
||||
expected_block_extrinsics,
|
||||
"at block: {}",
|
||||
block.header.number
|
||||
);
|
||||
|
||||
block
|
||||
};
|
||||
|
||||
let import_and_maintain = |mut client: Arc<TestClient>, block: TestBlock| {
|
||||
let hash = block.hash();
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
block_on(txpool.maintain(chain_event(
|
||||
client.expect_header(hash).expect("there should be header"),
|
||||
)));
|
||||
};
|
||||
|
||||
block_on(
|
||||
txpool.maintain(chain_event(
|
||||
client
|
||||
@@ -811,19 +812,28 @@ mod tests {
|
||||
|
||||
// let's create one block and import it
|
||||
let block = propose_block(&client, 0, 2, 7);
|
||||
let hashof1 = block.hash();
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
|
||||
block_on(
|
||||
txpool.maintain(chain_event(
|
||||
client.expect_header(hashof1).expect("there should be header"),
|
||||
)),
|
||||
);
|
||||
import_and_maintain(client.clone(), block);
|
||||
assert_eq!(txpool.ready().count(), 5);
|
||||
|
||||
// now let's make sure that we can still make some progress
|
||||
let block = propose_block(&client, 1, 2, 5);
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
let block = propose_block(&client, 1, 1, 5);
|
||||
import_and_maintain(client.clone(), block);
|
||||
assert_eq!(txpool.ready().count(), 4);
|
||||
|
||||
// again let's make sure that we can still make some progress
|
||||
let block = propose_block(&client, 2, 1, 4);
|
||||
import_and_maintain(client.clone(), block);
|
||||
assert_eq!(txpool.ready().count(), 3);
|
||||
|
||||
// again let's make sure that we can still make some progress
|
||||
let block = propose_block(&client, 3, 1, 3);
|
||||
import_and_maintain(client.clone(), block);
|
||||
assert_eq!(txpool.ready().count(), 2);
|
||||
|
||||
// again let's make sure that we can still make some progress
|
||||
let block = propose_block(&client, 4, 2, 2);
|
||||
import_and_maintain(client.clone(), block);
|
||||
assert_eq!(txpool.ready().count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -849,9 +859,9 @@ mod tests {
|
||||
amount: 100,
|
||||
nonce: 0,
|
||||
}
|
||||
.into_signed_tx(),
|
||||
.into_unchecked_extrinsic(),
|
||||
)
|
||||
.chain((0..extrinsics_num - 1).map(|v| Extrinsic::IncludeData(vec![v as u8; 10])))
|
||||
.chain((1..extrinsics_num as u64).map(extrinsic))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let block_limit = genesis_header.encoded_size() +
|
||||
@@ -862,7 +872,7 @@ mod tests {
|
||||
.sum::<usize>() +
|
||||
Vec::<Extrinsic>::new().encoded_size();
|
||||
|
||||
block_on(txpool.submit_at(&BlockId::number(0), SOURCE, extrinsics)).unwrap();
|
||||
block_on(txpool.submit_at(&BlockId::number(0), SOURCE, extrinsics.clone())).unwrap();
|
||||
|
||||
block_on(txpool.maintain(chain_event(genesis_header.clone())));
|
||||
|
||||
@@ -905,7 +915,13 @@ mod tests {
|
||||
|
||||
let proposer = block_on(proposer_factory.init(&genesis_header)).unwrap();
|
||||
|
||||
// Give it enough time
|
||||
// Exact block_limit, which includes:
|
||||
// 99 (header_size) + 718 (proof@initialize_block) + 246 (one Transfer extrinsic)
|
||||
let block_limit = {
|
||||
let builder =
|
||||
client.new_block_at(genesis_header.hash(), Default::default(), true).unwrap();
|
||||
builder.estimate_block_size(true) + extrinsics[0].encoded_size()
|
||||
};
|
||||
let block = block_on(proposer.propose(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
@@ -915,7 +931,7 @@ mod tests {
|
||||
.map(|r| r.block)
|
||||
.unwrap();
|
||||
|
||||
// The block limit didn't changed, but we now include the proof in the estimation of the
|
||||
// The block limit was increased, but we now include the proof in the estimation of the
|
||||
// block size and thus, only the `Transfer` will fit into the block. It reads more data
|
||||
// than we have reserved in the block limit.
|
||||
assert_eq!(block.extrinsics().len(), 1);
|
||||
@@ -934,6 +950,15 @@ mod tests {
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let tiny = |nonce| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
|
||||
};
|
||||
let huge = |who| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE))
|
||||
.signer(AccountKeyring::numeric(who))
|
||||
.build()
|
||||
};
|
||||
|
||||
block_on(
|
||||
txpool.submit_at(
|
||||
&BlockId::number(0),
|
||||
@@ -941,9 +966,9 @@ mod tests {
|
||||
// add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources
|
||||
(0..MAX_SKIPPED_TRANSACTIONS * 2)
|
||||
.into_iter()
|
||||
.map(|i| exhausts_resources_extrinsic_from(i))
|
||||
.map(huge)
|
||||
// and some transactions that are okay.
|
||||
.chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _)))
|
||||
.chain((0..MAX_SKIPPED_TRANSACTIONS as u64).into_iter().map(tiny))
|
||||
.collect(),
|
||||
),
|
||||
)
|
||||
@@ -997,15 +1022,27 @@ mod tests {
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let tiny = |who| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY))
|
||||
.signer(AccountKeyring::numeric(who))
|
||||
.nonce(1)
|
||||
.build()
|
||||
};
|
||||
let huge = |who| {
|
||||
ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE))
|
||||
.signer(AccountKeyring::numeric(who))
|
||||
.build()
|
||||
};
|
||||
|
||||
block_on(
|
||||
txpool.submit_at(
|
||||
&BlockId::number(0),
|
||||
SOURCE,
|
||||
(0..MAX_SKIPPED_TRANSACTIONS + 2)
|
||||
.into_iter()
|
||||
.map(|i| exhausts_resources_extrinsic_from(i))
|
||||
.map(huge)
|
||||
// and some transactions that are okay.
|
||||
.chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _)))
|
||||
.chain((0..MAX_SKIPPED_TRANSACTIONS + 2).into_iter().map(tiny))
|
||||
.collect(),
|
||||
),
|
||||
)
|
||||
@@ -1018,7 +1055,7 @@ mod tests {
|
||||
.expect("there should be header"),
|
||||
)),
|
||||
);
|
||||
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 2);
|
||||
assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 4);
|
||||
|
||||
let mut proposer_factory =
|
||||
ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None);
|
||||
@@ -1049,8 +1086,13 @@ mod tests {
|
||||
.map(|r| r.block)
|
||||
.unwrap();
|
||||
|
||||
// then the block should have no transactions despite some in the pool
|
||||
assert_eq!(block.extrinsics().len(), 1);
|
||||
// then the block should have one or two transactions. This maybe random as they are
|
||||
// processed in parallel. The same signer and consecutive nonces for huge and tiny
|
||||
// transactions guarantees that max two transactions will get to the block.
|
||||
assert!(
|
||||
(1..3).contains(&block.extrinsics().len()),
|
||||
"Block shall contain one or two extrinsics."
|
||||
);
|
||||
assert!(
|
||||
cell2.lock().0 > MAX_SKIPPED_TRANSACTIONS,
|
||||
"Not enough calls to current time, which indicates the test might have ended because of deadline, not soft deadline"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
//! # use sp_runtime::generic::BlockId;
|
||||
//! # use std::{sync::Arc, time::Duration};
|
||||
//! # use substrate_test_runtime_client::{
|
||||
//! # runtime::{Extrinsic, Transfer}, AccountKeyring,
|
||||
//! # runtime::Transfer, AccountKeyring,
|
||||
//! # DefaultTestClientBuilderExt, TestClientBuilderExt,
|
||||
//! # };
|
||||
//! # use sc_transaction_pool::{BasicPool, FullChainApi};
|
||||
|
||||
@@ -313,7 +313,7 @@ mod tests {
|
||||
use sp_core::Blake2Hasher;
|
||||
use sp_state_machine::Backend;
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::Extrinsic, DefaultTestClientBuilderExt, TestClientBuilderExt,
|
||||
runtime::ExtrinsicBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -322,9 +322,11 @@ mod tests {
|
||||
let backend = builder.backend();
|
||||
let client = builder.build();
|
||||
|
||||
let genesis_hash = client.info().best_hash;
|
||||
|
||||
let block = BlockBuilder::new(
|
||||
&client,
|
||||
client.info().best_hash,
|
||||
genesis_hash,
|
||||
client.info().best_number,
|
||||
RecordProof::Yes,
|
||||
Default::default(),
|
||||
@@ -335,12 +337,11 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
let proof = block.proof.expect("Proof is build on request");
|
||||
let genesis_state_root = client.header(genesis_hash).unwrap().unwrap().state_root;
|
||||
|
||||
let backend = sp_state_machine::create_proof_check_backend::<Blake2Hasher>(
|
||||
block.storage_changes.transaction_storage_root,
|
||||
proof,
|
||||
)
|
||||
.unwrap();
|
||||
let backend =
|
||||
sp_state_machine::create_proof_check_backend::<Blake2Hasher>(genesis_state_root, proof)
|
||||
.unwrap();
|
||||
|
||||
assert!(backend
|
||||
.storage(&sp_core::storage::well_known_keys::CODE)
|
||||
@@ -364,7 +365,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
block_builder.push(Extrinsic::ReadAndPanic(8)).unwrap_err();
|
||||
block_builder.push(ExtrinsicBuilder::new_read_and_panic(8).build()).unwrap_err();
|
||||
|
||||
let block = block_builder.build().unwrap();
|
||||
|
||||
@@ -380,7 +381,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
block_builder.push(Extrinsic::Read(8)).unwrap();
|
||||
block_builder.push(ExtrinsicBuilder::new_read(8).build()).unwrap();
|
||||
|
||||
let block = block_builder.build().unwrap();
|
||||
|
||||
|
||||
@@ -71,15 +71,12 @@ const SLOT_DURATION_MS: u64 = 1000;
|
||||
struct DummyFactory {
|
||||
client: Arc<TestClient>,
|
||||
epoch_changes: SharedEpochChanges<TestBlock, Epoch>,
|
||||
config: BabeConfiguration,
|
||||
mutator: Mutator,
|
||||
}
|
||||
|
||||
struct DummyProposer {
|
||||
factory: DummyFactory,
|
||||
parent_hash: Hash,
|
||||
parent_number: u64,
|
||||
parent_slot: Slot,
|
||||
}
|
||||
|
||||
impl Environment<TestBlock> for DummyFactory {
|
||||
@@ -88,15 +85,9 @@ impl Environment<TestBlock> for DummyFactory {
|
||||
type Error = Error;
|
||||
|
||||
fn init(&mut self, parent_header: &<TestBlock as BlockT>::Header) -> Self::CreateProposer {
|
||||
let parent_slot = crate::find_pre_digest::<TestBlock>(parent_header)
|
||||
.expect("parent header has a pre-digest")
|
||||
.slot();
|
||||
|
||||
future::ready(Ok(DummyProposer {
|
||||
factory: self.clone(),
|
||||
parent_hash: parent_header.hash(),
|
||||
parent_number: *parent_header.number(),
|
||||
parent_slot,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -123,39 +114,6 @@ impl DummyProposer {
|
||||
Err(e) => return future::ready(Err(e)),
|
||||
};
|
||||
|
||||
let this_slot = crate::find_pre_digest::<TestBlock>(block.header())
|
||||
.expect("baked block has valid pre-digest")
|
||||
.slot();
|
||||
|
||||
// figure out if we should add a consensus digest, since the test runtime
|
||||
// doesn't.
|
||||
let epoch_changes = self.factory.epoch_changes.shared_data();
|
||||
let epoch = epoch_changes
|
||||
.epoch_data_for_child_of(
|
||||
descendent_query(&*self.factory.client),
|
||||
&self.parent_hash,
|
||||
self.parent_number,
|
||||
this_slot,
|
||||
|slot| Epoch::genesis(&self.factory.config, slot),
|
||||
)
|
||||
.expect("client has data to find epoch")
|
||||
.expect("can compute epoch for baked block");
|
||||
|
||||
let first_in_epoch = self.parent_slot < epoch.start_slot;
|
||||
if first_in_epoch {
|
||||
// push a `Consensus` digest signalling next change.
|
||||
// we just reuse the same randomness and authorities as the prior
|
||||
// epoch. this will break when we add light client support, since
|
||||
// that will re-check the randomness logic off-chain.
|
||||
let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor {
|
||||
authorities: epoch.authorities.clone(),
|
||||
randomness: epoch.randomness,
|
||||
})
|
||||
.encode();
|
||||
let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data);
|
||||
block.header.digest_mut().push(digest)
|
||||
}
|
||||
|
||||
// mutate the block header according to the mutator.
|
||||
(self.factory.mutator)(&mut block.header, Stage::PreSeal);
|
||||
|
||||
@@ -351,7 +309,7 @@ impl TestNetFactory for BabeTestNet {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
#[should_panic(expected = "No BABE pre-runtime digest found")]
|
||||
async fn rejects_empty_block() {
|
||||
sp_tracing::try_init_simple();
|
||||
let mut net = BabeTestNet::new(3);
|
||||
@@ -398,7 +356,6 @@ async fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + '
|
||||
|
||||
let environ = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: mutator.clone(),
|
||||
};
|
||||
@@ -483,7 +440,7 @@ async fn authoring_blocks() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
#[should_panic(expected = "valid babe headers must contain a predigest")]
|
||||
async fn rejects_missing_inherent_digest() {
|
||||
run_one_test(|header: &mut TestHeader, stage| {
|
||||
let v = std::mem::take(&mut header.digest_mut().logs);
|
||||
@@ -496,7 +453,7 @@ async fn rejects_missing_inherent_digest() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
#[should_panic(expected = "has a bad seal")]
|
||||
async fn rejects_missing_seals() {
|
||||
run_one_test(|header: &mut TestHeader, stage| {
|
||||
let v = std::mem::take(&mut header.digest_mut().logs);
|
||||
@@ -509,7 +466,7 @@ async fn rejects_missing_seals() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
#[should_panic(expected = "Expected epoch change to happen")]
|
||||
async fn rejects_missing_consensus_digests() {
|
||||
run_one_test(|header: &mut TestHeader, stage| {
|
||||
let v = std::mem::take(&mut header.digest_mut().logs);
|
||||
@@ -770,7 +727,6 @@ async fn importing_block_one_sets_genesis_epoch() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -814,7 +770,6 @@ async fn revert_prunes_epoch_changes_and_removes_weights() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -902,7 +857,6 @@ async fn revert_not_allowed_for_finalized() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -943,7 +897,6 @@ async fn importing_epoch_change_block_prunes_tree() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -1030,7 +983,7 @@ async fn importing_epoch_change_block_prunes_tree() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[should_panic]
|
||||
#[should_panic(expected = "Slot number must increase: parent slot: 999, this slot: 999")]
|
||||
async fn verify_slots_are_strictly_increasing() {
|
||||
let mut net = BabeTestNet::new(1);
|
||||
|
||||
@@ -1042,7 +995,6 @@ async fn verify_slots_are_strictly_increasing() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -1082,7 +1034,6 @@ async fn obsolete_blocks_aux_data_cleanup() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -1168,7 +1119,6 @@ async fn allows_skipping_epochs() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
@@ -1298,7 +1248,6 @@ async fn allows_skipping_epochs_on_some_forks() {
|
||||
|
||||
let mut proposer_factory = DummyFactory {
|
||||
client: client.clone(),
|
||||
config: data.link.config.clone(),
|
||||
epoch_changes: data.link.epoch_changes.clone(),
|
||||
mutator: Arc::new(|_, _| ()),
|
||||
};
|
||||
|
||||
@@ -66,7 +66,7 @@ use sp_runtime::{
|
||||
BuildStorage, DigestItem, EncodedJustification, Justifications, Storage,
|
||||
};
|
||||
use std::{marker::PhantomData, sync::Arc, task::Poll};
|
||||
use substrate_test_runtime_client::{runtime::Header, ClientExt};
|
||||
use substrate_test_runtime_client::{BlockBuilderExt, ClientExt};
|
||||
use tokio::time::Duration;
|
||||
|
||||
const GENESIS_HASH: H256 = H256::zero();
|
||||
@@ -165,20 +165,22 @@ impl BeefyTestNet {
|
||||
// push genesis to make indexing human readable (index equals to block number)
|
||||
all_hashes.push(self.peer(0).client().info().genesis_hash);
|
||||
|
||||
let built_hashes = self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
|
||||
let mut block_num: NumberFor<Block> = self.peer(0).client().info().best_number;
|
||||
let built_hashes = self.peer(0).generate_blocks(count, BlockOrigin::File, |mut builder| {
|
||||
block_num = block_num.saturating_add(1).try_into().unwrap();
|
||||
if include_mmr_digest {
|
||||
let block_num = *block.header.number();
|
||||
let num_byte = block_num.to_le_bytes().into_iter().next().unwrap();
|
||||
let mmr_root = MmrRootHash::repeat_byte(num_byte);
|
||||
add_mmr_digest(&mut block.header, mmr_root);
|
||||
add_mmr_digest(&mut builder, mmr_root);
|
||||
}
|
||||
|
||||
if *block.header.number() % session_length == 0 {
|
||||
add_auth_change_digest(&mut block.header, validator_set.clone());
|
||||
if block_num % session_length == 0 {
|
||||
add_auth_change_digest(&mut builder, validator_set.clone());
|
||||
}
|
||||
|
||||
let block = builder.build().unwrap().block;
|
||||
assert_eq!(block.header.number, block_num);
|
||||
|
||||
block
|
||||
});
|
||||
all_hashes.extend(built_hashes);
|
||||
@@ -325,18 +327,22 @@ sp_api::mock_impl_runtime_apis! {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_mmr_digest(header: &mut Header, mmr_hash: MmrRootHash) {
|
||||
header.digest_mut().push(DigestItem::Consensus(
|
||||
BEEFY_ENGINE_ID,
|
||||
ConsensusLog::<AuthorityId>::MmrRoot(mmr_hash).encode(),
|
||||
));
|
||||
fn add_mmr_digest(builder: &mut impl BlockBuilderExt, mmr_hash: MmrRootHash) {
|
||||
builder
|
||||
.push_deposit_log_digest_item(DigestItem::Consensus(
|
||||
BEEFY_ENGINE_ID,
|
||||
ConsensusLog::<AuthorityId>::MmrRoot(mmr_hash).encode(),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn add_auth_change_digest(header: &mut Header, new_auth_set: BeefyValidatorSet) {
|
||||
header.digest_mut().push(DigestItem::Consensus(
|
||||
BEEFY_ENGINE_ID,
|
||||
ConsensusLog::<AuthorityId>::AuthoritiesChange(new_auth_set).encode(),
|
||||
));
|
||||
fn add_auth_change_digest(builder: &mut impl BlockBuilderExt, new_auth_set: BeefyValidatorSet) {
|
||||
builder
|
||||
.push_deposit_log_digest_item(DigestItem::Consensus(
|
||||
BEEFY_ENGINE_ID,
|
||||
ConsensusLog::<AuthorityId>::AuthoritiesChange(new_auth_set).encode(),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn make_beefy_ids(keys: &[BeefyKeyring]) -> Vec<AuthorityId> {
|
||||
|
||||
@@ -48,7 +48,7 @@ use sp_runtime::{
|
||||
Justifications,
|
||||
};
|
||||
use std::{collections::HashSet, pin::Pin};
|
||||
use substrate_test_runtime_client::runtime::BlockNumber;
|
||||
use substrate_test_runtime_client::{runtime::BlockNumber, BlockBuilderExt};
|
||||
use tokio::runtime::Handle;
|
||||
|
||||
use authorities::AuthoritySet;
|
||||
@@ -399,22 +399,27 @@ async fn run_to_completion(
|
||||
run_to_completion_with(blocks, net, peers, |_| None).await
|
||||
}
|
||||
|
||||
fn add_scheduled_change(block: &mut Block, change: ScheduledChange<BlockNumber>) {
|
||||
block.header.digest_mut().push(DigestItem::Consensus(
|
||||
GRANDPA_ENGINE_ID,
|
||||
sp_consensus_grandpa::ConsensusLog::ScheduledChange(change).encode(),
|
||||
));
|
||||
fn add_scheduled_change(builder: &mut impl BlockBuilderExt, change: ScheduledChange<BlockNumber>) {
|
||||
builder
|
||||
.push_deposit_log_digest_item(DigestItem::Consensus(
|
||||
GRANDPA_ENGINE_ID,
|
||||
sp_consensus_grandpa::ConsensusLog::ScheduledChange(change).encode(),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn add_forced_change(
|
||||
block: &mut Block,
|
||||
builder: &mut impl BlockBuilderExt,
|
||||
median_last_finalized: BlockNumber,
|
||||
change: ScheduledChange<BlockNumber>,
|
||||
) {
|
||||
block.header.digest_mut().push(DigestItem::Consensus(
|
||||
GRANDPA_ENGINE_ID,
|
||||
sp_consensus_grandpa::ConsensusLog::ForcedChange(median_last_finalized, change).encode(),
|
||||
));
|
||||
builder
|
||||
.push_deposit_log_digest_item(DigestItem::Consensus(
|
||||
GRANDPA_ENGINE_ID,
|
||||
sp_consensus_grandpa::ConsensusLog::ForcedChange(median_last_finalized, change)
|
||||
.encode(),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -605,28 +610,24 @@ async fn transition_3_voters_twice_1_full_observer() {
|
||||
},
|
||||
14 => {
|
||||
// generate transition at block 15, applied at 20.
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_b), delay: 4 },
|
||||
);
|
||||
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
net.lock().peer(0).push_blocks(5, false);
|
||||
},
|
||||
20 => {
|
||||
// at block 21 we do another transition, but this time instant.
|
||||
// add more until we have 30.
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(&peers_c), delay: 0 },
|
||||
);
|
||||
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
net.lock().peer(0).push_blocks(9, false);
|
||||
},
|
||||
@@ -708,13 +709,12 @@ async fn sync_justifications_on_change_blocks() {
|
||||
// at block 21 we do add a transition which is instant
|
||||
let hashof21 = net
|
||||
.peer(0)
|
||||
.generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
.generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
|
||||
);
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
})
|
||||
.pop()
|
||||
.unwrap();
|
||||
@@ -778,26 +778,24 @@ async fn finalizes_multiple_pending_changes_in_order() {
|
||||
net.peer(0).push_blocks(20, false);
|
||||
|
||||
// at block 21 we do add a transition which is instant
|
||||
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
net.peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
|
||||
);
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
|
||||
// add more blocks on top of it (until we have 25)
|
||||
net.peer(0).push_blocks(4, false);
|
||||
|
||||
// at block 26 we add another which is enacted at block 30
|
||||
net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
net.peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_c), delay: 4 },
|
||||
);
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
|
||||
// add more blocks on top of it (until we have 30)
|
||||
@@ -833,23 +831,21 @@ async fn force_change_to_new_set() {
|
||||
let voters_future = initialize_grandpa(&mut net, peers_a);
|
||||
let net = Arc::new(Mutex::new(net));
|
||||
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
|
||||
net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
// add a forced transition at block 12.
|
||||
add_forced_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
0,
|
||||
ScheduledChange { next_authorities: voters.clone(), delay: 10 },
|
||||
);
|
||||
|
||||
// add a normal transition too to ensure that forced changes take priority.
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(genesis_authorities), delay: 5 },
|
||||
);
|
||||
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
|
||||
net.lock().peer(0).push_blocks(25, false);
|
||||
@@ -885,14 +881,15 @@ async fn allows_reimporting_change_blocks() {
|
||||
let (mut block_import, ..) = net.make_block_import(client.clone());
|
||||
|
||||
let full_client = client.as_client();
|
||||
let builder = full_client
|
||||
let mut builder = full_client
|
||||
.new_block_at(full_client.chain_info().genesis_hash, Default::default(), false)
|
||||
.unwrap();
|
||||
let mut block = builder.build().unwrap().block;
|
||||
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
|
||||
);
|
||||
let block = builder.build().unwrap().block;
|
||||
|
||||
let block = || {
|
||||
let block = block.clone();
|
||||
@@ -929,16 +926,17 @@ async fn test_bad_justification() {
|
||||
let (mut block_import, ..) = net.make_block_import(client.clone());
|
||||
|
||||
let full_client = client.as_client();
|
||||
let builder = full_client
|
||||
let mut builder = full_client
|
||||
.new_block_at(full_client.chain_info().genesis_hash, Default::default(), false)
|
||||
.unwrap();
|
||||
let mut block = builder.build().unwrap().block;
|
||||
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
|
||||
);
|
||||
|
||||
let block = builder.build().unwrap().block;
|
||||
|
||||
let block = || {
|
||||
let block = block.clone();
|
||||
let mut import = BlockImportParams::new(BlockOrigin::File, block.header);
|
||||
@@ -1629,6 +1627,7 @@ async fn grandpa_environment_passes_actual_best_block_to_voting_rules() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn grandpa_environment_checks_if_best_block_is_descendent_of_finality_target() {
|
||||
sp_tracing::try_init_simple();
|
||||
use finality_grandpa::voter::Environment;
|
||||
|
||||
let peers = &[Ed25519Keyring::Alice];
|
||||
@@ -1662,10 +1661,9 @@ async fn grandpa_environment_checks_if_best_block_is_descendent_of_finality_targ
|
||||
BlockId::Number(4),
|
||||
6,
|
||||
BlockOrigin::File,
|
||||
|builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
block.header.digest_mut().push(DigestItem::Other(vec![1]));
|
||||
block
|
||||
|mut builder| {
|
||||
builder.push_deposit_log_digest_item(DigestItem::Other(vec![1])).unwrap();
|
||||
builder.build().unwrap().block
|
||||
},
|
||||
false,
|
||||
false,
|
||||
@@ -1999,13 +1997,12 @@ async fn revert_prunes_authority_changes() {
|
||||
|
||||
type TestBlockBuilder<'a> =
|
||||
BlockBuilder<'a, Block, PeersFullClient, substrate_test_runtime_client::Backend>;
|
||||
let edit_block = |builder: TestBlockBuilder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
let edit_block = |mut builder: TestBlockBuilder| {
|
||||
add_scheduled_change(
|
||||
&mut block,
|
||||
&mut builder,
|
||||
ScheduledChange { next_authorities: make_ids(peers), delay: 0 },
|
||||
);
|
||||
block
|
||||
builder.build().unwrap().block
|
||||
};
|
||||
|
||||
let api = TestApi::new(make_ids(peers));
|
||||
@@ -2047,10 +2044,9 @@ async fn revert_prunes_authority_changes() {
|
||||
BlockId::Number(23),
|
||||
3,
|
||||
BlockOrigin::File,
|
||||
|builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
block.header.digest_mut().push(DigestItem::Other(vec![1]));
|
||||
block
|
||||
|mut builder| {
|
||||
builder.push_deposit_log_digest_item(DigestItem::Other(vec![1])).unwrap();
|
||||
builder.build().unwrap().block
|
||||
},
|
||||
false,
|
||||
false,
|
||||
@@ -2079,10 +2075,9 @@ async fn revert_prunes_authority_changes() {
|
||||
BlockId::Number(25),
|
||||
3,
|
||||
BlockOrigin::File,
|
||||
|builder| {
|
||||
let mut block = builder.build().unwrap().block;
|
||||
block.header.digest_mut().push(DigestItem::Other(vec![2]));
|
||||
block
|
||||
|mut builder| {
|
||||
builder.push_deposit_log_digest_item(DigestItem::Other(vec![2])).unwrap();
|
||||
builder.build().unwrap().block
|
||||
},
|
||||
false,
|
||||
false,
|
||||
|
||||
@@ -326,11 +326,10 @@ mod tests {
|
||||
use sp_consensus::BlockOrigin;
|
||||
use sp_consensus_grandpa::GRANDPA_ENGINE_ID;
|
||||
use sp_keyring::Ed25519Keyring;
|
||||
use sp_runtime::traits::Header as _;
|
||||
use std::sync::Arc;
|
||||
use substrate_test_runtime_client::{
|
||||
ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt, TestClientBuilder,
|
||||
TestClientBuilderExt,
|
||||
BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
|
||||
TestClientBuilder, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -348,8 +347,7 @@ mod tests {
|
||||
let mut authority_set_changes = Vec::new();
|
||||
|
||||
for n in 1..=100 {
|
||||
let mut block = client.new_block(Default::default()).unwrap().build().unwrap().block;
|
||||
|
||||
let mut builder = client.new_block(Default::default()).unwrap();
|
||||
let mut new_authorities = None;
|
||||
|
||||
// we will trigger an authority set change every 10 blocks
|
||||
@@ -376,9 +374,11 @@ mod tests {
|
||||
.encode(),
|
||||
);
|
||||
|
||||
block.header.digest_mut().logs.push(digest);
|
||||
builder.push_deposit_log_digest_item(digest).unwrap();
|
||||
}
|
||||
|
||||
let block = builder.build().unwrap().block;
|
||||
|
||||
futures::executor::block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
|
||||
if let Some(new_authorities) = new_authorities {
|
||||
|
||||
@@ -297,7 +297,7 @@ mod tests {
|
||||
};
|
||||
use sp_consensus::BlockOrigin;
|
||||
use sp_runtime::codec::Encode;
|
||||
use substrate_test_runtime::Extrinsic;
|
||||
use substrate_test_runtime::ExtrinsicBuilder;
|
||||
use substrate_test_runtime_client::{self, prelude::*, TestClientBuilder};
|
||||
|
||||
#[tokio::test]
|
||||
@@ -470,7 +470,9 @@ mod tests {
|
||||
let mut client = TestClientBuilder::with_tx_storage(u32::MAX).build();
|
||||
let mut block_builder = client.new_block(Default::default()).unwrap();
|
||||
|
||||
let ext = Extrinsic::Store(vec![0x13, 0x37, 0x13, 0x38]);
|
||||
// encoded extrinsic: [161, .. , 2, 6, 16, 19, 55, 19, 56]
|
||||
let ext = ExtrinsicBuilder::new_indexed_call(vec![0x13, 0x37, 0x13, 0x38]).build();
|
||||
let pattern_index = ext.encoded_size() - 4;
|
||||
|
||||
block_builder.push(ext.clone()).unwrap();
|
||||
let block = block_builder.build().unwrap().block;
|
||||
@@ -494,7 +496,7 @@ mod tests {
|
||||
0x70,
|
||||
cid::multihash::Multihash::wrap(
|
||||
u64::from(cid::multihash::Code::Blake2b256),
|
||||
&sp_core::hashing::blake2_256(&ext.encode()[2..]),
|
||||
&sp_core::hashing::blake2_256(&ext.encode()[pattern_index..]),
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
|
||||
@@ -88,13 +88,11 @@ use sp_runtime::{
|
||||
};
|
||||
use substrate_test_runtime_client::AccountKeyring;
|
||||
pub use substrate_test_runtime_client::{
|
||||
runtime::{Block, Extrinsic, Hash, Header, Transfer},
|
||||
runtime::{Block, ExtrinsicBuilder, Hash, Header, Transfer},
|
||||
TestClient, TestClientBuilder, TestClientBuilderExt,
|
||||
};
|
||||
use tokio::time::timeout;
|
||||
|
||||
type AuthorityId = sp_consensus_babe::AuthorityId;
|
||||
|
||||
/// A Verifier that accepts all blocks and passes them on with the configured
|
||||
/// finality to be imported.
|
||||
#[derive(Clone)]
|
||||
@@ -474,7 +472,7 @@ where
|
||||
amount: 1,
|
||||
nonce,
|
||||
};
|
||||
builder.push(transfer.into_signed_tx()).unwrap();
|
||||
builder.push(transfer.into_unchecked_extrinsic()).unwrap();
|
||||
nonce += 1;
|
||||
builder.build().unwrap().block
|
||||
},
|
||||
@@ -497,16 +495,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_authorities_change_block(
|
||||
&mut self,
|
||||
new_authorities: Vec<AuthorityId>,
|
||||
) -> Vec<H256> {
|
||||
self.generate_blocks(1, BlockOrigin::File, |mut builder| {
|
||||
builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap();
|
||||
builder.build().unwrap().block
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a reference to the client.
|
||||
pub fn client(&self) -> &PeersClient {
|
||||
&self.client
|
||||
|
||||
@@ -1183,7 +1183,7 @@ async fn syncs_indexed_blocks() {
|
||||
64,
|
||||
BlockOrigin::Own,
|
||||
|mut builder| {
|
||||
let ex = Extrinsic::Store(n.to_le_bytes().to_vec());
|
||||
let ex = ExtrinsicBuilder::new_indexed_call(n.to_le_bytes().to_vec()).nonce(n).build();
|
||||
n += 1;
|
||||
builder.push(ex).unwrap();
|
||||
builder.build().unwrap().block
|
||||
@@ -1305,11 +1305,13 @@ async fn syncs_huge_blocks() {
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
|
||||
let mut nonce = 0;
|
||||
net.peer(0).generate_blocks(32, BlockOrigin::Own, |mut builder| {
|
||||
// Add 32 extrinsics 32k each = 1MiB total
|
||||
for _ in 0..32 {
|
||||
let ex = Extrinsic::IncludeData([42u8; 32 * 1024].to_vec());
|
||||
for _ in 0..32u64 {
|
||||
let ex = ExtrinsicBuilder::new_include_data(vec![42u8; 32 * 1024]).nonce(nonce).build();
|
||||
builder.push(ex).unwrap();
|
||||
nonce += 1;
|
||||
}
|
||||
builder.build().unwrap().block
|
||||
});
|
||||
|
||||
@@ -254,8 +254,10 @@ mod tests {
|
||||
use sp_runtime::generic::BlockId;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::Block, ClientBlockImportExt, DefaultTestClientBuilderExt, TestClient,
|
||||
TestClientBuilderExt,
|
||||
runtime::{
|
||||
substrate_test_pallet::pallet::Call as PalletCall, Block, ExtrinsicBuilder, RuntimeCall,
|
||||
},
|
||||
ClientBlockImportExt, DefaultTestClientBuilderExt, TestClient, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
struct TestNetwork();
|
||||
@@ -385,7 +387,10 @@ mod tests {
|
||||
|
||||
// then
|
||||
assert_eq!(pool.0.status().ready, 1);
|
||||
assert_eq!(pool.0.ready().next().unwrap().is_propagable(), false);
|
||||
assert!(matches!(
|
||||
pool.0.ready().next().unwrap().data().function,
|
||||
RuntimeCall::SubstrateTest(PalletCall::storage_change { .. })
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -403,12 +408,8 @@ mod tests {
|
||||
let key = &b"hello"[..];
|
||||
let value = &b"world"[..];
|
||||
let mut block_builder = client.new_block(Default::default()).unwrap();
|
||||
block_builder
|
||||
.push(substrate_test_runtime_client::runtime::Extrinsic::OffchainIndexSet(
|
||||
key.to_vec(),
|
||||
value.to_vec(),
|
||||
))
|
||||
.unwrap();
|
||||
let ext = ExtrinsicBuilder::new_offchain_index_set(key.to_vec(), value.to_vec()).build();
|
||||
block_builder.push(ext).unwrap();
|
||||
|
||||
let block = block_builder.build().unwrap().block;
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
@@ -416,11 +417,8 @@ mod tests {
|
||||
assert_eq!(value, &offchain_db.get(sp_offchain::STORAGE_PREFIX, &key).unwrap());
|
||||
|
||||
let mut block_builder = client.new_block(Default::default()).unwrap();
|
||||
block_builder
|
||||
.push(substrate_test_runtime_client::runtime::Extrinsic::OffchainIndexClear(
|
||||
key.to_vec(),
|
||||
))
|
||||
.unwrap();
|
||||
let ext = ExtrinsicBuilder::new_offchain_index_clear(key.to_vec()).nonce(1).build();
|
||||
block_builder.push(ext).unwrap();
|
||||
|
||||
let block = block_builder.build().unwrap().block;
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
|
||||
@@ -184,12 +184,13 @@ async fn follow_with_runtime() {
|
||||
// Initialized must always be reported first.
|
||||
let event: FollowEvent<String> = get_next_event(&mut sub).await;
|
||||
|
||||
// it is basically json-encoded substrate_test_runtime_client::runtime::VERSION
|
||||
let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
|
||||
\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\
|
||||
[\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\
|
||||
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\
|
||||
[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\
|
||||
\"transactionVersion\":1,\"stateVersion\":1}";
|
||||
[\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\
|
||||
[\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\
|
||||
[\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}";
|
||||
let runtime: RuntimeVersion = serde_json::from_str(runtime_str).unwrap();
|
||||
|
||||
let finalized_block_runtime =
|
||||
|
||||
@@ -37,10 +37,11 @@ use sp_core::{
|
||||
H256,
|
||||
};
|
||||
use sp_keystore::{testing::MemoryKeystore, Keystore};
|
||||
use sp_runtime::Perbill;
|
||||
use std::sync::Arc;
|
||||
use substrate_test_runtime_client::{
|
||||
self,
|
||||
runtime::{Block, Extrinsic, SessionKeys, Transfer},
|
||||
runtime::{Block, Extrinsic, ExtrinsicBuilder, SessionKeys, Transfer},
|
||||
AccountKeyring, Backend, Client, DefaultTestClientBuilderExt, TestClientBuilderExt,
|
||||
};
|
||||
|
||||
@@ -51,7 +52,7 @@ fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic {
|
||||
from: sender.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
};
|
||||
tx.into_signed_tx()
|
||||
ExtrinsicBuilder::new_transfer(tx).build()
|
||||
}
|
||||
|
||||
type FullTransactionPool = BasicPool<FullChainApi<Client<Backend>, Block>, Block>;
|
||||
@@ -111,7 +112,13 @@ async fn author_submit_transaction_should_not_cause_error() {
|
||||
#[tokio::test]
|
||||
async fn author_should_watch_extrinsic() {
|
||||
let api = TestSetup::into_rpc();
|
||||
let xt = to_hex(&uxt(AccountKeyring::Alice, 0).encode(), true);
|
||||
let xt = to_hex(
|
||||
&ExtrinsicBuilder::new_call_with_priority(0)
|
||||
.signer(AccountKeyring::Alice.into())
|
||||
.build()
|
||||
.encode(),
|
||||
true,
|
||||
);
|
||||
|
||||
let mut sub = api.subscribe("author_submitAndWatchExtrinsic", [xt]).await.unwrap();
|
||||
let (tx, sub_id) = timeout_secs(10, sub.next::<TransactionStatus<H256, Block>>())
|
||||
@@ -125,15 +132,11 @@ async fn author_should_watch_extrinsic() {
|
||||
|
||||
// Replace the extrinsic and observe the subscription is notified.
|
||||
let (xt_replacement, xt_hash) = {
|
||||
let tx = Transfer {
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
};
|
||||
let tx = tx.into_signed_tx().encode();
|
||||
let tx = ExtrinsicBuilder::new_call_with_priority(1)
|
||||
.signer(AccountKeyring::Alice.into())
|
||||
.build()
|
||||
.encode();
|
||||
let hash = blake2_256(&tx);
|
||||
|
||||
(to_hex(&tx, true), hash)
|
||||
};
|
||||
|
||||
@@ -152,10 +155,10 @@ async fn author_should_watch_extrinsic() {
|
||||
async fn author_should_return_watch_validation_error() {
|
||||
const METHOD: &'static str = "author_submitAndWatchExtrinsic";
|
||||
|
||||
let invalid_xt = ExtrinsicBuilder::new_fill_block(Perbill::from_percent(100)).build();
|
||||
|
||||
let api = TestSetup::into_rpc();
|
||||
let failed_sub = api
|
||||
.subscribe(METHOD, [to_hex(&uxt(AccountKeyring::Alice, 179).encode(), true)])
|
||||
.await;
|
||||
let failed_sub = api.subscribe(METHOD, [to_hex(&invalid_xt.encode(), true)]).await;
|
||||
|
||||
assert_matches!(
|
||||
failed_sub,
|
||||
|
||||
@@ -28,6 +28,22 @@ async fn block_stats_work() {
|
||||
let api = <Dev<Block, _>>::new(client.clone(), DenyUnsafe::No).into_rpc();
|
||||
|
||||
let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
|
||||
|
||||
let (expected_witness_len, expected_witness_compact_len, expected_block_len) = {
|
||||
let genesis_hash = client.chain_info().genesis_hash;
|
||||
let mut runtime_api = client.runtime_api();
|
||||
runtime_api.record_proof();
|
||||
runtime_api.execute_block(genesis_hash, block.clone()).unwrap();
|
||||
let witness = runtime_api.extract_proof().unwrap();
|
||||
let pre_root = *client.header(genesis_hash).unwrap().unwrap().state_root();
|
||||
|
||||
(
|
||||
witness.clone().encoded_size() as u64,
|
||||
witness.into_compact_proof::<HasherOf<Block>>(pre_root).unwrap().encoded_size() as u64,
|
||||
block.encoded_size() as u64,
|
||||
)
|
||||
};
|
||||
|
||||
client.import(BlockOrigin::Own, block).await.unwrap();
|
||||
|
||||
// Can't gather stats for a block without a parent.
|
||||
@@ -43,9 +59,9 @@ async fn block_stats_work() {
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(BlockStats {
|
||||
witness_len: 630,
|
||||
witness_compact_len: 534,
|
||||
block_len: 99,
|
||||
witness_len: expected_witness_len,
|
||||
witness_compact_len: expected_witness_compact_len,
|
||||
block_len: expected_block_len,
|
||||
num_extrinsics: 0,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -29,9 +29,11 @@ use sc_block_builder::BlockBuilderProvider;
|
||||
use sc_rpc_api::DenyUnsafe;
|
||||
use sp_consensus::BlockOrigin;
|
||||
use sp_core::{hash::H256, storage::ChildInfo};
|
||||
use sp_io::hashing::blake2_256;
|
||||
use std::sync::Arc;
|
||||
use substrate_test_runtime_client::{prelude::*, runtime};
|
||||
use substrate_test_runtime_client::{
|
||||
prelude::*,
|
||||
runtime::{ExtrinsicBuilder, Transfer},
|
||||
};
|
||||
|
||||
const STORAGE_KEY: &[u8] = b"child";
|
||||
|
||||
@@ -218,7 +220,7 @@ async fn should_notify_about_storage_changes() {
|
||||
// Cause a change:
|
||||
let mut builder = client.new_block(Default::default()).unwrap();
|
||||
builder
|
||||
.push_transfer(runtime::Transfer {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 42,
|
||||
@@ -244,18 +246,26 @@ async fn should_send_initial_storage_changes_and_notifications() {
|
||||
let mut client = Arc::new(substrate_test_runtime_client::new());
|
||||
let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
|
||||
|
||||
let alice_balance_key =
|
||||
blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
|
||||
let alice_balance_key = [
|
||||
sp_core::hashing::twox_128(b"System"),
|
||||
sp_core::hashing::twox_128(b"Account"),
|
||||
sp_core::hashing::blake2_128(&AccountKeyring::Alice.public()),
|
||||
]
|
||||
.concat()
|
||||
.iter()
|
||||
.chain(AccountKeyring::Alice.public().0.iter())
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>();
|
||||
|
||||
let api_rpc = api.into_rpc();
|
||||
let sub = api_rpc
|
||||
.subscribe("state_subscribeStorage", [[StorageKey(alice_balance_key.to_vec())]])
|
||||
.subscribe("state_subscribeStorage", [[StorageKey(alice_balance_key)]])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut builder = client.new_block(Default::default()).unwrap();
|
||||
builder
|
||||
.push_transfer(runtime::Transfer {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 42,
|
||||
@@ -280,22 +290,42 @@ async fn should_query_storage() {
|
||||
async fn run_tests(mut client: Arc<TestClient>) {
|
||||
let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
|
||||
|
||||
let mut add_block = |nonce| {
|
||||
let mut add_block = |index| {
|
||||
let mut builder = client.new_block(Default::default()).unwrap();
|
||||
// fake change: None -> None -> None
|
||||
builder.push_storage_change(vec![1], None).unwrap();
|
||||
builder
|
||||
.push(ExtrinsicBuilder::new_storage_change(vec![1], None).build())
|
||||
.unwrap();
|
||||
// fake change: None -> Some(value) -> Some(value)
|
||||
builder.push_storage_change(vec![2], Some(vec![2])).unwrap();
|
||||
builder
|
||||
.push(ExtrinsicBuilder::new_storage_change(vec![2], Some(vec![2])).build())
|
||||
.unwrap();
|
||||
// actual change: None -> Some(value) -> None
|
||||
builder
|
||||
.push_storage_change(vec![3], if nonce == 0 { Some(vec![3]) } else { None })
|
||||
.push(
|
||||
ExtrinsicBuilder::new_storage_change(
|
||||
vec![3],
|
||||
if index == 0 { Some(vec![3]) } else { None },
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.unwrap();
|
||||
// actual change: None -> Some(value)
|
||||
builder
|
||||
.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) })
|
||||
.push(
|
||||
ExtrinsicBuilder::new_storage_change(
|
||||
vec![4],
|
||||
if index == 0 { None } else { Some(vec![4]) },
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.unwrap();
|
||||
// actual change: Some(value1) -> Some(value2)
|
||||
builder.push_storage_change(vec![5], Some(vec![nonce as u8])).unwrap();
|
||||
builder
|
||||
.push(
|
||||
ExtrinsicBuilder::new_storage_change(vec![5], Some(vec![index as u8])).build(),
|
||||
)
|
||||
.unwrap();
|
||||
let block = builder.build().unwrap().block;
|
||||
let hash = block.header.hash();
|
||||
executor::block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
@@ -482,12 +512,13 @@ async fn should_return_runtime_version() {
|
||||
let client = Arc::new(substrate_test_runtime_client::new());
|
||||
let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
|
||||
|
||||
// it is basically json-encoded substrate_test_runtime_client::runtime::VERSION
|
||||
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
|
||||
\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\
|
||||
[\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\
|
||||
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\
|
||||
[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\
|
||||
\"transactionVersion\":1,\"stateVersion\":1}";
|
||||
[\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\
|
||||
[\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\
|
||||
[\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}";
|
||||
|
||||
let runtime_version = api.runtime_version(None.into()).unwrap();
|
||||
let serialized = serde_json::to_string(&runtime_version).unwrap();
|
||||
|
||||
@@ -520,10 +520,9 @@ mod tests {
|
||||
use futures::executor::block_on;
|
||||
use sc_transaction_pool::BasicPool;
|
||||
use sp_consensus::SelectChain;
|
||||
use sp_runtime::traits::BlindCheckable;
|
||||
use substrate_test_runtime_client::{
|
||||
prelude::*,
|
||||
runtime::{Extrinsic, Transfer},
|
||||
runtime::{ExtrinsicBuilder, Transfer, TransferData},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -542,13 +541,13 @@ mod tests {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
}
|
||||
.into_signed_tx();
|
||||
.into_unchecked_extrinsic();
|
||||
block_on(pool.submit_one(&BlockId::hash(best.hash()), source, transaction.clone()))
|
||||
.unwrap();
|
||||
block_on(pool.submit_one(
|
||||
&BlockId::hash(best.hash()),
|
||||
source,
|
||||
Extrinsic::IncludeData(vec![1]),
|
||||
ExtrinsicBuilder::new_call_do_not_propagate().nonce(1).build(),
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(pool.status().ready, 2);
|
||||
@@ -558,8 +557,6 @@ mod tests {
|
||||
|
||||
// then
|
||||
assert_eq!(transactions.len(), 1);
|
||||
assert!(transactions[0].1.clone().check().is_ok());
|
||||
// this should not panic
|
||||
let _ = transactions[0].1.transfer();
|
||||
assert!(TransferData::try_from(&transactions[0].1).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ use substrate_test_runtime_client::{
|
||||
new_native_or_wasm_executor,
|
||||
prelude::*,
|
||||
runtime::{
|
||||
genesismap::{insert_genesis_block, GenesisConfig},
|
||||
currency::DOLLARS,
|
||||
genesismap::{insert_genesis_block, GenesisStorageBuilder},
|
||||
Block, BlockNumber, Digest, Hash, Header, RuntimeApi, Transfer,
|
||||
},
|
||||
AccountKeyring, BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
|
||||
@@ -66,7 +67,7 @@ fn construct_block(
|
||||
state_root: Hash,
|
||||
txs: Vec<Transfer>,
|
||||
) -> (Vec<u8>, Hash) {
|
||||
let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::<Vec<_>>();
|
||||
let transactions = txs.into_iter().map(|tx| tx.into_unchecked_extrinsic()).collect::<Vec<_>>();
|
||||
|
||||
let iter = transactions.iter().map(Encode::encode);
|
||||
let extrinsics_root = LayoutV0::<BlakeTwo256>::ordered_trie_root(iter).into();
|
||||
@@ -137,9 +138,9 @@ fn block1(genesis_hash: Hash, backend: &InMemoryBackend<BlakeTwo256>) -> (Vec<u8
|
||||
"25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c",
|
||||
),
|
||||
vec![Transfer {
|
||||
from: AccountKeyring::One.into(),
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Two.into(),
|
||||
amount: 69,
|
||||
amount: 69 * DOLLARS,
|
||||
nonce: 0,
|
||||
}],
|
||||
)
|
||||
@@ -167,14 +168,12 @@ fn finality_notification_check(
|
||||
|
||||
#[test]
|
||||
fn construct_genesis_should_work_with_native() {
|
||||
let mut storage = GenesisConfig::new(
|
||||
let mut storage = GenesisStorageBuilder::new(
|
||||
vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
|
||||
vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
|
||||
1000,
|
||||
None,
|
||||
Default::default(),
|
||||
1000 * DOLLARS,
|
||||
)
|
||||
.genesis_map();
|
||||
.build_storage();
|
||||
let genesis_hash = insert_genesis_block(&mut storage);
|
||||
|
||||
let backend = InMemoryBackend::from((storage, StateVersion::default()));
|
||||
@@ -200,14 +199,12 @@ fn construct_genesis_should_work_with_native() {
|
||||
|
||||
#[test]
|
||||
fn construct_genesis_should_work_with_wasm() {
|
||||
let mut storage = GenesisConfig::new(
|
||||
let mut storage = GenesisStorageBuilder::new(
|
||||
vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
|
||||
vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
|
||||
1000,
|
||||
None,
|
||||
Default::default(),
|
||||
1000 * DOLLARS,
|
||||
)
|
||||
.genesis_map();
|
||||
.build_storage();
|
||||
let genesis_hash = insert_genesis_block(&mut storage);
|
||||
|
||||
let backend = InMemoryBackend::from((storage, StateVersion::default()));
|
||||
@@ -231,39 +228,6 @@ fn construct_genesis_should_work_with_wasm() {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_genesis_with_bad_transaction_should_panic() {
|
||||
let mut storage = GenesisConfig::new(
|
||||
vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
|
||||
vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
|
||||
68,
|
||||
None,
|
||||
Default::default(),
|
||||
)
|
||||
.genesis_map();
|
||||
let genesis_hash = insert_genesis_block(&mut storage);
|
||||
|
||||
let backend = InMemoryBackend::from((storage, StateVersion::default()));
|
||||
let (b1data, _b1hash) = block1(genesis_hash, &backend);
|
||||
let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend);
|
||||
let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
|
||||
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
|
||||
let r = StateMachine::new(
|
||||
&backend,
|
||||
&mut overlay,
|
||||
&new_native_or_wasm_executor(),
|
||||
"Core_execute_block",
|
||||
&b1data,
|
||||
Default::default(),
|
||||
&runtime_code,
|
||||
CallContext::Onchain,
|
||||
)
|
||||
.execute(ExecutionStrategy::NativeElseWasm);
|
||||
assert!(r.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_initializes_from_genesis_ok() {
|
||||
let client = substrate_test_runtime_client::new();
|
||||
@@ -273,14 +237,14 @@ fn client_initializes_from_genesis_ok() {
|
||||
.runtime_api()
|
||||
.balance_of(client.chain_info().best_hash, AccountKeyring::Alice.into())
|
||||
.unwrap(),
|
||||
1000
|
||||
1000 * DOLLARS
|
||||
);
|
||||
assert_eq!(
|
||||
client
|
||||
.runtime_api()
|
||||
.balance_of(client.chain_info().best_hash, AccountKeyring::Ferdie.into())
|
||||
.unwrap(),
|
||||
0
|
||||
0 * DOLLARS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -305,7 +269,7 @@ fn block_builder_works_with_transactions() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 42,
|
||||
amount: 42 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -340,42 +304,43 @@ fn block_builder_works_with_transactions() {
|
||||
.runtime_api()
|
||||
.balance_of(client.chain_info().best_hash, AccountKeyring::Alice.into())
|
||||
.unwrap(),
|
||||
958
|
||||
958 * DOLLARS
|
||||
);
|
||||
assert_eq!(
|
||||
client
|
||||
.runtime_api()
|
||||
.balance_of(client.chain_info().best_hash, AccountKeyring::Ferdie.into())
|
||||
.unwrap(),
|
||||
42
|
||||
42 * DOLLARS
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_builder_does_not_include_invalid() {
|
||||
let mut client = substrate_test_runtime_client::new();
|
||||
|
||||
let mut builder = client.new_block(Default::default()).unwrap();
|
||||
|
||||
builder
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 42,
|
||||
amount: 42 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert!(builder
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Eve.into(),
|
||||
to: AccountKeyring::Alice.into(),
|
||||
amount: 42,
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 30 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.is_err());
|
||||
|
||||
let block = builder.build().unwrap().block;
|
||||
//transfer from Eve should not be included
|
||||
assert_eq!(block.extrinsics.len(), 1);
|
||||
block_on(client.import(BlockOrigin::Own, block)).unwrap();
|
||||
|
||||
let hashof0 = client
|
||||
@@ -491,7 +456,7 @@ fn uncles_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 41,
|
||||
amount: 41 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -523,7 +488,7 @@ fn uncles_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 1,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -537,7 +502,7 @@ fn uncles_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -646,7 +611,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 41,
|
||||
amount: 41 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -678,7 +643,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 1,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -692,7 +657,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -868,7 +833,7 @@ fn finality_target_with_best_not_on_longest_chain() {
|
||||
.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 41,
|
||||
amount: 41 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -993,7 +958,7 @@ fn importing_diverged_finalized_block_should_trigger_reorg() {
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1048,7 +1013,7 @@ fn finalizing_diverged_block_should_trigger_reorg() {
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1166,7 +1131,7 @@ fn finality_notifications_content() {
|
||||
c1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 2,
|
||||
amount: 2 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1178,7 +1143,7 @@ fn finality_notifications_content() {
|
||||
d3.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 2,
|
||||
amount: 2 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1252,7 +1217,7 @@ fn state_reverted_on_reorg() {
|
||||
a1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Bob.into(),
|
||||
amount: 10,
|
||||
amount: 10 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1265,7 +1230,7 @@ fn state_reverted_on_reorg() {
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 50,
|
||||
amount: 50 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1273,19 +1238,19 @@ fn state_reverted_on_reorg() {
|
||||
// Reorg to B1
|
||||
block_on(client.import_as_best(BlockOrigin::Own, b1.clone())).unwrap();
|
||||
|
||||
assert_eq!(950, current_balance(&client));
|
||||
assert_eq!(950 * DOLLARS, current_balance(&client));
|
||||
let mut a2 = client.new_block_at(a1.hash(), Default::default(), false).unwrap();
|
||||
a2.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Charlie.into(),
|
||||
amount: 10,
|
||||
amount: 10 * DOLLARS,
|
||||
nonce: 1,
|
||||
})
|
||||
.unwrap();
|
||||
let a2 = a2.build().unwrap().block;
|
||||
// Re-org to A2
|
||||
block_on(client.import_as_best(BlockOrigin::Own, a2)).unwrap();
|
||||
assert_eq!(980, current_balance(&client));
|
||||
assert_eq!(980 * DOLLARS, current_balance(&client));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1342,7 +1307,7 @@ fn doesnt_import_blocks_that_revert_finality() {
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1386,7 +1351,7 @@ fn doesnt_import_blocks_that_revert_finality() {
|
||||
c1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 2,
|
||||
amount: 2 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1579,7 +1544,7 @@ fn returns_status_for_pruned_blocks() {
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
@@ -1718,8 +1683,9 @@ fn storage_keys_prefix_and_start_key_works() {
|
||||
res,
|
||||
[
|
||||
child_root.clone(),
|
||||
array_bytes::hex2bytes_unchecked("3a636f6465"),
|
||||
array_bytes::hex2bytes_unchecked("3a686561707061676573"),
|
||||
array_bytes::hex2bytes_unchecked("3a636f6465"), //":code"
|
||||
array_bytes::hex2bytes_unchecked("3a65787472696e7369635f696e646578"), //":extrinsic_index"
|
||||
array_bytes::hex2bytes_unchecked("3a686561707061676573"), //":heappages"
|
||||
]
|
||||
);
|
||||
|
||||
@@ -1732,7 +1698,13 @@ fn storage_keys_prefix_and_start_key_works() {
|
||||
.unwrap()
|
||||
.map(|x| x.0)
|
||||
.collect();
|
||||
assert_eq!(res, [array_bytes::hex2bytes_unchecked("3a686561707061676573")]);
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
array_bytes::hex2bytes_unchecked("3a65787472696e7369635f696e646578"),
|
||||
array_bytes::hex2bytes_unchecked("3a686561707061676573")
|
||||
]
|
||||
);
|
||||
|
||||
let res: Vec<_> = client
|
||||
.storage_keys(
|
||||
@@ -1762,54 +1734,32 @@ fn storage_keys_prefix_and_start_key_works() {
|
||||
|
||||
#[test]
|
||||
fn storage_keys_works() {
|
||||
sp_tracing::try_init_simple();
|
||||
|
||||
let expected_keys =
|
||||
substrate_test_runtime::storage_key_generator::get_expected_storage_hashed_keys();
|
||||
|
||||
let client = substrate_test_runtime_client::new();
|
||||
|
||||
let block_hash = client.info().best_hash;
|
||||
|
||||
let prefix = StorageKey(array_bytes::hex2bytes_unchecked(""));
|
||||
|
||||
let res: Vec<_> = client
|
||||
.storage_keys(block_hash, Some(&prefix), None)
|
||||
.unwrap()
|
||||
.take(9)
|
||||
.take(19)
|
||||
.map(|x| array_bytes::bytes2hex("", &x.0))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
"00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0",
|
||||
"085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb",
|
||||
"0befda6e1ca4ef40219d588a727f1271",
|
||||
"1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34",
|
||||
"1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824",
|
||||
"237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204",
|
||||
"26aa394eea5630e07c48ae0c9558cef75e0621c4869aa60c02be9adcc98a0d1d",
|
||||
"29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729",
|
||||
"3a636f6465",
|
||||
]
|
||||
);
|
||||
|
||||
assert_eq!(res, expected_keys[0..19],);
|
||||
|
||||
// Starting at an empty key nothing gets skipped.
|
||||
let res: Vec<_> = client
|
||||
.storage_keys(block_hash, Some(&prefix), Some(&StorageKey("".into())))
|
||||
.unwrap()
|
||||
.take(9)
|
||||
.take(19)
|
||||
.map(|x| array_bytes::bytes2hex("", &x.0))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
"00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0",
|
||||
"085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb",
|
||||
"0befda6e1ca4ef40219d588a727f1271",
|
||||
"1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34",
|
||||
"1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824",
|
||||
"237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204",
|
||||
"26aa394eea5630e07c48ae0c9558cef75e0621c4869aa60c02be9adcc98a0d1d",
|
||||
"29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729",
|
||||
"3a636f6465",
|
||||
]
|
||||
);
|
||||
assert_eq!(res, expected_keys[0..19],);
|
||||
|
||||
// Starting at an incomplete key nothing gets skipped.
|
||||
let res: Vec<_> = client
|
||||
@@ -1824,16 +1774,12 @@ fn storage_keys_works() {
|
||||
.collect();
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
"3a636f6465",
|
||||
"3a686561707061676573",
|
||||
"52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56",
|
||||
"5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5",
|
||||
"5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133",
|
||||
"6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081",
|
||||
"66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808",
|
||||
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
|
||||
]
|
||||
expected_keys
|
||||
.iter()
|
||||
.filter(|&i| i > &"3a636f64".to_string())
|
||||
.take(8)
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
);
|
||||
|
||||
// Starting at a complete key the first key is skipped.
|
||||
@@ -1849,38 +1795,33 @@ fn storage_keys_works() {
|
||||
.collect();
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
"3a686561707061676573",
|
||||
"52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56",
|
||||
"5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5",
|
||||
"5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133",
|
||||
"6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081",
|
||||
"66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808",
|
||||
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
|
||||
]
|
||||
expected_keys
|
||||
.iter()
|
||||
.filter(|&i| i > &"3a636f6465".to_string())
|
||||
.take(8)
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
);
|
||||
|
||||
const SOME_BALANCE_KEY : &str = "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e2c1dc507e2035edbbd8776c440d870460c57f0008067cc01c5ff9eb2e2f9b3a94299a915a91198bd1021a6c55596f57";
|
||||
let res: Vec<_> = client
|
||||
.storage_keys(
|
||||
block_hash,
|
||||
Some(&prefix),
|
||||
Some(&StorageKey(array_bytes::hex2bytes_unchecked(
|
||||
"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
|
||||
))),
|
||||
Some(&StorageKey(array_bytes::hex2bytes_unchecked(SOME_BALANCE_KEY))),
|
||||
)
|
||||
.unwrap()
|
||||
.take(5)
|
||||
.take(8)
|
||||
.map(|x| array_bytes::bytes2hex("", &x.0))
|
||||
.collect();
|
||||
assert_eq!(
|
||||
res,
|
||||
[
|
||||
"811ecfaadcf5f2ee1d67393247e2f71a1662d433e8ce7ff89fb0d4aa9561820b",
|
||||
"a93d74caa7ec34ea1b04ce1e5c090245f867d333f0f88278a451e45299654dc5",
|
||||
"a9ee1403384afbfc13f13be91ff70bfac057436212e53b9733914382ac942892",
|
||||
"cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f",
|
||||
"e3b47b6c84c0493481f97c5197d2554f",
|
||||
]
|
||||
expected_keys
|
||||
.iter()
|
||||
.filter(|&i| i > &SOME_BALANCE_KEY.to_string())
|
||||
.take(8)
|
||||
.cloned()
|
||||
.collect::<Vec<String>>()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1999,7 +1940,7 @@ fn reorg_triggers_a_notification_even_for_sources_that_should_not_trigger_notifi
|
||||
b1.push_transfer(Transfer {
|
||||
from: AccountKeyring::Alice.into(),
|
||||
to: AccountKeyring::Ferdie.into(),
|
||||
amount: 1,
|
||||
amount: 1 * DOLLARS,
|
||||
nonce: 0,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use codec::{Decode, Encode};
|
||||
use codec::Encode;
|
||||
use futures::{
|
||||
executor::block_on,
|
||||
future::{ready, Ready},
|
||||
@@ -33,7 +33,7 @@ use sp_runtime::{
|
||||
ValidTransaction,
|
||||
},
|
||||
};
|
||||
use substrate_test_runtime::{AccountId, Block, Extrinsic, Transfer, H256};
|
||||
use substrate_test_runtime::{AccountId, Block, Extrinsic, ExtrinsicBuilder, TransferData, H256};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct TestApi {
|
||||
@@ -65,8 +65,10 @@ impl ChainApi for TestApi {
|
||||
_source: TransactionSource,
|
||||
uxt: <Self::Block as BlockT>::Extrinsic,
|
||||
) -> Self::ValidationFuture {
|
||||
let nonce = uxt.transfer().nonce;
|
||||
let from = uxt.transfer().from;
|
||||
let transfer = TransferData::try_from(&uxt)
|
||||
.expect("uxt is expected to be bench_call (carrying TransferData)");
|
||||
let nonce = transfer.nonce;
|
||||
let from = transfer.from;
|
||||
|
||||
match self.block_id_to_number(at) {
|
||||
Ok(Some(num)) if num > 5 => return ready(Ok(Err(InvalidTransaction::Stale.into()))),
|
||||
@@ -131,13 +133,8 @@ impl ChainApi for TestApi {
|
||||
}
|
||||
}
|
||||
|
||||
fn uxt(transfer: Transfer) -> Extrinsic {
|
||||
Extrinsic::Transfer {
|
||||
transfer,
|
||||
signature: Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
|
||||
.expect("infinite input; no dead input space; qed"),
|
||||
exhaust_resources_when_not_first: false,
|
||||
}
|
||||
fn uxt(transfer: TransferData) -> Extrinsic {
|
||||
ExtrinsicBuilder::new_bench_call(transfer).build()
|
||||
}
|
||||
|
||||
fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
||||
@@ -146,7 +143,7 @@ fn bench_configured(pool: Pool<TestApi>, number: u64) {
|
||||
let mut tags = Vec::new();
|
||||
|
||||
for nonce in 1..=number {
|
||||
let xt = uxt(Transfer {
|
||||
let xt = uxt(TransferData {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
|
||||
@@ -463,7 +463,8 @@ mod tests {
|
||||
use sc_transaction_pool_api::TransactionStatus;
|
||||
use sp_runtime::transaction_validity::TransactionSource;
|
||||
use std::{collections::HashMap, time::Instant};
|
||||
use substrate_test_runtime::{AccountId, Extrinsic, Transfer, H256};
|
||||
use substrate_test_runtime::{AccountId, ExtrinsicBuilder, Transfer, H256};
|
||||
use substrate_test_runtime_client::AccountKeyring::{Alice, Bob};
|
||||
|
||||
const SOURCE: TransactionSource = TransactionSource::External;
|
||||
|
||||
@@ -477,7 +478,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -494,7 +495,7 @@ mod tests {
|
||||
// given
|
||||
let pool = pool();
|
||||
let uxt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -520,8 +521,8 @@ mod tests {
|
||||
TestApi::default().into(),
|
||||
);
|
||||
|
||||
// after validation `IncludeData` will be set to non-propagable
|
||||
let uxt = Extrinsic::IncludeData(vec![42]);
|
||||
// after validation `IncludeData` will be set to non-propagable (validate_transaction mock)
|
||||
let uxt = ExtrinsicBuilder::new_include_data(vec![42]).build();
|
||||
|
||||
// when
|
||||
let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt));
|
||||
@@ -542,7 +543,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -553,7 +554,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
@@ -565,7 +566,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 3,
|
||||
@@ -594,7 +595,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -605,7 +606,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
@@ -616,7 +617,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 3,
|
||||
@@ -645,7 +646,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -659,27 +660,27 @@ mod tests {
|
||||
// then
|
||||
assert!(pool.validated_pool.is_banned(&hash1));
|
||||
}
|
||||
use codec::Encode;
|
||||
|
||||
#[test]
|
||||
fn should_limit_futures() {
|
||||
sp_tracing::try_init_simple();
|
||||
|
||||
let xt = uxt(Transfer {
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
});
|
||||
|
||||
// given
|
||||
let limit = Limit { count: 100, total_bytes: 200 };
|
||||
let limit = Limit { count: 100, total_bytes: xt.encoded_size() };
|
||||
|
||||
let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let hash1 = block_on(pool.submit_one(
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
}),
|
||||
))
|
||||
.unwrap();
|
||||
let hash1 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
||||
assert_eq!(pool.validated_pool().status().future, 1);
|
||||
|
||||
// when
|
||||
@@ -687,7 +688,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
from: Bob.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 10,
|
||||
@@ -715,7 +716,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
@@ -738,7 +739,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: INVALID_NONCE,
|
||||
@@ -763,7 +764,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -795,7 +796,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -828,7 +829,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
@@ -843,7 +844,7 @@ mod tests {
|
||||
&BlockId::Number(0),
|
||||
SOURCE,
|
||||
uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -863,7 +864,7 @@ mod tests {
|
||||
// given
|
||||
let pool = pool();
|
||||
let uxt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -887,7 +888,7 @@ mod tests {
|
||||
// given
|
||||
let pool = pool();
|
||||
let uxt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -918,7 +919,7 @@ mod tests {
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -928,7 +929,7 @@ mod tests {
|
||||
|
||||
// when
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
from: Bob.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
amount: 4,
|
||||
nonce: 1,
|
||||
@@ -952,13 +953,17 @@ mod tests {
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let xt = Extrinsic::IncludeData(Vec::new());
|
||||
// after validation `IncludeData` will have priority set to 9001
|
||||
// (validate_transaction mock)
|
||||
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||
block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||
|
||||
// then
|
||||
// after validation `Transfer` will have priority set to 4 (validate_transaction
|
||||
// mock)
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
from: Bob.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
amount: 4,
|
||||
nonce: 1,
|
||||
@@ -977,12 +982,16 @@ mod tests {
|
||||
|
||||
let pool = Pool::new(options, true.into(), TestApi::default().into());
|
||||
|
||||
let xt = Extrinsic::IncludeData(Vec::new());
|
||||
// after validation `IncludeData` will have priority set to 9001
|
||||
// (validate_transaction mock)
|
||||
let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||
block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap();
|
||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||
|
||||
// after validation `Transfer` will have priority set to 4 (validate_transaction
|
||||
// mock)
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
@@ -992,7 +1001,9 @@ mod tests {
|
||||
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||
|
||||
// when
|
||||
let xt = Extrinsic::Store(Vec::new());
|
||||
// after validation `Store` will have priority set to 9001 (validate_transaction
|
||||
// mock)
|
||||
let xt = ExtrinsicBuilder::new_indexed_call(Vec::new()).build();
|
||||
block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)).unwrap();
|
||||
assert_eq!(pool.validated_pool().status().ready, 2);
|
||||
|
||||
@@ -1014,7 +1025,7 @@ mod tests {
|
||||
|
||||
// when
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 1,
|
||||
@@ -1030,7 +1041,7 @@ mod tests {
|
||||
// But now before the previous one is imported we import
|
||||
// the one that it depends on.
|
||||
let xt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 4,
|
||||
nonce: 0,
|
||||
|
||||
@@ -362,6 +362,7 @@ mod tests {
|
||||
use sc_transaction_pool_api::TransactionSource;
|
||||
use sp_runtime::generic::BlockId;
|
||||
use substrate_test_runtime::{AccountId, Transfer, H256};
|
||||
use substrate_test_runtime_client::AccountKeyring::Alice;
|
||||
|
||||
#[test]
|
||||
fn revalidation_queue_works() {
|
||||
@@ -370,7 +371,7 @@ mod tests {
|
||||
let queue = Arc::new(RevalidationQueue::new(api.clone(), pool.clone()));
|
||||
|
||||
let uxt = uxt(Transfer {
|
||||
from: AccountId::from_h256(H256::from_low_u64_be(1)),
|
||||
from: Alice.into(),
|
||||
to: AccountId::from_h256(H256::from_low_u64_be(2)),
|
||||
amount: 5,
|
||||
nonce: 0,
|
||||
|
||||
@@ -31,7 +31,10 @@ use sp_runtime::{
|
||||
},
|
||||
};
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
use substrate_test_runtime::{Block, Extrinsic, Hashing, Transfer, H256};
|
||||
use substrate_test_runtime::{
|
||||
substrate_test_pallet::pallet::Call as PalletCall, BalancesCall, Block, Extrinsic,
|
||||
ExtrinsicBuilder, Hashing, RuntimeCall, Transfer, TransferData, H256,
|
||||
};
|
||||
|
||||
pub(crate) const INVALID_NONCE: u64 = 254;
|
||||
|
||||
@@ -70,9 +73,11 @@ impl ChainApi for TestApi {
|
||||
let block_number = self.block_id_to_number(at).unwrap().unwrap();
|
||||
|
||||
let res = match uxt {
|
||||
Extrinsic::Transfer { transfer, .. } => {
|
||||
let nonce = transfer.nonce;
|
||||
|
||||
Extrinsic {
|
||||
function: RuntimeCall::Balances(BalancesCall::transfer_allow_death { .. }),
|
||||
..
|
||||
} => {
|
||||
let TransferData { nonce, .. } = (&uxt).try_into().unwrap();
|
||||
// This is used to control the test flow.
|
||||
if nonce > 0 {
|
||||
let opt = self.delay.lock().take();
|
||||
@@ -115,14 +120,20 @@ impl ChainApi for TestApi {
|
||||
Ok(transaction)
|
||||
}
|
||||
},
|
||||
Extrinsic::IncludeData(_) => Ok(ValidTransaction {
|
||||
Extrinsic {
|
||||
function: RuntimeCall::SubstrateTest(PalletCall::include_data { .. }),
|
||||
..
|
||||
} => Ok(ValidTransaction {
|
||||
priority: 9001,
|
||||
requires: vec![],
|
||||
provides: vec![vec![42]],
|
||||
longevity: 9001,
|
||||
propagate: false,
|
||||
}),
|
||||
Extrinsic::Store(_) => Ok(ValidTransaction {
|
||||
Extrinsic {
|
||||
function: RuntimeCall::SubstrateTest(PalletCall::indexed_call { .. }),
|
||||
..
|
||||
} => Ok(ValidTransaction {
|
||||
priority: 9001,
|
||||
requires: vec![],
|
||||
provides: vec![vec![43]],
|
||||
@@ -185,8 +196,7 @@ impl ChainApi for TestApi {
|
||||
}
|
||||
|
||||
pub(crate) fn uxt(transfer: Transfer) -> Extrinsic {
|
||||
let signature = TryFrom::try_from(&[0; 64][..]).unwrap();
|
||||
Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false }
|
||||
ExtrinsicBuilder::new_transfer(transfer).build()
|
||||
}
|
||||
|
||||
pub(crate) fn pool() -> Pool<TestApi> {
|
||||
|
||||
@@ -35,11 +35,11 @@ use sp_consensus::BlockOrigin;
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::Block as _,
|
||||
transaction_validity::{InvalidTransaction, TransactionSource, ValidTransaction},
|
||||
transaction_validity::{TransactionSource, ValidTransaction},
|
||||
};
|
||||
use std::{collections::BTreeSet, pin::Pin, sync::Arc};
|
||||
use substrate_test_runtime_client::{
|
||||
runtime::{Block, Extrinsic, Hash, Header, Index, Transfer},
|
||||
runtime::{Block, Extrinsic, ExtrinsicBuilder, Hash, Header, Index, Transfer, TransferData},
|
||||
AccountKeyring::*,
|
||||
ClientBlockImportExt,
|
||||
};
|
||||
@@ -86,7 +86,11 @@ fn submission_should_work() {
|
||||
let pool = pool();
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![209]);
|
||||
}
|
||||
|
||||
@@ -96,16 +100,25 @@ fn multiple_submission_should_work() {
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![209, 210]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn early_nonce_should_be_culled() {
|
||||
sp_tracing::try_init_simple();
|
||||
let pool = pool();
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 208))).unwrap();
|
||||
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, Vec::<Index>::new());
|
||||
}
|
||||
|
||||
@@ -114,11 +127,19 @@ fn late_nonce_should_be_queued() {
|
||||
let pool = pool();
|
||||
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, Vec::<Index>::new());
|
||||
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![209, 210]);
|
||||
}
|
||||
|
||||
@@ -128,14 +149,22 @@ fn prune_tags_should_work() {
|
||||
let hash209 = block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
|
||||
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![209, 210]);
|
||||
|
||||
pool.validated_pool().api().push_block(1, Vec::new(), true);
|
||||
block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![hash209]))
|
||||
.expect("Prune tags");
|
||||
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![210]);
|
||||
}
|
||||
|
||||
@@ -148,7 +177,11 @@ fn should_ban_invalid_transactions() {
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap_err();
|
||||
|
||||
// when
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, Vec::<Index>::new());
|
||||
|
||||
// then
|
||||
@@ -197,7 +230,11 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() {
|
||||
block_on(pool.submit_one(&BlockId::number(2), SOURCE, xt.clone())).expect("2. Imported");
|
||||
assert_eq!(pool.validated_pool().status().ready, 1);
|
||||
assert_eq!(pool.validated_pool().status().future, 1);
|
||||
let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
|
||||
let pending: Vec<_> = pool
|
||||
.validated_pool()
|
||||
.ready()
|
||||
.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
|
||||
.collect();
|
||||
assert_eq!(pending, vec![211]);
|
||||
|
||||
// prune it and make sure the pool is empty
|
||||
@@ -472,6 +509,7 @@ fn finalization() {
|
||||
|
||||
#[test]
|
||||
fn fork_aware_finalization() {
|
||||
sp_tracing::try_init_simple();
|
||||
let api = TestApi::empty();
|
||||
// starting block A1 (last finalized.)
|
||||
let a_header = api.push_block(1, vec![], true);
|
||||
@@ -888,48 +926,6 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_accept_old_signatures() {
|
||||
let client = Arc::new(substrate_test_runtime_client::new());
|
||||
let best_hash = client.info().best_hash;
|
||||
let finalized_hash = client.info().finalized_hash;
|
||||
let pool = Arc::new(
|
||||
BasicPool::new_test(
|
||||
Arc::new(FullChainApi::new(client, None, &sp_core::testing::TaskExecutor::new())),
|
||||
best_hash,
|
||||
finalized_hash,
|
||||
)
|
||||
.0,
|
||||
);
|
||||
|
||||
let transfer = Transfer { from: Alice.into(), to: Bob.into(), nonce: 0, amount: 1 };
|
||||
let _bytes: sp_core::sr25519::Signature = transfer.using_encoded(|e| Alice.sign(e)).into();
|
||||
|
||||
// generated with schnorrkel 0.1.1 from `_bytes`
|
||||
let old_singature = sp_core::sr25519::Signature::try_from(
|
||||
&array_bytes::hex2bytes(
|
||||
"c427eb672e8c441c86d31f1a81b22b43102058e9ce237cabe9897ea5099ffd426\
|
||||
cd1c6a1f4f2869c3df57901d36bedcb295657adb3a4355add86ed234eb83108",
|
||||
)
|
||||
.expect("hex invalid")[..],
|
||||
)
|
||||
.expect("signature construction failed");
|
||||
|
||||
let xt = Extrinsic::Transfer {
|
||||
transfer,
|
||||
signature: old_singature,
|
||||
exhaust_resources_when_not_first: false,
|
||||
};
|
||||
|
||||
assert_matches::assert_matches!(
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())),
|
||||
Err(error::Error::Pool(sc_transaction_pool_api::error::Error::InvalidTransaction(
|
||||
InvalidTransaction::BadProof
|
||||
))),
|
||||
"Should be invalid transaction with bad proof",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import_notification_to_pool_maintain_works() {
|
||||
let mut client = Arc::new(substrate_test_runtime_client::new());
|
||||
@@ -975,7 +971,7 @@ fn import_notification_to_pool_maintain_works() {
|
||||
fn pruning_a_transaction_should_remove_it_from_best_transaction() {
|
||||
let (pool, api, _guard) = maintained_pool();
|
||||
|
||||
let xt1 = Extrinsic::IncludeData(Vec::new());
|
||||
let xt1 = ExtrinsicBuilder::new_include_data(Vec::new()).build();
|
||||
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported");
|
||||
assert_eq!(pool.status().ready, 1);
|
||||
@@ -1001,7 +997,7 @@ fn stale_transactions_are_pruned() {
|
||||
let (pool, api, _guard) = maintained_pool();
|
||||
|
||||
xts.into_iter().for_each(|xt| {
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_signed_tx()))
|
||||
block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_unchecked_extrinsic()))
|
||||
.expect("1. Imported");
|
||||
});
|
||||
assert_eq!(pool.status().ready, 0);
|
||||
@@ -1010,9 +1006,12 @@ fn stale_transactions_are_pruned() {
|
||||
// Almost the same as our initial transactions, but with some different `amount`s to make them
|
||||
// generate a different hash
|
||||
let xts = vec![
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 1, amount: 2 }.into_signed_tx(),
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 2, amount: 2 }.into_signed_tx(),
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 3, amount: 2 }.into_signed_tx(),
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 1, amount: 2 }
|
||||
.into_unchecked_extrinsic(),
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 2, amount: 2 }
|
||||
.into_unchecked_extrinsic(),
|
||||
Transfer { from: Alice.into(), to: Bob.into(), nonce: 3, amount: 2 }
|
||||
.into_unchecked_extrinsic(),
|
||||
];
|
||||
|
||||
// Import block
|
||||
|
||||
Reference in New Issue
Block a user