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:
Michal Kucharczyk
2023-05-04 18:20:22 +02:00
committed by GitHub
parent 3a90728de0
commit 6a295e7c28
34 changed files with 1943 additions and 2356 deletions
@@ -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"
+1 -1
View File
@@ -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};
+10 -9
View File
@@ -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();
+5 -56
View File
@@ -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(|_, _| ()),
};
+24 -18
View File
@@ -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> {
+56 -61
View File
@@ -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 {
+5 -3
View File
@@ -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(),
)
+2 -14
View File
@@ -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
+5 -3
View File
@@ -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
});
+12 -14
View File
@@ -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 =
+17 -14
View File
@@ -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,
+19 -3
View File
@@ -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,
}),
);
+47 -16
View File
@@ -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();
+4 -7
View File
@@ -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());
}
}
+83 -142
View File
@@ -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,
+18 -8
View File
@@ -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> {
+57 -58
View File
@@ -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