Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 7 additions & 66 deletions core/sr-primitives/src/generic/unchecked_extrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ mod tests {
use super::*;
use runtime_io::blake2_256;
use crate::codec::{Encode, Decode};
use crate::traits::SignedExtension;
use crate::generic::Era;
use crate::traits::{SignedExtension, BlockNumberToHash, Lookup, CurrentHeight};
use serde::{Serialize, Deserialize};

struct TestContext;
Expand Down Expand Up @@ -237,6 +238,7 @@ mod tests {
struct TestExtra;
impl SignedExtension for TestExtra {
type AccountId = u64;
type AdditionalSigned = ();
}

type Ex = UncheckedExtrinsic<TestAccountId, TestCall, TestSig, TestExtra>;
Expand All @@ -254,8 +256,7 @@ mod tests {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (TEST_ACCOUNT, vec![0u8; 0], Era::immortal(), 0u64).encode()),
Era::immortal(),
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
TestExtra
);
let encoded = ux.encode();
Expand All @@ -267,9 +268,8 @@ mod tests {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (TEST_ACCOUNT, vec![0u8; 257], Era::immortal(), 0u64)
TestSig(TEST_ACCOUNT, (vec![0u8; 257], TestExtra)
.using_encoded(blake2_256)[..].to_owned()),
Era::immortal(),
TestExtra
);
let encoded = ux.encode();
Expand All @@ -289,20 +289,18 @@ mod tests {
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, vec![0u8; 0]),
Era::immortal(),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE));
}

#[test]
fn immortal_signed_check_should_work() {
fn signed_check_should_work() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 0], Era::immortal(), 0u64, TestExtra).encode()),
Era::immortal(),
TestSig(TEST_ACCOUNT, (vec![0u8; 0], TestExtra).encode()),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
Expand All @@ -312,63 +310,6 @@ mod tests {
);
}

#[test]
fn mortal_signed_check_should_work() {
Comment thread
kianenigma marked this conversation as resolved.
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 0], Era::mortal(32, 42), 42u64, TestExtra).encode()),
Era::mortal(32, 42),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &TestContext),
Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] })
);
}

#[test]
fn later_mortal_signed_check_should_work() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (vec![0u8; 0], Era::mortal(32, 11), 11u64, TestExtra).encode()),
Era::mortal(32, 11),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(
<Ex as Checkable<TestContext>>::check(ux, &TestContext),
Ok(CEx { signed: Some((TEST_ACCOUNT, TestExtra)), function: vec![0u8; 0] }));
}

#[test]
fn too_late_mortal_signed_check_should_fail() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (TEST_ACCOUNT, vec![0u8; 0], Era::mortal(32, 10), 10u64).encode()),
Era::mortal(32, 10),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE));
}

#[test]
fn too_early_mortal_signed_check_should_fail() {
let ux = Ex::new_signed(
vec![0u8; 0],
TEST_ACCOUNT,
TestSig(TEST_ACCOUNT, (TEST_ACCOUNT, vec![0u8; 0], Era::mortal(32, 43), 43u64).encode()),
Era::mortal(32, 43),
TestExtra
);
assert!(ux.is_signed().unwrap_or(false));
assert_eq!(<Ex as Checkable<TestContext>>::check(ux, &TestContext), Err(crate::BAD_SIGNATURE));
}

#[test]
fn encoding_matches_vec() {
let ex = Ex::new_unsigned(vec![0u8; 0]);
Expand Down
109 changes: 62 additions & 47 deletions core/sr-primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,11 +815,11 @@ pub trait SignedExtension:

/// Any additional data that will go into the signed payload. This may be created dynamically
/// from the transaction using the `additional_signed` function.
type AdditionalSigned: Encode;
type AdditionalSigned: Encode + Default;

/// Construct any additional data that should be in the signed payload of the transaction. Can
/// also perform any pre-signature-verification checks and return an error if needed.
fn additional_signed(&self) -> Result<Self::AdditionalSigned, &'static str>;
fn additional_signed(&self) -> Result<Self::AdditionalSigned, &'static str> { Ok(Default::default()) }

/// Validate a signed transaction for the transaction queue.
fn validate(
Expand Down Expand Up @@ -848,58 +848,73 @@ pub trait SignedExtension:
) -> Result<(), DispatchError> { Self::validate_unsigned(weight).map(|_| ()) }
}

