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 31 Aug 20233 min read
received txspv checklistverified tx

Summary

Why
Different implementations need a single, unambiguous checklist for proving a received transaction is genuine, so that verification does not silently vary between wallets and services.
What
BRC-67 is a definitive list of the checks a client must perform to verify a Bitcoin transaction using (SPV), without needing to trust the sender.
How
A developer checks that every evaluates to true, that total input exceed total output satoshis, that every input traces via a back to a mined block (following ancestor transactions if some inputs are still unconfirmed), and that and values are as expected.

What this lets you do

  • Verify a transaction's unlocking scripts evaluate to TRUE
  • Check that input value exceeds output value to confirm a valid fee
  • Trace every input's Merkle path back to a mined block
  • Follow chains of unbroadcast offline transactions back to their confirmed ancestors
  • Confirm nLocktime and nSequence fields match expected defaults

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

Reference for an AI

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

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 satoshis 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