Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

Commit deb3860

Browse files
author
Sacha Lansky
authored
Merge pull request #44 from substrate-developer-hub/sl/tx-doc-and-review
Transaction and execution doc
2 parents e32e6d1 + 0d20055 commit deb3860

File tree

9 files changed

+562
-121
lines changed

9 files changed

+562
-121
lines changed

old-docs-migration/docs/02-concepts/d-transaction-pool.md

+5-109
Original file line numberDiff line numberDiff line change
@@ -7,119 +7,15 @@ category: concepts
77
keywords: transaction, pool, order, ordering, sorting, validity
88
---
99

10-
The transaction pool contains all transactions ([signed](/v3/concepts/extrinsics#signed-transactions)
11-
and [unsigned](/v3/concepts/extrinsics#unsigned-transactions)) broadcasted to the network that have been
12-
received and validated by the local node.
13-
14-
## Validity
15-
16-
The transaction pool checks for transaction validity.
17-
Note that `validity` of the transaction is not hard-wired to the transaction pool, but is defined by the runtime.
18-
Example validity checks are:
19-
20-
- Checking if the Transaction Index (nonce) is correct.
21-
- Checking if the account has enough funds to pay for the associated fees.
22-
- Checking if the signature is valid.
23-
24-
The transaction pool also regularly checks validity of existing transactions within the pool.
25-
A transaction will be dropped from the pool if it is found to be invalid or is an expired mortal transaction.
26-
27-
[`validate_transaction`](/rustdocs/latest/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction) is called from the runtime to checks for a valid signature and nonce (or output for a UTXO chain) and returns a `Result`.
10+
## Validity
11+
[content not used / to remove]
2812
It does this check in isolation, so it will not catch errors such as the same output being spent twice.
13+
`validate_transaction` does not check whether calls to a pallet will succeed.
2914

30-
Although it is possible, `validate_transaction` does not check whether calls to pallets will succeed.
31-
It is a potential DoS vector since all transactions in the network will be passed into `validate_transaction`.
32-
33-
The `validate_transaction` function should focus on providing the necessary information for the pool to order and prioritize transactions, and quickly reject all transactions that are invalid or outdated.
34-
The function will be called frequently, potentially multiple times for the same transaction.
35-
It is also possible for `validate_transaction` to fail a dependent transaction that would pass `execute_block` if it were executed in the correct order.
36-
37-
## Sorting
38-
39-
If the transaction is valid, the transaction queue sorts transactions into two groups:
40-
41-
- Ready Queue - Contains transactions that can be included in a new pending block.
42-
For runtimes built with FRAME, the transactions must follow the exact order in the ready queue.
43-
- Future Queue - Contains transactions that may become valid in the future.
44-
For example, a transaction may have a `nonce` that is too high for its account.
45-
This transaction will wait in the future queue until the preceding transactions are included in the chain.
46-
47-
Although it's possible to design a custom runtime to remove the queues' strict transaction ordering requirements.
15+
[ todo : put this in architecture? or design? ]
16+
It's possible to design a custom runtime to remove the strict ordering requirements of the queue.
4817
This would allow full nodes to implement different strategies on transaction propagation and block inclusion.
4918

50-
## Transaction dependencies
51-
52-
The [`ValidTransaction` struct](/rustdocs/latest/sp_runtime/transaction_validity/struct.ValidTransaction.html) defines the `requires` and `provides` parameters to build a dependency graph of transactions.
53-
Together with `priority` (discussed below), this dependency graph allows the pool to produce a valid linear ordering of transactions.
54-
55-
For runtimes built with FRAME, the nodes order transactions with an account-based system.
56-
Every signed transaction needs to contain a nonce, which is incremented by 1 every time a new transaction is made.
57-
For example, the first transaction from a new account will have `nonce = 0` and the second transaction will have `nonce = 1`.
58-
59-
At minimum, FRAME transactions have a `provides` tag of `encode(sender ++ nonce)` and a `requires` tag of `encode(sender ++ (nonce -1)) if nonce > 1`.
60-
Transactions do not require anything if `nonce=0`.
61-
As a result, all transactions coming from a single sender will form a sequence in which they should be included.
62-
63-
Substrate supports multiple `provides` and `requires` tags, so custom runtimes can create alternate dependency (ordering) schemes.
64-
65-
## Transaction priority
66-
67-
Transaction `priority` in the `ValidTransaction` struct determines the ordering of transactions that are in the ready queue.
68-
If a node is the next block author, it will order transactions from high to low priority in the next block until it reaches the weight or length limit of the block.
69-
70-
`priority` defines the linear ordering of a graph in the case of one transaction unlocking multiple dependent transactions.
71-
For example, if we have two (or more) transactions that have their dependencies satisfied, then we use `priority` to choose the order for them.
72-
73-
For runtimes built with [FRAME](/v3/runtime/frame), `priority` is defined as the `fee` that the transaction is going to pay.
74-
For example:
75-
76-
- If we receive 2 transactions from _different_ senders (with `nonce=0`), we use `priority` to
77-
determine which transaction is more important and included in the block first.
78-
- If we receive 2 transactions from the _same_ sender with an identical `nonce`, only one
79-
transaction can be included on-chain. We use `priority` to choose the transaction with a higher
80-
`fee` to store in the transaction pool.
81-
82-
Note that the pool does not know about fees, accounts, or signatures — it only deals with the validity of the transaction and the abstract notion of the `priority`, `requires`, and `provides` parameters.
83-
All other details are defined by the runtime via the `validate_transaction` function.
84-
85-
## Transaction lifecycle
86-
87-
A transaction can follow two paths:
88-
89-
### Block produced by our node
90-
91-
1. Our node listens for transactions on the network.
92-
1. Each transaction is verified and valid transactions are placed in the transaction pool.
93-
1. The pool is responsible for ordering the transactions and returning ones that are ready to be included in the block.
94-
Transactions in the ready queue are used to construct a block.
95-
1. Transactions are executed and state changes are stored in local memory.
96-
Transactions from the `ready` queue are also propagated (gossiped) to peers over the network.
97-
We use the exact ordering as the pending block since transactions in the front of the queue have a higher priority and are more likely to be successfully executed in the next block.
98-
1. The constructed block is published to the network.
99-
All other nodes on the network receive and execute the block.
100-
101-
Notice that transactions are not removed from the ready queue when blocks are authored, but removed _only_ on block import.
102-
This is due to the possibility that a recently-authored block may not make it into the canonical chain.
103-
104-
### Block received from network
105-
106-
The block is executed and the entire block either succeeds or fails.
107-
108-
## Signed extensions
109-
110-
[`SignedExtension`](/rustdocs/latest/sp_runtime/traits/trait.SignedExtension.html) is a trait by which a transaction can be extended with additional data or logic.
111-
Signed extensions are used anywhere you want some information about a transaction prior to execution.
112-
This is heavily used in the transaction pool.
113-
114-
The runtime can use some of this data, for example the `Call` that will be dispatched, to calculate transaction fees.
115-
Signed extensions also include an `AdditionalSigned` type that can hold any encodable data, and therefore allow you to perform any custom logic prior to including or dispatching a transaction.
116-
The transaction queue regularly calls functions from `SignedExtension` to validate transactions prior to block construction to avoid including transactions that will fail in blocks.
117-
118-
Despite the name, `SignedExtension` can also be used to verify [unsigned transactions](/v3/concepts/extrinsics#unsigned-transactions).
119-
The `*_unsigned` set of methods can be implemented to encapsulate validation, spam, and replay protection logic that is needed by the transaction pool.
120-
121-
- [Signed Extension API](/rustdocs/latest/sp_runtime/traits/trait.SignedExtension.html)
122-
12319
## Further Reading
12420

12521
- [Extrinsics](/v3/concepts/extrinsics)
+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
A place for content that's not been used anywhere.
2+
Perhaps to scrap, haven't decided yet.
3+
4+
# Transactions
5+
6+
## Where transactions are defined
7+
8+
As discussed in [Runtime development](), the Substrate runtime contains the business logic that defines valid transactions, determines whether the transactions are sent as signed or unsigned, and how transactions change the state of the chain.
9+
10+
Typically, you use pallets to compose the runtime functions and to implement the transactions you want your chain to support.
11+
After you compile the runtime, users interact with the blockchain to submit requests that are processed as transactions.
12+
For example, a user might submit a request to transfer funds from one account to another.
13+
The request becomes a signed transaction that contains the signature for that user account and if there are sufficient funds in the user's account to pay for the transaction, the transaction executes successfully, and the transfer is made.
14+
15+
<!-- Although inherents are very different by nature compared to signed and unsigned transaction types, they are treated like any other transaction from the perspective of the transaction pool. -->
16+
17+
<!-- See how FRAME implements and used these types of transactions:
18+
- #[pallet::inherent]:
19+
- #[pallet::validate_unsigned]:
20+
- dispatch origins: signed, unsigned, none (inherent) -->
21+
22+
A `CheckedExtrinsic` is quite different on the other hand.
23+
It's format requires:
24+
25+
- a `function` corresponding to the call being made.
26+
- a `signed` field which carries information on where this extrinsic comes from (`AccountId`) and the number of extrinsics that have come before from the same source (defined by the `CheckedExtrinsic` signed extension).
27+
28+
29+
<!-- All signed transactions in a FRAME runtime have the following formatted around the `UncheckExtrinsics` type and
30+
31+
- tip
32+
- period
33+
- current_block
34+
- era
35+
- extra
36+
- raw_payload
37+
- signature
38+
- address
39+
40+
And look like this when decoded:
41+
42+
```text
43+
Extra: (CheckNonZeroSender, CheckSpecVersion, CheckTxVersion, CheckGenesis, CheckEra(Era::Mortal(2048, 99)), CheckNonce(0), CheckWeight, ChargeTransactionPayment<0>)
44+
Additional Signed: (259, 1, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, (), (), ())
45+
Raw Payload: [6, 0, 255, 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 145, 1, 58, 6, 0, 0, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
46+
```
47+
48+
Notice some other [signed extensions](#signed-extensions) which perform certain checks on the format of the transaction.
49+
-->
50+
51+
## Validity
52+
53+
The validity of a transaction is verified by checks defined in the runtime.
54+
Before a transaction is propagated to other nodes, it is "tagged" and checked for whether:
55+
56+
- The signature is valid.
57+
- The account has enough funds to pay for the associated fees.
58+
- The transaction index (nonce) is correct.
59+
60+
The transaction pool also regularly checks for transaction validity of existing transactions within the pool.
61+
Every transaction is defined in the runtime using the [`ValidTransaction`](https://docs.substrate.io/rustdocs/latest/sp_runtime/transaction_validity/struct.ValidTransaction.html) struct.
62+
A transaction will be dropped from the pool if it is found to be invalid or expired, for example:
63+
64+
- If another transaction contains the same transaction dependencies (see: [`requires`](https://docs.substrate.io/rustdocs/latest/sp_runtime/transaction_validity/struct.ValidTransaction.html#structfield.requires) and [`TransactionTag`](https://docs.substrate.io/rustdocs/latest/sp_runtime/transaction_validity/type.TransactionTag.html)).
65+
- If the transaction has exceeded the [`TransactionLongevity`](https://docs.substrate.io/rustdocs/latest/sp_runtime/transaction_validity/type.TransactionLongevity.html#), i.e. the amount of blocks it can remain valid for.
66+
67+
Other causes for invalid transactions are listed [here](https://docs.substrate.io/rustdocs/latest/sp_runtime/transaction_validity/enum.InvalidTransaction.html).
68+
69+
The [`TaggedTransactionQueue`](https://docs.substrate.io/rustdocs/latest/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html) runtime API provides a [`validate_transaction`](/rustdocs/latest/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction) method whose job is to verify the correctness of the transaction against the current state (i.e. the signature and nonce).
70+
The function will be called frequently, potentially multiple times for the same transaction.
71+
In doing so, it provides the necessary information for the transaction pool to order and prioritize transactions.
72+
It is also possible for `validate_transaction` to reject a dependent transaction that would pass `execute_block` if it were executed in the correct order.
73+
74+
75+
A decoded signed transaction from a JSON-RPC call would look like:
76+
77+
```json
78+
"method":{
79+
"pallet":"balances",
80+
"method":"transfer"
81+
},
82+
"signature":{
83+
"signature":"0x94b63112648e8e692f0076fa1ccab3a04510c269d1392c1df2560503865e144e3afd578f1e37e98063b64b98a77a89a9cdc8ade579dcac0984e78d90646a052001",
84+
"signer":{
85+
"id":"Gr5sBB1EgdmQ7FG3Ud2BdECWQTMDXNgGPfdHMMtDsmT4Dj3"
86+
}
87+
},
88+
"nonce":"12",
89+
"args":{
90+
"dest":{
91+
"id":"J6ksma2jVeHRcRoYPZBkJRzRbckys7oSmgvjKLrVbj1U8bE"
92+
},
93+
"value":"100000000"
94+
},
95+
"tip":"0",
96+
"hash":"0xfbc5e5de75d64abe5aa3ee9272a3112b3ce53710664f6f2b9416b2ffda8799c2",
97+
"info":{
98+
"weight":"201217000",
99+
"class":"Normal",
100+
"partialFee":"2583332634"
101+
}
102+
}
103+
```
104+
105+
An inherent would look like:
106+
107+
```json
108+
"method":{
109+
"pallet":"timestamp",
110+
"method":"set"
111+
},
112+
"signature":null,
113+
"nonce":null,
114+
"args":{
115+
"now":"1620636072000"
116+
},
117+
"tip":null,
118+
"hash":"0x8b853f49b6543e4fcbc796ad3574ea5601d2869d80629e080e501da4cb7b74b4",
119+
"info":{
120+
121+
}
122+
}
123+
```
124+
125+
126+
The [`ValidTransaction` struct](/rustdocs/latest/sp_runtime/transaction_validity/struct.ValidTransaction.html) defines two parameters used to determine the ordering of transactions in the pool: `requires` and `provides`.
127+
Together they create a dependency graph which allows the pool to produce a valid linear ordering of transactions.
128+
129+
Substrate supports multiple `provides` and `requires` tags.
130+
This enables runtime engineers to create alternate ordering schemes.
131+
132+
133+
## FRAME implementation
134+
135+
See how the core mechanisms described in this article are implemented in FRAME:
136+
- `pallet_transaction_payment_rpc`: RPC interface for the transaction payment pallet.
137+
- `pallet_transaction_payment`: Transaction Payment Pallet
138+
- `pallet_transaction_storage`: Transaction storage pallet. Indexes transactions and …
139+
- `pallet_transaction_payment_rpc_runtime_api`: Runtime API definition for transaction payment pallet.
140+
141+
`Operational` transactions are getting additional priority bump (3/4 * `u64::max()`), because that prevents other transactions from getting in front of them in the pool, but now equal to the `OperationalVirtualTip` amount configurable by a runtime developer.
142+
143+
Notes:
144+
145+
- We need some note in the "welcome" section that says that our docs describe building parachains with Substrate, specifically for runtimes built with FRAME.

source/docs/main-docs/02-fundamentals/architecture.md

-10
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,6 @@ It defines what transactions are valid and invalid and determines how the chain'
3232
The client on the other hand, or everything part of the node that's outside the runtime, is responsible for handling peer discovery, transaction pools, consensus and answering RPC calls from the outside world.
3333
While performing these tasks, the outer node sometimes needs to query the runtime for information, or provide information to the runtime.
3434

35-
Communication of this sort is made possible by runtime APIs and host functions.
36-
37-
### Runtime APIs and host functions
38-
39-
A **host function** is a function that is expressed outside of the runtime whose job is to provide data required by the runtime, like providing hardware information about a node or network status.
40-
A **runtime API** provides a way to query information about the runtime, useful to make calls for querying a runtime's metadata or querying some storage item.
41-
42-
Although designed to be constraint-free, any Substrate runtime must implement a runtime API for basic block execution and runtime versioning (see: [`Core`](/rustdocs/latest/sp_api/trait.Core.html)) and another for providing metadata to external applications (see: [`Metadata`](/rustdocs/latest/sp_api/trait.Metadata.html)).
43-
Other [runtime APIs]() are available out of the box.
44-
4535
Learn more about [availble runtime APIs](./link-todo-design) in Substrate.
4636

4737
### Wasm runtimes

0 commit comments

Comments
 (0)