Generalised Transaction Queue API (#741)

* First effort

* API versioning

* Introduce validate_transaction

* Introduce the API plus fixes.

* Docs

* Typo

* Add longevity parameter to transaction validity info.
This commit is contained in:
Gav Wood
2018-09-17 18:43:59 +02:00
committed by GitHub
parent 263786df05
commit f10d8e177d
52 changed files with 263 additions and 143 deletions
+47 -1
View File
@@ -31,6 +31,7 @@ extern crate parity_codec_derive;
#[cfg_attr(test, macro_use)]
extern crate srml_support as runtime_support;
#[cfg_attr(not(feature = "std"), macro_use)]
extern crate sr_std as rstd;
extern crate sr_io as runtime_io;
extern crate parity_codec as codec;
@@ -51,11 +52,12 @@ use rstd::prelude::*;
use rstd::marker::PhantomData;
use rstd::result;
use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, OnFinalise,
MakePayment, Hash};
MakePayment, Hash, As};
use runtime_support::Dispatchable;
use codec::{Codec, Encode};
use system::extrinsics_root;
use primitives::{ApplyOutcome, ApplyError};
use primitives::transaction_validity::{TransactionValidity, TransactionPriority, TransactionLongevity};
mod internal {
pub enum ApplyError {
@@ -213,6 +215,50 @@ impl<
header.state_root().check_equal(&storage_root);
assert!(header.state_root() == &storage_root, "Storage root must match that calculated.");
}
/// Check a given transaction for validity. This doesn't execute any
/// side-effects; it merely checks whether the transaction would panic if it were included or not.
///
/// Changes made to the storage should be discarded.
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
let encoded_len = uxt.encode().len();
let xt = match uxt.check_with(Lookup::lookup) {
// Checks out. Carry on.
Ok(xt) => xt,
// An unknown account index implies that the transaction may yet become valid.
Err("invalid account index") => return TransactionValidity::Unknown,
// Technically a bad signature could also imply an out-of-date account index, but
// that's more of an edge case.
Err(_) => return TransactionValidity::Invalid,
};
if let Some(sender) = xt.sender() {
// pay any fees.
if Payment::make_payment(sender, encoded_len).is_err() {
return TransactionValidity::Invalid
}
// check index
let mut expected_index = <system::Module<System>>::account_nonce(sender);
if xt.index() < &expected_index {
return TransactionValidity::Invalid
}
if *xt.index() > expected_index + As::sa(256) {
return TransactionValidity::Unknown
}
let mut deps = Vec::new();
while expected_index < *xt.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())
} else {
return TransactionValidity::Invalid
}
}
}
#[cfg(test)]