bitcoin_wire/transaction

Deserialize, inspect, validate, and serialize Bitcoin transactions.

Types

A violation of Bitcoin consensus rules detected during transaction validation.

Each variant identifies a specific rule that the transaction breaks.

pub type ConsensusViolation {
  NoInputs
  NoOutputs
  BaseSizeLimitExceeded(Int)
  OutputValueOutOfRange(index: Int, value: OutputValue)
  TotalOutputValueOutOfRange(index: Int, total: Int)
  CoinbaseWithMultipleInputs
  InvalidCoinbaseScriptSigLength
  DuplicateInput(
    outpoint: OutPoint,
    first_index: Int,
    duplicate_index: Int,
  )
}

Constructors

  • NoInputs

    The transaction has no inputs.

    Every Bitcoin transaction must contain at least one input. Transactions with zero inputs are invalid under consensus rules.

  • NoOutputs

    The transaction has no outputs.

    Every Bitcoin transaction must contain at least one output. Transactions with zero outputs are invalid under consensus rules.

  • BaseSizeLimitExceeded(Int)

    The stripped transaction serialization exceeded Bitcoin Core’s context-independent transaction base-size limit.

    The contained value is the measured base size in bytes: version, CompactSize counts and script lengths, inputs, outputs, and lock time. The maximum is 1,000,000 bytes. SegWit marker, flag, and witness bytes are excluded from this transaction-level check but contribute to the separate 4,000,000-WU block-weight limit.

  • OutputValueOutOfRange(index: Int, value: OutputValue)

    An output value is outside the valid money range.

    Consensus requires each output value to satisfy:

    0 <= value <= 2,100,000,000,000,000 satoshis
    

    The upper bound is 21,000,000 BTC expressed in satoshis.

    The index field indicates the zero-based position of the output, and value preserves the invalid signed 64-bit amount exactly. Use output_value_to_string to display it without native integer limits.

  • TotalOutputValueOutOfRange(index: Int, total: Int)

    The cumulative sum of output values exceeds the valid money range.

    During validation, Bitcoin nodes maintain a running total of all output values and require that the cumulative sum never exceed 2,100,000,000,000,000 satoshis.

    The index field indicates the zero-based position of the output at which the running total first exceeded 2,100,000,000,000,000 satoshis.

    The total field is the cumulative output value at that point. Individual amounts are checked first, so the first excessive total is at most twice the maximum money amount and fits exactly in Int on both targets.

  • CoinbaseWithMultipleInputs

    A transaction identified as a coinbase transaction contains more than one input.

    A coinbase transaction is defined as a transaction whose single input has a null outpoint. Under consensus rules, such a transaction must contain exactly one input.

  • InvalidCoinbaseScriptSigLength

    A coinbase transaction’s scriptSig length is invalid.

    Coinbase scriptSig must be between 2 and 100 bytes (inclusive).

  • DuplicateInput(
      outpoint: OutPoint,
      first_index: Int,
      duplicate_index: Int,
    )

    The transaction contains duplicate inputs referencing the same outpoint.

    Each input in a transaction must reference a unique previous output.

    The outpoint field identifies the duplicated outpoint.

    The first_index field indicates the zero-based index of the first occurrence of this outpoint in the input list.

    The duplicate_index field indicates the zero-based index of the subsequent input that duplicates the same outpoint.

Phantom type indicating a transaction that has passed the context-free Bitcoin consensus checks performed by validate_context_free_consensus.

This does not indicate full transaction validity. Context-dependent checks such as script execution, signature verification, and UTXO lookup are not performed.

pub type ContextFreeValidated =
  @internal ContextFreeValidated

An error that occurred while decoding a Bitcoin transaction from bytes.

Carries the byte offset where the error occurred, the kind of error, and internal parser-location details used to build the public structural path.

pub opaque type DecodeError

The specific kind of error that occurred during transaction decoding.

Categorizes decode failures into distinct variants.

pub type DecodeErrorKind {
  NonByteAlignedInput(bit_count: Int)
  UnexpectedEof(bytes_needed: Int, remaining: Int)
  NonMinimalCompactSize(encoded_size: Int, value: Int)
  InvalidSegwitMarkerFlag(marker: Int, flag: Int)
  SuperfluousWitnessRecord
  InsufficientBytes(claimed: Int, remaining: Int)
  IntegerOutOfRange(String)
  PolicyLimitExceeded(
    limit: DecodePolicyLimit,
    value: Int,
    max: Int,
  )
  TrailingBytes(Int)
}

