Extensible transactions (and tips) (#3102)

* Make extrinsics extensible.

Also Remove old extrinsic types.

* Rest of mockup. Add tips.

* Fix some build issues

* Runtiem builds :)

* Substrate builds.

* Fix a doc test

* Compact encoding

* Extract out the era logic into an extension

* Weight Check signed extension. (#3115)

* Weight signed extension.

* Revert a bit + test for check era.

* Update Cargo.toml

* Update node/cli/src/factory_impl.rs

* Update node/executor/src/lib.rs

* Update node/executor/src/lib.rs

* Don't use len for weight - use data.

* Operational Transaction; second attempt (#3138)

* working poc added.

* some fixes.

* Update doc.

* Fix all tests + final logic.

* more refactoring.

* nits.

* System block limit in bytes.

* Silent the storage macro warnings.

* More logic more tests.

* Fix import.

* Refactor names.

* Fix build.

* Update srml/balances/src/lib.rs

* Final refactor.

* Bump transaction version

* Fix weight mult test.

* Fix more tests and improve doc.

* Bump.

* Make some tests work again.

* Fix subkey.

* Remove todos + bump.

* Ignore expensive test.

* Bump.
This commit is contained in:
Gavin Wood
2019-07-23 01:06:49 +08:00
committed by Kian Peymani
parent 4f5654b67d
commit 78bc5edc14
55 changed files with 1965 additions and 1646 deletions
@@ -18,6 +18,7 @@
use rstd::prelude::*;
use crate::codec::{Encode, Decode};
use crate::traits::DispatchError;
/// Priority for a transaction. Additive. Higher is better.
pub type TransactionPriority = u64;
@@ -36,40 +37,81 @@ pub enum TransactionValidity {
/// Transaction is invalid. Details are described by the error code.
Invalid(i8),
/// Transaction is valid.
Valid {
/// Priority of the transaction.
///
/// Priority determines the ordering of two transactions that have all
/// their dependencies (required tags) satisfied.
priority: TransactionPriority,
/// Transaction dependencies
///
/// A non-empty list signifies that some other transactions which provide
/// given tags are required to be included before that one.
requires: Vec<TransactionTag>,
/// Provided tags
///
/// A list of tags this transaction provides. Successfully importing the transaction
/// will enable other transactions that depend on (require) those tags to be included as well.
/// Provided and required tags allow Substrate to build a dependency graph of transactions
/// and import them in the right (linear) order.
provides: Vec<TransactionTag>,
/// Transaction longevity
///
/// Longevity describes minimum number of blocks the validity is correct.
/// After this period transaction should be removed from the pool or revalidated.
longevity: TransactionLongevity,
/// A flag indicating if the transaction should be propagated to other peers.
///
/// By setting `false` here the transaction will still be considered for
/// including in blocks that are authored on the current node, but will
/// never be sent to other peers.
propagate: bool,
},
Valid(ValidTransaction),
/// Transaction validity can't be determined.
Unknown(i8),
}
impl From<Result<ValidTransaction, DispatchError>> for TransactionValidity {
fn from(r: Result<ValidTransaction, DispatchError>) -> Self {
match r {
Ok(v) => TransactionValidity::Valid(v),
Err(e) => TransactionValidity::Invalid(e.into()),
}
}
}
/// Information concerning a valid transaction.
#[derive(Clone, PartialEq, Eq, Encode)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct ValidTransaction {
/// Priority of the transaction.
///
/// Priority determines the ordering of two transactions that have all
/// their dependencies (required tags) satisfied.
pub priority: TransactionPriority,
/// Transaction dependencies
///
/// A non-empty list signifies that some other transactions which provide
/// given tags are required to be included before that one.
pub requires: Vec<TransactionTag>,
/// Provided tags
///
/// A list of tags this transaction provides. Successfully importing the transaction
/// will enable other transactions that depend on (require) those tags to be included as well.
/// Provided and required tags allow Substrate to build a dependency graph of transactions
/// and import them in the right (linear) order.
pub provides: Vec<TransactionTag>,
/// Transaction longevity
///
/// Longevity describes minimum number of blocks the validity is correct.
/// After this period transaction should be removed from the pool or revalidated.
pub longevity: TransactionLongevity,
/// A flag indicating if the transaction should be propagated to other peers.
///
/// By setting `false` here the transaction will still be considered for
/// including in blocks that are authored on the current node, but will
/// never be sent to other peers.
pub propagate: bool,
}
impl Default for ValidTransaction {
fn default() -> Self {
ValidTransaction {
priority: 0,
requires: vec![],
provides: vec![],
longevity: TransactionLongevity::max_value(),
propagate: true,
}
}
}
impl ValidTransaction {
/// Combine two instances into one, as a best effort. This will take the superset of each of the
/// `provides` and `requires` tags, it will sum the priorities, take the minimum longevity and
/// the logic *And* of the propagate flags.
pub fn combine_with(mut self, mut other: ValidTransaction) -> Self {
ValidTransaction {
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),
propagate: self.propagate && other.propagate,
}
}
}
impl Decode for TransactionValidity {
fn decode<I: crate::codec::Input>(value: &mut I) -> Option<Self> {
match value.read_byte()? {
@@ -81,9 +123,9 @@ impl Decode for TransactionValidity {
let longevity = TransactionLongevity::decode(value)?;
let propagate = bool::decode(value).unwrap_or(true);
Some(TransactionValidity::Valid {
Some(TransactionValidity::Valid(ValidTransaction {
priority, requires, provides, longevity, propagate,
})
}))
},
2 => Some(TransactionValidity::Unknown(i8::decode(value)?)),
_ => None,
@@ -101,24 +143,24 @@ mod tests {
1, 5, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 2, 3, 4, 4, 12, 4, 5, 6, 42, 0, 0, 0, 0, 0, 0, 0
];
assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Some(TransactionValidity::Valid {
assert_eq!(TransactionValidity::decode(&mut &*old_encoding), Some(TransactionValidity::Valid(ValidTransaction {
priority: 5,
requires: vec![vec![1, 2, 3, 4]],
provides: vec![vec![4, 5, 6]],
longevity: 42,
propagate: true,
}));
})));
}
#[test]
fn should_encode_and_decode() {
let v = TransactionValidity::Valid {
let v = TransactionValidity::Valid(ValidTransaction {
priority: 5,
requires: vec![vec![1, 2, 3, 4]],
provides: vec![vec![4, 5, 6]],
longevity: 42,
propagate: false,
};
});
let encoded = v.encode();
assert_eq!(