As defined in rusty-kaspa (consensus/core/src/tx.rs).
Two transaction versions
Since the Toccata hardfork two transaction versions are valid, and the version selects which of two mutually exclusive field sets an input and output use:
| Version | Constant | What it enables |
|---|---|---|
0 | TX_VERSION | The original layout. Inputs commit to a sig_op_count; outputs have no covenant binding. |
1 | TX_VERSION_TOCCATA | Output covenant bindings, input compute-budget mass, non-native (non-coinbase) subnetworks — “user lanes” — and gas commitments. |
Version 0 remains valid, so an ordinary payment needs nothing from this list. You need version 1 the moment you want a covenant binding on an output, or a script whose execution cost exceeds what a sigop count can express.
Transaction
| Field | Type | Notes |
|---|---|---|
version | u16 | 0 or 1 — see above. |
inputs | array | See Input. |
outputs | array | See Output. |
lock_time | u64 | Earliest point of inclusion: 0 = immediate; below 500 billion (LOCK_TIME_THRESHOLD) = minimum DAA score; 500 billion and above = minimum Unix timestamp (ms). |
subnetwork_id | 20 bytes | All zeros for native transactions; a reserved subnetwork id marks coinbase transactions. Version 1 additionally permits non-native, non-coinbase subnetworks (user lanes). |
gas | u64 | 0 for native transactions. Carries the gas commitment for a version 1 subnetwork transaction. |
payload | bytes | Arbitrary data field. Empty pre-Crescendo; enabled for native transactions since the Crescendo hardfork. |
A transaction also carries a commitment to its storage mass (KIP-9) alongside a cached transaction id. Neither is a field you set directly — the SDKs fill them.
Input
| Field | Type | Notes |
|---|---|---|
previous_outpoint | outpoint | The UTXO being spent: transaction_id (32 bytes) + index (u32) of the output in that transaction. |
signature_script | bytes | Unlocking script - data pushes of signatures/data (and for P2SH, the redeem script). |
sequence | u64 | Sequence number (relative lock-time semantics). |
compute_commit | enum | The input’s compute mass commitment. See below. |
compute_commit replaced the old standalone sig_op_count field at Toccata. It is one of two variants, and which one is required follows from the transaction version:
| Variant | Payload | Used by |
|---|---|---|
SigopCount | u8 | Version 0 transactions |
ComputeBudget | u16 | Version 1 transactions |
Both resolve to a script unit allowance for that input, plus a small free per-input budget. A sigop count expresses “this input performs N signature checks”; a compute budget prices arbitrary script execution directly, which is what covenant and ZK scripts need.
The SDK surfaces still expose sig_op_count and add compute_budget beside it — in the Python SDK, for example, TransactionInput(..., sig_op_count=1, compute_budget=0). Set the one matching your transaction version.
Output
| Field | Type | Notes |
|---|---|---|
value | u64 | Amount in sompi. |
script_public_key | struct | Locking script: version (u16) + script (bytes). Decoded from the recipient’s address. |
covenant | optional | The output’s covenant binding, or absent. Version 1 only. |
A covenant binding carries two fields:
| Field | Type | Notes |
|---|---|---|
authorizing_input | u16 | Index of the input that authorizes this output’s creation. |
covenant_id | 32 bytes | The covenant lineage the output belongs to. |
Consensus derives the id itself on genesis and checks inheritance on continuation — see Covenant IDs & Bindings.
Notes
- The fee is not a field - it’s implicit:
sum(input values) - sum(output values). - A transaction’s mass (compute / storage / transient, in grams) is calculated from these fields; RPC representations return it alongside the transaction. See Units.
- Mixing versions is not a thing: a version 0 transaction cannot carry covenant bindings or compute budgets, and a version 1 transaction commits compute per input rather than sigops.
- The transaction ID is a hash over the transaction with the signature scripts and payload zeroed/excluded, so the ID is stable while signatures are added (this is what makes PSKT workflows possible). The transaction hash covers everything.
- Signing: the default scheme is Schnorr over secp256k1, with a blake2b-256 sighash keyed with the domain
TransactionSigningHash. ECDSA is also supported (see address versions).