Skip to content

Class BSV::Transaction::Beef

Inherits: Object

Background Evaluation Extended Format (BEEF) for SPV-ready transaction bundles. Encodes one or more transactions together with their merkle proofs (BUMPs), enabling recipients to verify inclusion without querying a block explorer.

Supports BRC-62 (V1), BRC-96 (V2), and BRC-95 (Atomic BEEF) formats.

@example Parse a BEEF bundle and find a transaction

beef = BSV::Transaction::Beef.from_hex(beef_hex)
tx = beef.find_transaction(txid_bytes)

Constants

Version constants

ATOMIC_BEEF

BRC-96

BEEF_V1

Version magic bytes as LE uint32 (matching pack('V') / unpack1('V')). Stream bytes: 01 00 BE EF / 02 00 BE EF / 01 01 01 01

BEEF_V2

BRC-62

Transaction format flags

FORMAT_RAW_TX

Raw transaction without a merkle proof.

FORMAT_RAW_TX_AND_BUMP

Raw transaction with an associated BUMP index.

FORMAT_TXID_ONLY

Only the transaction ID (no raw data).

Attributes

bumps [R]

  • @return [Array] merkle proofs (BUMPs) referenced by transactions

subject_txid [R]

  • @return [String, nil] 32-byte subject txid (Atomic BEEF only)

transactions [R]

  • @return [Array] the transactions in dependency order

txs_not_valid [R]

Returns transactions that could not be sorted due to cycles, or nil.

