TxSubmission2
Mini-protocol number: 4
TxSubmission2
is the mini protocol in charge of diffusing pending transactions
through the network. It is a pull-based miniprotocol: data is transmitted only
upon explicit request from the client.
The goal of TxSubmission2
is to let other peers know about the transactions
that the local node considers valid (with respects to the chain that the local
node has selected in Chain Selection in the
consensus layer), and transmit such transactions if requested.
An important piece of information is that transactions flow in the opposite direction than blocks/headers. Blocks flow from block-producers to their clients reaching the entirety of the network, while transactions flow from all the network aiming to reach block-producers. For this reason, in the state machine below it might seem that agency is flipped but this is intentional. It is the “client” (or the “initiator”) the one that gives transactions to the “server” (or “responder).
Honest nodes will try to validate every transaction they come to know about.
There are some situations in which this miniprotocol would terminate abruptly, closing all the connections to the remote peer. Actions that are considered as misbehaviour are (not exclusively):
- Violation of the miniprotocol state machine,
- Too many or not enough transactions sent or acknowledged via the client or server,
- Requesting zero transactions,
- The client requesting a transaction that was not announced by the server.
warning
TODO: Make this list exhaustive
State machine
The state machine for TxSubmission2 is as follows:
stateDiagram direction LR [*] --> StInit StInit --> StIdle: MsgInit StIdle --> StTxs: MsgRequestTxs StTxs --> StIdle: MsgReplyTxs StIdle --> StTxIdsNonBlocking: MsgRequestTxIdsNonBlocking StTxIdsNonBlocking --> StIdle: MsgReplyTxIds StIdle --> StTxIdsBlocking: MsgRequestTxIdsBlocking StTxIdsBlocking --> StIdle: MsgReplyTxIds StTxIdsBlocking --> [*]: MsgDone classDef initiator color:#080 classDef responder color:#008, text-decoration: underline class StIdle responder class StInit initiator class StTxs initiator class StTxIdsBlocking initiator class StTxIdsNonBlocking initiator
State agencies
State | Agency |
---|---|
StInit | Initiator |
StIdle | Responder |
StTxs | Initiator |
StTxIdsBlocking | Initiator |
StTxIdsNonBlocking | Initiator |
State transitions
From state | Message | Parameters | To state |
---|---|---|---|
StInit | MsgInit | StIdle | |
StIdle | MsgRequestTxIdsNonBlocking | ack , req | StTxIdsNonBlocking |
StIdle | MsgRequestTxIdsBlocking | ack , req | StTxIdsBlocking |
StTxIdsNonBlocking | MsgReplyTxIds | [(id, size)] | StIdle |
StTxIdsBlocking | MsgReplyTxIds | [(id, size)] | StIdle |
StIdle | MsgRequestTxs | [id] | StTxs |
StTxs | MsgReplyTxs | [tx] | StIdle |
StIdle | MsgDone | End |
Codecs
The messages depicted in the state machine follow this CDDL specification:
;; messages.cddl
txSubmission2Message
= msgInit
; corresponds to either MsgRequestTxIdsBlocking or
; MsgRequestTxIdsNonBlocking in the spec
/ msgRequestTxIds
/ msgReplyTxIds
/ msgRequestTxs
/ msgReplyTxs
/ tsMsgDone
msgInit = [6]
msgRequestTxIds = [0, tsBlocking, txCount, txCount]
msgReplyTxIds = [1, txIdsAndSizes ]
msgRequestTxs = [2, txIdList ]
msgReplyTxs = [3, txList ]
tsMsgDone = [4]
tsBlocking = false / true
txCount = base.word16
; The codec only accepts indefinite-length lists.
txIdList = [ *txId.txId ]
txList = [ *tx.tx ]
txIdAndSize = [base.txId, txSizeInBytes]
; The codec only accepts definite-length lists.
txIdsAndSizes = [ *txIdAndSize ]
txSizeInBytes = base.word32
;# import tx as tx
;# import txId as txId
;# import base as base
A transaction ID is a tag-encoded alternative of the transaction IDs for each of the eras. Note that in Byron there are 4 alternatives for a transaction ID:
;; txid.cddl
txId =
base.ns7<byronTxId,
shelley.transaction_id,
allegra.transaction_id,
mary.transaction_id,
alonzo.transaction_id,
conway.transaction_id,
babbage.transaction_id>
byronTxId = [0, byron.txid]
/ [1, byron.certificateid]
/ [2, byron.updid]
/ [3, byron.voteid]
;# include byron as byron
;# include shelley as shelley
;# include allegra as allegra
;# include mary as mary
;# include alonzo as alonzo
;# include babbage as babbage
;# include conway as conway
;# import base as base
A transaction as transmitted in TxSubmission2
is a tag-encoded
alternative of the transactions for each of the eras. Note that for
Shelley-onwards, the transaction is serialized in CBOR-in-CBOR:
;; tx.cddl
tx =
base.ns7<byron.tx,
serialisedShelleyTx<shelley.transaction>,
serialisedShelleyTx<allegra.transaction>,
serialisedShelleyTx<mary.transaction>,
serialisedShelleyTx<alonzo.transaction>,
serialisedShelleyTx<babbage.transaction>,
serialisedShelleyTx<conway.transaction>>
serialisedShelleyTx<era> = #6.24(bytes .cbor era)
;# include byron as byron
;# include shelley as shelley
;# include allegra as allegra
;# include mary as mary
;# include alonzo as alonzo
;# include babbage as babbage
;# include conway as conway
;# import base as base