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
@@ -315,6 +315,10 @@ impl_runtime_apis! {
Executive::apply_extrinsic(extrinsic)
}
fn apply_trusted_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_trusted_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
+5 -1
View File
@@ -82,7 +82,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to 0. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 221,
spec_version: 222,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
};
@@ -686,6 +686,10 @@ impl_runtime_apis! {
Executive::apply_extrinsic(extrinsic)
}
fn apply_trusted_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_trusted_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
@@ -195,7 +195,7 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
inherent_data
)?
{
block_builder.push(extrinsic)?;
block_builder.push_trusted(extrinsic)?;
}
// proceed with transactions
@@ -218,7 +218,7 @@ impl<Block, B, E, RA, A> ProposerInner<Block, SubstrateClient<B, E, Block, RA>,
let pending_tx_data = pending_tx.data().clone();
let pending_tx_hash = pending_tx.hash().clone();
trace!("[{:?}] Pushing to the block.", pending_tx_hash);
match sc_block_builder::BlockBuilder::push(&mut block_builder, pending_tx_data) {
match sc_block_builder::BlockBuilder::push_trusted(&mut block_builder, pending_tx_data) {
Ok(()) => {
debug!("[{:?}] Pushed to the block.", pending_tx_hash);
}
+36 -7
View File
@@ -121,11 +121,23 @@ where
backend,
})
}
/// Push onto the block's list of extrinsics.
///
/// This will ensure the extrinsic can be validly executed (by executing it).
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), ApiErrorFor<A, Block>> {
self.push_internal(xt, false)
}
/// Push onto the block's list of extrinsics.
///
/// This will ensure the extrinsic can be validly executed (by executing it);
pub fn push(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), ApiErrorFor<A, Block>> {
/// This will treat incoming extrinsic `xt` as untrusted and perform additional checks
/// (currenty checking signature).
pub fn push_trusted(&mut self, xt: <Block as BlockT>::Extrinsic) -> Result<(), ApiErrorFor<A, Block>> {
self.push_internal(xt, true)
}
fn push_internal(&mut self, xt: <Block as BlockT>::Extrinsic, skip_signature: bool) -> Result<(), ApiErrorFor<A, Block>> {
let block_id = &self.block_id;
let extrinsics = &mut self.extrinsics;
@@ -152,12 +164,29 @@ where
}
})
} else {
self.api.map_api_result(|api| {
match api.apply_extrinsic_with_context(
let use_trusted = skip_signature && self
.api
.has_api_with::<dyn BlockBuilderApi<Block, Error = ApiErrorFor<A, Block>>, _>(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
)? {
|version| version >= 5,
)?;
self.api.map_api_result(|api| {
let apply_result = if use_trusted {
api.apply_trusted_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
)?
} else {
api.apply_extrinsic_with_context(
block_id,
ExecutionContext::BlockConstruction,
xt.clone(),
)?
};
match apply_result {
Ok(_) => {
extrinsics.push(xt);
Ok(())
+1 -1
View File
@@ -402,7 +402,7 @@ fn should_return_runtime_version() {
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
\"specVersion\":1,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",2],\
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",4],\
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",5],\
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\
[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]]}";
+2 -1
View File
@@ -705,6 +705,7 @@ mod tests {
use futures::executor::block_on;
use sp_consensus::SelectChain;
use sp_runtime::traits::BlindCheckable;
use sp_runtime::generic::CheckSignature;
use substrate_test_runtime_client::{prelude::*, runtime::{Extrinsic, Transfer}};
use sc_transaction_pool::{BasicPool, FullChainApi};
@@ -733,7 +734,7 @@ mod tests {
// then
assert_eq!(transactions.len(), 1);
assert!(transactions[0].1.clone().check().is_ok());
assert!(transactions[0].1.clone().check(CheckSignature::Yes).is_ok());
// this should not panic
let _ = transactions[0].1.transfer();
}
+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])),
);
+2 -2
View File
@@ -222,7 +222,7 @@ fn should_generate_heartbeats() {
assert_eq!(state.read().transactions.len(), 2);
// check stuff about the transaction.
let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap();
let heartbeat = match ex.1 {
let heartbeat = match ex.call {
crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h,
e => panic!("Unexpected call: {:?}", e),
};
@@ -332,7 +332,7 @@ fn should_not_send_a_report_if_already_online() {
assert_eq!(pool_state.read().transactions.len(), 0);
// check stuff about the transaction.
let ex: Extrinsic = Decode::decode(&mut &*transaction).unwrap();
let heartbeat = match ex.1 {
let heartbeat = match ex.call {
crate::mock::Call::ImOnline(crate::Call::heartbeat(h, _)) => h,
e => panic!("Unexpected call: {:?}", e),
};
@@ -43,7 +43,7 @@ pub mod compatibility_v3 {
sp_api::decl_runtime_apis! {
/// The `BlockBuilder` api trait that provides the required functionality for building a block.
#[api_version(4)]
#[api_version(5)]
pub trait BlockBuilder {
/// Compatibility version of `apply_extrinsic` for v3.
///
@@ -58,6 +58,10 @@ sp_api::decl_runtime_apis! {
/// Returns an inclusion outcome which specifies if this extrinsic is included in
/// this block or not.
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult;
/// Apply the given extrinsic.
///
/// Same as `apply_extrinsic`, but skips signature verification.
fn apply_trusted_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult;
/// Finish the current block.
#[renamed("finalise_block", 3)]
fn finalize_block() -> <Block as BlockT>::Header;
@@ -39,6 +39,15 @@ pub use self::digest::{
use crate::codec::Encode;
use sp_std::prelude::*;
/// Perform singature check.
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum CheckSignature {
/// Perform.
Yes,
/// Don't perform.
No,
}
fn encode_with_vec_prefix<T: Encode, F: Fn(&mut Vec<u8>)>(encoder: F) -> Vec<u8> {
let size = ::sp_std::mem::size_of::<T>();
let reserve = match size {
@@ -24,7 +24,8 @@ use crate::{
self, Member, MaybeDisplay, SignedExtension, Checkable, Extrinsic, ExtrinsicMetadata,
IdentifyAccount,
},
generic::CheckedExtrinsic, transaction_validity::{TransactionValidityError, InvalidTransaction},
generic::{CheckSignature, CheckedExtrinsic},
transaction_validity::{TransactionValidityError, InvalidTransaction},
};
const TRANSACTION_VERSION: u8 = 4;
@@ -120,18 +121,26 @@ where
{
type Checked = CheckedExtrinsic<AccountId, Call, Extra>;
fn check(self, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
fn check(self, check_signature: CheckSignature, lookup: &Lookup) -> Result<Self::Checked, TransactionValidityError> {
Ok(match self.signature {
Some((signed, signature, extra)) => {
let signed = lookup.lookup(signed)?;
let raw_payload = SignedPayload::new(self.function, extra)?;
if !raw_payload.using_encoded(|payload| {
signature.verify(payload, &signed)
}) {
return Err(InvalidTransaction::BadProof.into())
}
let (function, extra, _) = raw_payload.deconstruct();
let (function, extra) = if let CheckSignature::No = check_signature {
(self.function, extra)
} else {
let raw_payload = SignedPayload::new(self.function, extra)?;
if !raw_payload.using_encoded(|payload| {
signature.verify(payload, &signed)
}) {
return Err(InvalidTransaction::BadProof.into())
}
let (function, extra, _) = raw_payload.deconstruct();
(function, extra)
};
CheckedExtrinsic {
signed: Some((signed, extra)),
function,
@@ -322,6 +331,7 @@ mod tests {
use sp_io::hashing::blake2_256;
use crate::codec::{Encode, Decode};
use crate::traits::{SignedExtension, IdentifyAccount, IdentityLookup};
use crate::generic::CheckSignature;
use serde::{Serialize, Deserialize};
type TestContext = IdentityLookup<u64>;
@@ -402,7 +412,7 @@ mod tests {
fn unsigned_check_should_work() {
let ux = Ex::new_unsigned(vec![0u8; 0]);
assert!(!ux.is_signed().unwrap_or(false));
assert!(<Ex as Checkable<TestContext>>::check(ux, &Default::default()).is_ok());
assert!(<Ex as Checkable<TestContext>>::check(ux, CheckSignature::Yes, &Default::default()).is_ok());
}
#[test]
@@ -415,7 +425,7 @@ mod tests {
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
<Ex as Checkable<TestContext>>::check(ux, CheckSignature::Yes, &Default::default()),
Err(InvalidTransaction::BadProof.into()),
);
}
@@ -430,7 +440,7 @@ mod tests {
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &Default::default()),
<Ex as Checkable<TestContext>>::check(ux, CheckSignature::Yes, &Default::default()),
Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }),
);
}
+89 -18
View File
@@ -25,11 +25,10 @@ use crate::traits::{
};
#[allow(deprecated)]
use crate::traits::ValidateUnsigned;
use crate::{generic, KeyTypeId, ApplyExtrinsicResult};
use crate::{generic::{self, CheckSignature}, KeyTypeId, ApplyExtrinsicResult};
pub use sp_core::{H256, sr25519};
use sp_core::{crypto::{CryptoType, Dummy, key_types, Public}, U256};
use crate::transaction_validity::{TransactionValidity, TransactionValidityError};
use crate::transaction_validity::{TransactionValidity, TransactionValidityError, InvalidTransaction};
/// Authority Id
#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)]
pub struct UintAuthorityId(pub u64);
@@ -295,12 +294,69 @@ impl<'a, Xt> Deserialize<'a> for Block<Xt> where Block<Xt>: Decode {
}
}
/// Test transaction, tuple of (sender, call, signed_extra)
/// with index only used if sender is some.
///
/// If sender is some then the transaction is signed otherwise it is unsigned.
/// Test validity.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
pub struct TestXt<Call, Extra>(pub Option<(u64, Extra)>, pub Call);
pub enum TestValidity {
/// Valid variant that will pass all checks.
Valid,
/// Variant with invalid signature.
///
/// Will fail signature check.
SignatureInvalid(TransactionValidityError),
/// Variant with invalid logic.
///
/// Will fail all checks.
OtherInvalid(TransactionValidityError),
}
/// Test transaction.
///
/// Used to mock actual transaction.
#[derive(PartialEq, Eq, Clone, Encode, Decode)]
pub struct TestXt<Call, Extra> {
/// Signature with extra.
///
/// if some, then the transaction is signed. Transaction is unsigned otherwise.
pub signature: Option<(u64, Extra)>,
/// Validity.
///
/// Instantiate invalid variant and transaction will fail correpsonding checks.
pub validity: TestValidity,
/// Call.
pub call: Call,
}
impl<Call, Extra> TestXt<Call, Extra> {
/// New signed test `TextXt`.
pub fn new_signed(signature: (u64, Extra), call: Call) -> Self {
TestXt {
signature: Some(signature),
validity: TestValidity::Valid,
call,
}
}
/// New unsigned test `TextXt`.
pub fn new_unsigned(call: Call) -> Self {
TestXt {
signature: None,
validity: TestValidity::Valid,
call,
}
}
/// Build invalid variant of `TestXt`.
pub fn invalid(mut self, err: TransactionValidityError) -> Self {
self.validity = TestValidity::OtherInvalid(err);
self
}
/// Build badly signed variant of `TestXt`.
pub fn badly_signed(mut self) -> Self {
self.validity = TestValidity::SignatureInvalid(TransactionValidityError::Invalid(InvalidTransaction::BadProof));
self
}
}
// Non-opaque extrinsics always 0.
parity_util_mem::malloc_size_of_is_0!(any: TestXt<Call, Extra>);
@@ -313,24 +369,39 @@ impl<Call, Extra> Serialize for TestXt<Call, Extra> where TestXt<Call, Extra>: E
impl<Call, Extra> Debug for TestXt<Call, Extra> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TestXt({:?}, ...)", self.0.as_ref().map(|x| &x.0))
write!(f, "TestXt({:?}, {}, ...)",
self.signature.as_ref().map(|x| &x.0),
if let TestValidity::Valid = self.validity { "valid" } else { "invalid" }
)
}
}
impl<Call: Codec + Sync + Send, Context, Extra> Checkable<Context> for TestXt<Call, Extra> {
type Checked = Self;
fn check(self, _: &Context) -> Result<Self::Checked, TransactionValidityError> { Ok(self) }
fn check(self, signature: CheckSignature, _: &Context) -> Result<Self::Checked, TransactionValidityError> {
match self.validity {
TestValidity::Valid => Ok(self),
TestValidity::SignatureInvalid(e) =>
if let CheckSignature::No = signature {
Ok(self)
} else {
Err(e)
},
TestValidity::OtherInvalid(e) => Err(e),
}
}
}
impl<Call: Codec + Sync + Send, Extra> traits::Extrinsic for TestXt<Call, Extra> {
type Call = Call;
type SignaturePayload = (u64, Extra);
fn is_signed(&self) -> Option<bool> {
Some(self.0.is_some())
Some(self.signature.is_some())
}
fn new(c: Call, sig: Option<Self::SignaturePayload>) -> Option<Self> {
Some(TestXt(sig, c))
fn new(call: Call, signature: Option<Self::SignaturePayload>) -> Option<Self> {
Some(TestXt { signature, call, validity: TestValidity::Valid })
}
}
@@ -344,7 +415,7 @@ impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
type Call = Call;
type DispatchInfo = Info;
fn sender(&self) -> Option<&Self::AccountId> { self.0.as_ref().map(|x| &x.0) }
fn sender(&self) -> Option<&Self::AccountId> { self.signature.as_ref().map(|x| &x.0) }
/// Checks to see if this is a valid *transaction*. It returns information on it if so.
#[allow(deprecated)] // Allow ValidateUnsigned
@@ -364,14 +435,14 @@ impl<Origin, Call, Extra, Info> Applyable for TestXt<Call, Extra> where
info: Self::DispatchInfo,
len: usize,
) -> ApplyExtrinsicResult {
let maybe_who = if let Some((who, extra)) = self.0 {
Extra::pre_dispatch(extra, &who, &self.1, info, len)?;
let maybe_who = if let Some((who, extra)) = self.signature {
Extra::pre_dispatch(extra, &who, &self.call, info, len)?;
Some(who)
} else {
Extra::pre_dispatch_unsigned(&self.1, info, len)?;
Extra::pre_dispatch_unsigned(&self.call, info, len)?;
None
};
Ok(self.1.dispatch(maybe_who.into()).map_err(Into::into))
Ok(self.call.dispatch(maybe_who.into()).map_err(Into::into))
}
}
+5 -5
View File
@@ -31,7 +31,7 @@ use crate::codec::{Codec, Encode, Decode};
use crate::transaction_validity::{
ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction,
};
use crate::generic::{Digest, DigestItem};
use crate::generic::{Digest, DigestItem, CheckSignature};
pub use sp_arithmetic::traits::{
AtLeast32Bit, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion,
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
@@ -637,7 +637,7 @@ pub trait Checkable<Context>: Sized {
type Checked;
/// Check self, given an instance of Context.
fn check(self, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
fn check(self, signature: CheckSignature, c: &Context) -> Result<Self::Checked, TransactionValidityError>;
}
/// A "checkable" piece of information, used by the standard Substrate Executive in order to
@@ -649,15 +649,15 @@ pub trait BlindCheckable: Sized {
type Checked;
/// Check self.
fn check(self) -> Result<Self::Checked, TransactionValidityError>;
fn check(self, signature: CheckSignature) -> Result<Self::Checked, TransactionValidityError>;
}
// Every `BlindCheckable` is also a `StaticCheckable` for arbitrary `Context`.
impl<T: BlindCheckable, Context> Checkable<Context> for T {
type Checked = <Self as BlindCheckable>::Checked;
fn check(self, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
BlindCheckable::check(self)
fn check(self, signature: CheckSignature, _c: &Context) -> Result<Self::Checked, TransactionValidityError> {
BlindCheckable::check(self, signature)
}
}
+10 -1
View File
@@ -41,6 +41,7 @@ use sp_runtime::{
BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT,
GetNodeBlockType, GetRuntimeBlockType, Verify, IdentityLookup,
},
generic::CheckSignature,
};
use sp_version::RuntimeVersion;
pub use sp_core::{hash::H256};
@@ -126,7 +127,7 @@ impl serde::Serialize for Extrinsic {
impl BlindCheckable for Extrinsic {
type Checked = Self;
fn check(self) -> Result<Self, TransactionValidityError> {
fn check(self, _signature: CheckSignature) -> Result<Self, TransactionValidityError> {
match self {
Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)),
Extrinsic::Transfer(transfer, signature) => {
@@ -493,6 +494,10 @@ cfg_if! {
system::execute_transaction(extrinsic)
}
fn apply_trusted_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
system::execute_transaction(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
system::finalize_block()
}
@@ -680,6 +685,10 @@ cfg_if! {
system::execute_transaction(extrinsic)
}
fn apply_trusted_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
system::execute_transaction(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
system::finalize_block()
}
+2 -1
View File
@@ -29,6 +29,7 @@ use sp_runtime::{
transaction_validity::{
TransactionValidity, ValidTransaction, InvalidTransaction, TransactionValidityError,
},
generic::CheckSignature,
};
use codec::{KeyedVec, Encode, Decode};
use frame_system::Trait;
@@ -243,7 +244,7 @@ pub fn finalize_block() -> Header {
#[inline(always)]
fn check_signature(utx: &Extrinsic) -> Result<(), TransactionValidityError> {
use sp_runtime::traits::BlindCheckable;
utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ())
utx.clone().check(CheckSignature::Yes).map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ())
}
fn execute_transaction_backend(utx: &Extrinsic) -> ApplyExtrinsicResult {