NetworksRelease VersioningOffline transaction signingGlossary
Hardfork Update Process

Maximizing Transaction Size

Each spend, output, mint, and burn in an Iron Fish transaction increases its size. The maximum size of a transaction is the maximum size of a block minus the size of the block's header and miner's fee transaction.

This example creates a maximum-size transaction. In practice, you may want to specify which notes are spent in the transaction to maximize the number of outputs and set a lower transaction size limit to avoid competing for block space with other transactions.

import { Asset } from '@ironfish/rust-nodejs'
import {
  CreateTransactionRequest,
  CurrencyUtils,
  IronfishSdk,
  RawTransactionSerde,
  NoteEncrypted,
  Verifier,
} from '@ironfish/sdk'

async function main(): Promise<void> {
  const sdk = await IronfishSdk.init({ dataDir: '~/.dev0' })
  const client = await sdk.connectRpc()

  // Fetch an account
  const defaultAccountResponse = await client.wallet.getDefaultAccount()
  if (defaultAccountResponse.content.account === null) {
    throw new Error('Expected a default account')
  }

  const accountName = defaultAccountResponse.content.account.name

  const accountResponse = await client.wallet.getAccountPublicKey({
    account: accountName,
  })

  const publicAddress = accountResponse.content.publicKey

  // Proof size is 192 bytes
  const BYTES_PER_OUTPUT = NoteEncrypted.size + 192

  // Get the max transaction size from the node
  const consensusParams = await client.chain.getConsensusParameters()
  const maxTransactionSizeBytes = Verifier.getMaxTransactionBytes(consensusParams.content.maxBlockSizeBytes)
  console.log('Max transaction size (bytes):', maxTransactionSizeBytes)

  // Create some example outputs
  let numOfOutputs = Math.floor(maxTransactionSizeBytes / BYTES_PER_OUTPUT)
  console.log('Rough estimate of how many outputs can fit in a transaction:', numOfOutputs)

  const outputs: CreateTransactionRequest['outputs'] = []
  for (let i = 0; i < numOfOutputs; i++) {
    outputs.push({
      publicAddress,
      amount: CurrencyUtils.encode(1n),
      memo: 'test',
      assetId: Asset.nativeId().toString('hex'),
    })
  }

  // Recreate the raw transaction until it fits in the block
  let bytes = Infinity
  let spends = Infinity
  while (bytes > maxTransactionSizeBytes) {
    console.log(`Calculating size of transaction with ${numOfOutputs} outputs...`)

    const options: CreateTransactionRequest = {
      outputs: outputs.slice(0, numOfOutputs),
      account: accountName,
      feeRate: '200',
    }

    const response = await client.wallet.createTransaction(options)
    const rawTransaction = RawTransactionSerde.deserialize(
      Buffer.from(response.content.transaction, 'hex'),
    )
    bytes = rawTransaction.size()
    spends = rawTransaction.spends.length

    numOfOutputs--
  }

  console.log(
    `Fit ${numOfOutputs} outputs in a transaction with ${spends} spends. Transaction size (bytes): ${bytes}`,
  )
}

Join our newsletter and stay up to date with privacy and crypto.

Discover our impactful presence — read our blog.

Learn

  • FAQ
  • Whitepaper
  • Tokenomics

Use

  • Get Started
  • Node App
  • Mine
  • Block Explorer
  • Ecosystem

Developers

  • Documentation
  • Github

Community

  • Foundation
  • Governance
  • Grants
  • Our Community

Company

  • About Us
  • Media Kit
  • Contact Us
Privacy Policy

|

Copyright 2024 Iron Fish.