Beersy
BRC-237

Payment Evidence Statements for BREAD and BEEF

Two different wallets checking the same unconfirmed payment describe what they verified in totally different ways, so there is no way to compare "three hops back to a confirmed block" against "a valid " or to let an app set one acceptance rule that regardless of which wallet it is talking to. This leaves users and apps guessing what was actually checked before goods change hands, with no shared way to say it.

About SPV, accepting a payment without downloading the chain.

AlsoProofsBEEF

RexStarBSVchanged 31 Oct 202654 min read

Reference for an AI

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

Summary

Why
Receivers need a single, shared way to state exactly what they checked about an unmined payment, since BEEF-based and hop-counting (BREAD) verification describe the same in incompatible terms.
What
BRC-237 is a specification for a canonical JSON statement that records what a receiver verified about an unmined Bitcoin SV payment, built from either BREAD-style ancestry distance or a .
How
A maker that holds either a BEEF or raw records walks back through the payment's unconfirmed ancestors, records which checks passed and how far each input is from a trusted header, serializes the result as canonical JSON, and optionally signs it with BRC-77 or exposes it through a BRC-100 wallet method called…

What this lets you do

  • Produce a canonical JSON statement describing exactly what was checked about an unmined payment
  • Build the statement from either a BEEF or from a wallet's own ancestry records
  • Report longest and shortest unconfirmed distance to a trusted
  • Convert Electrum-style Merkle branches into BRC-74 format
  • Sign a statement with BRC-77 and expose it via an optional wallet method

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

unmined paymenancestry + cheevidence state

The specification

Abstract

This BRC defines a payment statement, a small canonical JSON object in which a receiver records what it verified about an unmined payment and what it did not: the ancestors anchored by a to a header it trusts, whether every input reaches one, the longest and shortest unconfirmed distance to an , which unconfirmed transactions passed script, amount and lock-time checks, and the payment's observed status. A receiver that reports ancestry distance, as BREAD does, and a receiver that holds a can each make one from the evidence it already has. No statement says that a payment will be mined. The BRC also converts Electrum-form Merkle branches to BRC-74 paths and defines an optional signature and wallet method.

Motivation

Two of evidence are in use for a payment that is not yet mined.

The first is ancestry distance. The receiver walks back from the payment through its unconfirmed ancestors until it reaches a transaction with a Merkle path to a , and reports the number of steps. The number records distance; which checks were run is a separate fact. ElectrumSVP's release for version 0.2.0-beta.1 describe evidence of this kind under the name BREAD: "Improved BREAD verification, including local proof-data handling, unconfirmed transaction verification, confirmed-ancestor anchoring, hop reporting, and BREAD JSON export". Its 0.2.0 release notes expand the name as Blockchain Referenced Evidence and Data.

The second is BEEF (BRC-62, with the Atomic form of BRC-95 and the V2 form of BRC-96), which carries unconfirmed ancestors back to transactions with BRC-74 Merkle paths. With it, a receiver can run every script, check every signature, and check that each transaction's inputs cover its outputs, the checks that BRC-67 lists for . When it does, the result answers whether every spend from those coins to the payment is valid. The BEEF alone does not say whether a receiver ran those checks, or against which headers.

Neither kind of evidence answers whether the payment will be mined, or whether a conflicting spend of one of its inputs exists. Those depend on what miners do next. A receiver can look for a conflicting spend at a given moment, through a node it runs or a service it asks, and that is the most it can hold.

Each kind of evidence is described in its own terms today. "Three hops" and "a valid BEEF" may describe the same payment, and neither phrase alone lists the checks behind it. A statement in common terms lets:

  • a user see what their wallet checked before they hand over goods;
  • an application apply one acceptance policy, whichever wallet serves it;
  • a wallet of either kind report what it knows, without adopting the other kind's format or architecture.

Scope and conformance

Layer. Interface: what one program tells another about a payment, whether wallet to application, wallet to user or wallet to wallet. Whether to accept a payment is policy, and this document does not set it.

Three roles are used, and a MUST binds only an implementation that claims the role its sentence names:

  • a maker produces statements (sections 2 to 4, 6 and 7);
  • a reader reads them (section 5);
  • a wallet that offers the method of section 8, which that section binds.

Adoption is voluntary. A wallet that makes no statements does not follow this document, and its other behaviour is unaffected.

What this document does not require. How a maker obtains its material or its block headers; how it stores anything; which transport carries a statement; whether a maker validates at all (a statement whose validation is "none" conforms); whether and how it checks for a conflicting spend; the values of its bounds and of a reader's; and the BRC-100 interface, which section 8 uses optionally. A statement is self-contained: reading it needs no service and no key, and checking its anchors needs only block headers.

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as described in RFC 2119 and RFC 8174 when, and only when, they appear in capitals.

Specification

1. Terms

  • Payment: the transaction a statement is about.
  • Txid: the double SHA-256 of a transaction's bytes. Inside a transaction, a BEEF, an Atomic BEEF's prefix and a BRC-74 path, a txid is in internal byte order, the order the hash gives; in a statement, and in this document's tables, it is 64 lowercase hexadecimal digits in display order, the reverse. A maker MUST compute every txid from the bytes it holds. An input names the transaction it spends by txid in internal byte order, and the maker matches it against the txids it computed in that same order. A txid written beside the bytes is a claim.
  • Material: what the maker holds of the payment's ancestry, of one of two kinds: a BEEF as received (BRC-62 V1, 0100beef, or BRC-96 V2, 0200beef, alone or inside a BRC-95 Atomic BEEF), or raw transactions and Merkle paths from the maker's own records. A statement is made over one material.
  • Header source: the block headers the maker trusts, by height, and its , the highest of them; the source holds the tip's header. How the maker obtains them is outside this document. Every anchor is only as good as this source (see Security Considerations).
  • Median time past: the median of the timestamps (bytes 68 to 71 of the 80-byte header, little-endian) of the 11 blocks ending at the header source's tip, that is the tip and the 10 blocks below it. A maker whose header source lacks one of those headers has no median time past.
  • Merkle path: BRC-74 bytes. In a BEEF, a path counts for a transaction only when that transaction's entry names its index: BRC-62's has-BUMP byte 01 and index, or BRC-96's format 01 and index. In records, a path is held for a txid, as BRC-74 bytes or as an Electrum-form branch (section 6).
  • Own path: for a txid at offset x of level 0 of a path of tree height h (the lowest such offset, if the txid is at more than one), the h steps that fold it. At step i, from 0 to h - 1, the working hash and its sibling, the node at offset (x >> i) XOR 1 of level i, are hashed together, the left node first, as the double SHA-256 of their 64 bytes. The sibling is the hash the path gives at that offset, the working hash again where the path that offset a duplicate (flag 01), or the node computed from the two nodes below it. The working hash starts as the txid and its last value is the root. A step with no sibling ends the fold with no root, and a txid that is not at level 0 has no own path. A one-transaction block is the exception: a path of tree height 1 that holds one node, the txid at offset 0, has no step, and its root is the txid.
  • Anchor: a transaction the maker holds, with a Merkle path that (a) gives a root by the fold of the transaction's own path, which takes exactly the path's tree height of steps, or none for a one-transaction block; (b) names a height at or below the header source's tip at which the header source holds a header; (c) gives a root equal to the of that header (bytes 36 to 67 of the 80-byte header, in internal byte order); (d) is for a transaction that is not exactly 64 bytes long; and (e) at no step of the own path hashes 64 bytes, the two nodes in the order hashed, that decode as a transaction. Any field carried with the material that asserts confirmation, a height or a header included, is a claim, and is not evidence of an anchor.
  • Decodes as a transaction, for 64 bytes: read in the standard transaction serialization, they give, ending exactly at byte 64, a 4-byte version; an input count of at least 1; each input as a 32-byte txid, a 4-byte index, a script length and that many bytes, and a 4-byte sequence number; an output count of at least 1; each output as an 8-byte value, a script length and that many bytes, with every value, and the running sum of the values, at most 2,100,000,000,000,000; and a 4-byte lock time. Counts and lengths are VarInts, in any of their forms.
  • Unconfirmed set U: the transactions the walk of section 2.1 reaches that are not anchors. The payment is in U unless it is itself an anchor.
  • Unresolved input: an input of a transaction in U whose source transaction the maker does not hold.

2. Making a statement

2.1 The walk

The maker starts at the payment and visits each transaction once, in whatever order the material holds them. It reads the Merkle path of each visited transaction that has one, as BRC-74 permits (below). A path that meets condition (b) of an anchor is checked as one (section 1), and its transaction is not followed further. A path that does not meet condition (b), because it names a height above the tip or one for which the header source holds no header, is not checked: the maker treats its transaction as if it carried no path. Every other visited transaction joins U, and each of its inputs is followed to the transaction it spends, or recorded as unresolved if the maker does not hold that transaction. The inputs come from the held bytes, never from anything carried beside them. The maker decodes only the transactions the walk visits. It reads the rest of the material only as far as its framing needs and, in an Atomic BEEF, as far as each entry's txid and the its inputs name, to tell an ancestor from an unrelated entry. Framing a BEEF reads every path in it, and a node's flag sets the node's length, so a path that holds a flag other than 00, 01 or 02 cannot be framed: it is MALFORMED whether or not a visited transaction names it.

A BEEF V2 entry that carries only a txid holds no transaction, so an input that spends it is unresolved. BRC-96 treats such an entry as valid by agreement between the parties exchanging the BEEF, and that agreement is not evidence a statement records. A maker that holds the transaction MAY make its statement from its records instead.

An Atomic BEEF that lacks an ancestor is material here. BRC-95 fails the validation of such an Atomic BEEF; a maker reads it, and the statement names the inputs that are unresolved. A statement about it does not say that it passes BRC-95 validation. BRC-95's other rules apply as written: the subject, the 32 bytes after the prefix read in internal byte order, is the payment, and the material holds the subject and its ancestors and nothing else. An ancestor is any entry the material holds whose txid an input of the subject, or of another ancestor, names, an anchor's inputs included. A transaction beyond an anchor is therefore an ancestor: BRC-95 permits it, the byte bound counts it, and the walk does not visit it. An entry that carries only a txid has no inputs, so it names no further ancestor, and one whose txid no such input names is unrelated, as an unrelated transaction is.

A maker MUST refuse, with the code given, and return no statement:

CodeWhen
MALFORMEDMaterial that does not decode completely: bytes missing or left over (a decoder is told its input is complete). A BEEF whose version is not 0100beef or 0200beef, so the legacy efbe0001 too. An Atomic BEEF whose subject is not the payment, or that holds an entry other than the subject and its ancestors, an entry that carries only a txid included. A BEEF that holds one txid twice. A path in a BEEF that holds a flag other than 00, 01 or 02, whether or not a visited transaction names it. A payment not in the material. Bytes whose txid differs from the txid they are held under. A transaction in U with no inputs or no outputs. An input naming an output that its held source does not have. A path of a visited transaction that BRC-74 does not permit (below).
ANCHOR_MISMATCHA Merkle path that meets condition (b) of an anchor fails condition (a), (c), (d) or (e). The transaction is not treated as unconfirmed instead.
CONFLICTTwo inputs of transactions in U spend the same output, within one transaction or across two; or a transaction in U spends an output that an anchor the walk reached also spends.
OVER_BOUNDThe maker reads more bytes than its bound: for a BEEF, its whole length, with any Atomic prefix, since the maker frames all of it; for records, the bytes of each transaction the walk visits and of the path held for each of those, as BRC-74 bytes (an Electrum-form branch as converted), and nothing else the records hold. Or the walk reads more transactions, anchors and U together, than its bound; or the longest path through U holds more transactions than its bound on distance. Or the statement, in its canonical form (section 4), is longer than the maker's bound on statement length.