Populated by {#sort_transactions!} when cycles are detected (F5.5). - @return [Array, nil]

version [RW]

  • @return [Integer] BEEF version constant

Public Class Methods

from_binary(data)

Deserialise a BEEF bundle from binary data.

Supports V1 (BRC-62), V2 (BRC-96), and Atomic (BRC-95) formats. After parsing, input source transactions are wired automatically. - @param data [String] raw BEEF binary - @raise [ArgumentError] - @return [Beef] the parsed BEEF bundle

from_hex(hex)

Deserialise a BEEF bundle from a hex string. - @param hex [String] hex-encoded BEEF data - @return [Beef] the parsed BEEF bundle

Public Instance Methods

find_atomic_transaction(txid)

Find a transaction and recursively wire its ancestry (source transactions and merkle paths) for atomic proof validation. - @param txid [String] 32-byte txid in display byte order - @return [Transaction, nil] the transaction with full proof tree, or nil

find_bump(txid)

Find the merkle path (BUMP) for a transaction by its txid.

First checks the transaction-table entries, then scans @bumps directly for a BUMP whose level-0 leaves contain the txid. - @param txid [String] 32-byte txid in display byte order - @return [MerklePath, nil] the merkle path, or nil if not found

find_transaction(txid)

Find a transaction in the bundle by its transaction ID. - @param txid [String] 32-byte txid in display byte order - @return [Transaction, nil] the matching transaction, or nil

find_transaction_for_signing(txid)

Find a transaction with all source_transactions wired for signing. - @param txid [String] 32-byte txid in display byte order - @return [Transaction, nil] the transaction with wired inputs, or nil

initialize(version: = BEEF_V1, bumps: = [], transactions: = [])

  • @param version [Integer] BEEF version constant (default: BEEF_V1, matching to_binary's default for ARC compatibility; from_binary overwrites this with the parsed version)
  • @param bumps [Array] merkle proofs
  • @param transactions [Array] transaction entries
  • @return [Beef] a new instance of Beef

make_txid_only(txid)

Convert a transaction entry to TXID-only format. - @param txid [String] 32-byte txid in display byte order - @return [BeefTx, nil] the converted entry, or nil if not found

merge(other)

Merge all BUMPs and transactions from another BEEF bundle.

BUMP indices are remapped during merge. New BeefTx instances are constructed rather than sharing references with the source bundle (F5.9). - @param other [Beef] the BEEF bundle to merge from - @raise [ArgumentError] if a transaction in +other+ has a +bump_index+ that does not point to any BUMP in +other.bumps+ (i.e. the source bundle is internally inconsistent) - @return [self]

merge_bump(merkle_path)

Add or deduplicate a merkle path (BUMP) in this BEEF bundle.

If an existing BUMP shares the same block_height and merkle root, it is combined (via MerklePath#combine) and the existing index is returned. Otherwise the BUMP is appended.

After the BUMP is stored, any existing FORMAT_RAW_TX transactions whose txid appears in the new BUMP's level-0 leaves are retroactively upgraded to FORMAT_RAW_TX_AND_BUMP (F5.6). - @param merkle_path [MerklePath] the BUMP to merge - @return [Integer] the index of the (possibly merged) BUMP

merge_raw_tx(raw_bytes, bump_index: = nil)

Add a transaction from raw binary data.

If the transaction already exists, upgrades weaker entries to stronger formats when a raw tx or bump_index is now available (F5.7). - @param raw_bytes [String] raw transaction binary - @param bump_index [Integer, nil] optional BUMP index - @return [BeefTx] the new or upgraded BeefTx entry

merge_transaction(tx)

Add a transaction to this BEEF bundle.

Recursively merges the transaction's ancestors (via source_transaction references on inputs) and their merkle paths. Duplicate transactions (same txid) are upgraded if a stronger format is now available (F5.7): TXID_ONLY → RAW_TX or RAW_TX_AND_BUMP; RAW_TX → RAW_TX_AND_BUMP. - @param tx [Transaction] the transaction to merge - @return [BeefTx] the (possibly existing or upgraded) BeefTx entry

sort_transactions!()

Sort transactions in topological (dependency) order in place.

After sorting, every transaction's input ancestors appear before it in the array. This is required for correct BEEF serialisation.

Transactions that form a cycle (i.e. cannot be topologically sorted) are moved to +@txs_not_valid+ rather than being silently dropped (F5.5). - @return [self]

to_atomic_binary(subject_txid)

Serialise as Atomic BEEF (BRC-95), wrapping V2 data with a subject txid. - @param subject_txid [String] 32-byte subject transaction ID - @return [String] raw Atomic BEEF binary

to_atomic_hex(subject_txid)

Serialise as Atomic BEEF (BRC-95) hex string. - @param subject_txid [String] 32-byte subject transaction ID - @return [String] hex-encoded Atomic BEEF

to_binary(version: = BEEF_V1)

Serialise the BEEF bundle to binary format.

Defaults to V1 (BRC-62) for compatibility with ARC and the reference TS SDK. Pass +version: BEEF_V2+ for BRC-96 format. - @param version [Integer] BEEF_V1 (default) or BEEF_V2 - @raise [ArgumentError] if version is BEEF_V1 and the bundle contains any FORMAT_TXID_ONLY entries (V1 / BRC-62 has no TXID-only format; pass +version: BEEF_V2+ to serialise such bundles) - @return [String] raw BEEF binary

to_hex()

Serialise the BEEF bundle to a hex string.

Uses the bundle's own +@version+, so a BEEF parsed from V2 round-trips to V2 hex, and a BEEF parsed from V1 (or freshly constructed via the default constructor) round-trips to V1 hex. - @return [String] hex-encoded BEEF data

valid?(allow_txid_only: = false)

Check structural validity of the BEEF bundle.

A valid BEEF has every transaction either: * proven (has a BUMP / merkle_path), or * all its inputs reference transactions that are themselves valid within this bundle.

For FORMAT_RAW_TX_AND_BUMP entries, the BUMP linkage and computed root are also verified (F5.4). - @param allow_txid_only [Boolean] whether TXID-only entries count as valid (default: false) - @return [Boolean] true if structurally valid

verify(chain_tracker = nil, allow_txid_only: = false)

Verify the BEEF bundle against a chain tracker (SPV).

Calls {#valid?} first for structural checks, then optionally verifies each BUMP's computed merkle root against the chain tracker (F5.3). - @param chain_tracker [#valid_root_for_height?] optional chain tracker (see {ChainTracker}) that responds to +valid_root_for_height?(root_hex, block_height)+ - @param allow_txid_only [Boolean] passed to {#valid?} - @return [Boolean] true if the bundle is structurally valid and, when a chain tracker is provided, all BUMP roots are confirmed by the chain