Block Assembly

medium · bitcoin, mempool, fees

Block Assembly (Mempool Selection)

Assemble a block from a mempool using a simple policy:

  • Greedy by fee rate (fee / size).
  • Include a transaction only if all inputs are available.
  • Enforce a max block size.

Types

type Outpoint struct {
    TxID  [32]byte
    Index uint32
}

type Tx struct {
    ID       [32]byte
    Size     int
    Fee      uint64
    Inputs   []Outpoint
    Outputs  int
    Coinbase bool
    Reward   uint64 // for coinbase only
}

type UTXOSet map[Outpoint]bool

type Block struct {
    Txs       []Tx // coinbase must be first
    TotalFees uint64
    TotalSize int
}

func AssembleBlock(mempool []Tx, utxo UTXOSet, maxBlockSize int, subsidy uint64) Block

Rules

  • Sort mempool by fee rate (higher first). Tie-breakers: higher fee, then lexicographic ID bytes.
  • Start with TotalSize = CoinbaseSize (defined below).
  • A tx can be included if:
    • TotalSize + tx.Size <= maxBlockSize
    • all Inputs are in the current UTXO set (including outputs created by already-included txs).
  • When a tx is included, remove its spent inputs and add its new outputs: (tx.ID, output_index) for output_index in [0, Outputs).
  • Coinbase transaction:
    • CoinbaseSize = 100 bytes
    • Reward = subsidy + TotalFees
    • Coinbase=true, Fee=0, Inputs=nil, Outputs=1, ID=zero-hash

Notes

  • Inputs contain individually valid non-coinbase candidates with positive sizes, unique nonzero IDs, no duplicate input within one candidate, and nonnegative output counts fitting uint32. Candidates may conflict or depend on each other.
  • maxBlockSize >= 100. Size arithmetic fits int; subsidy plus all candidate fees fits uint64. Fee-rate cross-products may still exceed uint64.
  • Do not mutate the caller's mempool or UTXO set. Rejected candidates must consume no inputs, even if some of their inputs are available.
  • An outpoint is available exactly when utxo[outpoint] == true; a missing key or a false-valued entry is unavailable.
  • Transactions that fail the input or size checks are skipped (not retried).
  • Sort once and scan once. This policy is neither package-aware nor guaranteed to maximize fees. The generated coinbase output is not available to candidates.
  • Return a block with coinbase as the first transaction.
Run tests to see results
No issues detected
    Join Discord