A path that BRC-74 does not permit is one with a tree height of 0 or more than 64; a flag other than 00, 01 or 02; two nodes at one offset of a level; a node outside the tree, at an offset of 2^(h - i) or more at level i of a tree of height h; or a node, given as a hash or as the duplicate of its sibling, that differs from the node computed from the two nodes below it. These are checked on the path of every visited transaction, whether or not it meets condition (b), and the flags on every path of a BEEF, since framing reads them. Nodes off a transaction's own path take part in these checks and in nothing else.

A maker MUST have all four bounds and MUST refuse beyond them, never describe part of a graph. It MUST NOT emit a statement longer than its bound on statement length, and refuses OVER_BOUND instead. Their values are policy. A maker SHOULD use 1,000,000 bytes as its bound on statement length, the value section 5 recommends for a reader's bound, so that a reader with that bound reads every statement a maker with it emits.

After a reorganisation that replaces the block a path names, the header source holds another header at that height, and material that holds the path is refused ANCHOR_MISMATCH (condition c) until its path is replaced.

2.2 Anchoring and distance

  • fullyAnchored is true when no input is unresolved.
  • distanceMax, when the payment is fully anchored, is the number of transactions of U on the longest path from the payment back to an anchor. It is 1 when every input of the payment spends an anchor's output, and 0 when the payment is itself an anchor. It is null when the payment is not fully anchored.
  • distanceMin is the number of transactions of U on the shortest path from the payment back to an anchor, whether or not the payment is fully anchored. It is 0 when the payment is itself an anchor, and null when no path reaches an anchor.

A path's number of transactions of U equals its number of edges from the payment to the anchor: for a chain D, C, B, A in which D spends C, C spends B, B spends A and only A is anchored, both distances are 3.

2.3 Validation

A transaction X of U is validated when the maker has run each check below on X and on every transaction of U that X descends from, and every check passed. Only a transaction whose ancestry is fully anchored can be validated, because the checks read the outputs it spends.

  1. Scripts. For each input, the followed by the locking script of the output it spends evaluates to true under the consensus rules in force for the block after the header source's tip. Some of those rules depend on the height at which the spent output was created: for an output that an anchor created, the height of the anchor's block, and for an output that a transaction of U created, the block after the tip, as SV Node judges an output created in its mempool (validation.cpp L2667-L2674 and L2692-L2696). On mainnet the Genesis upgrade activated at height 620,538 and the Chronicle upgrade at 943,816 (SV Node chainparams.cpp L18-L23); for example, OP_2MUL is enabled for an output created at or above 943,816 and disabled for one created below it (interpreter.cpp L360-L372). A maker whose next block is below an upgrade's activation height applies the rules from before it. This check includes every signature check (BRC-67 step 1).
  2. Amounts. Each output's value, and the sum of X's outputs, is from 0 to 2,100,000,000,000,000 , and the outputs X spends add up to at least the sum of its outputs. BRC-67 step 2 asks for more than the outputs, as a stand-in for a fee rate. This check asks only that no value is created, and section 2.4 reports the fee.
  3. Lock time. X can be mined in the block after the header source's tip as it stands: its nLockTime is 0; or every input's sequence number is 0xFFFFFFFF; or its nLockTime is below 500,000,000 and below that block's height; or its nLockTime is 500,000,000 or more and below the median time past (section 1). An input that spends an output of an anchored does so only if that block's height is at least the 's height plus 100, the network's coinbase maturity (SV Node consensus.h L75). An input that spends an output of an anchored transaction whose first output's locking script begins 006a0463667478 (OP_FALSE OP_RETURN and a push of cftx), a confiscation transaction (frozentxo_db.cpp L614-L636), does so only if that block's height is at least the anchor's height plus 1,000 (consensus.h L79, validation.cpp L2627-L2636). Before Genesis, the relative lock times of BIP 68, set by each input's sequence number, also bound a transaction of version 2 or above (validation.cpp L272-L273 and L3463-L3468, policy.h L247-L255); a maker whose next block is below the Genesis activation height applies them too. BRC-67 step 4 asks that nLockTime and each nSequence be set to the values the receiver expects. This check asks only whether X can be mined in the next block; which values a receiver expects is its policy.

Only a check that ran under the consensus rules and failed is a refusal, and the maker then returns no statement:

CodeWhen
SCRIPT_FAILEDCheck 1 ran, and an evaluation ended false or broke a consensus rule.
VALUE_CREATEDCheck 2 fails.
PREMATURECheck 3 fails: X cannot be mined in the next block as it stands. This does not find X invalid. A transaction whose lock time is still to come may be meant to be replaced before then, as in the payment channels of BRC-9 step 9, and a statement can be made once a later tip lets check 3 pass.

A maker MUST NOT refuse because of a limit it sets for itself, such as a bound on a script's memory, operations or number length, or because of a stricter rule it applies for its own use. When the maker cannot complete a check on a transaction, it MUST leave that transaction, and every transaction of U that descends from it, out of the validated set, and MUST NOT refuse because of it. It cannot complete a check when its interpreter does not implement an opcode the script uses under the rules in force, or treats it otherwise than those rules do (as disabled, as invalid or as doing nothing); when an evaluation reaches one of its own limits; when a lock time needs a median time past it does not have; or when check 3 needs a relative lock time and the maker does not implement those. Nor can it complete the checks on a transaction of U whose own first output's locking script begins 006a0463667478: that is a confiscation transaction, which SV Node accepts only when it is whitelisted (validation.cpp L2562-L2587), and a maker cannot know the whitelist. A maker MAY also leave out a transaction that passes these checks but not a stricter check of its own, and it need not check a transaction that descends from one it left out. A statement records only checks that passed: a maker MUST NOT count as validated a transaction whose checks were not all completed.

A maker that ran a check and found that it failed MUST refuse. It MUST NOT then report that transaction as not checked, or make a distance-only statement about the same payment from material that holds it, while the failure stands; for PREMATURE, that is until a later tip lets check 3 pass.

validated lists the validated transactions. validation is "all" when the payment is fully anchored and every transaction of U is validated, "none" when U is not empty and no transaction is validated, and "partial" otherwise. A maker that runs no checks reports "none", and conforms. A payment that is itself an anchor has an empty U, so its validation is "all" whether or not the maker validates: the checks of this section apply to U, so both kinds of maker have run the same checks on such a payment, and both make the same statement.

When more than one refusal applies, a maker MAY report any of them.

2.4 Fee

lowestFeeRate covers validated transactions only. It is the fee and size of the validated transaction whose fee per byte is lowest, as {"bytes": size, "satoshis": fee}, where the fee is what its inputs spend less what its outputs pay, and the size is the length of its bytes. Among equal rates it is the one with the smallest txid. It is null when no transaction is validated. Two integers carry the rate without rounding. Whether the rate is enough for a miner is policy.

2.5 Status and observations

status is {"depth": d, "event": e}, where e is the event furthest down this table among those the maker observed for the payment, whatever order it observed them in:

eventMeaningdepth
receivedThe maker holds the payment, from another party.null
signed-locallyThe maker signed the payment itself.null
handed-to-broadcasterThe maker gave the payment to a broadcaster.null
seen-by-networkA node or service reported holding the payment among its unmined transactions.null
minedThe payment is itself an anchor.tip.height less the anchor's height, plus 1

A maker MUST say mined when the payment is itself an anchor, and MUST NOT say it otherwise, whatever it was told.

conflicts is {"checked": false}, or a check the maker made for a conflicting spend:

{"at": t, "checked": true, "found": f, "kind": k, "scope": s}
  • at: when the observation was made, in Unix seconds, no later than madeAt.
  • found: true if a transaction other than those in U was observed spending an output in .
  • kind: own-node, a node the maker operates, or third-party, a node or service operated by another party.
  • scope: payment, the outputs the payment's own inputs spend, or unconfirmed, the outputs spent by every transaction of U.

How the observation is made is operation, and outside this document. found: false says only that none was seen at time at.

madeAt is when the statement was made, in Unix seconds.

tip is {"blockHash": b, "height": n}: the header source's tip when the statement was made, and the double SHA-256 of its header in display order. Every depth and lock-time in the statement is for that tip: check 3 was made for the block at n + 1.

3. The statement

A statement is a JSON object with exactly these fields:

FieldTypeValue
anchorsarrayOne {"blockHash", "height", "txid"} per anchor the walk reached, sorted by txid. blockHash is the double SHA-256 of the header the path reached, in display order.
conflictsobjectSection 2.5.
distanceMaxinteger or nullSection 2.2.
distanceMininteger or nullSection 2.2.
fullyAnchoredbooleanSection 2.2.
lowestFeeRateobject or nullSection 2.4.
madeAtintegerSection 2.5.
statusobjectSection 2.5.
tipobjectSection 2.5.
txidstringThe payment.
unconfirmedarrayThe txids of U, sorted.
unresolvedarrayOne {"txid", "vout"} per unresolved input, the output it spends, sorted by txid and then by vout.
validatedarrayThe txids of the validated transactions, sorted.
validationstringnone, partial or all (section 2.3).
versionstringbsv-payment-evidence/v1

Every txid and block hash is 64 lowercase hexadecimal digits, in display order. Every array is in strictly ascending order of the strings and integers named, so no txid (or txid and vout) is in it twice.

4. Canonical form

A statement is exchanged as the bytes of its canonical form:

  • keys sorted by their bytes at every level, with no whitespace and the separators , and :;
  • integers in decimal, from 0 to 2^53 - 1, with no sign, leading zero, fraction or exponent; there are no other numbers;
  • strings only from the values of section 3, so no character is ever escaped; null, true and false as JSON writes them;
  • the whole encoded as ASCII.

This is the canonical form of BRC-179 section 7.2, extended with integers and null as above. A maker MUST emit it.

5. Reading a statement

A reader has a bound on the length of the bytes it reads. Its value is policy, and a reader SHOULD use 1,000,000 bytes, the value section 2.1 recommends for a maker's bound on statement length. A reader MUST, in this order:

  1. refuse OVER_BOUND if the bytes are longer than its bound, before it parses them;
  2. refuse MALFORMED_STATEMENT unless the bytes are ASCII, nest arrays and objects at most 32 deep (the outermost object is depth 1), and parse as a JSON object, with no key twice in one object, whose version is a string;
  3. refuse UNKNOWN_VERSION if version is not bsv-payment-evidence/v1, and read no further;
  4. refuse MALFORMED_STATEMENT if the bytes are not the canonical form of the object they parse to; if a field is missing, unexpected or of the wrong type (a boolean is true or false, never a number); if a txid or block hash is not 64 lowercase hexadecimal digits; if a vout is above 2^32 - 1, the largest output index a transaction can name; if an array is not in the strictly ascending order section 3 gives; if validation, status.event, conflicts.kind or conflicts.scope has a value that sections 2.3 and 2.5 do not list; or if the fields disagree with one another:
    • fullyAnchored is true exactly when unresolved is empty;
    • no txid is in both anchors and unconfirmed;
    • the payment is either in anchors, with unconfirmed empty, or in unconfirmed;
    • distanceMax is null exactly when fullyAnchored is false, and distanceMin is null exactly when anchors is empty;
    • for a payment in anchors, anchors holds that entry only and both distances are 0; otherwise a fully anchored payment has an anchor, a distance that is not null is at least 1 and at most the length of unconfirmed, and distanceMin is at most distanceMax;
    • validated is within unconfirmed, and validation is the value section 2.3 gives for these lists;
    • the payment is in validated only if validated equals unconfirmed and fullyAnchored is true;
    • the txid of an unresolved entry is not in anchors, unconfirmed or validated;
    • lowestFeeRate is null exactly when validated is empty, and its bytes is at least 1;
    • status.event is mined exactly when the payment is in anchors, and status.depth is a positive integer then and null otherwise;
    • conflicts.at, when present, is at most madeAt;
    • every anchor's height is at most tip.height, and for a payment in anchors, status.depth is tip.height less the payment's anchor height, plus 1.

A reader MUST NOT take a statement to say more than its fields do. A fully anchored payment is not a mined payment. Validation all does not mean the payment will be mined. found: false does not mean that no conflicting spend exists.

6. Merkle branches in the Electrum form

