Beersy
BRC-11

TSC Proof Format with Heights

identify the block they belong to by its hash, which means anyone checking one has to keep every block hash to look it up. This argues for using the block's height instead, roughly halving what a lightweight client needs to store.

Tone Engelchanged 1 May 20234 min read
target valuematch header averified block

Summary

Why
Merkle proofs need a way to point at the specific to check against, and identifying that block by hash requires bulky hash indices that double the storage cost of keeping headers locally.
What
BRC-11 adds "height" as a new target type for TSC merkle proofs, so a proof can point at a block by its position in the chain instead of by a hash.
How
A proof sets its to height and gives a plain integer (encoded as a Bitcoin VarInt in binary form), which lets the verifier jump straight to that block header in a flat, unindexed store of fixed 80 byte headers.

What this lets you do

  • Identify a block by height instead of hash in a merkle proof
  • Store block headers without building a hash-to-height index
  • Cut local header storage roughly in half
  • Look up a header directly by its fixed 80 byte offset
  • Verify a proof by matching the computed against the header at that height

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

Reference for an AI

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

The specification

Abstract

This is an argument for using block height as the standard for indexing within .

It argues for a backward compatible protocol extension in the short term and through deprecation, a long term reduction in the space cost of a usable local copy of block headers by a factor of two.

The referenced specification, the "Spec": TSC Merkle proof standardised format

Motivation

The Spec implies that a compatible implementation support the capability to lookup block hash and values, to confirm that they correspond to actual mined blocks.

The Project Babbage team has implemented a block header management system called primarily to support validating merkle proofs as defined in the Spec.

We have a focus on space efficiency as we target the full range of client application deployment scenarios, including mobile and IoT.

You hear that a full set of block headers is only 50MB and only grows at 4MB per year - and this is true - but it refers to the serialized binary space required for just the headers, without the indices required to implement the Spec.

Because the required indices are hash values (merkle root and block header hash), which together make up 64 of the 80 block header bytes, it is likely unavoidable that any implementation will be approximately the size of the headers themselves: To turn a hash into a height, the indices must list all the hash values paired with their height values.

While it is possible to use partial indices and trade index size for IO operations, the indices are not actually needed at all. As Elon says, "the best part is no part."

Stepping Back: What's the Point of Merkle Proofs?

The purpose of a merkle proof is to prove that a particular bit of data, a bitcoin transaction, was recorded at a particular location in the block chain.

The nodes in the proof enable the computation of what the merkle root should be for a block containing the transaction at a particular index position.

To complete the proof, it must be verified that the computed merkle root matches the actual merkle root of the target block.

Being given a merkle root value as part of the proof does NOT complete the proof.

The only thing that completes the proof is to confirm from a trusted copy of block headers that one exists with the computed merkle root value.

Being given a merkle root, block hash, or block header as part of the proof is only useful as an identifier for which block header to check in the trusted copy. If a matching block header isn't found, the proof is invalid, no matter what additional target values are provided.

Furthermore, if the trusted copy includes a merkle root index, then proof can be completed directly from the computed merkle root value: Look it up in your own index, if it is found, the proof is valid and the block is identified.

It is therefore the case, that the existing target and targetType values in a proof per the Spec are unnecessary.

It may actually be the case, that the only useful targetType would be height. With a height value, no indices are needed at all, the target block header can be found directly since all headers are exactly 80 bytes long. The trusted copy does not require any indices.

Specification

1. Add height as a supported targetType

In "Binary form", proofs reserve two bits of "flags" bytes (bits 1 and 2) to identify what the "JSON form" calls the targetType of the proof.

Here are the current and proposed values for targetType:

NameBinary Flags ValueJSON ValueBinary target formatJSON target format
Block Hashexisting0'hash' (default)32 bytes64 hex chars
Block Headerexisting1'header'80 bytes160 hex chars
Merkle Rootexisting2'merkleRoot'32 bytes64 hex chars
Heightnew3'height'Bitcoin VarIntinteger

2. Deprecate targetType Other Than height

As discussed in Motivation above, the existing target types and target values are irrelevant to being able to complete a merkle proof given the remaining values.

Implementations

The Project Babbage Chaintracks package currently implements the Spec with this extension.

A comparison of Chaintracks and the Pulse block header packages is listed under References.

References

Was this helpful?

Search Beersy

Search standards by number, title, author or topic