Constructors

  • NonByteAlignedInput(bit_count: Int)

    The input does not contain a whole number of bytes.

    Bitcoin wire-format inputs are byte-aligned. The wrapped value is the exact total number of bits in the supplied input.

  • UnexpectedEof(bytes_needed: Int, remaining: Int)

    The input ended before enough bytes could be read.

    Arguments

    bytes_needed

    The number of bytes the decoder required.

    remaining

    The number of bytes available at that point.

  • NonMinimalCompactSize(encoded_size: Int, value: Int)

    A CompactSize-encoded integer used a non-minimal encoding.

    Bitcoin’s serialization rules require CompactSize integers to use the shortest possible encoding. This error occurs when a value could have been encoded in fewer bytes than were used.

    Arguments

    encoded_size

    The size of the encoded CompactSize in bytes.

    value

    The decoded integer value.

  • InvalidSegwitMarkerFlag(marker: Int, flag: Int)

    The SegWit marker byte (0x00) was present but the flag byte was not 0x01.

    Arguments

    marker

    The marker byte.

    flag

    The invalid flag byte.

  • SuperfluousWitnessRecord

    SegWit serialization was used, but every input witness stack was empty.

    Transactions without witness data must use legacy serialization. A witness stack containing a zero-length item is nonempty and does not trigger this error.

  • InsufficientBytes(claimed: Int, remaining: Int)

    A length or count requires more bytes than remain in the input.

    Unlike UnexpectedEof, which reports a failed read, this error reports a decoded length or count that is known in advance not to fit in the remaining input. This is distinct from PolicyLimitExceeded, which enforces configured resource limits.

    Examples:

    • A scriptSig length claims a 100-byte script, but only 99 bytes remain.
    • An input count claims one input, whose smallest encoding is 41 bytes, but only 40 bytes remain.

    Arguments

    claimed

    The number of bytes required.

    This may be a conservative estimate, such as remaining + 1, rather than the exact requirement to avoid integer overflow on JavaScript.

    remaining

    The number of bytes available.

  • IntegerOutOfRange(String)

    A decoded 64-bit integer value exceeds the range representable by the runtime.

    The original value is preserved as a string for diagnostics.

  • PolicyLimitExceeded(
      limit: DecodePolicyLimit,
      value: Int,
      max: Int,
    )

    A policy limit was exceeded.

    Arguments

    limit

    The DecodePolicy limit that was violated.

    value

    The measured or decoded quantity that exceeded max.

    max

    The configured maximum.

  • TrailingBytes(Int)

    One transaction was successfully decoded, but extra bytes remain, so deserialization failed.

    This indicates the input buffer contains more data than a single valid transaction. The wrapped Int is the count of trailing bytes that were not consumed.

Configuration policy for transaction decoding limits.

This type controls byte and collection-count limits during transaction decoding. Callers can configure tighter limits to constrain work and allocation when decoding untrusted inputs.

Limits are enforced during decoding. If a limit is exceeded, decoding fails with PolicyLimitExceeded.

The limits complement one another: transaction size bounds the complete input buffer, while input, output, and total witness item count limits bound collection sizes as the transaction is decoded. See the corresponding decode_policy_with_* functions for enforcement details.

Builder functions do not validate whether custom limits are useful for decoding consensus-valid transactions. Callers that override default_decode_policy are responsible for choosing sensible values for their use case. Overly strict or unusual values may simply cause decoding to fail with existing decode errors.

See Also

  • default_decode_policy for the default decoding limits
  • deserialize_with_policy to apply a custom policy
pub opaque type DecodePolicy

Identifies the configured DecodePolicy limit that was exceeded.

Carried by PolicyLimitExceeded. Use get_decode_error_path to identify where the violation occurred.

pub type DecodePolicyLimit {
  MaxTransactionSize
  MaxInputCount
  MaxOutputCount
  MaxWitnessItemCount
}

Constructors

  • MaxTransactionSize

    The maximum input buffer size was exceeded.

    In PolicyLimitExceeded, value is the total byte size of the supplied buffer. This limit is checked before decoding begins.

  • MaxInputCount

    The maximum number of transaction inputs was exceeded.

  • MaxOutputCount

    The maximum number of transaction outputs was exceeded.

  • MaxWitnessItemCount

    The maximum total number of witness items across all input stacks was exceeded.

    In PolicyLimitExceeded, value is the cumulative item count through the current stack, including zero-length items. The error points to that stack’s item-count field, before any of its items are decoded.

