Build block without checking signatures (#4916)

* in executive

* in other places

* to UnsafeResult

* move doc comment

* apply suggestions

* allow validity mocking for TestXt

* add test

* augment checkable instead of another trait

* fix im online test

* blockbuilder dihotomy

* review suggestions

* update test

* Update client/block-builder/src/lib.rs

* updae spec_version

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Nikolay Volf
2020-02-19 01:34:31 +03:00
committed by GitHub
parent ba2362dadd
commit e50f610907
15 changed files with 247 additions and 68 deletions
+53 -16
View File
@@ -79,13 +79,15 @@
use sp_std::{prelude::*, marker::PhantomData};
use frame_support::weights::{GetDispatchInfo, WeighBlock, DispatchInfo};
use sp_runtime::{
generic::Digest, ApplyExtrinsicResult,
generic::Digest,
ApplyExtrinsicResult,
traits::{
self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalize, OnInitialize,
NumberFor, Block as BlockT, OffchainWorker, Dispatchable, Saturating,
},
transaction_validity::TransactionValidity,
};
use sp_runtime::generic::CheckSignature;
#[allow(deprecated)]
use sp_runtime::traits::ValidateUnsigned;
use codec::{Codec, Encode};
@@ -255,13 +257,22 @@ where
pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
let encoded = uxt.encode();
let encoded_len = encoded.len();
Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded))
Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded), CheckSignature::Yes)
}
/// Apply extrinsic outside of the block execution function.
///
/// Same as `apply_extrinsic`, but skips signature checks.
pub fn apply_trusted_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
let encoded = uxt.encode();
let encoded_len = encoded.len();
Self::apply_extrinsic_with_len(uxt, encoded_len, Some(encoded), CheckSignature::No)
}
/// Apply an extrinsic inside the block execution function.
fn apply_extrinsic_no_note(uxt: Block::Extrinsic) {
let l = uxt.encode().len();
match Self::apply_extrinsic_with_len(uxt, l, None) {
match Self::apply_extrinsic_with_len(uxt, l, None, CheckSignature::Yes) {
Ok(_) => (),
Err(e) => { let err: &'static str = e.into(); panic!(err) },
}
@@ -272,9 +283,13 @@ where
uxt: Block::Extrinsic,
encoded_len: usize,
to_note: Option<Vec<u8>>,
check_signature: CheckSignature,
) -> ApplyExtrinsicResult {
// Verify that the signature is good.
let xt = uxt.check(&Default::default())?;
let xt = uxt.check(
check_signature,
&Default::default(),
)?;
// We don't need to make sure to `note_extrinsic` only after we know it's going to be
// executed to prevent it from leaking in storage since at this point, it will either
@@ -322,7 +337,7 @@ where
/// Changes made to storage should be discarded.
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
let encoded_len = uxt.using_encoded(|d| d.len());
let xt = uxt.check(&Default::default())?;
let xt = uxt.check(CheckSignature::Yes, &Default::default())?;
let dispatch_info = xt.get_dispatch_info();
xt.validate::<UnsignedValidator>(dispatch_info, encoded_len)
@@ -516,8 +531,8 @@ mod tests {
)
}
fn sign_extra(who: u64, nonce: u64, fee: u64) -> Option<(u64, SignedExtra)> {
Some((who, extra(nonce, fee)))
fn sign_extra(who: u64, nonce: u64, fee: u64) -> (u64, SignedExtra) {
(who, extra(nonce, fee))
}
#[test]
@@ -526,7 +541,7 @@ mod tests {
pallet_balances::GenesisConfig::<Runtime> {
balances: vec![(1, 211)],
}.assimilate_storage(&mut t).unwrap();
let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69)));
let xt = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(2, 69)));
let weight = xt.get_dispatch_info().weight as u64;
let mut t = sp_io::TestExternalities::new(t);
t.execute_with(|| {
@@ -606,7 +621,7 @@ mod tests {
fn bad_extrinsic_not_inserted() {
let mut t = new_test_ext(1);
// bad nonce check!
let xt = sp_runtime::testing::TestXt(sign_extra(1, 30, 0), Call::Balances(BalancesCall::transfer(33, 69)));
let xt = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 30, 0), Call::Balances(BalancesCall::transfer(33, 69)));
t.execute_with(|| {
Executive::initialize_block(&Header::new(
1,
@@ -624,7 +639,7 @@ mod tests {
fn block_weight_limit_enforced() {
let mut t = new_test_ext(10000);
// given: TestXt uses the encoded len as fixed Len:
let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let xt = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let encoded = xt.encode();
let encoded_len = encoded.len() as Weight;
let limit = AvailableBlockRatio::get() * MaximumBlockWeight::get() - 175;
@@ -641,7 +656,7 @@ mod tests {
assert_eq!(<frame_system::Module<Runtime>>::all_extrinsics_weight(), 175);
for nonce in 0..=num_to_exhaust_block {
let xt = sp_runtime::testing::TestXt(
let xt = sp_runtime::testing::TestXt::new_signed(
sign_extra(1, nonce.into(), 0), Call::Balances(BalancesCall::transfer(33, 0)),
);
let res = Executive::apply_extrinsic(xt);
@@ -661,9 +676,9 @@ mod tests {
#[test]
fn block_weight_and_size_is_stored_per_tx() {
let xt = sp_runtime::testing::TestXt(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let x1 = sp_runtime::testing::TestXt(sign_extra(1, 1, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let x2 = sp_runtime::testing::TestXt(sign_extra(1, 2, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let xt = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let x1 = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 1, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let x2 = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 2, 0), Call::Balances(BalancesCall::transfer(33, 0)));
let len = xt.clone().encode().len() as u32;
let mut t = new_test_ext(1);
t.execute_with(|| {
@@ -687,7 +702,7 @@ mod tests {
#[test]
fn validate_unsigned() {
let xt = sp_runtime::testing::TestXt(None, Call::Balances(BalancesCall::set_balance(33, 69, 69)));
let xt = sp_runtime::testing::TestXt::new_unsigned(Call::Balances(BalancesCall::set_balance(33, 69, 69)));
let mut t = new_test_ext(1);
t.execute_with(|| {
@@ -696,6 +711,28 @@ mod tests {
});
}
#[test]
fn apply_trusted_skips_signature_check_but_not_others() {
let xt1 = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)))
.badly_signed();
let mut t = new_test_ext(1);
t.execute_with(|| {
assert_eq!(Executive::apply_trusted_extrinsic(xt1), Ok(Ok(())));
});
let xt2 = sp_runtime::testing::TestXt::new_signed(sign_extra(1, 0, 0), Call::Balances(BalancesCall::transfer(33, 0)))
.invalid(TransactionValidityError::Invalid(InvalidTransaction::Call));
t.execute_with(|| {
assert_eq!(
Executive::apply_trusted_extrinsic(xt2),
Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
);
});
}
#[test]
fn can_pay_for_tx_fee_on_full_lock() {
let id: LockIdentifier = *b"0 ";
@@ -708,7 +745,7 @@ mod tests {
110,
lock,
);
let xt = sp_runtime::testing::TestXt(
let xt = sp_runtime::testing::TestXt::new_signed(
sign_extra(1, 0, 0),
Call::System(SystemCall::remark(vec![1u8])),
);