Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

StateAgency
StInitInitiator
StIdleResponder
StTxsInitiator
StTxIdsBlockingInitiator
StTxIdsNonBlockingInitiator

State transitions

From stateMessageParametersTo state
StInitMsgInitStIdle
StIdleMsgRequestTxIdsNonBlockingack, reqStTxIdsNonBlocking
StIdleMsgRequestTxIdsBlockingack, reqStTxIdsBlocking
StTxIdsNonBlockingMsgReplyTxIds[(id, size)]StIdle
StTxIdsBlockingMsgReplyTxIds[(id, size)]StIdle
StIdleMsgRequestTxs[id]StTxs
StTxsMsgReplyTxs[tx]StIdle
StIdleMsgDoneEnd

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