An error that occurred while deserializing a Bitcoin transaction from hex.

Distinguishes invalid hexadecimal input from decode policy and transaction decoding failures.

pub type DeserializeHexError {
  InvalidHex
  DecodeFailed(DecodeError)
}

Constructors

  • InvalidHex

    The hexadecimal string could not be converted to bytes.

    This occurs before any transaction decoding begins, typically due to an odd-length hex string or the presence of invalid hexadecimal characters.

  • DecodeFailed(DecodeError)

    The input exceeded a decode policy limit or its decoded bytes were not a well-formed Bitcoin transaction encoding.

    A byte-size policy error can be returned before hex-to-bytes conversion. This wraps a DecodeError containing details about the failure.

A transaction input.

An input references a previous transaction output and provides the data required to satisfy that output’s spending conditions.

pub opaque type Input

Phantom type tag for ScriptBytes — marks bytes from an input’s scriptSig.

pub type InputScript

An outpoint carried by a transaction input.

For ordinary inputs, this identifies the output being spent. For coinbase inputs, it contains the null-outpoint marker and references no output.

pub opaque type OutPoint

A transaction output.

An output contains an encoded value and a raw scriptPubKey. Decoding alone does not establish that the value is within the consensus money range or that the script’s spending conditions can be satisfied.

pub opaque type Output

Phantom type tag for ScriptBytes — marks a scriptPubKey (output locking script).

pub type OutputScript

The recognised structural script type of a transaction output’s locking script.

Identifies which recognised Bitcoin script template a script_pubkey matches, enabling type-safe dispatch when inspecting outputs.

This type is intentionally classification-only. Its variants do not carry embedded script data such as hashes, public keys, witness programs, multisig parameters, or OP_RETURN payloads. Call get_raw_script_bytes when caller code needs to perform additional script-specific analysis.

pub type OutputScriptType {
  P2PK
  P2PKH
  P2SH
  P2WPKH
  P2WSH
  P2TR
  P2A
  BareMultisig
  NullData
  OtherWitnessProgram(version: Int)
  Unrecognized
}

Constructors

  • P2PK

    Pay-to-public-key template.

    Structurally matches a 33- or 65-byte key payload followed by OP_CHECKSIG. The classifier does not validate the public key encoding.

  • P2PKH

    Pay-to-public-key-hash.

    The most common legacy output type.

  • P2SH

    Pay-to-script-hash.

    The hash of the redeem script is embedded in the scriptPubKey. The actual spending conditions are revealed in the input’s scriptSig.

  • P2WPKH

    Pay-to-witness-public-key-hash.

    SegWit v0 output for single-key spends.

  • P2WSH

    Pay-to-witness-script-hash.

    SegWit v0 output for script-based spends.

  • P2TR

    Pay-to-taproot.

    SegWit v1 output supporting key-path and script-path spends.

  • P2A

    Bitcoin Core’s pay-to-anchor relay-policy template.

    Structurally matches exactly OP_1 OP_DATA_2 4E 73 (51 02 4E 73). Recognition is limited to Bitcoin Core’s named relay policy template; it does not introduce consensus validation.

  • BareMultisig

    Bare m-of-n multisig template using OP_CHECKMULTISIG directly in the scriptPubKey.

    Structurally matches 1–20 key payloads and 1–20 required signatures with minimally encoded counts. Key payloads may use direct, OP_PUSHDATA1, OP_PUSHDATA2, or OP_PUSHDATA4 pushes, provided their decoded sizes are 33 or 65 bytes. The classifier checks only the payload shape; it does not validate SEC prefixes or curve points. Relay-policy limits such as the 1–3-key standardness rule are outside this classification.

  • NullData

    A structurally recognized null-data output.

    This variant represents the null-data script template, not every script that begins with OP_RETURN.

    Matches scripts that begin with OP_RETURN and whose remaining bytes satisfy Bitcoin Core-compatible push-only parsing. For historical compatibility, this includes OP_RESERVED, even though executing that opcode fails. All encoded push operations must be complete. Script size does not affect classification.

    An OP_RETURN script with a non-push opcode or malformed push operation after OP_RETURN classifies as Unrecognized instead.

  • OtherWitnessProgram(version: Int)

    A well-formed witness program that is not one of this library’s named output types.

    version is the decoded witness version (1–16). Version 1 with a 32-byte witness program is P2TR, and the exact 51 02 4E 73 template is P2A, so neither appears here. A later valid witness-program assignment remains OtherWitnessProgram until a major release adds a dedicated constructor.

    Forward-compatible. Do not treat this the same as Unrecognized.

  • Unrecognized

    Does not match any recognised structural output template.

    This is the unmatched structural fallback, not a relay-policy decision.