The Electrum protocol's blockchain.transaction.get_merkle returns a Merkle branch as {"block_height": h, "merkle": [...], "pos": p}: the sibling hashes from the bottom of the tree up, each as hex in display byte order, and the transaction's index in the block. Electrum-protocol servers return branches in this form. A maker MAY hold paths in this form, and raw transactions held with such branches are material (section 1). A maker that converts a branch to a BRC-74 path MUST:

  1. compute the txid from the raw transaction it holds;
  2. refuse MALFORMED, and make no path, if the raw transaction does not decode completely; if the branch is not an object of exactly block_height, merkle and pos, with non-negative integers h and p (h below 2^64, since BRC-74 writes it as a VarInt) and each sibling 64 lowercase hexadecimal digits; if it has more than 64 siblings (BRC-74's limit on a tree's height); or if p is 2^n or more, where n is the number of siblings (with no sibling, p is 0). The conversion refuses nothing else;
  3. write the path with block height h and tree height n, or, with no sibling, tree height 1 and the transaction alone at offset 0, a one-transaction block. Level 0 holds the transaction at offset p with flag 02 and its txid in internal byte order, and, when n > 0, the first sibling at offset p XOR 1. Each level i from 1 to n - 1 holds sibling i at offset (p >> i) XOR 1. Nodes in a level are in ascending offset. A sibling equal to the working hash at a level where the working node's offset is even is written with flag 01 and no hash; every other sibling is written with flag 00 and its hash in internal byte order.

The conversion hashes the branch only to find those duplicates. The converted path is a Merkle path like any other: it anchors only through the checks of section 1, against the maker's own header source, so a step that hashes 64 bytes that decode as a transaction is refused ANCHOR_MISMATCH there, when the path is checked. Only the siblings, h and p are used. A maker that holds a branch and does not convert it MUST check it as if converted, with the same refusals and the same anchor. Folding the branch as the Electrum protocol does and folding the converted path give the same root.

7. Signing (optional)

A maker MAY sign the canonical bytes of a statement as a BRC-77 message. The BRC-77 serialization travels beside the statement, never inside it. A verifier checks it over the exact bytes it received; any other serialization of the same object does not verify. A signature says who made a statement and adds nothing to what the statement claims.

8. Offering statements to applications (optional)

A wallet that implements BRC-100 MAY offer one additional method, getPaymentEvidence:

  • Arguments. Either txid, a payment the wallet holds, or atomicBEEF, an Atomic BEEF (BRC-95) for the wallet to evaluate without storing it; and sign, a boolean, false when omitted. For atomicBEEF the material is that Atomic BEEF alone: the wallet's records resolve none of its inputs, so any party with the same bytes and the same headers can make the same statement. For atomicBEEF, too, status.event is received unless the payment is an anchor, whatever the wallet's records say of the payment, and conflicts is {"checked":false} or an observation made for this call.
  • Result. statement, the statement as a string, and, when sign is true, signature, the BRC-77 serialization as hex. A string keeps the bytes exact across transports that re-serialize objects.
  • Errors. A refusal is a BRC-100 error, with status "error", a code of ERR_EVIDENCE_ followed by the refusal code of section 2 (for example ERR_EVIDENCE_ANCHOR_MISMATCH), and a description; no statement is returned. For txid, a payment the wallet does not hold and a call the user has not permitted for that payment both give the code ERR_EVIDENCE_UNKNOWN_TXID with the same description. A call with neither txid nor atomicBEEF gives ERR_MISSING_PARAMETER, one with both gives ERR_CONFLICTING_PARAMETERS, and a sign that is not a boolean gives ERR_INVALID_PARAMETER_VALUE, the codes BRC-100 suggests for those cases; none returns a statement.

A wallet that offers the method MUST return the statement's canonical bytes (section 4) unchanged, and its errors as above.

The method is not one of BRC-100's methods. It changes no BRC-100 argument, result, call code or default behaviour, and an application that does not call it sees no change. This document assigns it no wire call code. As BRC-100's compatibility contract requires of an unsupported extension, a wallet that does not offer the method fails the call explicitly, and that failure says nothing about the payment.

An application learns whether a wallet offers the method by calling it, never from the getVersion string (BRC-205 section 6), and a wallet that publishes a BRC-179 capability declares it there as <product>.<surface>.getPaymentEvidence, at the tier of its most sensitive step.

Rationale

Two distances. The longest path is the worst case. A payment is good only if every input is good, and a short path through one input says nothing about a long path through another, so a limit on unconfirmed depth compares with distanceMax. distanceMin, the distance to the nearest anchor, exists even when some input is unresolved. On a chain the two are equal; on S5 they are 3 and 1. Carrying both lets an application see the gap.

A failed check is a refusal. A statement that recorded a failed check would rely on every application reading it correctly in order not to accept an invalid payment. A refusal cannot be misread, and it keeps none meaning "not checked".

Not checked is not failed. A validation refusal (section 2.3) says the payment cannot be mined as it stands, so it is kept for checks that ran under the consensus rules and failed. A maker's own limits, and rules its interpreter does not implement, only leave transactions out of the validated set: the statement then says less, and nothing false.

A path that does not match is a refusal. A Merkle path that leads to a root other than that of the header the maker trusts at its height is contradicted evidence: it is fabricated, or from a block the maker's chain does not hold. Treating its transaction as unconfirmed would hide that. A path above the tip, or at a height for which the header source holds no header, is neither confirmed nor contradicted, so its transaction is walked as an unconfirmed one, and a later statement may anchor it. A path that BRC-74 does not permit is wrong whatever the headers say, so it is refused before any header is read.

The own path. Two inner nodes read as a transaction are 64 bytes long, so condition (d), which never anchors a 64-byte transaction, keeps inner nodes from standing for a transaction. Condition (e) keeps a transaction from standing for inner nodes, and, like condition (a), it concerns only the steps that fold the transaction's own txid, since only those decide what the path proves about that transaction. Nodes elsewhere in a compound path are checked against one another and nothing more: a pair among them that decodes as a transaction proves nothing about this transaction either way (vector S14).

Partial material is reported. A statement exists to say what is missing, so an Atomic BEEF that lacks an ancestor is read and the gap is named. Refusing it would leave a receiver that holds partial evidence no way to say so. Bytes that are wrong in themselves, such as an unrelated entry in an Atomic BEEF, a txid twice or a path BRC-74 does not permit, are refused.

Bounds refuse. A walk cut short would report unresolved inputs for a reason a reader cannot see. A statement longer than a reader's bound is refused unread, so a maker refuses to emit one longer than its own, and one recommended value for both keeps a maker and a reader that use it in agreement.

Status apart from evidence. Broadcast, relay and mining are events the maker observes, and the evidence fields are checks it ran. Keeping them apart stops a report of the first kind standing in for the second. mined is the one status the evidence itself supports, so it is the one status derived from it. The tip is named so that a reader can check the depth, and the lock-time verdict, against its own headers.

Test Vectors

The vectors were generated from code by the reference implementation, never typed.

Common inputs: the header source is the table below and its tip is 950,010, unless a vector says otherwise; madeAt is 1793318400 (2026-10-30T00:00:00Z); the Genesis and Chronicle activation heights are mainnet's, 620,538 and 943,816, and every block here is at height 949,999 or above, so every output is created, and every input judged, under the rules in force after both; the maker's bounds are 1000 transactions, a distance of 100, 32,000,000 bytes of material and 1,000,000 bytes of statement unless a vector says otherwise; the maker validates unless a vector says "distance only"; status is received and conflicts is not checked unless a vector says otherwise; a reader's bound is 1,000,000 bytes unless a vector says otherwise. The headers are synthetic: the header source is an input of each vector, so no proof of is needed. Every key is the secret SHA-256(payment evidence test vector: + ), and every signature uses RFC 6979 . The keys are test keys and protect nothing.

Keys

LabelPublic key
payer036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3
not the payer0295214b460ee5aeacb289344c9a2c25070c622181bc1ac9b55436e5c3b72d0bd8
receiver03fb1aaf51797cd0551feeeacb42dfd98be2bbcd072e6d9445d3a2620b103c3adc

Every output pays to the payer key, and every input is signed by it with SIGHASH_ALL | SIGHASH_FORKID, except as follows. BADSIG's signature is by the not the payer key. The second output of A6 is locked with 8d5487 (OP_2MUL OP_4 OP_EQUAL), and X6 spends it with 52 (OP_2). T64 is exactly 64 bytes: its input's unlocking script is 51515151 in place of OP_TRUE, and its only output has an empty locking script, which P64 spends with 51 (OP_TRUE). TL and TLATE carry lock times given as a time, 1793002399 and 1793002400, with sequence 0xfffffffe. A transaction that carries a Merkle path spends output 0 of a transaction whose txid, in internal byte order, is SHA-256(payment evidence test vector: + its name), with the unlocking script OP_TRUE; only the conflict check of section 2.1 reads that input (vector M20). T01's output value is the first from 100,000 up that puts 01 at byte 4 of its txid in internal byte order. DS spends A1 output 0 and, with OP_TRUE, the outpoint A1 itself spends. Z4, txid 3721db44eccd6e28b0b7cb36cbab33dbdb1f8643603f4d437ace61442800466b, is spent by P4 and held by no maker. CF and CFU each have a first output of 0 satoshis locked with 006a046366747815019d57f040e087001d86955e34665a10eef59c654f, which begins 006a0463667478, so each is a confiscation transaction: CF is mined, and CFS spends its second output; CFU spends A1 output 0.

Header source

HeightBlock hashHeader
950001d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e000000206b0d72cc817bdfe98bc0ccb64c9c8c0a70774fe82939b6a50cff8db0fce17353faac2f5d9533c2686ccf4c05aeb9bd51ed9e5ea108156765378a6e1209a309424002df6affff7f2000000000
95000264a53adabc6a36de2c5176485d47e64c06f56d1b588e638ba8c7d349bdc459fc000000209e5e4ce3338d9d9b195d37052de72eaeaa5ed949e21b634374555030d62031d790d075c6504da015e31e8b4dd7f9b3f13203f6ec553227fa499469aed264cb1a9804df6affff7f2000000000
9500034ef4e7bfd2500d3ef2c4b89cce091e27feb0f1a82a4ceaca0395f35b9827eda700000020fc59c4bd49d3c7a88b638e581b6df5064ce6475d4876512cde366abcda3aa564eadfa677c67f2ba97e98f9e7df20bb5ffcffe6e0b5b1158f35af500f74943648f006df6affff7f2000000000
950004ee55e78df915a761c888acb74bf87c5290c24af8a170e8510e7e43f6104e291600000020a7ed27985bf39503caea4c2aa8f1b0fe271e09ce9cb8c4f23e0d50d2bfe7f44e3fe4119fc9cc69434be8030f23c73af7ce85b9edfa54f46b2acf04894afac78f4809df6affff7f2000000000
95000523cd77f659989d40993179d03215f98288825156a8d56b5eeec397ae4e4d275e0000002016294e10f6437e0e51e870a1f84ac290527cf84bb7ac88c861a715f98de755eef589bf0ce95f64670549013576e136278958bd9b225891d9384b510518f0a9fda00bdf6affff7f2000000000
950006ab14e92c0acb7212d9a1219e6c468b0f2c4ee53a7c351486bf99e916dfa1f90f000000205e274d4eae97c3ee5e6bd5a85651828882f91532d0793199409d9859f677cd235fbc9265a1d243f9085e07d40e3c2d788cbcf9f82a3d6af6809a6612b05c6f29f80ddf6affff7f2000000000
950007a036c06c92ea0d49b3b6862932aa4533730bcc711249099595efd41573bd33db000000200ff9a1df16e999bf8614357c3ae54e2c0f8b466c9e21a1d91272cb0a2ce914abaf6aad4a6fc106d25c5f08419945672a02c50051e362701fe1cf22d6993ebe115010df6affff7f2000000000
950008cd2ccdbacf490cb9b574720989e69c3a427159e3059b85fcadc6d1b04d5ed86f00000020db33bd7315d4ef959509491271cc0b733345aa322986b6b3490dea926cc036a02bbbf06acfeea203c81dc858f5b9f865eda979478e7b1b2a70660212ad8e411ba812df6affff7f2000000000
950009f954b173e1932e44aafc432a0171c2b4c755f11cd479cf3bae8da4d82bcb87fc000000206fd85e4db0d1c6adfc859b05e35971423a9ce689097274b5b90c49cfbacd2ccd3bb86fd84bd65820432eb446ddb8e90be9caba4f10e4eb79a414b31066cb618f0015df6affff7f2000000000
950010e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a00000020fc87cb2bd8a48dae3bcf79d41cf155c7b4c271012a43fcaa442e93e173b154f9153f4a5e0b2934460eda12e4a427a7125d11e165c771a529056b72135d2697cc5817df6affff7f2000000000

