Skip to content

Learn

Crypto Spot Research

Bitcoin inclusion proofs: a confirmed transfer can already be spent

A Bitcoin transaction can have an authentic inclusion proof long after every output it created has been spent. Inclusion answers a historical question: was this transaction committed to the specified block? A current-reserve claim asks another question: which particular outputs remain unspent under the selected chain and observation policy?

Build a three-column record for transaction inclusion, block-chain membership and current output status. Keep ownership or control evidence outside those three columns. None of these technical checks alone identifies customer liabilities or establishes who can sign a valid spend.

Identify an output, not merely a payment screenshot

Start with network, transaction identifier, output index, output value and script. An outpoint consists of the transaction identifier and output index together. A proof concerning transaction T does not specify which of T’s several outputs supports the research claim.

Retrieve the complete transaction and independently locate the output being counted. Preserve raw value units and the exact locking script. An explorer address is a presentation of supported script types, not a substitute for the output bytes. A transaction total can include recipient outputs, change and other outputs with different attribution.

Write a cutoff block hash and height for the current-status question. Also state whether an unconfirmed mempool spend should make an otherwise chain-unspent output unavailable in your report. That choice changes the observation, so it belongs beside the amount rather than in an undocumented tool default.

What the proof and the node actually check

The gettxoutproof reference describes a proof of transaction inclusion. Its retrieval note explains why an index or an explicitly supplied block hash can matter. A node failing to locate a transaction through one lookup path does not establish that the transaction never confirmed.

The Bitcoin Core 30.0 verifytxoutproof reference additionally describes the node’s best-chain requirement. Record both the proof result and the node’s chain context. A mathematical path to an old branch and acceptance on the node’s current best chain are related but distinct observations.

Use gettxout in the same documented version for the selected output’s unspent status. Its include_mempool parameter affects whether an unconfirmed spend excludes the output. A null response requires interpretation in that context; it is not a complete explanation of what happened to the coins.

These are read-only evidence operations. Another researcher should be able to inspect the request parameters, repeat the queries against an appropriate node and understand any different result without guessing which transaction or cutoff you meant.

A hypothetical transfer followed by a spend

Assume a fictional Bitcoin-compatible history, with ordinary transactions and no coinbase restriction involved. At height 100, transaction T consumes 3 BTC and creates output T:0 of 2 BTC for the researched script, output T:1 of 0.9999 BTC for another script and a fee of 0.0001 BTC.

The creation arithmetic is 3 = 2 + 0.9999 + 0.0001. Retaining that bridge prevents a screenshot of the three-bitcoin input from becoming evidence of three bitcoin received by the researched output.

At height 110, transaction U spends T:0. Under the example’s stipulated valid history, U creates 1.5 BTC for a recipient, 0.4998 BTC for a change script and pays 0.0002 BTC. Thus 2 = 1.5 + 0.4998 + 0.0002.

ObservationT included at height 100?T:0 unspent on chain?Amount represented by T:0 now
Cutoff height 105YesYes2 BTC
Cutoff height 115YesNo0 BTC
Cutoff height 120YesNo0 BTC

At height 120 the historical inclusion proof still concerns a real inclusion in this selected history. It does not restore the spent outpoint. Reporting two bitcoin of current reserves solely because the proof remains valid would confuse a receipt with an inventory.

The table does not establish that the researched owner has zero bitcoin everywhere. The change output may be controlled by that owner, or it may not; the scenario has not supplied that evidence. Identify and verify any replacement outpoint separately before adding it to an owner-level inventory.

Reconcile amounts without counting descendants twice

For an inventory at one cutoff, list the relevant unspent outpoints and sum their values once. Do not add T:0’s historical two bitcoin to U’s 0.4998 change merely because both transactions appear in the owner’s activity history. The earlier outpoint was consumed to create the later outputs.

Conversely, do not remove an entire transaction because one output was spent. If T had another independently attributed output that remains unspent, its status must be checked separately. Transaction-level labels are too coarse for an output-level reserve statement.

Use a transition ledger: created, observed unspent, observed mempool spend, confirmed spent, or unresolved. If a spending transaction is located, retain its input reference to the exact outpoint. Matching a similar value or a familiar address is weaker than an explicit input relationship.

Boundary case: a pending spend

Return to a cutoff before U confirms. Suppose U is visible in the node’s mempool. A query excluding mempool effects can still show T:0 as chain-unspent, while a query including those effects can omit it. Both responses can be consistent with their parameters.

Report “unspent in the selected chain, with a locally observed pending spend” rather than forcing one universal available balance. A later mempool disappearance does not prove the spend was canceled: it might confirm, be replaced, be evicted or vanish after a node restart. Find the chain transition or leave its explanation unresolved.

Another node may not have seen the same pending transaction. Save node identity, software version and retrieval time. The mempool observation is local evidence, not a guaranteed global first-seen record or proof of the owner’s intention.

Boundary case: an old branch or missing history

If the block containing T leaves the node’s best chain, retain its old block hash and the earlier result. A proof’s bytes need not change for its relevance to the current chain to change. Recheck the transaction on the replacement chain before updating the inventory.

A pruned node, missing transaction index, incorrect output index or wrong network can also prevent a useful response. Classify retrieval failure before assigning a spent status. Where possible, compare a narrow object through another appropriately configured source; do not simply replace every disagreement with the largest balance.

Match the query’s actual tip to the cutoff

The documented gettxout interface is a current-node query, not an arbitrary historical-block balance method. A research cutoff at height 105 cannot be recreated by calling it today and attaching the old date. Use a retained observation from that state, an appropriately reconstructed historical chain state or another explicitly justified historical method.

Even a current run can cross a new-block boundary between queries. Save the returned bestblock where available and the surrounding node-tip observations. If the proof and UTXO checks refer to different states, either align them or label the gap. For a null result without its own bestblock field, preserve enough surrounding context to avoid inventing an exact snapshot identity.

Normalize units before totaling the surviving list. A BTC display and a satoshi integer can describe the same output, so they must not become separate inventory lines. Preserve the original representation beside the converted quantity to make that check repeatable.

A review checklist another reader can execute

ActionRequired artifactConclusion it can support
Decode TTransaction bytes and output indexThe named output was created with specified value and script
Check inclusionProof, target block and verifier resultT belongs to that block under the verification conditions
Check chain contextCutoff hash, height and node statusThe block belongs to the selected best-chain view
Check T:0Explicit mempool parameter and responseIts unspent status under that observation policy
Locate a spendU input referencing T:0The precise consumption relationship
Sum inventoryDated list of distinct surviving outpointsCovered unspent quantity, with attribution assumptions

Reopen the record after a reorganization, a newly confirmed spend, corrected script attribution or discovery of an indexing gap. Publish a dated inventory with unresolved outputs visible. An inclusion proof remains valuable historical evidence even when it no longer supports a current-balance statement.

FAQ

Does the name gettxoutproof mean it proves an output is unspent?

No. Read the method’s documented claim: the proof concerns transaction inclusion. Current output status requires another check.

Does a null gettxout response prove the whole wallet is empty?

No. It concerns the requested outpoint and observation parameters. Explain the missing result and inspect other attributed outputs separately.