A signed 64-bit output amount in satoshis, stored as exact wire bytes.

Every signed 64-bit value is preserved exactly on both Erlang and JavaScript targets, including negative amounts and amounts above Bitcoin’s consensus money range. This type does not establish consensus validity.

Use output_value_to_string or output_value_to_bytes_le for exact, portable representations, or output_value_to_int for a checked native integer conversion.

pub opaque type OutputValue

Phantom type indicating a transaction that has been successfully parsed from its canonical Bitcoin wire-format serialization but has not yet been validated against Bitcoin consensus rules.

pub type Parsed =
  @internal Parsed

Raw Bitcoin script bytes.

The kind type parameter is a phantom tag distinguishing input scripts (ScriptBytes(InputScript)) from output scripts (ScriptBytes(OutputScript)).

This type represents an uninterpreted script as it appears on the wire. No validation or opcode parsing is performed at this level.

pub opaque type ScriptBytes(kind)

A Bitcoin transaction.

A transaction transfers value by consuming previously created outputs (inputs) and creating new outputs. Transactions are either legacy (pre-SegWit) or SegWit, which affects whether witness data is present in the serialized structure.

pub opaque type Transaction(state)

A single item from a witness stack.

A witness item is an arbitrary byte sequence that may represent a public key, signature, script, or other data. Its meaning is context-dependent; this library does not interpret it.

pub opaque type WitnessItem

A witness stack for a single transaction input.

Each input in a SegWit transaction has an associated stack of byte sequences supplied as witness data. Their interpretation depends on the spending conditions. This library exposes the items without executing or validating them.

pub opaque type WitnessStack

Values

pub fn classify_output_script(
  script: ScriptBytes(OutputScript),
) -> OutputScriptType

Classify the script type of a transaction output’s locking script.

Matches script_pubkey bytes against recognised Bitcoin script templates and returns the corresponding OutputScriptType.

Classification is per-script and structural. It does not determine whether the containing transaction satisfies a node’s configurable relay policy. It also does not extract, decode, or interpret embedded hashes, public keys, witness programs, multisig parameters, signatures, or data payloads. For caller-specific script analysis, use get_raw_script_bytes on the original script.

Classification

├─ 76 A9 14 [×20] 88 AC                  → P2PKH
├─ A9 14 [×20] 87                        → P2SH
├─ 00 14 [×20]                           → P2WPKH
├─ 00 20 [×32]                           → P2WSH
├─ 51 20 [×32]                           → P2TR
├─ 51 02 4E 73                           → P2A
├─ 21 [×33] AC                           → P2PK (33-byte payload)
├─ 41 [×65] AC                           → P2PK (65-byte payload)
├─ 6A …                                  (OP_RETURN prefix)
│   ├─ complete push-only operations     → NullData
│   └─ otherwise                         → Unrecognized
└─ (none matched)
    ├─ [51–60] [02–28] [×push_length]    → OtherWitnessProgram(version)
    └─ structural m-of-n (1 ≤ m ≤ n ≤ 20, minimal counts)
        ├─ AND key-payload count = n     → BareMultisig
        └─ otherwise                     → Unrecognized

Example

fn wallet_supports_output(output: Output) -> Bool {
  case classify_output_script(get_output_script_pubkey(output)) {
    P2WPKH | P2TR -> True
    _ -> False
  }
}
pub fn compute_base_size(tx: Transaction(state)) -> Int

Compute the transaction’s BIP 141 base size in bytes.

This is the byte size of the complete canonical stripped serialization produced by serialize_stripped. For legacy transactions, it is identical to compute_total_size. For SegWit transactions, it excludes the marker, flag, and all witness stack bytes.

This calculation measures the existing transaction fields without allocating a serialized BitArray.

pub fn compute_total_size(tx: Transaction(state)) -> Int

Compute the transaction’s BIP 141 total size in bytes.

This is the byte size of the complete canonical wire serialization produced by serialize. For legacy transactions, it is identical to compute_base_size. For SegWit transactions, it also includes the marker, flag, and all witness stack bytes.

This calculation measures the existing transaction fields without allocating a serialized BitArray.

pub fn compute_txid(tx: Transaction(state)) -> hash256.Hash256