impl<
AccountId,
A: SignedExtension<AccountId=AccountId>,
B: SignedExtension<AccountId=AccountId>,
> SignedExtension for (A, B) {
type AccountId = AccountId;
type AdditionalSigned = (A::AdditionalSigned, B::AdditionalSigned);

fn additional_signed(&self) -> Result<Self::AdditionalSigned, &'static str> {
Ok((self.0.additional_signed()?, self.1.additional_signed()?))
}
macro_rules! tuple_impl_indexed {
($first:ident, $($rest:ident,)+ ; $first_index:tt, $($rest_index:tt,)+) => {
tuple_impl_indexed!([$first] [$($rest)+] ; [$first_index,] [$($rest_index,)+]);
};
([$($direct:ident)+] ; [$($index:tt,)+]) => {
impl<
AccountId,
$($direct: SignedExtension<AccountId=AccountId>),+
> SignedExtension for ($($direct),+,) {
type AccountId = AccountId;
type AdditionalSigned = ($($direct::AdditionalSigned,)+);
fn additional_signed(&self) -> Result<Self::AdditionalSigned, &'static str> {
Ok(( $(self.$index.additional_signed()?,)+ ))
}
fn validate(
&self,
who: &Self::AccountId,
weight: crate::weights::Weight,
) -> Result<ValidTransaction, DispatchError> {
let aggregator = vec![$(<$direct as SignedExtension>::validate(&self.$index, who, weight)?),+];
Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a)))
}
fn pre_dispatch(
self,
who: &Self::AccountId,
weight: crate::weights::Weight,
) -> Result<(), DispatchError> {
$(self.$index.pre_dispatch(who, weight)?;)+
Ok(())
}
fn validate_unsigned(
weight: crate::weights::Weight,
) -> Result<ValidTransaction, DispatchError> {
let aggregator = vec![$($direct::validate_unsigned(weight)?),+];
Ok(aggregator.into_iter().fold(ValidTransaction::default(), |acc, a| acc.combine_with(a)))
}
fn pre_dispatch_unsigned(
weight: crate::weights::Weight,
) -> Result<(), DispatchError> {
$($direct::pre_dispatch_unsigned(weight)?;)+
Ok(())
}
}

fn validate(
&self,
who: &Self::AccountId,
weight: crate::weights::Weight,
) -> Result<ValidTransaction, DispatchError> {
let a = self.0.validate(who, weight)?;
let b = self.1.validate(who, weight)?;
Ok(a.combine_with(b))
}
fn pre_dispatch(
self,
who: &Self::AccountId,
weight: crate::weights::Weight,
) -> Result<(), DispatchError> {
self.0.pre_dispatch(who, weight)?;
self.1.pre_dispatch(who, weight)?;
Ok(())
}
fn validate_unsigned(
weight: crate::weights::Weight,
) -> Result<ValidTransaction, DispatchError> {
let a = A::validate_unsigned(weight)?;
let b = B::validate_unsigned(weight)?;
Ok(a.combine_with(b))
}
fn pre_dispatch_unsigned(
weight: crate::weights::Weight,
) -> Result<(), DispatchError> {
A::pre_dispatch_unsigned(weight)?;
B::pre_dispatch_unsigned(weight)?;
Ok(())
}
};
([$($direct:ident)+] [] ; [$($index:tt,)+] []) => {
tuple_impl_indexed!([$($direct)+] ; [$($index,)+]);
};
(
[$($direct:ident)+] [$first:ident $($rest:ident)*]
;
[$($index:tt,)+] [$first_index:tt, $($rest_index:tt,)*]
) => {
tuple_impl_indexed!([$($direct)+] ; [$($index,)+]);
tuple_impl_indexed!([$($direct)+ $first] [$($rest)*] ; [$($index,)+ $first_index,] [$($rest_index,)*]);
};
}

/// To be used only for testing.
// TODO: merge this into `tuple_impl` once codec supports `trait Codec` for longer tuple lengths.
#[allow(non_snake_case)]
tuple_impl_indexed!(A, B, C, D, E, F, G, H, I, J, ; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,);

/// Only for base bone testing when you don't care about signed extensions at all.\
#[cfg(feature = "std")]
impl SignedExtension for () {
type AccountId = u64;
type AdditionalSigned = ();
fn additional_signed(&self) -> result::Result<(), &'static str> { Ok(()) }
}