Vectors S11 and M12 use a header source that holds the 11 blocks ending at the tip: the table above plus a header at height 950000, block hash a7259cbb2bde89b111fb6b7a61f1ce9ebeb2088db84f2f1e00933598fa4e9f23:

00000020d50cbe4fa99f43bdcd39efc070f7635f17b65aa6cb99fd70be0f3b6375213c42a59eb7b873142035ddceaee8caa686bb7ece1e9ee4ab72e2ba46314439191194e8ffde6affff7f2000000000

Their median time past is 1793002400. The table alone holds no header at height 950000, so it gives no median time past.

Vector M22 uses a header source that is the table above plus the block of CF, at height 949,999, block hash 18fb1eb3ef350fad0145f44278a930e575156e6c8ebc168738328453508c6afb:

000000200b21c7e7ebd8f56f14cf86e3184298b27152624f94d981c89691a359265aba67d5a41d520d3d2ba29119cbde4eb4adc93e164d822ea42243404d87501a16466990fdde6affff7f2000000000

Transactions

NameTxidBytes
A12c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee34401000000010ddbe8f7bd041d50ea45fa1d9abc6c62fc35e5e91cb1ef61d2c3ba08c72a75ea000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P1e2127516adc12a98fdc758e7d6ab36c38505cb6731f6c9b68c3cdc02b3a33896010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006b483045022100afd0af566d92711cc3fa91d6d1409ab41e1d4008a552760983f84dddd398c0f902205aa4926a19253ac987fce476bb8ab7aee1a14c882e0a6074fde19ab0eff4da174121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
A2ecd202a719806cfd5e5a5d768878512bc440a3239e49708a7ab4ea98bc618ee601000000012dd251ad7d3437397d359f7c7df83f01af6c7963934222956785a790dc39d99a000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
B28e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c0100000001e68e61bc98eab47a8a70499e23a340c42b517888765d5a5efd6c8019a702d2ec000000006a47304402207c91686d795c90eabf584a221b1e0cba9145e9e1b0c018b11e4a8b54f658f6eb02204c28638b09f98366a64030670ceae2a0137f2091fc97dd2e4cf962b9a43fc9f84121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
C204f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a01000000015c6994e55ef5d3098cb0dffcf4037ca0e419edeeaa1cd720b0d4d90c9f69168e000000006a4730440220416b977da3d863f1dfac7509c20c589bc04c143bbe1afbad725f17fe5284edc602201da34b01f7c79181a61aa61007d948922803e90b3820ee1c3bf56850b04e7c174121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff013c860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
D283a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db701000000019a2368a6fba9d56a3354d5401d646f5ad975131f635937d3f1d002c4b7aff204000000006a4730440220732a8993c5983880684b0b66096023448fd931f0baf7b365eac4165817b6887f02202b318fc1e6dbff167395bf1df60cf1b8eaac4bd581e1829e5622c29a957bb8c54121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff010a860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
A305e134ab77ba252ee5b17bc519fcfc24d23d70bf0c3f40eea65ca43ea53f61fe0100000001c06f2aa49efe4e17440086bf32ce7ac8deb7fa67e0e6780cc11bd99e0a2c00f2000000000151ffffffff0250c30000000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac50c30000000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
B36a5434d9c86b7a77bfec289f42d0344ff80d904d8542f1001779cad3fabf1b000100000001fe613fa53ea45ca6ee403f0cbf703dd224fcfc19c57bb1e52e25ba77ab34e105000000006b483045022100ce2bc41e423c1591aa4d91dfb6c23533915be8a161cd567ac2028180231f485b0220260aafb86d9b14f5a531bc3581e5c6179afa2931373c95d62c214983d0cfdc6e4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff011ec30000000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
C396c8a32fb64394dfc9357306687db01d67c8cadd4ae7483f3123f27f8e6e48f10100000001001bbffad3ca791700f142854d900df84f34d0429f28ecbf777a6bc8d934546a000000006a47304402205b3a7ab7817a61107393a0db81201417e4ad5db9957d52bf8bcfeeb997affe5a022021afc250c0f0715d92b416f6d04a8343b4b9942d02f7f0427f9eb0ea0bd84ef34121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff01ecc20000000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P3215984478daf11bbe5da2cd5946792e2a1247f11f644eb7ed95e49e27ce56da60100000002f1486e8e7ff223313f48e74addcac8671db07d68067335c9df9443b62fa3c896000000006b483045022100943569633e37774ece3788de136b1dbc44e81f39f9e6859ec5674dc4c7576fe902202be98d80bed53af0ae6e4d7696acc412c00ec52cd92ba6b3e7766d9dcbd4918d4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3fffffffffe613fa53ea45ca6ee403f0cbf703dd224fcfc19c57bb1e52e25ba77ab34e105010000006a473044022045235ccc847fa7db2d9763ba03fde894bdd9fda3d1fa3dd341880a6450e25fef02205722e2f22b7db4c31e80016137c7015f0d8ce9a275fe93fec0a96441aeffd2154121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff010a860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
A42749e001f0e6a84653059d4a2404641852717ebd373d935d0ec80b240afd8bae01000000017833ba4d7927e865248d4a7f845ca3b2a589f54251ada803645bdd1a22367b07000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
B46208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a5950100000001ae8bfd0a240bc80e5d933d37bd7e7152186404244a9d055346a8e6f001e04927000000006b4830450221009bc8d449beb818a25683dd702c185d33c884a1e62ec357f134a6ad5ca3d30fbd02204cdf06d8d1e5aa5d29ce56e79bf89749799632e47e435c58e6083c1aad8b77aa4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P4df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c010000000295a59779b32c26b267bfd4e063f1ca376b311245e6beaa67b1df955757df0862000000006b483045022100a95750632f4bcdad72f1aa47887c1bb8de0cd8facd972b4760a0b0d81a4f97f602204d4a95dd315d3d0e4ed926b5d46a7683418f7d32be0c06eded7e094d9136e2f54121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff6b4600284461ce7a434d3f6043861fdbdb33abcb36cbb7b0286ecdec44db2137000000006a47304402206b60963ab400117c56cc2237e86e661ea826f2420cdc86d3a9aaed3095042ff8022015c12482686d813cee12bb3d75c76bdd6a8339b7419c1d6c0750e92a93329d124121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016cfb0100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
E5ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a30100000001635947ef12b20d2b411090d5ca4db8377624988820ec1d22fad13dcca46a6384000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
BADSIG664569513982851cb5aefe29541ddf7de327a14206111191b9d5c07bfa59a60d010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006b48304502210082ac64baa07fab3df18f289ca1a8e5ebd809f641b40950640c2c0ae91875ab09022066bd7ba5ab08c7a6498db0e2ebdbce76fdc84e443416e640adf4434d56609a5c4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
RICH8b2fa28e38610df8d9038d48e1035213d8345cfbe38262c5e78159eac52297ce010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006a47304402205d8889878571c949d3d9367a93b628a83cdfedabc212d6a8da8424fb47fd89e90220254d3a6f57dd7093edccfb18d6ecb86cf7e6b0e34dcba89717eb2792a0b9d4b74121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff01a1860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
LATEd35962714bdb0a3c002e03fffaae05a4700152e23bc5f795f146dedc908d92da010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006b483045022100931d7375eda07bac7fe325d23f826af1feb84310a51a9a72c9727c4e7f4a6c45022004fb05b964cdbb48b733eda5046246af8c994976cfa0e67065f396e373bc440b4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3feffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac047f0e00
Xe2127516adc12a98fdc758e7d6ab36c38505cb6731f6c9b68c3cdc02b3a33896010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006b483045022100afd0af566d92711cc3fa91d6d1409ab41e1d4008a552760983f84dddd398c0f902205aa4926a19253ac987fce476bb8ab7aee1a14c882e0a6074fde19ab0eff4da174121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
Y2db39e9d04331e1e9065267846828abea8c20c94f082f57c9a816a3bc88a2c40010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006b4830450221009c3b9c7117e117dd12f2028b5fc303b1977dd40768e12577cc994697b6f562cd0220388fed744f6f9b90cce9eb3ca9e5772721f1124b51489f704b880f3f5ade64204121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff013c860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
BOTH21a2a6decd9c12fd240a0f39b9e829471221ea15797ff3625a5b0f9fce8df64b01000000029638a3b302dc3c8cb6c9f63167cb0585c336abd6e758c7fd982ac1ad167512e2000000006b483045022100dec41f2fd6230f48b0af685b35f9c45ec453a2fc36133049cf62901a50c331c1022000dbe2736de85c7c4c48a296bbf56de37cce5d4e0b7fc3f78e2588511d1030cf4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff402c8ac83b6a819a7cf582f0940cc2a8be8a8246782665901e1e33049d9eb32d000000006b483045022100fd6f9d78ae4a5d01027544a974a40fcc8d063385853a71a693946bdb11756b4702200d3db1df1c32853849dd96cf99ea07e59dfae28bf76f513baa694a0f51b545f04121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff01780c0300000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
A6a7274c4562611d5914aee0f2e991a81176f446ecde0d70eeefe6cfc6404b379b01000000010224dd1e481f0fd12f9932799188d9482329f46571dff21bf16b6c2cad5d3845000000000151ffffffff02a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac50c3000000000000038d548700000000
B66158929cc6db06e57aad638ac4b426e53ab9dc1593e33a5b08eabcae6c26f3eb01000000019b374b40c6cfe6efee700ddeec46f47611a891e9f2e0ae14591d6162454c27a7000000006a4730440220599490f1b3be6210bf02d60ea351275ac37363d4328673331797fd486f5cd80602205cc2658a0037268cd4aad8969a23fd411199ac4db474c3752031f51ffe87f6a64121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
X6c60f7125b095b56b4c703a279599203ccee550bf33811e53617f3c8c4431269001000000019b374b40c6cfe6efee700ddeec46f47611a891e9f2e0ae14591d6162454c27a7010000000152ffffffff011ec30000000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P6420adb2e2fd48ee95bae1e7e972b329a516106e6bfb1b6a321d399561822670f0100000002ebf3266caebcea085b3ae39315dcb93ae526b4c48a63ad7ae506dbc69c925861000000006b483045022100eb412527b03ad09d308102a5c12f9415c72af224c4572a66c5b44f14e20841d302207e9bcdede07338ce8a2c54ea5d22148799644ae867ad417526b9e391bd573c0b4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff902631448c3c7f61531e8133bf50e5ce3c209995273a704c6bb595b025710fc6000000006b483045022100c14d1b76d29288f7e3bf192b76dd420d7326dcc340985f179d38ed65880c6d3e022011a22815086b75d8aa366c128ec7dbfaec634d74cb19dc3f5a7cd60a8d56905c4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff0128490200000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
T646444bf849ea4136a9608b60996cc7d552d65d94c7183ae4f71a678add2de1e02010000000103254c9167ae1de0add271e079a00da53b5e54e6da92dffabb1ada240222f576000000000451515151ffffffff01a0860100000000000000000000
P6423a67c1ad73128861b4741229a462f66d851e60c32e571b9fc8482d279c0f3b30100000001021eded2ad78a6714fae83714cd9652d557dcc9609b608966a13a49e84bf4464000000000151ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
TL525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006a4730440220102209fb202e103f9259e1aa1f26d7ad374dee1adcc4c82c80fcd96a59cad36f02200959f5112871a54e0cb095175a5c8412dd3fe254f6d68a0a6bec25f887d37ec54121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3feffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac9f0bdf6a
TLATEc575cfff2bcd77600fb9f21d5708b69665aabdb98a3229ea38801664a45249b4010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006a47304402205dab601da164e7598ea5c65a02cfccebcd2904c8624aea6e4aa91855d5835c1b022031e3abbc37976f79b83d84e77c281b66015ae1b67e2991e5b18c75fc1c4927c14121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3feffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988aca00bdf6a
A86ee90c20d3bbd231987e0573f79320f22f9f150a9fa56ec5b5802a99421cd17c0100000001b40ed0e317387d6c4472f6f43bc4b8335e58066b8bd6953efea5f7548e8ec810000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P8db874543d0c2b32bfe1e38c17a15609285746d278a7abe919e334ae83ee5f98e01000000017cd11c42992a80b5c56ea59f0a159f2ff22093f773057e9831d2bbd3200ce96e000000006a4730440220627c9d22a7b2b75d9fc4b442a7ea26e714b721c33eca95ffdde38c9ee9ffac34022058d275c5181ba8c8b3eaad8e321b447eca8ad9d59559b21d33aafd1112cd4bcb4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
T01e214b7aee5ba78b228a3ec5c14c396cf0b0cca6d668dfc79034fde01206489430100000001e8e99c0d85a14ac57d4253af99fc4ab39097e853fc695b4c3fba2d6d8d203906000000000151ffffffff015f870100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
P013641df02bc7f167afff33c58aec95af11b55df782a1a38783d19ffbb11549a9401000000014389642001de4f0379fc8d666dca0c0bcf96c3145ceca328b278bae5aeb714e2000000006a47304402202bb6d3c07877f489109768b44b4122af671927bbce88412e9c8bd5271b923670022016e57d21e4d5f5aa20024e617524fb444d45ed78be9d559558e76b2734da39574121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff012d870100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
DSbdd08561a7c9ab11ad839dbe9760a564c31a34bbf352371b26be942a3bba9eef010000000244e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006a47304402204b03fadd92054f9538b9ecf5d70f5b8fcf22a9774d4c603a8763e1783065fa31022069bc82ae9e4eefc1f4ca1f646cf3813e5c450e016c48cbf5207d4698f8351d294121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff0ddbe8f7bd041d50ea45fa1d9abc6c62fc35e5e91cb1ef61d2c3ba08c72a75ea000000000151ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
CFfe8ef6f7bc70c02f4d05e03030aea556a7342298c52c3c2841ac13aa72c1104d010000000196c93e406e31b8c5dbfeb0e196372f821bcb4f658283102d1fd84f7cc71bab2c000000000151ffffffff0200000000000000001d006a046366747815019d57f040e087001d86955e34665a10eef59c654fa0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
CFS407a99aade12b75765162a6b5ff33750d4d66a076ab9b8895084a4fee5021f2901000000014d10c172aa13ac41283c2cc5982234a756a5ae3030e0054d2fc070bcf7f68efe010000006b483045022100a1a9c4609310d2382d6d598b359db2ebac99354c30510a7616cd7a267d7519f502204fb20d0214e3b505e255b4d611114c7d9cc3af4c623a0452148a1ff66134ff804121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff016e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000
CFUb93c53d9615c0a2bf6f72791a41abc329d70944630f4fd5dc894fd6c5cf5418c010000000144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c000000006a4730440220506fadc65c59834c4c9d82712d3f202cdb80b9ad08061c5f5bb2232491c8253f02207f676fd420928b4443b790b5b634e441a542f3d1484197aa5fb9bdbc6c30013c4121036f1c70084d945c9cf4e48a15c90089b078c0a82d78ce6bfb0f3243e38021a6b3ffffffff0200000000000000001d006a046366747815019d57f040e087001d86955e34665a10eef59c654f6e860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac00000000