Compute the transaction identifier (txid) for a transaction.

The txid is the double SHA-256 hash of the transaction’s stripped serialization. The returned hash uses the same little-endian byte order found on the Bitcoin wire.

pub fn compute_virtual_size(tx: Transaction(state)) -> Int

Compute the transaction’s virtual size in virtual bytes (vbytes).

A virtual byte is four weight units. The result is the transaction’s BIP 141 weight divided by four and rounded up. For example, a transaction weighing 665 weight units has a virtual size of 167 vbytes.

This calculation does not allocate a serialized BitArray or enforce size or weight limits.

pub fn compute_weight(tx: Transaction(state)) -> Int

Compute the transaction’s BIP 141 weight in weight units.

Weight is calculated as base_size * 3 + total_size. Equivalently, each byte in the stripped serialization contributes four weight units and each byte present only in the complete serialization contributes one.

This calculation measures the existing transaction fields without allocating a serialized BitArray or measuring the base fields more than once.

This function only measures the transaction. It does not enforce the enclosing block’s consensus weight limit.

pub fn compute_wtxid(tx: Transaction(state)) -> hash256.Hash256

Compute the witness transaction identifier (wtxid) for a transaction.

The wtxid is the double SHA-256 hash of the transaction’s full wire serialization. The returned hash uses the same little-endian byte order found on the Bitcoin wire. For legacy transactions, the wtxid is identical to the txid.

pub fn decode_policy_max_input_count(policy: DecodePolicy) -> Int

Get the maximum transaction input count.

pub fn decode_policy_max_output_count(
  policy: DecodePolicy,
) -> Int

Get the maximum transaction output count.

pub fn decode_policy_max_tx_size(policy: DecodePolicy) -> Int

Get the maximum serialized transaction size.

pub fn decode_policy_max_witness_item_count(
  policy: DecodePolicy,
) -> Int

Get the maximum total witness item count across all input stacks.

pub fn decode_policy_with_max_input_count(
  policy: DecodePolicy,
  max_input_count: Int,
) -> DecodePolicy

Return a policy with a custom maximum transaction input count.

After the decoded count has been checked against the bytes remaining in the input, this limit is enforced before any input is decoded. It can bound input parsing and list allocation more tightly than the transaction-size limit alone.

pub fn decode_policy_with_max_output_count(
  policy: DecodePolicy,
  max_output_count: Int,
) -> DecodePolicy

Return a policy with a custom maximum transaction output count.

After the decoded count has been checked against the bytes remaining in the input, this limit is enforced before any output is decoded. It can bound output parsing and list allocation more tightly than the transaction-size limit alone.

pub fn decode_policy_with_max_tx_size(
  policy: DecodePolicy,
  max_tx_size: Int,
) -> DecodePolicy

Return a policy with a custom maximum serialized transaction size.

For byte-aligned input, this limit is checked before whole-value decoding begins and provides its primary byte envelope. It is not applied when a transaction is decoded as a prefix inside a block; the enclosing block policy owns that byte envelope.

pub fn decode_policy_with_max_witness_item_count(
  policy: DecodePolicy,
  max_witness_item_count: Int,
) -> DecodePolicy

Return a policy with a custom maximum total witness item count.

This limit counts items across all input stacks in one transaction, including zero-length items. After each stack’s count has been checked against the bytes remaining, its contribution to the cumulative count is checked before any of its items are decoded. Empty stacks contribute zero items.

pub fn default_decode_policy() -> DecodePolicy

The default transaction decoding policy.

Provides permissive limits, applied automatically when using deserialize or deserialize_hex. They indirectly bound heap usage during binary decoding by limiting serialized size and collection counts. Callers with stricter resource budgets can configure lower limits.

By default, whole-value decoding accepts serialized transactions up to 4,000,000 bytes, up to 100,000 inputs, up to 125,000 outputs, and up to 4,000,000 witness items in total across all input stacks, including zero-length items.

These defaults cover canonical encodings of consensus-valid transactions within Bitcoin’s 4,000,000-weight-unit block limit. Consensus validation is separate.

pub fn deserialize(
  bytes: BitArray,
) -> Result(Transaction(Parsed), DecodeError)

Deserialize a Bitcoin transaction from its canonical Bitcoin wire-format serialization.

This is the standard entry point for converting a complete serialized Bitcoin transaction into a typed value. The entire input must contain exactly one transaction; trailing bytes are rejected.

This function applies the permissive default_decode_policy limits on transaction size, input/output counts, and total witness item count.