/// An "executable" piece of information, used by the standard Substrate Executive in order to
Expand Down
2 changes: 1 addition & 1 deletion core/sr-primitives/src/transaction_validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ impl ValidTransaction {
/// the logic *And* of the propagate flags.
pub fn combine_with(mut self, mut other: ValidTransaction) -> Self {
ValidTransaction {
priority: self.priority + other.priority,
priority: self.priority.saturating_add(other.priority),
requires: { self.requires.append(&mut other.requires); self.requires },
provides: { self.provides.append(&mut other.provides); self.provides },
longevity: self.longevity.min(other.longevity),
Expand Down
11 changes: 7 additions & 4 deletions node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use primitives::bytes;
use primitives::{ed25519, sr25519, OpaqueMetadata};
use runtime_primitives::{
ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str,
traits::{self, NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify}
traits::{self, NumberFor, BlakeTwo256, Block as BlockT, StaticLookup, Verify}, weights::Weight,
};
use client::{
block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api},
Expand Down Expand Up @@ -113,6 +113,7 @@ pub fn native_version() -> NativeVersion {

parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const MaximumBlockWeight: Weight = 4 * 1024 * 1024;
}

impl system::Trait for Runtime {
Expand All @@ -136,6 +137,8 @@ impl system::Trait for Runtime {
type Origin = Origin;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
type MaximumBlockWeight = MaximumBlockWeight;
}

impl aura::Trait for Runtime {
Expand Down Expand Up @@ -228,11 +231,11 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (system::CheckNonce<Runtime>, balances::TakeFees<Runtime>);
pub type SignedExtra<R> = (system::CheckNonce<R>, system::CheckWeight<R>, balances::TakeFees<R>);
Comment thread
kianenigma marked this conversation as resolved.
Outdated
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, AccountSignature, SignedExtra>;
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, AccountSignature, SignedExtra<Runtime>>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra<Runtime>>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, Context, Runtime, AllModules>;

Expand Down
3 changes: 3 additions & 0 deletions node-template/runtime/src/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ mod tests {
use primitives::{H256, Blake2Hasher};
use support::{impl_outer_origin, assert_ok, parameter_types};
use runtime_primitives::{traits::{BlakeTwo256, IdentityLookup}, testing::Header};
use runtime_primitives::weights::Weight;

impl_outer_origin! {
pub enum Origin for Test {}
Expand All @@ -85,6 +86,7 @@ mod tests {
pub struct Test;
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: Weight = 1024;
}
impl system::Trait for Test {
type Origin = Origin;
Expand All @@ -97,6 +99,7 @@ mod tests {
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
}
impl Trait for Test {
type Event = ();
Expand Down
21 changes: 14 additions & 7 deletions node/cli/src/factory_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use rand::rngs::StdRng;

use parity_codec::Decode;
use keyring::sr25519::Keyring;
use node_runtime::{Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall};
use node_runtime::{Call, CheckedExtrinsic, UncheckedExtrinsic, SignedExtra, BalancesCall, Runtime};
use primitives::{sr25519, crypto::Pair};
use parity_codec::Encode;
use sr_primitives::{generic::Era, traits::{Block as BlockT, Header as HeaderT, SignedExtension}};
Expand Down Expand Up @@ -51,6 +51,16 @@ pub struct FactoryState<N> {

type Number = <<node_primitives::Block as BlockT>::Header as HeaderT>::Number;

impl<Number> FactoryState<Number> {
fn build_extra(index: node_primitives::Index, phase: u64) -> node_runtime::SignedExtra<Runtime> {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gavofyork how about this? The factory seems to be an attachment that only works with substrate node and it should be fine to borrow this type.

(
system::CheckEra::from(Era::mortal(256, phase)),
system::CheckNonce::from(index),
system::CheckWeight::from(),
balances::TakeFees::from(0))
Comment thread
gavofyork marked this conversation as resolved.
Outdated
}
}

impl RuntimeAdapter for FactoryState<Number> {
type AccountId = node_primitives::AccountId;
type Balance = node_primitives::Balance;
Expand Down Expand Up @@ -127,19 +137,16 @@ impl RuntimeAdapter for FactoryState<Number> {
) -> <Self::Block as BlockT>::Extrinsic {
let index = self.extract_index(&sender, prior_block_hash);
let phase = self.extract_phase(*prior_block_hash);
let era = system::CheckEra::from(Era::mortal(256, phase));
let check_nonce = system::CheckNonce::from(index);
let take_fees = balances::TakeFees::from(0);

sign::<service::Factory, Self>(CheckedExtrinsic {
signed: Some((sender.clone(), (era, (check_nonce, take_fees)))),
signed: Some((sender.clone(), Self::build_extra(index, phase))),
function: Call::Balances(
BalancesCall::transfer(
indices::address::Address::Id(destination.clone().into()),
(*amount).into()
)
)
}, key, (prior_block_hash.clone(), ((), ())))
}, key, (prior_block_hash.clone(), (), (), ()))
}

fn inherent_extrinsics(&self) -> InherentData {
Expand Down Expand Up @@ -227,7 +234,7 @@ fn gen_seed_bytes(seed: u64) -> [u8; 32] {
fn sign<F: ServiceFactory, RA: RuntimeAdapter>(
xt: CheckedExtrinsic,
key: &sr25519::Pair,
additional_signed: <SignedExtra as SignedExtension>::AdditionalSigned,
additional_signed: <SignedExtra<Runtime> as SignedExtension>::AdditionalSigned,
) -> <RA::Block as BlockT>::Extrinsic {
let s = match xt.signed {
Some((signed, extra)) => {
Expand Down
Loading