Beersy
BRC-67

Simplified Payment Verification

Earlier descriptions of how a light client checks a payment were spread across documents and leaned on each other. This states the process on its own terms so it can be read and implemented without following a trail of references.

No author creditedchanged 18 Aug 20263 min read

Reference for an AI

Everything an assistant needs to answer questions about BRC-67 accurately, including what it depends on.

Summary

Why
Anyone receiving a Bitcoin transaction from a needs a fixed, agreed set of checks to confirm it is genuinely valid before trusting it, without needing the entire blockchain.
What
BRC-67 is a definitive list of the four checks a client must perform to verify a received transaction using (SPV), without relying on a full node.
How
A developer checks that every evaluates to true, confirms the inputs sum to more than the outputs, verifies each input has a tracing back to a mined block (following the chain of ancestor transactions if some are still unconfirmed), and checks that and hold their…

What this lets you do

  • Verify a transaction's unlocking scripts evaluate to true
  • Confirm inputs pay more in total than outputs, to check fees
  • Trace each input's Merkle path back to a mined block
  • Follow chains of unconfirmed ancestor transactions when verifying offline-built transactions
  • Check nLocktime and nSequence match expected defaults or intended values

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

transactionspv checksverified

The specification

Abstract

Defining (SPV) without external reference for sake of clarity.

Motivation

Bitcoin's security model is built upon the idea of widespread distribution of blockheaders, where applications run SPV. This ensures that anyone can easily identify any attempt to commit fraud using tampered data. To ascertain the validity of data received from peers, any client on the network can employ Simplified Payment Verification. We require a clear and definitive reference that outlines the specific criteria. This way, implementations with variations in finer details can always refer back to the fundamental principles that remain constant over time.

Certain checks that are unique to each implementation, such as detecting encoding errors or malformed transactions, are not covered here. Although these checks are essential, they vary according to the implementation and are not included in the definitive list presented below.

Verification Steps

Checks made on receipt of a transaction from a :

  1. Script evaluation of each results in TRUE.

  2. The sum of the satoshis-in must be greater than the sum of the satoshis-out.

  3. Each input must be associated with a to a block.

  4. , and of each input are set to the expected values.

Script Evaluation

Often this is referred to as "check the signatures" which is indeed usually the case but it is possible to have transactions which do not require signatures so for the sake of technical exactitude - running script evaluation is really what is happening here. The interpretation requires that each input unlocking script is concatenated with the previous locking script and the interpreter runs given that input. The result should be a truthy value left on the stack after execution, otherwise the predicate has failed and the utxo has not been unlocked.

Check Fees

Each input is a pointer to a previous output, each output has a value. Therefore to calculate the input we must have details of the previous transactions from which we are spending utxos. We use this information to determine the fees paid by the transaction. We compare these fees with the size of the Tx in bytes to arrive at a rate: sats/byte. The acceptable rate is well known, various services publish this information. At the time of publishing this rate is equivalent to 1 satoshi for a standard transaction, therefore the check could simply be:

sumInputAmounts > sumOutputAmounts

Merkle Path

If all inputs come from Transactions which are mined in a block, then the associated Merkle path is one which leads that txid to a . If some inputs are not in a block then we must include previous transaction data, and follow the history of all inputs until we arrive at a point where all inputs are associated with previous inputs which appear in a mined block. Various formats will this differently, but the universal rule is that SPV requires that we prove that all inputs come from legitimate transactions.

In a long chain of transactions conducted while not connected to the internet, each new transaction is appended to the end of the SPV data such that all prior transaction ancestry is propagated to all counterparties, until they are broadcasted. So we would expect large SPV data payloads only when many transactions happen offline, which in today's age will be extremely rare.

all inputs lead to a block

Locktime and Sequence

The nLocktime default is 00000000, and nSequence default is FFFFFFFF. If these values are not default then there is a naunced condition to the transaction which is explained here.

Was this helpful?

Search Beersy

Search standards by number, title, author or topic