For custom resource limits, use deserialize_with_policy instead.

The returned transaction is marked as Parsed, meaning its structure was successfully parsed but it has not yet been checked against Bitcoin consensus rules.

Returns

  • Ok(Transaction(Parsed)): Successfully deserialized within the default policy limits.
  • Error(DecodeError): The bytes were not a well-formed transaction encoding within the default policy limits.
pub fn deserialize_hex(
  hex: String,
) -> Result(Transaction(Parsed), DeserializeHexError)

Deserialize a Bitcoin transaction from its hexadecimal string representation.

This is a convenience function that combines hex-to-bytes conversion with transaction deserialization. It’s useful when working with transaction data in hexadecimal format, such as from block explorers, RPC responses, or test vectors.

This function applies default_decode_policy for resource limits. For custom resource limits, use deserialize_hex_with_policy instead.

Valid hex that exceeds the byte-size limit is rejected before conversion. Invalid hex takes precedence, including for oversized input. Checking an oversized string’s characters still requires work proportional to its length.

Returns

  • Ok(Transaction(Parsed)): Successfully deserialized within the default policy limits.
  • Error(InvalidHex): The hex string was invalid (odd length or invalid characters).
  • Error(DecodeFailed(error)): The decoded bytes were not a well-formed transaction encoding within the default policy limits.
pub fn deserialize_hex_with_policy(
  hex: String,
  policy: DecodePolicy,
) -> Result(Transaction(Parsed), DeserializeHexError)

Deserialize a Bitcoin transaction from hexadecimal with custom resource limits.

This function combines hex-to-bytes conversion with policy-based transaction deserialization, providing both the convenience of hexadecimal input and fine-grained control over resource limits. Use this when working with hex-encoded transaction data that requires custom resource constraints.

Valid hex that exceeds the byte-size limit is rejected before conversion. Invalid hex takes precedence, including for oversized input. Checking an oversized string’s characters still requires work proportional to its length.

Returns

  • Ok(Transaction(Parsed)): Successfully deserialized within the supplied policy limits.
  • Error(InvalidHex): The hex string was invalid (odd length or invalid characters).
  • Error(DecodeFailed(error)): The decoded bytes were not a well-formed transaction encoding within the supplied policy limits.
pub fn deserialize_with_policy(
  bytes: BitArray,
  policy: DecodePolicy,
) -> Result(Transaction(Parsed), DecodeError)

Deserialize a Bitcoin transaction with custom resource limits.

Like deserialize, but accepts a DecodePolicy to override the resource limits applied during decoding. Use default_decode_policy and the decode_policy_with_* builder functions to construct custom policies. Byte alignment is validated before resource limits. For byte-aligned inputs, limits that are exceeded produce a PolicyLimitExceeded error. See DecodePolicy and default_decode_policy for available options and defaults.

Returns

  • Ok(Transaction(Parsed)): Successfully deserialized within the supplied policy limits.
  • Error(DecodeError): The bytes were not a well-formed transaction encoding within the supplied policy limits.
pub fn get_decode_error_kind(err: DecodeError) -> DecodeErrorKind

Get the specific kind of decoding error that occurred.

Returns the DecodeErrorKind variant that categorizes what went wrong, such as UnexpectedEof, NonMinimalCompactSize, PolicyLimitExceeded, etc. This allows you to handle different error types differently.

Example

fn is_truncated(error: DecodeError) -> Bool {
  case get_decode_error_kind(error) {
    UnexpectedEof(_, _) -> True
    InsufficientBytes(_, _) -> True
    _ -> False
  }
}
pub fn get_decode_error_offset(err: DecodeError) -> Int

Get the byte offset where a decoding error occurred.

The offset is a zero-based position into the input buffer, indicating where the decoder was reading when it encountered the error. This is useful for debugging and error reporting.

pub fn get_decode_error_path(err: DecodeError) -> String

Get the structural path for a decoding error.

The path is derived from internal parser-location details and uses a stable, machine-friendly format rooted at transaction. Collection indices are zero-based and written in brackets.

For example, an error at the scriptSig length prefix of the third input produces transaction.inputs[2].script_sig.length.

The path identifies where the error occurred but does not include the byte offset or error kind. Use get_decode_error_offset and get_decode_error_kind for those details.

pub fn get_input_count(tx: Transaction(state)) -> Int

Get the number of inputs in a transaction.

Returns the decoded CompactSize input count from the transaction wire encoding.

