Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

Remove statement fields from Merkle proofs #129

Merged
merged 1 commit into from
Feb 23, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 21 additions & 31 deletions specs/data_structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ Data Structures
- [Public-Key Cryptography](#public-key-cryptography)
- [Merkle Trees](#merkle-trees)
- [Binary Merkle Tree](#binary-merkle-tree)
- [BinaryMerkleTreeProof](#binarymerkletreeproof)
- [BinaryMerkleTreeInclusionProof](#binarymerkletreeinclusionproof)
- [Namespace Merkle Tree](#namespace-merkle-tree)
- [NamespaceMerkleTreeProof](#namespacemerkletreeproof)
- [NamespaceMerkleTreeInclusionProof](#namespacemerkletreeinclusionproof)
- [Sparse Merkle Tree](#sparse-merkle-tree)
- [SparseMerkleTreeProof](#sparsemerkletreeproof)
- [SparseMerkleTreeInclusionProof](#sparsemerkletreeinclusionproof)
- [Erasure Coding](#erasure-coding)
- [Reed-Solomon Erasure Coding](#reed-solomon-erasure-coding)
- [2D Reed-Solomon Encoding Scheme](#2d-reed-solomon-encoding-scheme)
Expand Down Expand Up @@ -289,16 +289,13 @@ Note that rather than duplicating the last node if there are an odd number of no

Leaves and internal nodes are hashed differently: the one-byte `0x00` is prepended for leaf nodes while `0x01` is prepended for internal nodes. This avoids a second-preimage attack [where internal nodes are presented as leaves](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack) trees with leaves at different heights.

#### BinaryMerkleTreeProof
#### BinaryMerkleTreeInclusionProof

| name | type | description |
| ---------- | ----------------------------- | ----------------------------- |
| `root` | [HashDigest](#hashdigest) | Merkle root. |
| `key` | `byte[32]` | Key (i.e. index) of the leaf. |
| `siblings` | [HashDigest](#hashdigest)`[]` | Sibling hash values. |
| `leaf` | `byte[]` | Leaf value. |
| name | type | description |
| ---------- | ----------------------------- | --------------------------------------------------------------- |
| `siblings` | [HashDigest](#hashdigest)`[]` | Sibling hash values, ordered starting from the leaf's neighbor. |

A proof for a leaf in a [binary Merkle tree](#binary-merkle-tree).
A proof for a leaf in a [binary Merkle tree](#binary-merkle-tree), as per Section 2.1.1 of [Certificate Transparency (RFC-6962)](https://tools.ietf.org/html/rfc6962#section-2.1.1).

### Namespace Merkle Tree

Expand Down Expand Up @@ -346,18 +343,13 @@ For some intuition: the min and max namespace IDs for subtree roots with at leas

A compact commitment can be computed by taking the [hash](#hashing) of the [serialized](#serialization) root node.

#### NamespaceMerkleTreeProof
#### NamespaceMerkleTreeInclusionProof

| name | type | description |
| -------------------- | -------------------------------- | ----------------------------- |
| `rootHash` | [HashDigest](#hashdigest) | Root hash. |
| `rootNamespaceIDMin` | [NamespaceID](#type-aliases) | Root minimum namespace ID. |
| `rootNamespaceIDMax` | [NamespaceID](#type-aliases) | Root maximum namespace ID. |
| `key` | `byte[32]` | Key (i.e. index) of the leaf. |
| `siblingValues` | [HashDigest](#hashdigest)`[]` | Sibling hash values. |
| `siblingMins` | [NamespaceID](#type-aliases)`[]` | Sibling min namespace IDs. |
| `siblingMaxes` | [NamespaceID](#type-aliases)`[]` | Sibling max namespace IDs. |
| `leaf` | `byte[]` | Leaf value. |
| name | type | description |
| --------------- | -------------------------------- | --------------------------------------------------------------- |
| `siblingValues` | [HashDigest](#hashdigest)`[]` | Sibling hash values, ordered starting from the leaf's neighbor. |
| `siblingMins` | [NamespaceID](#type-aliases)`[]` | Sibling min namespace IDs. |
| `siblingMaxes` | [NamespaceID](#type-aliases)`[]` | Sibling max namespace IDs. |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NamespaceMerkleTreeInclusionProof is the inclusion proof for a single node right? Isn't siblingMins and Maxes implicitly included in siblingValues?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's only for the inclusion of a single leaf. The min and max sibling values are committed to in the hashes, but they're not known to a verifier. So they still need to be provided.


When verifying an NMT proof, the root hash is checked by reconstructing the root node `root_node` with the computed `root_node.v` (computed as with a [plain Merkle proof](#binarymerkletreeproof)) and the provided `rootNamespaceIDMin` and `rootNamespaceIDMax` as the `root_node.n_min` and `root_node.n_max`, respectively.

Expand Down Expand Up @@ -391,23 +383,21 @@ For internal node `node` with children `l` and `r`:
node.v = h(0x01, l.v, r.v)
```

#### SparseMerkleTreeProof
#### SparseMerkleTreeInclusionProof

SMTs can further be extended with _compact_ proofs. [Merkle proofs](#verifying-annotated-merkle-proofs) are composed, among other things, of a list of sibling node values. We note that, since nodes that are roots of empty subtrees have known values (the default value), these values do not need to be provided explicitly; it is sufficient to simply identify which siblings in the Merkle branch are roots of empty subtrees, which can be done with one bit per sibling.

For a Merkle branch of height `h`, an `h`-bit value is appended to the proof. The lowest bit corresponds to the sibling of the leaf node, and each higher bit corresponds to the next parent. A value of `1` indicates that the next value in the list of values provided explicitly in the proof should be used, and a value of `0` indicates that the default value should be used.

A proof into an SMT is structured as:

| name | type | description |
| ------------------ | ----------------------------- | ----------------------------------------------------------------------------------------------- |
| `root` | [HashDigest](#hashdigest) | Merkle root. |
| `key` | `byte[32]` | Key (i.e. index) of the leaf. |
| `depth` | `uint16` | Depth of the leaf node. The root node is at depth `0`. Must be `<= 256`. |
| `siblings` | [HashDigest](#hashdigest)`[]` | Sibling hash values. |
| `includedSiblings` | `byte[32]` | Bitfield of explicitly included sibling hashes. The lowest bit corresponds the leaf node level. |
| `leaf` | `byte[]` | Leaf value. |
| name | type | description |
| ------------------ | ----------------------------- | ------------------------------------------------------------------------ |
| `depth` | `uint16` | Depth of the leaf node. The root node is at depth `0`. Must be `<= 256`. |
| `siblings` | [HashDigest](#hashdigest)`[]` | Sibling hash values, ordered starting from the leaf's neighbor.. |
| `includedSiblings` | `byte[32]` | Bitfield of explicitly included sibling hashes. |

The `includedSiblings` is ordered by most-significant-byte first, with each byte ordered by most-significant-bit first. The lowest bit corresponds the leaf node level.
## Erasure Coding

In order to enable trust-minimized light clients (i.e. light clients that do not rely on an honest majority of validating state assumption), it is critical that light clients can determine whether the data in each block is _available_ or not, without downloading the whole block itself. The technique used here was formally described in the paper [Fraud and Data Availability Proofs: Maximising Light Client Security and Scaling Blockchains with Dishonest Majorities](https://arxiv.org/abs/1809.09044).
Expand Down