Skip to content

Commit ae3cfa0

Browse files
gabriele-0201pepyakin
authored andcommitted
validate_transaction and apply_extrinsic tests
1 parent 32d6f73 commit ae3cfa0

File tree

3 files changed

+134
-73
lines changed

3 files changed

+134
-73
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sugondat-chain/runtimes/sugondat-kusama/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ parachains-common = { git = "https://github.com/paritytech/polkadot-sdk.git", br
7979

8080
[dev-dependencies]
8181
sp-io = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.4.0"}
82-
sp-keyring = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.4.0"}
82+
sp-tracing = { git = "https://github.com/paritytech/polkadot-sdk", default-features = false, branch = "release-polkadot-v1.4.0"}
8383

8484
[features]
8585
default = [ "std" ]
Lines changed: 132 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,159 @@
1-
use polkadot_core_primitives::AccountId;
1+
use frame_support::traits::tokens::Precision;
2+
use sp_block_builder::runtime_decl_for_block_builder::BlockBuilderV6;
23
use sp_runtime::{
34
generic::SignedPayload,
4-
traits::{Applyable, Checkable, Lookup, Verify, StaticLookup, SignedExtension},
5-
transaction_validity::{InvalidTransaction, TransactionSource, TransactionValidityError},
6-
BuildStorage, KeyTypeId, MultiAddress, MultiSignature,
5+
transaction_validity::{
6+
InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
7+
},
8+
BuildStorage, MultiSignature,
79
};
8-
use sp_transaction_pool::runtime_api::TaggedTransactionQueue;
910

1011
use codec::Encode;
11-
use sp_core::{
12-
crypto::{key_types, Pair},
13-
sr25519,
14-
};
15-
use sp_keyring::sr25519::Keyring;
12+
use frame_support::traits::fungible::Balanced;
13+
use sp_core::{crypto::Pair, sr25519};
1614
use sp_transaction_pool::runtime_api::runtime_decl_for_tagged_transaction_queue::TaggedTransactionQueueV3;
1715
use sugondat_kusama_runtime::{
18-
Address, Balances, Blobs, Hash, Runtime, RuntimeCall, SignedExtra, UncheckedExtrinsic,
16+
Address, Hash, MaxBlobSize, MaxBlobs, MaxTotalBlobSize, Runtime, RuntimeCall, SignedExtra,
17+
UncheckedExtrinsic,
1918
};
20-
use sugondat_primitives::Signature;
2119

2220
use sugondat_kusama_runtime::*;
2321

24-
pub fn new_test_ext() -> sp_io::TestExternalities {
22+
fn new_test_ext() -> sp_io::TestExternalities {
2523
frame_system::GenesisConfig::<Runtime>::default()
2624
.build_storage()
2725
.unwrap()
2826
.into()
2927
}
3028

31-
#[test]
32-
fn test_validate_transaction_exceeded_max_blob_size() {
33-
new_test_ext().execute_with(|| {
34-
// Run a single block of the system in order to set the genesis hash.
35-
// The storage of `pallet_system` is initialized to hold 0x45... as the genesis
36-
// hash, so pushing a block with a different hash would overwrite it.
37-
// This ensures that the `CheckEra` and `CheckGenesis` provide the same
38-
// `additional_signed` payload data when constructing the transaction (here)
39-
// as well as validating it in `Runtime::validate_transaction`, which internally
40-
// calls `System::initialize` (prior to 1.5.0).
41-
{
42-
<frame_system::Pallet<Runtime>>::initialize(
43-
&(frame_system::Pallet::<Runtime>::block_number() + 1),
44-
&Hash::repeat_byte(1),
45-
&Default::default(),
46-
);
47-
<frame_system::Pallet<Runtime>>::finalize();
48-
}
49-
50-
let alice_pair: sr25519::Pair = sr25519::Pair::from_string("//Alice", None)
51-
.expect("Impossible generate Alice AccountId")
52-
.into();
53-
54-
let alice_account_id: <Runtime as frame_system::Config>::AccountId =
55-
alice_pair.public().into();
56-
let alice_address = Address::Id(alice_account_id.clone());
57-
58-
let source = TransactionSource::External;
59-
60-
let max_blob_size = sugondat_kusama_runtime::MaxBlobSize::get() as usize;
61-
62-
let runtime_call: RuntimeCall = pallet_sugondat_blobs::Call::submit_blob {
63-
namespace_id: 0,
64-
blob: vec![0; max_blob_size + 1],
65-
}
66-
.into();
67-
68-
let signed_extra: SignedExtra = (
69-
frame_system::CheckNonZeroSender::<Runtime>::new(),
70-
frame_system::CheckSpecVersion::<Runtime>::new(),
71-
frame_system::CheckTxVersion::<Runtime>::new(),
72-
frame_system::CheckGenesis::<Runtime>::new(),
73-
frame_system::CheckEra::<Runtime>::from(sp_runtime::generic::Era::immortal()),
74-
frame_system::CheckNonce::<Runtime>::from(0),
75-
frame_system::CheckWeight::<Runtime>::new(),
76-
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
77-
pallet_sugondat_blobs::PrevalidateBlobs::<Runtime>::new(),
29+
fn alice_pair() -> sr25519::Pair {
30+
sr25519::Pair::from_string("//Alice", None)
31+
.expect("Impossible generate Alice AccountId")
32+
.into()
33+
}
34+
35+
// Needed to be called inside Externalities
36+
fn prepare_environment_and_deposit_funds(account: <Runtime as frame_system::Config>::AccountId) {
37+
// Run a single block of the system in order to set the genesis hash.
38+
// The storage of `pallet_system` is initialized to hold 0x45... as the genesis
39+
// hash, so pushing a block with a different hash would overwrite it.
40+
// This ensures that the `CheckEra` and `CheckGenesis` provide the same
41+
// `additional_signed` payload data when constructing the transaction (here)
42+
// as well as validating it in `Runtime::validate_transaction`, which internally
43+
// calls `System::initialize` (prior to 1.5.0).
44+
{
45+
<frame_system::Pallet<Runtime>>::initialize(
46+
&(frame_system::Pallet::<Runtime>::block_number() + 1),
47+
&Hash::repeat_byte(1),
48+
&Default::default(),
7849
);
50+
<frame_system::Pallet<Runtime>>::finalize();
51+
}
52+
53+
// Store some funds into the account specified as argument
54+
let _ = <pallet_balances::Pallet<Runtime>>::deposit(
55+
&account,
56+
100_000_000_000,
57+
Precision::BestEffort,
58+
)
59+
.expect("Impossible Store Balance");
60+
}
61+
62+
// Needed to be called inside Externalities
63+
//
64+
// This function will only return a valid UTX if called after
65+
// `prepare_environment_and_deposit_funds`, as certain signed extension
66+
// operations require a storage preparation
67+
fn create_submit_blob_utx(
68+
signer: sr25519::Pair,
69+
namespace_id: u128,
70+
blob: Vec<u8>,
71+
) -> UncheckedExtrinsic {
72+
let signed_extra: SignedExtra = (
73+
frame_system::CheckNonZeroSender::<Runtime>::new(),
74+
frame_system::CheckSpecVersion::<Runtime>::new(),
75+
frame_system::CheckTxVersion::<Runtime>::new(),
76+
frame_system::CheckGenesis::<Runtime>::new(),
77+
frame_system::CheckEra::<Runtime>::from(sp_runtime::generic::Era::immortal()),
78+
frame_system::CheckNonce::<Runtime>::from(0),
79+
frame_system::CheckWeight::<Runtime>::new(),
80+
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
81+
pallet_sugondat_blobs::PrevalidateBlobs::<Runtime>::new(),
82+
);
83+
84+
let runtime_call: RuntimeCall = pallet_sugondat_blobs::Call::submit_blob {
85+
namespace_id: namespace_id.into(),
86+
blob,
87+
}
88+
.into();
7989

80-
let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap();
81-
let signature = raw_payload.using_encoded(|payload| {
82-
let sig = alice_pair.sign(payload);
83-
MultiSignature::Sr25519(sig)
84-
});
90+
let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap();
91+
let signature = MultiSignature::Sr25519(signer.sign(&raw_payload.encode()));
8592

86-
let tx =
87-
UncheckedExtrinsic::new_signed(runtime_call, alice_address.clone(), signature, signed_extra);
93+
UncheckedExtrinsic::new_signed(
94+
runtime_call,
95+
Address::Id(signer.public().into()),
96+
signature,
97+
signed_extra,
98+
)
99+
}
100+
101+
fn test_validate_transaction(blob_size: u32, assertion: impl FnOnce(TransactionValidity)) {
102+
new_test_ext().execute_with(|| {
103+
prepare_environment_and_deposit_funds(alice_pair().public().into());
104+
105+
let utx = create_submit_blob_utx(alice_pair(), 0, vec![0; blob_size as usize]);
106+
107+
let res =
108+
Runtime::validate_transaction(TransactionSource::External, utx, Hash::repeat_byte(8));
109+
assertion(res);
110+
});
111+
}
112+
113+
#[test]
114+
fn test_validate_transaction_ok() {
115+
test_validate_transaction(MaxBlobSize::get(), |res| assert!(res.is_ok()))
116+
}
88117

118+
#[test]
119+
fn test_validate_transaction_max_blob_size_exceeded() {
120+
test_validate_transaction(MaxBlobSize::get() + 1, |res| {
89121
assert_eq!(
122+
res,
90123
Err(TransactionValidityError::Invalid(
91124
InvalidTransaction::Custom(
92-
sugondat_primitives::InvalidTransactionCustomError::BlobExceedsSizeLimit as u8
125+
sugondat_primitives::InvalidTransactionCustomError::BlobExceedsSizeLimit as u8,
93126
)
94-
)),
95-
Runtime::validate_transaction(source, tx, Hash::repeat_byte(8))
96-
);
127+
))
128+
)
129+
});
130+
}
131+
132+
fn test_pre_dispatch(modify_storage: impl FnOnce()) {
133+
new_test_ext().execute_with(|| {
134+
modify_storage();
135+
136+
prepare_environment_and_deposit_funds(alice_pair().public().into());
137+
138+
let utx = create_submit_blob_utx(alice_pair(), 0, vec![0; 10]);
139+
140+
assert_eq!(
141+
Runtime::apply_extrinsic(utx),
142+
Err(TransactionValidityError::Invalid(
143+
InvalidTransaction::ExhaustsResources,
144+
))
145+
)
146+
});
147+
}
148+
149+
#[test]
150+
fn test_pre_dispatch_max_blobs_exceeded() {
151+
test_pre_dispatch(|| pallet_sugondat_blobs::TotalBlobs::<Runtime>::put(MaxBlobs::get()));
152+
}
153+
154+
#[test]
155+
fn test_pre_dispatch_max_total_blob_size_exceeded() {
156+
test_pre_dispatch(|| {
157+
pallet_sugondat_blobs::TotalBlobSize::<Runtime>::put(MaxTotalBlobSize::get())
97158
});
98159
}

0 commit comments

Comments
 (0)