Kaspalytics Learn is under (heavy) construction. Check back regularly!
Updated: Aug 4, 2026

Transaction Model

The objects a Kaspa transaction is built from - the transaction itself, its inputs and outputs, the outpoint, the locking script, and the coin record a node has to supply from its own state.

The pages before this one described what a transaction does. This one describes what it is made of: a small set of nested objects, each with a fixed list of fields and nothing else.

Four objects, nested

A transaction is not a flat record. It is one object holding two arrays, and the entries in those arrays hold objects of their own.

Transaction
├─ version, lockTime, subnetworkId, gas, payload
├─ inputs[]
│   └─ Input
│       ├─ previousOutpoint  →  { transactionId, index }
│       ├─ signatureScript
│       ├─ sequence
│       └─ computeCommit
└─ outputs[]
    └─ Output
        ├─ value
        ├─ scriptPublicKey  →  { version, script }
        └─ covenant         →  { authorizingInput, covenantId }   (optional)

That is the whole model. Everything a wallet shows you that is not in this tree - the fee, the sender, the amount an input is worth, the balance - is either computed from it or fetched from somewhere else.

The transaction

Seven fields wrap the two arrays.

FieldHoldsWhy it exists
version0 or 1Selects which field set inputs and outputs use. See below.
inputsarray of InputThe coins being spent. A non-coinbase transaction with none is rejected outright.
outputsarray of OutputThe coins being created.
lockTimeu64The earliest point the transaction may be included. Zero means immediately.
subnetworkId20 bytesAll zeros for an ordinary transaction. A reserved value marks the coinbase.
gasu64Zero for an ordinary transaction. Carries the gas commitment on a subnetwork transaction.
payloadbytesArbitrary data, empty by default, opened to ordinary transactions at Crescendo.

A plain payment sets three of them. Version zero, the inputs, the outputs. Lock time stays zero, the subnetwork id stays all zeros, gas stays zero, and the payload stays empty - so the four fields that look most exotic are the four an ordinary wallet never touches.

Lock time is worth one more sentence, because it is two things sharing a field. Below five hundred billion the value is read as a minimum DAA score; at or above it, as a Unix timestamp in milliseconds. The threshold is far past any block count the network will reach and far before any plausible timestamp, so the two ranges cannot collide.

An input names a coin, it does not contain it

This is the single most important thing about the model.

FieldHoldsWhy it exists
previousOutpointoutpointWhich coin is being spent.
signatureScriptbytesThe proof that spending it is allowed - signatures, and for pay-to-script-hash the redeem script too.
sequenceu64Relative lock time, and the finality flag. See below.
computeCommitenumHow much script execution this input is paying for.

The outpoint is two fields and nothing more:

FieldHolds
transactionId32 bytes - the transaction that created the coin
indexu32 - which of that transaction’s outputs it was

Notice what is absent: the amount. An input says that coin, not this much. The value being spent appears nowhere in the transaction, which means a transaction on its own cannot be checked. Somebody has to look the coin up.

Sequence carries two meanings in one number. The top bit is a disable flag; when it is set, the input has no relative lock. When it is clear, the low thirty-two bits are a number of blocks that must have passed since the coin’s own DAA score before the input may be spent. Separately, if every input is set to the maximum value - which has that top bit set - the transaction counts as final and its lock time no longer holds it back.

The compute commitment is one of two variants, and the transaction version decides which:

VariantTypeUsed by
sigOpCountu8Version 0
computeBudgetu16Version 1

Both resolve to the same thing - an allowance of script units for that input, on top of a small free budget every input gets. A sigop count says “this input checks N signatures”. A compute budget prices arbitrary execution directly, which is what a covenant or a proof verification needs.

An output is an amount and a lock

FieldHoldsWhy it exists
valueu64The amount, in sompi. Integers only; KAS is a display convention.
scriptPublicKeystructThe condition for spending the coin next.
covenantoptionalThe output’s covenant binding. Version 1 only.

The locking script is versioned, though only one version exists so far:

FieldHolds
versionu16 - zero is the only value consensus accepts today
scriptbytes - decoded from the recipient’s address

And a covenant binding, when present, is also two fields:

FieldHolds
authorizingInputu16 - the index of the input that permitted this output
covenantId32 bytes - the lineage the output belongs to

Which lock types are actually in circulation is charted at output script classes.

The coin record a node supplies

Because an input is only a pointer, validating a transaction means pairing every input with the coin it names. That coin is its own object, held in the node’s UTXO set rather than in the transaction:

FieldHoldsUsed for
amountu64The value being spent. This is where the fee arithmetic gets its inputs.
scriptPublicKeystructThe lock the signature script has to satisfy.
blockDaaScoreu64When the coin was created - the baseline for relative locks and for maturity.
isCoinbaseboolWhether the longer coinbase maturity rule applies.
covenantIdoptionalThe lineage the coin carries, checked against the covenant rules on spend.

Validation is a join between a transaction and a state. The transaction brings pointers and proofs, the node brings the coins, and a transaction paired with its coins is what the rules actually run against.

Two practical consequences follow. A wallet cannot build a transaction without first fetching its own coins - that is what getUtxosByAddresses is for, and why the node serving it needs the UTXO index switched on. And a node that has never seen the parent transaction cannot judge the child at all, which is exactly the situation the orphan pool exists to hold.

What is computed rather than stored

ValueWhere it comes from
Transaction idA hash over the transaction with signature scripts and payload left out, so the id is settled before anyone signs.
Transaction hashA hash over everything, signatures included.
FeeThe gap: total input value minus total output value. See Fees & Mass.
Compute massDerived from the size and the compute commitments.
Transient massDerived from serialized size.
Storage massDerived from the input and output amounts.

Storage mass is the one exception to the heading. The transaction carries a commitment to it, and consensus recalculates the figure and rejects the transaction if the two disagree - so it is stored and computed, and the stored copy is only ever a claim being checked. The SDKs fill it in; it is not a field you set.

The two versions

VersionEnables
0The original layout. Inputs commit a sigop count; outputs have no covenant field.
1Covenant bindings on outputs, compute budgets on inputs, non-native subnetworks, gas commitments. Arrived with Toccata.

The two are not mixable. A version 0 transaction cannot carry a covenant binding, and a version 1 transaction commits compute per input rather than counting signature operations. Version 0 stays valid indefinitely, so an ordinary payment needs nothing from the second row.

See Also: UTXO Model, Fees & Mass

Kaspalytics strives to provide accurate data - our highest level of effort is given to data validation and maintenance. However, we cannot guarantee 100% accuracy. Data is subject to inaccuracies and change.

Contact | © 2026 Kaspalytics