Transaction eras (#758)

* Initial groundwork

* A mess.

* Integrate

* Fix tests

* Unit tests

* Tests for unchecked_extrisnic

* fix tab

* Improve binary format.

* fix tests

* Rename extrinsic-pool -> transaction-pool

Closes #770

* Implement unimplemented.

* typo
This commit is contained in:
Gav Wood
2018-09-20 14:01:01 +02:00
committed by GitHub
parent 43068f8fc3
commit 67bf1a6eaa
42 changed files with 782 additions and 232 deletions
+33 -7
View File
@@ -46,7 +46,7 @@ use codec::{Encode, Decode, Codec, Input, Output};
use runtime_support::{StorageValue, StorageMap, Parameter};
use runtime_support::dispatch::Result;
use primitives::traits::{Zero, One, SimpleArithmetic, OnFinalise, MakePayment,
As, Lookup, Member, CheckedAdd, CheckedSub};
As, Lookup, Member, CheckedAdd, CheckedSub, GetHeight, BlockNumberToHash};
use address::Address as RawAddress;
use system::ensure_signed;
@@ -630,6 +630,13 @@ impl<T: Trait> Module<T> {
<TotalIssuance<T>>::put(v);
}
}
pub fn lookup(a: address::Address<T::AccountId, T::AccountIndex>) -> result::Result<T::AccountId, &'static str> {
match a {
address::Address::Id(i) => Ok(i),
address::Address::Index(i) => <Module<T>>::lookup_index(i).ok_or("invalid account index"),
}
}
}
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
@@ -637,14 +644,33 @@ impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
}
}
impl<T: Trait> Lookup for Module<T> {
pub struct ChainContext<T>(::rstd::marker::PhantomData<T>);
impl<T> Default for ChainContext<T> {
fn default() -> Self {
ChainContext(::rstd::marker::PhantomData)
}
}
impl<T: Trait> Lookup for ChainContext<T> {
type Source = address::Address<T::AccountId, T::AccountIndex>;
type Target = T::AccountId;
fn lookup(a: Self::Source) -> result::Result<Self::Target, &'static str> {
match a {
address::Address::Id(i) => Ok(i),
address::Address::Index(i) => <Module<T>>::lookup_index(i).ok_or("invalid account index"),
}
fn lookup(&self, a: Self::Source) -> result::Result<Self::Target, &'static str> {
<Module<T>>::lookup(a)
}
}
impl<T: Trait> GetHeight for ChainContext<T> {
type BlockNumber = T::BlockNumber;
fn get_height(&self) -> Self::BlockNumber {
<system::Module<T>>::block_number()
}
}
impl<T: Trait> BlockNumberToHash for ChainContext<T> {
type BlockNumber = T::BlockNumber;
type Hash = T::Hash;
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
Some(<system::Module<T>>::block_hash(n))
}
}
+1 -1
View File
@@ -17,7 +17,7 @@
//! Council system: Handles the voting in and maintenance of council members.
use rstd::prelude::*;
use primitives::traits::{Zero, One, As, Lookup, OnFinalise};
use primitives::traits::{Zero, One, As, OnFinalise};
use runtime_io::print;
use srml_support::{StorageValue, StorageMap, dispatch::Result};
use democracy;
+20 -30
View File
@@ -76,23 +76,22 @@ mod internal {
pub struct Executive<
System,
Block,
Lookup,
Context,
Payment,
Finalisation,
>(PhantomData<(System, Block, Lookup, Payment, Finalisation)>);
>(PhantomData<(System, Block, Context, Payment, Finalisation)>);
impl<
Address,
Context: Default,
System: system::Trait,
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
Lookup: traits::Lookup<Source=Address, Target=System::AccountId>,
Payment: MakePayment<System::AccountId>,
Finalisation: OnFinalise<System::BlockNumber>,
> Executive<System, Block, Lookup, Payment, Finalisation> where
Block::Extrinsic: Checkable<fn(Address) -> Result<System::AccountId, &'static str>> + Codec,
<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked: Applyable<Index=System::Index, AccountId=System::AccountId>,
<<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked as Applyable>::Call: Dispatchable,
<<<Block::Extrinsic as Checkable<fn(Address) -> Result<System::AccountId, &'static str>>>::Checked as Applyable>::Call as Dispatchable>::Origin: From<Option<System::AccountId>>
> Executive<System, Block, Context, Payment, Finalisation> where
Block::Extrinsic: Checkable<Context> + Codec,
<Block::Extrinsic as Checkable<Context>>::Checked: Applyable<Index=System::Index, AccountId=System::AccountId>,
<<Block::Extrinsic as Checkable<Context>>::Checked as Applyable>::Call: Dispatchable,
<<<Block::Extrinsic as Checkable<Context>>::Checked as Applyable>::Call as Dispatchable>::Origin: From<Option<System::AccountId>>
{
/// Start the execution of a particular block.
pub fn initialise_block(header: &System::Header) {
@@ -177,13 +176,13 @@ impl<
/// Actually apply an extrinsic given its `encoded_len`; this doesn't note its hash.
fn apply_extrinsic_no_note_with_len(uxt: Block::Extrinsic, encoded_len: usize) -> result::Result<internal::ApplyOutcome, internal::ApplyError> {
// Verify the signature is good.
let xt = uxt.check_with(Lookup::lookup).map_err(internal::ApplyError::BadSignature)?;
let xt = uxt.check(&Default::default()).map_err(internal::ApplyError::BadSignature)?;
if let Some(sender) = xt.sender() {
if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) {
// check index
let expected_index = <system::Module<System>>::account_nonce(sender);
if xt.index() != &expected_index { return Err(
if xt.index() < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future }
if index != &expected_index { return Err(
if index < &expected_index { internal::ApplyError::Stale } else { internal::ApplyError::Future }
) }
// pay any fees.
@@ -223,7 +222,7 @@ impl<
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
let encoded_len = uxt.encode().len();
let xt = match uxt.check_with(Lookup::lookup) {
let xt = match uxt.check(&Default::default()) {
// Checks out. Carry on.
Ok(xt) => xt,
// An unknown account index implies that the transaction may yet become valid.
@@ -233,7 +232,7 @@ impl<
Err(_) => return TransactionValidity::Invalid,
};
if let Some(sender) = xt.sender() {
if let (Some(sender), Some(index)) = (xt.sender(), xt.index()) {
// pay any fees.
if Payment::make_payment(sender, encoded_len).is_err() {
return TransactionValidity::Invalid
@@ -241,20 +240,20 @@ impl<
// check index
let mut expected_index = <system::Module<System>>::account_nonce(sender);
if xt.index() < &expected_index {
if index < &expected_index {
return TransactionValidity::Invalid
}
if *xt.index() > expected_index + As::sa(256) {
if *index > expected_index + As::sa(256) {
return TransactionValidity::Unknown
}
let mut deps = Vec::new();
while expected_index < *xt.index() {
while expected_index < *index {
deps.push((sender, expected_index).encode());
expected_index = expected_index + One::one();
}
TransactionValidity::Valid(encoded_len as TransactionPriority, deps, vec![(sender, *xt.index()).encode()], TransactionLongevity::max_value())
TransactionValidity::Valid(encoded_len as TransactionPriority, deps, vec![(sender, *index).encode()], TransactionLongevity::max_value())
} else {
return TransactionValidity::Invalid
}
@@ -268,19 +267,10 @@ mod tests {
use runtime_io::with_externalities;
use substrate_primitives::{H256, Blake2Hasher, RlpCodec};
use primitives::BuildStorage;
use primitives::traits::{Header as HeaderT, BlakeTwo256, Lookup};
use primitives::traits::{Header as HeaderT, BlakeTwo256};
use primitives::testing::{Digest, DigestItem, Header, Block};
use system;
struct NullLookup;
impl Lookup for NullLookup {
type Source = u64;
type Target = u64;
fn lookup(s: Self::Source) -> Result<Self::Target, &'static str> {
Ok(s)
}
}
impl_outer_origin! {
pub enum Origin for Runtime {
}
@@ -316,7 +306,7 @@ mod tests {
}
type TestXt = primitives::testing::TestXt<Call<Runtime>>;
type Executive = super::Executive<Runtime, Block<TestXt>, NullLookup, balances::Module<Runtime>, ()>;
type Executive = super::Executive<Runtime, Block<TestXt>, balances::ChainContext<Runtime>, balances::Module<Runtime>, ()>;
#[test]
fn balance_transfer_dispatch_works() {
+1 -2
View File
@@ -52,8 +52,7 @@ use rstd::cmp;
use runtime_support::{Parameter, StorageValue, StorageMap};
use runtime_support::dispatch::Result;
use session::OnSessionChange;
use primitives::traits::{Zero, One, Bounded, OnFinalise,
As, Lookup};
use primitives::traits::{Zero, One, Bounded, OnFinalise, As};
use balances::{address::Address, OnDilution};
use system::ensure_signed;
+16 -1
View File
@@ -44,7 +44,7 @@ extern crate safe_mix;
use rstd::prelude::*;
use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded,
Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, As};
Hash, Member, MaybeDisplay, EnsureOrigin, Digest as DigestT, As, GetHeight, BlockNumberToHash};
use substrate_primitives::storage::well_known_keys;
use runtime_support::{storage, StorageValue, StorageMap, Parameter};
use safe_mix::TripletMix;
@@ -384,6 +384,21 @@ impl<T: Trait> Module<T> {
}
}
impl<T: Trait> GetHeight for Module<T> {
type BlockNumber = T::BlockNumber;
fn get_height(&self) -> Self::BlockNumber {
<Module<T>>::block_number()
}
}
impl<T: Trait> BlockNumberToHash for Module<T> {
type BlockNumber = T::BlockNumber;
type Hash = T::Hash;
fn block_number_to_hash(&self, n: Self::BlockNumber) -> Option<Self::Hash> {
Some(<Module<T>>::block_hash(n))
}
}
#[cfg(any(feature = "std", test))]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]