Merkle paths

Each anchored transaction is in a block of its own, as the at pos; the other leaves are SHA-256(payment evidence test vector: filler + height + + index), except as follows. In the block of A8, the leaves at 2 and 3 are the first and the last 32 bytes of T64. In the block of T01, the leaf at 3 is R, 0000000000000000000451515151ffffffff0100000000000000000000000000 (internal byte order), so that T01's txid in internal byte order followed by R decodes as a transaction. The Electrum form gives pos and the siblings bottom-up; the BRC-74 path is its conversion (section 6).

NameHeightposSiblings (Electrum form)BRC-74 path
A195000117a7f67ff94372f106ab9f59422b9280fd2b0c981e67cf8dc66e3f6cdd9bbbc49<br>e4152cebe7bc09be26d234fb6c435cd211e742f1447b4a47bb55c6a70581d44cfef17e0e000202000049bcbbd9cdf6e366dcf87ce681c9b0d20f28b92294f5b96a102f3794ff677f7a010244e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c0101004cd48105a7c655bb474a7b44f142e711d25c436cfb34d226be09bce7eb2c15e4
A295000210aac0a69b2a97e02a6f103a2309ca105cb715d44ddfc99cf51c74e8b28b61786<br>ab3baadd2384b398f79c90082741f7a55fa2570d11c7b2b10d08eef975626d31fef27e0e00020200008617b6288b4ec751cf99fcdd445d71cb05a19c30a203f1a6027ea9b2690aac0a0102e68e61bc98eab47a8a70499e23a340c42b517888765d5a5efd6c8019a702d2ec010100316d6275f9ee080db1b2c7110d57a25fa5f7412708909cf798b38423ddaa3bab
A39500031f262106acbcd5b200ba686b689a00e1b2b874c1d79f0d9847533439edd020e0a<br>bf044d4fc3d0afa6a7ea035a99d55498080fadfee0f711705da8c9f8a0afe9b7fef37e0e00020200000a0e02dd9e43337584d9f0791d4c872b1b0ea089b686a60b205bcdcb6a1062f20102fe613fa53ea45ca6ee403f0cbf703dd224fcfc19c57bb1e52e25ba77ab34e105010100b7e9afa0f8c9a85d7011f7e0fead0f089854d5995a03eaa7a6afd0c34f4d04bf
A4950004148bdce1503e9475ae3af4f2468e5d1a567aee41f50d5a6c4e2b54532abd91ed0<br>0b5172355c1a44629cdb6f26e4503be43a6b55498d98108defec26e1cfaf844ffef47e0e0002020000d01ed9ab3245b5e2c4a6d5501fe4ae67a5d1e568244fafe35a47e90315cebd480102ae8bfd0a240bc80e5d933d37bd7e7152186404244a9d055346a8e6f001e049270101004f84afcfe126ecef8d10988d49556b3ae43b50e4266fdb9c62441a5c3572510b
E59500064ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a3<br>6b157ae9550c8fac7e5aab7c7121162e30ae5cb397a4bd97a661df741d2fcd44<br>9655485f14b20de881eefc0d22692ea5c3d9b724db6afe9206fbeb30eb5885b8fef67e0e0003020402a367ee8f4c2ee28a0e473067f46d9d71b29978060ef39efdb4df18bd14831ced0501010301010000b88558eb30ebfb0692fe6adb24b7d9c3a52e69220dfcee81e80db2145f485596
A6950007137da0e44e17db4fc7079ecdf38296b0800a963e7b5dbbc23564c5c139654e33b<br>96fc5df8ed76f78f4e603fccb74d461d416b8131d0a11efbe4336b51d9ad2c44fef77e0e00020200003be35496135c4c5623bcdbb5e763a900086b2938dfec7970fcb47de1440eda3701029b374b40c6cfe6efee700ddeec46f47611a891e9f2e0ae14591d6162454c27a7010100442cadd9516b33e4fb1ea1d031816b411d464db7cc3f604e8ff776edf85dfc96
T649500081ce32ab879aec2243f097a557d39e11844730e0e7145c536d8c9e803619b13f6d<br>cd865c7615cc3a4059dea1d8a8c6f582579e3da49e6e7f96599eb8fe07af4696fef87e0e00020200006d3fb11936809e8c6d535c14e7e0304784119ed357a597f04322ec9a87ab32ce0102021eded2ad78a6714fae83714cd9652d557dcc9609b608966a13a49e84bf44640101009646af07feb89e59967f6e9ea43d9e5782f5c6a8d8a1de59403acc15765c86cd
A8950009161fe9043151ceafaeb5d8c4f8ff45ba68fe1c74c4398d99ece9268c496f6222d<br>6444bf849ea4136a9608b60996cc7d552d65d94c7183ae4f71a678add2de1e02fef97e0e00020200002d22f696c46892ce9ed998434cc7e18fa65bf48f4f8c5debfaea1c154390fe6101027cd11c42992a80b5c56ea59f0a159f2ff22093f773057e9831d2bbd3200ce96e010100021eded2ad78a6714fae83714cd9652d557dcc9609b608966a13a49e84bf4464
T0195001020000000000000000000000000001ffffffff5151515104000000000000000000<br>899ba7a5d3c9e32cf1f2068b1c59a6dd0b83b24ab979b26787cb91df12b7e68bfefa7e0e00020202024389642001de4f0379fc8d666dca0c0bcf96c3145ceca328b278bae5aeb714e203000000000000000000000451515151ffffffff01000000000000000000000000000100008be6b712df91cb8767b279b94ab2830bdda6591c8b06f2f12ce3c9d3a5a79b89
CF949999103ea315f3d30238103cd439d76d566d1ed1b9a7b45b2aa8ad018f1cfc8f369d2<br>3fad8334668a72fe171a229270c0899d55a9ec45983ea45e2621e332908c9706feef7e0e0002020000d269f3c8cff118d08aaab2457b9a1bedd166d5769d43cd038123303d5f31ea0301024d10c172aa13ac41283c2cc5982234a756a5ae3030e0054d2fc070bcf7f68efe01010006978c9032e321265ea43e9845eca9559d89c07092221a17fe728a663483ad3f

Four vectors use a path other than the conversion:

PathWhat it isBRC-74 path
A1-junkA1's path with two more level-0 nodes, at offsets 2 and 3, that are not the block's: the node they give at offset 1 of level 1 differs from the one the path declares therefef17e0e000204000049bcbbd9cdf6e366dcf87ce681c9b0d20f28b92294f5b96a102f3794ff677f7a010244e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c020026dcbc75da62047ad4739ef3256d17ddc8d615e6b3d0d8d7e40428637b76de440300b5a08be98684587105e56417da2f038e6401968d43ff1dfa5b9b77b34e1ba2dc0101004cd48105a7c655bb474a7b44f142e711d25c436cfb34d226be09bce7eb2c15e4
A1-conflictA1's block with the third transaction and its duplicate also at level 0, and at offset 1 of level 1 a hash that is not the one they givefef17e0e000204000049bcbbd9cdf6e366dcf87ce681c9b0d20f28b92294f5b96a102f3794ff677f7a010244e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c0202967ea168a99425d700013485381d5ba0d488e4af6e5c92d92190659a52ae94d30301010100463834cdc4f8debcc79ec98967b74db7b04209cd7f12af1104daf5508cb860c2
A8-compoundA8's block whole at level 0, nothing at level 1: offsets 2 and 3 hold the two halves of T64's bytes, a pair that decodes as a transaction and is not on A8's own pathfef97e0e00020400002d22f696c46892ce9ed998434cc7e18fa65bf48f4f8c5debfaea1c154390fe6101027cd11c42992a80b5c56ea59f0a159f2ff22093f773057e9831d2bbd3200ce96e0202010000000103254c9167ae1de0add271e079a00da53b5e54e6da92dffabb1ada0300240222f576000000000451515151ffffffff01a086010000000000000000000000
A2-flagA2's path with the flag of the node at offset 0 of level 0 changed from 00 to 04, which BRC-74 does not define; the hash after it is unchangedfef27e0e00020200048617b6288b4ec751cf99fcdd445d71cb05a19c30a203f1a6027ea9b2690aac0a0102e68e61bc98eab47a8a70499e23a340c42b517888765d5a5efd6c8019a702d2ec010100316d6275f9ee080db1b2c7110d57a25fa5f7412708909cf798b38423ddaa3bab

