V1.1.0-MANTLE-TRANSACTION-ENCODING

FieldValue
Name[1.1.0] Mantle Transaction Encoding
Slug224
Statusdeprecated
TypeRFC
CategoryStandards Track
EditorDavid Rusu [email protected]
ContributorsFilip Dimitrijevic [email protected]

Timeline

  • 2026-05-28d45eed2 — Chore: mirror blochain specs into github/mdbook (#347)

Owner: @David Rusu

Reviewers: @Thomas Lavaur @Giacomo Pasini @Gusto Bacvinka @Daniel Sanchez Quiros @lvaro Castro-Castilla

Revision History

VersionChangesDate
1.0.0Initial revision.2026-01-20
1.1.0Added [RFC] Make Ledger Transaction an Operation2026-04-02

Introduction

This document specifies the canonical encoding of Mantle transactions (see [1.3.0] Mantle - Mantle Transaction) and its sub-components. Transactions sent through the mempool and included in blocks use this encoding.

Overview

The transaction encoding is specified in ABNF form to remove any ambiguity and guarantee a canonical encoding. The high level encoding choices which were not immediately derivable from the Mantle specification are listed here:

  1. All multi-byte integers use little-endian encoding
  2. Any lists are length-prefixed with fixed width uints
  3. We derive number of proofs and type of proof from the Ops list parsed earlier

Specification

Signed Mantle Tx

SignedMantleTx = MantleTx OpsProofs

Mantle Tx

MantleTx = Ops ExecutionGasPrice StorageGasPrice
ExecutionGasPrice = UINT64
StorageGasPrice = UINT64

In future iterations, we will use this encoding to derive the mantle_txhash

Operations

Ops = OpCount *Op
OpCount = Byte
Op = Opcode OpPayload
Opcode = Byte
OpPayload = Transfer /
ChannelInscribe /
ChannelBlob /
ChannelSetKeys /
SDPDeclare /
SDPWithdraw /
SDPActive /
LeaderClaim 

Channel Operations

ChannelInscribe = ChannelId Inscription Parent Signer
Inscription = UINT32 *BYTE
ChannelBlob = ChannelId Session BlobId BlobSize DaStorageGasPrice Parent Signer
Sesssion = UINT64
BlobId = Hash32
BlobSize = UINT64
DaStorageGasPrice = UINT64
ChannelSetKeys = ChannelId KeyCount *Signer
KeyCount = Byte
ChannelId = Hash32
Parent = Hash32
Signer = Ed25519PublicKey

SDP Operations

SDPDeclare = ServiceType LocatorCount *Locator ProviderId ZkId LockedNoteId
ServiceType = Byte ; 0 = BN, 1 = DA
LocatorCount = Byte ; Max 8
Locator = 2Byte *BYTE ; Max 329 bytes, multiaddr format
ProviderId = Ed25519PublicKey
ZkId = ZkPublicKey
LockedNoteId = NoteId
SDPWithdraw = DeclarationId Nonce LockedNoteId
DeclarationId = Hash32
Nonce = UINT64
SDPActive = DeclarationId Nonce Metadata
Metadata = UINT32 *BYTE ; Service-specific node activeness metadata

Leader operations

LeaderClaim = RewardsRoot VoucherNullifier
RewardsRoot = FieldElement ; Merkle root for voucher membership proof
VoucherNullifier = FieldElement

Transfer Operations

Transfer = Inputs Outputs
Inputs = InputCount *NoteId
InputCount = Byte
Outputs = OutputCount *Note
OutputCount = Byte
Note = Value ZkPublicKey
Value = UINT64
NoteId = FieldElement

Op Proofs

OpsProofs = *OpProof ; 1. Lenth must equal OpCount
; 2. OpProof variant is derived from the corresponding Op.
; That is, type(OpProofs[i]) == ProofFor(Op[i])
OpProof = Ed25519SigProof /
ZkSigProof /
ZkAndEd25519SigsProof /
ProofOfClaimProof
Ed25519SigProof = Ed25519Signature
ZkSigProof = ZkSignature
ZkAndEd25519SigsProof = ZkSignature Ed25519Signature
ProofOfClaimProof = Groth16

Common Structures

; Zero-knowledge signature
ZkSignature = Groth16
; Cryptographic primitives
Groth16 = 128BYTE      ; pi_a (32) + pi_b (64) + pi_c (32)
ZkPublicKey = FieldElement
Ed25519PublicKey = 32BYTE
Ed25519Signature = 64BYTE
FieldElement = 32BYTE       ; BN254 field element (little-endian)
Hash32 = 32BYTE

    ; Primitive types
UINT64 = 8BYTE ; 64-bit unsigned integer, little-endian
UINT32 = 4BYTE ; 32-bit unsigned integer, little-endian
Byte = OCTET