pub fn get_input_outpoint(input: Input) -> OutPoint

Get the outpoint from an input.

pub fn get_input_script_sig(
  input: Input,
) -> ScriptBytes(InputScript)

Get the scriptSig from an input.

For non-coinbase inputs, the scriptSig may provide data used during script execution. This library does not execute or validate scripts.

pub fn get_input_sequence(input: Input) -> Int

Get the sequence number from an input.

Sequence values can participate in relative lock-time consensus rules and transaction replacement policy. This library exposes the value without interpreting those semantics.

pub fn get_inputs(tx: Transaction(state)) -> List(Input)

Get the transaction inputs.

Returns the inputs in the same order they appear in the transaction serialization.

pub fn get_lock_time(tx: Transaction(state)) -> Int

Get the unsigned 32-bit lock-time value from a transaction.

Values less than 500,000,000 encode block heights, values greater than or equal to 500,000,000 encode Unix timestamps, and zero encodes no lock-time constraint.

Whether this value constrains transaction finality also depends on the input sequence numbers and block context. This library exposes the value without evaluating finality.

pub fn get_outpoint_txid(outpoint: OutPoint) -> hash256.Hash256

Get the transaction ID from an outpoint.

The hash uses the same little-endian byte order found on the Bitcoin wire. For coinbase inputs, which do not reference a previous output, this returns an all-zero hash.

pub fn get_outpoint_vout(outpoint: OutPoint) -> Int

Get the output index from an outpoint.

Returns the zero-based index of the output within the referenced transaction. For coinbase inputs (which don’t reference a previous output), returns 0xFFFFFFFF, a special sentinel value indicating no previous output.

pub fn get_output_count(tx: Transaction(state)) -> Int

Get the number of outputs in a transaction.

Returns the decoded CompactSize output count from the transaction wire encoding.

pub fn get_output_script_pubkey(
  output: Output,
) -> ScriptBytes(OutputScript)

Get the raw scriptPubKey from a transaction output.

A scriptPubKey encodes the conditions for spending an output. This library exposes the script bytes without executing or validating them.

pub fn get_output_value(output: Output) -> OutputValue

Get the decoded value from a transaction output.

For an output from a Transaction(Parsed), this value may be negative or exceed Bitcoin’s consensus money range. Use validate_context_free_consensus to check the transaction’s output values.

pub fn get_outputs(tx: Transaction(state)) -> List(Output)

Get the transaction outputs.

Returns the outputs in the same order they appear in the transaction serialization.

pub fn get_raw_script_bytes(script: ScriptBytes(k)) -> BitArray

Get the raw bytes from a ScriptBytes.

pub fn get_script_size(script: ScriptBytes(k)) -> Int

Get the byte size of a ScriptBytes.

The size is measured from the raw script bytes and excludes the CompactSize length prefix used when the script is serialized in a transaction.

pub fn get_version(tx: Transaction(state)) -> Int

Get the transaction version.

The version may affect which consensus rules or transaction semantics apply.

The version field is encoded as 4 little-endian bytes in the transaction wire format. This function returns those bytes interpreted as an unsigned 32-bit integer in the range 0 through 4_294_967_295.

Some Bitcoin documentation and APIs have represented this field as a signed 32-bit integer. This function does not use that convention.

For example, raw version bytes ff ff ff ff are returned as 4_294_967_295, not -1.

pub fn get_witness_item_bytes(item: WitnessItem) -> BitArray

Get the raw bytes from a witness item.

pub fn get_witness_items(
  stack: WitnessStack,
) -> List(WitnessItem)

Get the witness items from a witness stack.

Returns the witness items in order as they appear in the serialization.

pub fn get_witnesses(
  tx: Transaction(state),
) -> Result(List(WitnessStack), Nil)

Get the witness stacks from a SegWit transaction.

For SegWit transactions, the witness stacks are returned in order, corresponding 1-to-1 with the transaction inputs by position.

Returns

  • Ok(witnesses): The transaction uses SegWit serialization.
  • Error(Nil): The transaction uses legacy serialization, which does not contain witness data.
pub fn has_coinbase_shape(
  tx: Transaction(ContextFreeValidated),
) -> Bool

Check whether a context-free-validated transaction has coinbase shape.

The ContextFreeValidated state guarantees that transaction-local consensus checks have already been applied. For this function, True means the transaction has the context-free coinbase structure:

  • exactly one input
  • the input uses the null outpoint
  • the coinbase scriptSig length is within the consensus range

