# Transaction Chaining in Neptune Cash

**URL:** <https://talk.neptune.cash/t/transaction-chaining-in-neptune-cash/349>\
**Category:** Blockchain Architecture\
**Created:** [July 16, 2026, 7:27pm UTC](https://talk.neptune.cash/t/transaction-chaining-in-neptune-cash/349 "2026-07-16T19:27:04Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![aszepieniec](https://talk.neptune.cash/user_avatar/talk.neptune.cash/aszepieniec/32/5_2.png) [@aszepieniec](https://talk.neptune.cash/u/aszepieniec)\
**Post date:** [July 16, 2026, 7:27pm UTC](https://talk.neptune.cash/t/transaction-chaining-in-neptune-cash/349/1 "2026-07-16T19:27:04Z")

</div>

_Transaction chaining_ refers to the process of merging transactions that have a predecessor-successor relationship, meaning that some of the outputs of the predecessor are being spent as inputs by the successor. _Cut-through_ is the process of removing those edges from the resulting transaction.

Neptune Cash does not presently support transaction chaining. Every transaction must spend _confirmed_ inputs only. You simply cannot construct a transaction that spends the outputs of another transaction if that other transaction has not been confirmed yet. Mergers are allowed only if the two operands spend disjoint sets of UTXOs.

With an eye to decentralized finance, the inability to chain transactions is a particularly irksome limitation. It means that every block can support at most one interaction with a self-perpetuating UTXO (also known as smart contract). The name-giving output of that self-perpetuating UTXO, which contains the smart contract’s updated state, cannot be spent before it is confirmed. Phrased crudely, you get an on-chain uniswap throughput capped at one trade per block.

This post proposes a change to the transaction initiation pipeline in order to enable transaction chaining. Along the way, another irksome limitation of the current transaction initiation pipeline is fixed: the _relatively high cost of the `Raise` operation_ which is what sends `ProofCollection`-backed transaction to a `SingleProof`-backed one.

> **Note:** I wrote this note completely unaware that I had written [a similar one only half a year ago](https://talk.neptune.cash/t/proposal-transaction-chaining-in-neptune-cash/207). I decided not to merge the two in order to benefit from independent perspectives. Before proceeding with an implementation, it’s probably worth cross-comparing and weighing the differences and noting the similarities.

## Dual Pipeline

Duplicate the transaction initiation pipeline. On the left lives the existing pipeline consisting of `PrimitiveWitness`, `TransactionKernel`, `SingleProof`, _etc._ On the right lives a mirror image up to new names and up to one important new addition: the _unconfirmed inputs that are being spent_ – for want of a better term, _thruputs_.

Thruputs are functionally equivalent to inputs in the sense of balancing a transaction. However, since they represent unconfirmed transactions, their `RemovalRecord`s are not known yet. And so the type of this field is _vector of `AdditionRecord`s_. When chainable transactions are chained, the operation goes through only if all thruputs of the successor are outputs of the predecessor, and the result eliminates those UTXOs altogether.

To accommodate this new field, a new kernel data structure is required: `LinkKernel`, which is the same as `TransactionKernel` except for the new field `thruputs: Vec<AdditionRecord>`. Likewise, the `Transaction` structure gets a chaining counterpart called `LinkTx` whose fields are `kernel: LinkKernel` and `proof: Proof`.

Whereas regular `Transaction`s have three stages (`PrimitiveWitness`, `ProofCollection`, `SingleProof`), `LinkTx`s have only two: `LinkWitness` and `LinkProof`. The raise operation, which recursively validates all the proofs in a `ProofCollection` to produce a `SingleProof`, is exchanged for a direct validation of the witness. More precisely, the chaining-related operations are:

- `Forge : LinkWitness -> LinkTx` (Comparable to `Prove` followed by `Raise`.)
- `Chain : LinkTx * LinkTx -> LinkTx` (Comparable to `Merge`, except with cut-through.)
- `Update : LinkTx -> LinkTx` (Comparable to `Update`.)
- `Fix : LinkTx -> Transaction` (No comparison possible.) This operation works only if `thruputs` is empty, and requires a new case in the `SingleProof` program.
- `Cast : Transaction -> LinkTx` (No comparison possible.) This operation populates `thruputs` with the empty list.

## Discussion

Merging the `Prove`-followed-by-`Raise` step into one `Forge` step is likely to be cheaper. There are still proofs to be recursively validated – namely, the type script and lock script proofs. However, these are the _only_ proofs to be recursively validated in the `Forge` step whereas the high cost of the `Raise` step comes from _also_ recursively validating other proofs, mainly `RemovalRecordsIntegrity`. The _logic_ of `RemovalrecordsIntegrity` is still being validated; but its _proof_ is not. Instead, its program code is duplicated and run in a different context.

At the same time, the _raison d’ètre_ of the `ProofCollection` continues. This intermediate stage exists so that light machines can cheaply and securely initiate transactions, provided that they can find someone to do the heavy-lifting recursive part. Having a dual pipeline leaves the original one intact (up to the one extra branch into `SingleProof`).

Likewise, the dual pipeline does not affect the logic of the merge bit or of coinbase transactions. Composers can continue their current configuration.

One downside is that the `SingleProof` hash changes, along with complications downstream from there.
