JoshOrndorff / recipes

A Hands-On Cookbook for Aspiring Blockchain Chefs
GNU General Public License v3.0
378 stars 187 forks source link

Recipe for TaggedTransactionQueue #139

Open JoshOrndorff opened 4 years ago

JoshOrndorff commented 4 years ago

In PR #140 I removed outdated/incomplete notes about patterns in the utxo workshop. Most of the topics are covered elsewhere in the recipes, or sufficiently outdated to not be included.

There was one bit about ordering and prioritizing transactions using the tagged transaction pool runtime api. This idea could be fleshed out more and re-introduced. Here is the text that was removed.

To customize the transaction ordering logic for a Substrate blockchain, use the [`TaggedTransactionQueue`](https://substrate.dev/rustdocs/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html) trait to specify the transaction queue logic and mitigate race conditions. To do so, implement the following function,

rust, ignore
fn validate_transaction(
    &self,
    at: &BlockId<Block>,
    tx: <Block as BlockT>::Extrinsic
) -> Result<TransactionValidity, Error>

This function signature reveals that, in the event of a successful call, the return type must be [`TransactionValidity`](https://substrate.dev/rustdocs/master/sp_runtime/transaction_validity/enum.TransactionValidity.html). This enum has three variants

rust, ignore
pub enum TransactionValidity {
    Invalid(i8),
    Valid {
        priority: TransactionPriority,
        requires: Vec<TransactionTag>,
        provides: Vec<TransactionTag>,
        longevity: TransactionLongevity,
    },
    Unknown(i8),
}

In the context of the [`utxo-workshop`](https://github.com/nczhu/utxo-workshop), specify the hashes of required transactions (`missing_utxos`) in the `requires` field while also specifying the list of transactions for which this utxo satisfies `requires` in the `provides` field. The `longevity` field is set somewhat arbitrarily for this example, and the `priority` field serves to enforce an ordering on the set of transactions.  
JoshOrndorff commented 4 years ago

In #212 @nczhu brainstormed on this idea

A blockchain’s transaction pool is a place that contains all of the networks unconfirmed transactions. Within the transaction pool, multiple verification steps, among other networking logic are being executed. In particular, In Substrate, we can invoke something called the TaggedTransactionQueue, which is an api trait that lets us interfere with the blockchain’s transaction queue. The Transaction queue checks for transaction validity and evaluates a struct called validTransaction, before transactions are executed. This runtime api lets us tag validTransaction with multiple properties like:

Priority: designates the order that transactions can precede each other Requires: vector of prequiresite tags that must be satisfied by a previous transaction, before this transaction is queued up to be processed. Provides: the tags fulfilled from a transaction, likely satisfying the “requires” tags for a consequetive transaction. Longevity: describes minimum number of blocks where the transaction can still stay in the pool. After this period transaction should be removed from the pool or revalidated. propagate: is a boolean flag indicating if the transaction should be propagated to other peers. The default is true.