This does not prove that the transaction is valid as the coinbase transaction of a block. Block-level checks such as transaction position, block height, subsidy, and fees are outside the scope of this function.

Returns True if the transaction has coinbase shape, False otherwise.

pub fn input_has_null_outpoint(input: Input) -> Bool

Check whether an input contains the null outpoint.

The null outpoint is the structural coinbase input marker. This function does not establish that the containing transaction has valid coinbase shape. Use validate_context_free_consensus followed by has_coinbase_shape for that guarantee.

pub fn is_null_outpoint(outpoint: OutPoint) -> Bool

Check whether an outpoint is the null outpoint.

The null outpoint is the special previous output reference used as the coinbase input marker: an all-zero txid with vout 0xFFFFFFFF.

pub fn is_segwit(tx: Transaction(state)) -> Bool

Check whether a transaction uses the SegWit format.

SegWit (Segregated Witness) transactions separate witness data from the main transaction structure, enabling features like improved scalability and transaction malleability fixes.

Returns True for SegWit transactions, False for legacy transactions.

pub fn is_witness_stack_empty(stack: WitnessStack) -> Bool

Check whether a witness stack contains no items.

A stack containing a zero-length item is not empty. Emptiness refers to the number of items, not the number of bytes contained in those items.

pub fn output_value_to_bytes_le(value: OutputValue) -> BitArray

Return an output amount’s exact eight bytes in little-endian wire order.

pub fn output_value_to_int(
  value: OutputValue,
) -> Result(Int, Nil)

Attempt to convert an output amount to a native integer.

Always succeeds on the Erlang target. On the JavaScript target, succeeds only within the safe integer range -9_007_199_254_740_991 through 9_007_199_254_740_991, inclusive; otherwise returns Error(Nil) without rounding the amount.

This conversion does not check Bitcoin’s consensus money range. Output amounts from a transaction that passed validate_context_free_consensus are guaranteed to convert successfully on both targets.

pub fn output_value_to_string(value: OutputValue) -> String

Return an output amount’s exact signed base-10 representation.

This preserves the full value on both Erlang and JavaScript targets, including amounts outside Bitcoin’s consensus money range.

pub fn serialize(tx: Transaction(state)) -> BitArray

Serialize a transaction in its full wire form, including witness data.

Returns the complete serialization used when computing the wtxid: version, SegWit marker and flag (if applicable), inputs, outputs, witness stacks (if applicable), and lock_time. For legacy transactions, this is identical to serialize_stripped.

See Also

  • compute_wtxid — hashes this serialization to produce the wtxid
  • serialize_stripped — the no-witness serialization used for the txid
pub fn serialize_stripped(tx: Transaction(state)) -> BitArray

Serialize a transaction without witness data (the “stripped” form).

Returns the stripped transaction serialization used when computing the txid: version, inputs, outputs, and lock_time — with no SegWit marker, flag, or witness stacks, regardless of whether the transaction is SegWit.

See Also

  • compute_txid — hashes this serialization to produce the txid
  • serialize — the full wire serialization including witness data
pub fn validate_context_free_consensus(
  tx: Transaction(Parsed),
) -> Result(
  Transaction(ContextFreeValidated),
  List(ConsensusViolation),
)

Validate a transaction against context-free Bitcoin consensus rules.

“Context-free” means these checks require only the transaction itself — no UTXO set, no block context, and no knowledge of other transactions.

This function enforces all Bitcoin consensus rules that apply to an individual transaction and can be evaluated without UTXO, script-execution, block, or chain context.

The following consensus rules are enforced:

  • At least one input
  • At least one output
  • Base (stripped) serialization is at most 1,000,000 bytes, matching Bitcoin Core’s transaction-level check. SegWit marker, flag, and witness bytes are excluded from this check but contribute to the enclosing block’s separate 4,000,000-WU weight limit.
  • Output values are between 0 and 2,100,000,000,000,000 satoshis
  • Cumulative output value does not exceed 2,100,000,000,000,000 satoshis
  • Coinbase transactions contain exactly one input
  • Coinbase scriptSig length is 2–100 bytes (inclusive)
  • No two inputs reference the same previous output

Context-dependent checks — script execution, signature verification, input-spend validation against the UTXO set, and block-level rules — are not performed.

Returns

  • Ok(Transaction(ContextFreeValidated)): The transaction passed all context-free consensus checks listed above.
  • Error(violations): The transaction failed one or more context-free consensus checks. The list contains the detected violations.
✨ Search Document