Material

An Atomic BEEF here is 01010101, the subject's txid in internal byte order, and a BRC-62 V1 BEEF (0100beef) carrying the paths listed, in order, and then the transactions listed, in order, each anchored one with the index of its path. Where a vector says V2, the BEEF is a BRC-96 V2 BEEF (0200beef) in the same order, each anchored transaction in format 01 with its path's index, each one listed as txid only in format 02, and each other in format 00. Its length and SHA-256 confirm the bytes. Records are raw transactions and Electrum-form paths, by name, from the tables above.

Statements

Equality: identical bytes of the canonical form.

S1: distance 1, every check run

  • Material: Atomic BEEF of P1: paths A1; transactions A1 (path 0), P1; 433 bytes, SHA-256 63b6ac11d00e79ad817f1942305428d0114c0ce79f0e9224cae3df1be26079f0.
  • Inputs: status handed-to-broadcaster; a conflict check at 1793318340, kind own-node, scope unconfirmed, found false.
{"anchors":[{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001,"txid":"2c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee344"}],"conflicts":{"at":1793318340,"checked":true,"found":false,"kind":"own-node","scope":"unconfirmed"},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":{"bytes":192,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"handed-to-broadcaster"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"e2127516adc12a98fdc758e7d6ab36c38505cb6731f6c9b68c3cdc02b3a33896","unconfirmed":["e2127516adc12a98fdc758e7d6ab36c38505cb6731f6c9b68c3cdc02b3a33896"],"unresolved":[],"validated":["e2127516adc12a98fdc758e7d6ab36c38505cb6731f6c9b68c3cdc02b3a33896"],"validation":"all","version":"bsv-payment-evidence/v1"}

S2: a chain of three, every check run

  • Material: Atomic BEEF of D2: paths A2; transactions A2 (path 0), B2, C2, D2; 816 bytes, SHA-256 4dfaa602f47e4720d77226c76f49576775c06442aca3a7df4a02ba9c9fa4b6ac.
{"anchors":[{"blockHash":"64a53adabc6a36de2c5176485d47e64c06f56d1b588e638ba8c7d349bdc459fc","height":950002,"txid":"ecd202a719806cfd5e5a5d768878512bc440a3239e49708a7ab4ea98bc618ee6"}],"conflicts":{"checked":false},"distanceMax":3,"distanceMin":3,"fullyAnchored":true,"lowestFeeRate":{"bytes":191,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","unconfirmed":["04f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a","83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","8e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c"],"unresolved":[],"validated":["04f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a","83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","8e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c"],"validation":"all","version":"bsv-payment-evidence/v1"}

S3: the same chain, distance only

  • Material: Atomic BEEF of D2: paths A2; transactions A2 (path 0), B2, C2, D2; 816 bytes, SHA-256 4dfaa602f47e4720d77226c76f49576775c06442aca3a7df4a02ba9c9fa4b6ac.
  • Inputs: distance only.
{"anchors":[{"blockHash":"64a53adabc6a36de2c5176485d47e64c06f56d1b588e638ba8c7d349bdc459fc","height":950002,"txid":"ecd202a719806cfd5e5a5d768878512bc440a3239e49708a7ab4ea98bc618ee6"}],"conflicts":{"checked":false},"distanceMax":3,"distanceMin":3,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","unconfirmed":["04f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a","83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","8e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c"],"unresolved":[],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S4: the same chain from the receiver's records, the path in Electrum form, distance only

  • Material: records: transactions A2, B2, C2, D2; the Electrum-form path of A2; payment D2.
  • Inputs: distance only.
{"anchors":[{"blockHash":"64a53adabc6a36de2c5176485d47e64c06f56d1b588e638ba8c7d349bdc459fc","height":950002,"txid":"ecd202a719806cfd5e5a5d768878512bc440a3239e49708a7ab4ea98bc618ee6"}],"conflicts":{"checked":false},"distanceMax":3,"distanceMin":3,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","unconfirmed":["04f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a","83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","8e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c"],"unresolved":[],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S5: an uneven diamond: longest path 3, shortest 1

  • Material: Atomic BEEF of P3: paths A3; transactions A3 (path 0), B3, C3, P3; 999 bytes, SHA-256 8b8bd197f55ef26145ea1fee3a87a32fd38dc98a05498f21a35fc839496d2828.
{"anchors":[{"blockHash":"4ef4e7bfd2500d3ef2c4b89cce091e27feb0f1a82a4ceaca0395f35b9827eda7","height":950003,"txid":"05e134ab77ba252ee5b17bc519fcfc24d23d70bf0c3f40eea65ca43ea53f61fe"}],"conflicts":{"checked":false},"distanceMax":3,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":{"bytes":339,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"215984478daf11bbe5da2cd5946792e2a1247f11f644eb7ed95e49e27ce56da6","unconfirmed":["215984478daf11bbe5da2cd5946792e2a1247f11f644eb7ed95e49e27ce56da6","6a5434d9c86b7a77bfec289f42d0344ff80d904d8542f1001779cad3fabf1b00","96c8a32fb64394dfc9357306687db01d67c8cadd4ae7483f3123f27f8e6e48f1"],"unresolved":[],"validated":["215984478daf11bbe5da2cd5946792e2a1247f11f644eb7ed95e49e27ce56da6","6a5434d9c86b7a77bfec289f42d0344ff80d904d8542f1001779cad3fabf1b00","96c8a32fb64394dfc9357306687db01d67c8cadd4ae7483f3123f27f8e6e48f1"],"validation":"all","version":"bsv-payment-evidence/v1"}

S6: one input whose source is not held, every check run

  • Material: Atomic BEEF of P4: paths A4; transactions A4 (path 0), B4, P4; 773 bytes, SHA-256 54b7baac8d64b816291290e1b75c26294433be4ef89ee44328cacb45088dfa35.
{"anchors":[{"blockHash":"ee55e78df915a761c888acb74bf87c5290c24af8a170e8510e7e43f6104e2916","height":950004,"txid":"2749e001f0e6a84653059d4a2404641852717ebd373d935d0ec80b240afd8bae"}],"conflicts":{"checked":false},"distanceMax":null,"distanceMin":2,"fullyAnchored":false,"lowestFeeRate":{"bytes":192,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c","unconfirmed":["6208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a595","df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c"],"unresolved":[{"txid":"3721db44eccd6e28b0b7cb36cbab33dbdb1f8643603f4d437ace61442800466b","vout":0}],"validated":["6208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a595"],"validation":"partial","version":"bsv-payment-evidence/v1"}

S7: the same from the receiver's records, distance only

  • Material: records: transactions A4, B4, P4; the Electrum-form path of A4; payment P4.
  • Inputs: distance only.
{"anchors":[{"blockHash":"ee55e78df915a761c888acb74bf87c5290c24af8a170e8510e7e43f6104e2916","height":950004,"txid":"2749e001f0e6a84653059d4a2404641852717ebd373d935d0ec80b240afd8bae"}],"conflicts":{"checked":false},"distanceMax":null,"distanceMin":2,"fullyAnchored":false,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c","unconfirmed":["6208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a595","df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c"],"unresolved":[{"txid":"3721db44eccd6e28b0b7cb36cbab33dbdb1f8643603f4d437ace61442800466b","vout":0}],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S8: the payment is itself an anchor, its path in Electrum form

  • Material: records: transactions E5; the Electrum-form path of E5; payment E5.
{"anchors":[{"blockHash":"ab14e92c0acb7212d9a1219e6c468b0f2c4ee53a7c351486bf99e916dfa1f90f","height":950006,"txid":"ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a3"}],"conflicts":{"checked":false},"distanceMax":0,"distanceMin":0,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":5,"event":"mined"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a3","unconfirmed":[],"unresolved":[],"validated":[],"validation":"all","version":"bsv-payment-evidence/v1"}

S9: a signature by the wrong key, distance only

  • Material: Atomic BEEF of BADSIG: paths A1; transactions A1 (path 0), BADSIG; 433 bytes, SHA-256 078b4cf6087ea739dd9987c131aa1f75b78383c482ccf7cc5eb9885ffe09a694.
  • Inputs: distance only.
  • Note: For a maker that has not run check 1 on this material. A maker that has run it refuses (M6) and makes no distance-only statement about it (section 2.3).
{"anchors":[{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001,"txid":"2c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee344"}],"conflicts":{"checked":false},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"664569513982851cb5aefe29541ddf7de327a14206111191b9d5c07bfa59a60d","unconfirmed":["664569513982851cb5aefe29541ddf7de327a14206111191b9d5c07bfa59a60d"],"unresolved":[],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S10: a Merkle path above the header source's tip: not checked, the walk goes on

  • Material: Atomic BEEF of D2: paths A2; transactions A2 (path 0), B2, C2, D2; 816 bytes, SHA-256 4dfaa602f47e4720d77226c76f49576775c06442aca3a7df4a02ba9c9fa4b6ac.
  • Inputs: the header source is the table cut at its tip, height 950001.
{"anchors":[],"conflicts":{"checked":false},"distanceMax":null,"distanceMin":null,"fullyAnchored":false,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001},"txid":"83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","unconfirmed":["04f2afb7c402d0f1d33759631f1375d95a6f641d40d554336ad5a9fba668239a","83a6965907f29d1b0561a9da97c7fccaf160aa38dbb2a8a5cfad4d5745362db7","8e16699f0cd9d4b020d71caaeeed19e4a07c03f4fcdfb08c09d3f55ee594695c","ecd202a719806cfd5e5a5d768878512bc440a3239e49708a7ab4ea98bc618ee6"],"unresolved":[{"txid":"9ad939dc90a785679522429363796caf013ff87d7c9f357d3937347dad51d22d","vout":0}],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S11: a lock time given as a time, below the median time past

  • Material: Atomic BEEF of TL: paths A1; transactions A1 (path 0), TL; 432 bytes, SHA-256 e3bd46b61095b816c1987425c42261de15430961a55a9a9a3e4468264b223291.
  • Inputs: the header source is the table plus the header at height 950000 given below it.
{"anchors":[{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001,"txid":"2c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee344"}],"conflicts":{"checked":false},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":{"bytes":191,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf","unconfirmed":["525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf"],"unresolved":[],"validated":["525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf"],"validation":"all","version":"bsv-payment-evidence/v1"}

S12: the same, without a header the median time past needs: left out

  • Material: Atomic BEEF of TL: paths A1; transactions A1 (path 0), TL; 432 bytes, SHA-256 e3bd46b61095b816c1987425c42261de15430961a55a9a9a3e4468264b223291.
  • Note: The header source is the table, which holds no header at height 950000, so the median time past of the 11 blocks ending at the tip cannot be computed.
{"anchors":[{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001,"txid":"2c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee344"}],"conflicts":{"checked":false},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf","unconfirmed":["525c61889807b4ba61f16c1f71f91d6ec30e794c8ff6f8727cf9b986bbc35acf"],"unresolved":[],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

S13: a script the maker cannot evaluate: left out, validation partial

  • Material: Atomic BEEF of P6: paths A6; transactions A6 (path 0), B6, X6, P6; 872 bytes, SHA-256 b9b3fe3ca0e6d200c60600dff944f8a4be80c74c282608bbdd7e4d21b82aeea5.
  • Note: A6 is mined at 950007, above the Chronicle activation height, so OP_2MUL (0x8d) is enabled for its output and X6's input evaluates to true under the rules in force. This vector is for a maker whose interpreter does not implement OP_2MUL, or treats it as disabled: it cannot complete the check, so it leaves X6, and P6, which spends it, out of the validated set. A maker that implements OP_2MUL validates both, and its statement differs (validation all); no vector is given for it.
{"anchors":[{"blockHash":"a036c06c92ea0d49b3b6862932aa4533730bcc711249099595efd41573bd33db","height":950007,"txid":"a7274c4562611d5914aee0f2e991a81176f446ecde0d70eeefe6cfc6404b379b"}],"conflicts":{"checked":false},"distanceMax":2,"distanceMin":2,"fullyAnchored":true,"lowestFeeRate":{"bytes":191,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"420adb2e2fd48ee95bae1e7e972b329a516106e6bfb1b6a321d399561822670f","unconfirmed":["420adb2e2fd48ee95bae1e7e972b329a516106e6bfb1b6a321d399561822670f","6158929cc6db06e57aad638ac4b426e53ab9dc1593e33a5b08eabcae6c26f3eb","c60f7125b095b56b4c703a279599203ccee550bf33811e53617f3c8c44312690"],"unresolved":[],"validated":["6158929cc6db06e57aad638ac4b426e53ab9dc1593e33a5b08eabcae6c26f3eb"],"validation":"partial","version":"bsv-payment-evidence/v1"}

S14: a pair off the anchor's own path that decodes as a transaction: the anchor holds

  • Material: Atomic BEEF of P8: paths A8-compound; transactions A8 (path 0), P8; 466 bytes, SHA-256 1467a7df31c392303975b6ddf4268b6fb02f5b0844187d1d7d38f0c05f8b5007.
  • Note: Offsets 2 and 3 of A8's path are the two halves of T64's bytes. The fold of A8's own path hashes A8 with offset 0, then their parent with the node computed from offsets 2 and 3, and never that pair, so condition (e) holds.
{"anchors":[{"blockHash":"f954b173e1932e44aafc432a0171c2b4c755f11cd479cf3bae8da4d82bcb87fc","height":950009,"txid":"6ee90c20d3bbd231987e0573f79320f22f9f150a9fa56ec5b5802a99421cd17c"}],"conflicts":{"checked":false},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":{"bytes":191,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"db874543d0c2b32bfe1e38c17a15609285746d278a7abe919e334ae83ee5f98e","unconfirmed":["db874543d0c2b32bfe1e38c17a15609285746d278a7abe919e334ae83ee5f98e"],"unresolved":[],"validated":["db874543d0c2b32bfe1e38c17a15609285746d278a7abe919e334ae83ee5f98e"],"validation":"all","version":"bsv-payment-evidence/v1"}

S15: S6 as a BEEF V2 that carries Z4 by txid only

  • Material: Atomic BEEF (V2) of P4: paths A4; transactions A4 (path 0), Z4 (txid only), B4, P4; 806 bytes, SHA-256 018e960e6caeee1fa521da01bf18d91524e13f95ead1704b5557482efa19231f.
  • Note: The same statement as S6: a txid-only entry holds no transaction, so the input that spends Z4 is unresolved (section 2.1).
{"anchors":[{"blockHash":"ee55e78df915a761c888acb74bf87c5290c24af8a170e8510e7e43f6104e2916","height":950004,"txid":"2749e001f0e6a84653059d4a2404641852717ebd373d935d0ec80b240afd8bae"}],"conflicts":{"checked":false},"distanceMax":null,"distanceMin":2,"fullyAnchored":false,"lowestFeeRate":{"bytes":192,"satoshis":50},"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c","unconfirmed":["6208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a595","df3f2029548cb31866c12a73d1ff6da9e3515acf66ce6c145ef34ce2e2ef9d6c"],"unresolved":[{"txid":"3721db44eccd6e28b0b7cb36cbab33dbdb1f8643603f4d437ace61442800466b","vout":0}],"validated":["6208df575795dfb167aabee64512316b37caf163e0d4bf67b2262cb37997a595"],"validation":"partial","version":"bsv-payment-evidence/v1"}

S16: a payment that is a confiscation transaction: left out, validation none

  • Material: Atomic BEEF of CFU: paths A1; transactions A1 (path 0), CFU; 470 bytes, SHA-256 9235e27de1c705025668181fd6113f2ad27e82952b3d8c761b4cc3d0abac0aeb.
  • Note: CFU's first output begins 006a0463667478, so CFU is a confiscation transaction, which SV Node accepts only when it is whitelisted. A maker cannot know the whitelist, so it cannot complete the checks on CFU: CFU is left out, and not refused (section 2.3).
{"anchors":[{"blockHash":"d73120d63050557443631be249d95eaaae2ee72d05375d199b9d8d33e34c5e9e","height":950001,"txid":"2c0746d0edc5d2afb97495acbcc4584087bdc07027360aa03b28cbf40e6ee344"}],"conflicts":{"checked":false},"distanceMax":1,"distanceMin":1,"fullyAnchored":true,"lowestFeeRate":null,"madeAt":1793318400,"status":{"depth":null,"event":"received"},"tip":{"blockHash":"e125c62d3654c2f138f1c39bb74c56181e6d325c38844fd30cc1939d701c493a","height":950010},"txid":"b93c53d9615c0a2bf6f72791a41abc329d70944630f4fd5dc894fd6c5cf5418c","unconfirmed":["b93c53d9615c0a2bf6f72791a41abc329d70944630f4fd5dc894fd6c5cf5418c"],"unresolved":[],"validated":[],"validation":"none","version":"bsv-payment-evidence/v1"}

Refusals by a maker

Equality: a refusal with the code shown, and no statement.

VectorInputCodeBasis
M1: truncatedthe material of S1 without its last byteMALFORMEDthe last transaction ends early (BRC-62 framing); the decoder is told its input is complete
M2: trailing bytethe material of S1 followed by one byte 00MALFORMEDa byte after the end of the BEEF
M3: an impossible declared lengthbelowMALFORMED4,294,967,295 transactions declared, one present
M4: a path whose root is not the header'sthe material of S1ANCHOR_MISMATCHthe header at 950001 differs from the one in the header source table in the first byte of its Merkle root
M5: outputs above inputsAtomic BEEF of RICH: paths A1; transactions A1 (path 0), RICH; 432 bytes, SHA-256 3c4ae8c809029759b683a3dd737d4d54f8271415e466d561142858e6b334f5a4VALUE_CREATED100,001 out of 100,000 in
M6: a signature by the wrong keyAtomic BEEF of BADSIG: paths A1; transactions A1 (path 0), BADSIG; 433 bytes, SHA-256 078b4cf6087ea739dd9987c131aa1f75b78383c482ccf7cc5eb9885ffe09a694SCRIPT_FAILEDthe input's script does not end true
M7: a lock time not yet reachedAtomic BEEF of LATE: paths A1; transactions A1 (path 0), LATE; 433 bytes, SHA-256 5de525cb23c0b6bc15f69126da6c11eaa31fe95d899e0df717f6c8d7b5f41759PREMATURE 950020 with sequence 0xfffffffe, judged for the block at 950011
M8: two spends of one outputAtomic BEEF of BOTH: paths A1; transactions A1 (path 0), X, Y, BOTH; 967 bytes, SHA-256 92c57a32e872b06868ddbd160b269796abc19ed9c76f194f24dcb6d82006391fCONFLICTX and Y both spend A1:0
M9: more transactions than the boundthe material of S2; bound of 3 transactionsOVER_BOUNDS2 reads four transactions; the bound is three
M10: a longer path than the boundthe material of S2; bound of distance 2OVER_BOUNDS2's longest path holds three unconfirmed transactions; the bound is two
M11: a 64-byte transaction as an anchorAtomic BEEF of P64: paths T64; transactions T64 (path 0), P64; 305 bytes, SHA-256 81883aefaac00f3eedaf51ac8aaf0c8bdc12948fddd7d881dd37e54f84a20fc4ANCHOR_MISMATCHT64 is exactly 64 bytes, so its path is no evidence (section 1, condition d)
M12: a lock time equal to the median time pastAtomic BEEF of TLATE: paths A1; transactions A1 (path 0), TLATE; 432 bytes, SHA-256 9ece889c41273845d410b1caa7bfb4f16c752e7a9536c28c3e260a72426c553c; the header source is the table plus the header at height 950000 given below itPREMATUREnLockTime 1793002400 with sequence 0xfffffffe; the median time past of the 11 blocks ending at 950010 is 1793002400
M13: an Atomic BEEF over the byte boundthe material of S1; bound of 432 bytes of materialOVER_BOUNDS1's material, the whole Atomic BEEF with its 36 bytes of prefix and subject, is 433 bytes; the bound is one byte less
M14: an Atomic BEEF with an unrelated transactionAtomic BEEF of P1: paths A1; transactions A1 (path 0), A2, P1; 520 bytes, SHA-256 ed83aeb8d4c55ed6d5bc67c5e4d6d81cb68c8ee77ab2b5d88e24d75345690765MALFORMEDA2 is neither P1 nor one of its ancestors (BRC-95)
M15: a txid twiceAtomic BEEF of P1: paths A1, A1; transactions A1 (path 0), A1 (path 1), P1; 631 bytes, SHA-256 b5d7f6ac76b275499306bc10dd0a148d131ea37a1d371bbb1f789fc22d5e240dMALFORMEDA1 is held twice
M16: the legacy version wordthe material of S1 with its BEEF version bytes 0100beef changed to efbe0001MALFORMEDefbe0001 is not a BRC-62 version
M17: a junk pair under a declared nodeAtomic BEEF of P1: paths A1-junk; transactions A1 (path 0), P1; 501 bytes, SHA-256 8584216fa12376a7b8937f5fbdcca91021cdf54f760a203113818231ffccf2c9MALFORMEDthe path is A1-junk: the node computed at offset 1 of level 1 differs from the declared one, which BRC-74 does not permit
M18: a declared sibling that conflicts with the nodes below itAtomic BEEF of P1: paths A1-conflict; transactions A1 (path 0), P1; 469 bytes, SHA-256 cfc5192f0ad74f99d3640b28514bad911b766479ff721502df02fd4bcfe695baMALFORMEDthe path is A1-conflict: the node at offset 1 of level 1, A1's own sibling there, differs from the one computed from offsets 2 and 3
M19: a level of the anchor's own path that decodes as a transactionAtomic BEEF of P01: paths T01; transactions T01 (path 0), P01; 432 bytes, SHA-256 4dc07f5aedfc3b5c57cdf7f6f9534669708da26922b20f941aa8e8553bab613cANCHOR_MISMATCHT01's txid, in internal byte order, followed by its sibling R decodes as a 64-byte transaction (section 1, condition e)
M20: a spend of an output an anchor also spendsAtomic BEEF of DS: paths A1; transactions A1 (path 0), DS; 474 bytes, SHA-256 3cfd4950db1cafd98eb99b0064935f00f353d17826ca8247b925d9d147f8f1aaCONFLICTDS spends A1:0 and the outpoint A1 itself spends, so it conflicts with a mined spend
M21: records over the byte boundrecords: transactions A2, B2, C2, D2; the Electrum-form path of A2; payment D2; distance only; bound of 768 bytes of materialOVER_BOUNDthe walk reads S4's four transactions, 659 bytes, and A2's path, 110 bytes as BRC-74 bytes, 769 in all; the bound is one byte less
M22: a spend of a confiscation output before 1,000 blocksAtomic BEEF of CFS: paths CF; transactions CF (path 0), CFS; 471 bytes, SHA-256 86c50c3bb0554dd4f760df91bfdde797c28a87991e265f7858dedd25b8955589; the header source is the table plus the header at height 949999 given below itPREMATURECF's first output begins 006a0463667478, so CF is a confiscation transaction; it is mined at 949,999, and the block after the tip, 950,011, is below 949,999 plus 1,000
M23: an undefined flag in a path no transaction namesAtomic BEEF of P1: paths A1, A2-flag; transactions A1 (path 0), P1; 543 bytes, SHA-256 83ae2550985e91da512b4ad005787dbfdd9ea547383d1c2db1ac993e2f55973dMALFORMEDthe second path is A2-flag, which no transaction names: its flag 04 leaves the node's length unknown, so the BEEF cannot be framed (section 2.1)
M24: an Atomic BEEF with an unrelated txid-only entryAtomic BEEF (V2) of P1: paths A1; transactions A1 (path 0), A2 (txid only), P1; 466 bytes, SHA-256 636958b5367f71efb47f52d3350d6f44ae6392be70bd32bf5634dc7adace92abMALFORMEDA2's entry carries only its txid, and no input of P1 names it, so it is not an ancestor (BRC-95)
M25: a statement over the maker's boundthe material of S1; status handed-to-broadcaster; a conflict check at 1793318340, kind own-node, scope unconfirmed, found false; bound of 867 bytes of statementOVER_BOUNDS1's statement is 868 bytes; the maker's bound on statement length is one byte less

M3's input, in full:

0101010144e36e0ef4cb283ba00a362770c0bd874058c4bcac9574b9afd2c5edd046072c0100beef00feffffffff01000000010ddbe8f7bd041d50ea45fa1d9abc6c62fc35e5e91cb1ef61d2c3ba08c72a75ea000000000151ffffffff01a0860100000000001976a9149b0cc517962e22315ce8b46fd4fdd02db0bab31988ac0000000000

M4's header source is the table above with the header at height 950001 replaced by:

000000206b0d72cc817bdfe98bc0ccb64c9c8c0a70774fe82939b6a50cff8db0fce17353fbac2f5d9533c2686ccf4c05aeb9bd51ed9e5ea108156765378a6e1209a309424002df6affff7f2000000000

Conversion of an Electrum-form branch

The anchor of S8, transaction E5 (txid ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a3), is at index 4 of a block of five, so its branch repeats the working hash at two levels:

{"block_height":950006,"merkle":["ed1c8314bd18dfb4fd9ef30e067899b2719d6df46730470e8ae22e4c8fee67a3","6b157ae9550c8fac7e5aab7c7121162e30ae5cb397a4bd97a661df741d2fcd44","9655485f14b20de881eefc0d22692ea5c3d9b724db6afe9206fbeb30eb5885b8"],"pos":4}

Its BRC-74 path, byte for byte:

fef67e0e0003020402a367ee8f4c2ee28a0e473067f46d9d71b29978060ef39efdb4df18bd14831ced0501010301010000b88558eb30ebfb0692fe6adb24b7d9c3a52e69220dfcee81e80db2145f485596

Level 0 holds E5 at offset 4 (flag 02) and offset 5 with flag 01; level 1 holds offset 3 with flag 01; level 2 holds offset 0 with flag 00 and its hash. The same branch with pos 12 leaves a bit over after its three siblings: refused MALFORMED. A branch of 65 siblings, its three repeated, with pos 0, is longer than any BRC-74 tree: refused MALFORMED.

Refusals by a reader

Equality: a refusal with the code shown. Each input is a change to the bytes of a statement above, S1 unless the change names another.

VectorChangeCode
R1: another versionthe final 1 of version changed to 2, in canonical formUNKNOWN_VERSION
R2: an unexpected fielda field "note":"" added, in canonical formMALFORMED_STATEMENT
R3: not the canonical form (one space)one space after {"anchors":MALFORMED_STATEMENT
R4: fields that disagree (fullyAnchored false, nothing unresolved)fullyAnchored set to false, in canonical formMALFORMED_STATEMENT
R5: conflicts.checked a number, not a booleanconflicts set to {"checked":0}, in canonical formMALFORMED_STATEMENT
R6: nested 33 deepa field x holding 32 nested empty arrays added, in canonical formMALFORMED_STATEMENT
R7: a validated transaction named as the source of an unresolved inputS6 with unresolved naming B4, output 0, in canonical formMALFORMED_STATEMENT
R8: an anchor named as the source of an unresolved inputS6 with unresolved naming A4, output 0, in canonical formMALFORMED_STATEMENT
R9: the payment validated, not fully anchoredS6 with validated set to all of its unconfirmed, in canonical formMALFORMED_STATEMENT
R10: a key twice, the second naming another version,"version":"bsv-payment-evidence/v2" added before the final }MALFORMED_STATEMENT
R11: the payment validated, one of its ancestors notS2 with validated holding B2 and D2 only and validation set to partial, in canonical formMALFORMED_STATEMENT
R12: a list out of orderS3 with unconfirmed in descending order, in canonical formMALFORMED_STATEMENT
R13: an entry twiceS6 with its unresolved entry given twice, in canonical formMALFORMED_STATEMENT
R14: a txid in capitalsthe anchor's txid in capital letters, in canonical formMALFORMED_STATEMENT
R15: a value section 2.5 does not listconflicts.kind set to own, in canonical formMALFORMED_STATEMENT
R16: a depth the tip does not giveS8 with tip.height one more, its status.depth unchanged, in canonical formMALFORMED_STATEMENT
R17: an anchor above the tiptip.height set to one less than the anchor's height, in canonical formMALFORMED_STATEMENT
R18: over the reader's boundnone; the reader's bound is 867 bytes, one less than S1's lengthOVER_BOUND
R19: an anchored payment with a second anchorS8 with S1's anchor added to anchors, in canonical formMALFORMED_STATEMENT
R20: one txid as two anchorsa second entry for the anchor's txid, at a height one less, after the first, in canonical formMALFORMED_STATEMENT
R21: a conflict check after the statementconflicts.at set to one more than madeAt, in canonical formMALFORMED_STATEMENT
R22: an output index no transaction can nameS6 with its unresolved entry's vout set to 4,294,967,296 (2^32), in canonical formMALFORMED_STATEMENT

Signature

The receiver key signs the canonical bytes of S1 as a BRC-77 message verifiable by anyone, with the pinned to 571fc1f4ed6fafc9cfaa07f77e12149cd95a29f5981bb4633f6f39e47397df19 (the maker draws it at random). Equality: identical bytes.

4242330103fb1aaf51797cd0551feeeacb42dfd98be2bbcd072e6d9445d3a2620b103c3adc00571fc1f4ed6fafc9cfaa07f77e12149cd95a29f5981bb4633f6f39e47397df193045022100d6baa4f0054d9235a8f9fcdd059c83b7360f4a058e0bc397796c466323c2434a02207733ce0babc4ec3cd64200ff2843428939f0a62eb18d6b27b0b1c84b2f147ba9

It verifies over the bytes of S1, and does not verify over the bytes of R3, the same object with one space added.

Implementations

A reference implementation exists: a module of a wallet that makes a statement from an Atomic BEEF or from the wallet's records, in either mode, converts Electrum-form branches, and reads statements. Its script checks run on the interpreter of the wallet's existing BEEF verifier, the one its incoming payments pass, and it counts an input as passed only when that verifier accepts it. That interpreter predates Chronicle, so the implementation leaves out, and never refuses, a transaction whose script uses an opcode Chronicle restored or a signature with the sighash bit 0x20, or a transaction of version 2 or above whose script fails there. It does not implement the relative lock times of section 2.3, check 3, either, and leaves out a transaction that needs one.

Security Considerations

A statement is not a guarantee. A fully anchored payment with validation all has valid spends from proven coins to the payment. It can still go unmined: a conflicting spend may reach miners first, or its fee may be too low for them. A statement records evidence; the receiver's own policy decides whether to accept the payment.

Who made it. A statement says what its maker checked. An unsigned statement from the payer, or from any party with an interest in the payment being accepted, is no evidence: relying on it is relying on that party's word. A receiver makes its own statement from the material, or reads one from a maker it trusts, signed (section 7) when it has travelled.

The header source. An anchor is only as good as the header that confirms it. A source that serves headers whose proof of work nobody checked lets whoever controls it turn any Merkle path into an anchor. A maker SHOULD use headers whose proof of work it has checked. A reader of another party's statement can check the tip and each anchor's height and block hash against its own headers.

A 64-byte transaction. A block header does not say how tall the block's Merkle tree is, and the txid of a 64-byte transaction is computed as an inner node of the tree is, the double SHA-256 of 64 bytes. That allows two attacks, and the anchor definition closes each. In the first, two sibling inner nodes, read together as a transaction, have a Merkle path to the real root: whoever orders a block's transactions can search for an order in which such a pair also parses as a transaction with an output anyone can spend. Condition (d) closes it, since a 64-byte transaction is never an anchor. In the second, a real 64-byte transaction is mined, and its two halves are offered as the bottom step of a path one level taller, so that a transaction whose txid is the first half appears proven; vector M19 builds that shape, a txid with 01 at byte 4 beside a sibling that completes a transaction. Condition (e) closes it, since no step of the own path may hash 64 bytes that decode as a transaction. Neither condition alone is enough. No ordinary payment needs a 64-byte transaction, which has 4 bytes for all of its scripts together. A miner who orders a block can place beside an honest transaction a sibling it searched for, so that the transaction's path fails (e); that payment is then refused, never wrongly accepted.

Bounds. A payment can have very many ancestors, and every script costs time to evaluate. A maker bounds the material's size in bytes and the walk before it does that work (section 2.1), and a maker that evaluates scripts for others SHOULD also limit the work each script may do. Reaching such a limit leaves a transaction unvalidated; it is never a refusal (section 2.3). A statement grows with the payment, since each unconfirmed transaction and each unresolved input adds an entry: one transaction of hundreds of thousands of inputs whose sources are not held gives a statement of tens of megabytes. A maker bounds the statement it emits, and a reader the bytes it parses, at 1,000,000 bytes by default for both (sections 2.1 and 5).

Frozen outputs. SV Node refuses a transaction that spends an output on its freeze lists (validation.cpp L2596-L2607). No header carries those lists, so the checks of section 2.3 do not cover them: a validated transaction can spend a frozen output and never be mined.

Observations age. found: false held at time at, a status held at madeAt, and the depth at tip. A later conflicting spend or a later block changes none of those fields.

The method as an oracle. An application that may call the method of section 8 with any txid could learn which transactions the wallet holds, if the wallet answered calls it has not permitted otherwise than calls about a transaction it does not hold. Section 8 gives both the same error. With atomicBEEF, the status is received unless the payment is an anchor, and a conflict check is one made for that call, so the answer depends on the bytes, the wallet's headers and that check, and on nothing the wallet's records hold.

Privacy. A statement lists txids of the payment's ancestry, and a signed one links the maker's key to the payment. A maker SHOULD give a statement only to whom the user chose, such as the application that asked about that payment.

Not tested

  • No mainnet or testnet run: the vectors use synthetic headers without proof of work.
  • A second implementation, written from this document over @bsv/sdk 1.10.4, shares no code with the reference, but it reads the same vectors file and has the same author. On this revision it agrees with every vector, S1 to S16, M1 to M25 and R1 to R22, with the conversion and the signature, and with the document's own tables and material descriptions, 71 checks in all; a randomised pass over altered materials, paths, branches and statements found no fault. None has been run over the Go or Python SDKs.
  • No vector covers the maturity of a coinbase output, an output created before Genesis or before Chronicle, a relative lock time before Genesis, a transaction of version 2 or above, or a signature with the sighash bit 0x20.
  • Confiscation and freezing: M22 spends a confiscation output before it matures, and S16 leaves out a confiscation transaction. No vector spends a confiscation output once mature, and none covers a frozen output, since no maker here holds a freeze list.
  • Vector S13 is for a maker whose interpreter lacks OP_2MUL. No maker that implements it has been run on that material, and the statement such a maker would make is not given.
  • No vector holds an ancestor beyond an anchor in an Atomic BEEF.
  • No reorganisation was run. Vector M4, a header whose Merkle root differs from the path's, has the shape of one.
  • No wallet offers the method of section 8, so no application has called it, and no capability manifest has declared it. The reference implementation makes the statement for its atomicBEEF argument, without the method's errors.
  • The conversion of section 6 has not been run on branches fetched from a live Electrum-protocol server.
  • No conflicting-spend observation was made: the vectors record the fields only.
  • The bounds on statement length are exercised at one value each: the reader's in R18 and the maker's in M25.
  • No wallet that reports ancestry distance today, BREAD in ElectrumSVP included, has produced a statement.

References

Was this helpful?

Search Beersy

Search standards by number, title, author or topic