From 308f8a32d01cccd233578689faf80674f4b7e6a6 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Mon, 8 Apr 2024 16:00:05 -0700 Subject: [PATCH] Review submittd PR --- .gitignore | 3 +++ docs/mapstore.md | 20 ++++++++++---------- docs/smt.md | 42 +++++++++++++++++------------------------- proofs.go | 6 +++--- smt.go | 2 +- 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index aa638db..55b4fed 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ # Ignore Goland and JetBrains IDE files .idea/ + +# Visual Studio Code +.vscode diff --git a/docs/mapstore.md b/docs/mapstore.md index d36fc95..ebaf965 100644 --- a/docs/mapstore.md +++ b/docs/mapstore.md @@ -1,21 +1,17 @@ -# MapStore - - +# MapStore +- [Introduction](#introduction) - [Implementations](#implementations) - [SimpleMap](#simplemap) - [BadgerV4](#badgerv4) +- [Note On External Writability](#note-on-external-writability) - +## Introduction The `MapStore` is a simple interface used by the SM(S)T to store, delete and retrieve key-value pairs. It is intentionally simple and minimalistic so as to enable different key-value engines to implement and back the trie database. -Any key-value store used by the tries should **not** be able to be externally -writeable in production. This opens the possibility to attacks where the writer -can modify the trie database and prove values that were not inserted. - See: [the interface](../kvstore/interfaces.go) for a more detailed description of the simple interface required by the SM(S)T. @@ -35,11 +31,15 @@ See [simplemap.go](../kvstore/simplemap/simplemap.go) for more details. ### BadgerV4 -This library provides a wrapper around [dgraph-io/badger][badgerv4] to adhere to +This library provides a wrapper around [dgraph-io/badger][https://github.com/dgraph-io/badger] to adhere to the `MapStore` interface. See the [full documentation](./badger-store.md) for additional functionality and implementation details. See: [badger](../kvstore/badger/) for more details on the implementation of this submodule. -[badgerv4]: https://github.com/dgraph-io/badger +## Note On External Writability + +Any key-value store used by the tries should **not** be able to be externally +writeable in production. This opens the possibility to attacks where the writer +can modify the trie database and prove values that were not inserted. diff --git a/docs/smt.md b/docs/smt.md index 19cdbf7..b7bdfad 100644 --- a/docs/smt.md +++ b/docs/smt.md @@ -1,6 +1,4 @@ -# smt - - +# smt - [Overview](#overview) - [Implementation](#implementation) @@ -16,7 +14,8 @@ - [Visualisation](#visualisation) - [Values](#values) - [Nil values](#nil-values) -- [Hashers & Digests](#hashers--digests) +- [Hashers \& Digests](#hashers--digests) + - [Hash Function Recommendations](#hash-function-recommendations) - [Roots](#roots) - [Proofs](#proofs) - [Verification](#verification) @@ -31,8 +30,6 @@ - [Data Loss](#data-loss) - [Sparse Merkle Sum Trie](#sparse-merkle-sum-trie) - - ## Overview Sparse Merkle Tries (SMTs) are efficient and secure data structures for storing @@ -44,25 +41,6 @@ make SMTs valuable in applications like blockchains, decentralized databases, and authenticated data structures, providing optimized and trustworthy data storage and verification. -Although any hash function that satisfies the `hash.Hash` interface can be used -to construct the trie it is **strongly recommended** to use a hashing function -that provides the following properties: - -- **Collision resistance**: The hash function must be collision resistant, in - order for the inputs of the SMT to be unique. -- **Preimage resistance**: The hash function must be preimage resistant, to - protect against the attack of the Merkle tree construction attacks where the - attacker can modify unknown data. -- **Efficiency**: The hash function must be efficient, as it is used to compute - the hash of many nodes in the trie. - -Therefore it is recommended to use a hashing function such as: - -- `sha256` -- `sha3_256`/`keccak256` - -Or another sufficiently secure hashing algorithm. - See [smt.go](../smt.go) for more details on the implementation. ## Implementation @@ -362,6 +340,20 @@ graph TD VH --ValueHash-->L ``` +### Hash Function Recommendations + +Although any hash function that satisfies the `hash.Hash` interface can be used +to construct the trie, it is **strongly recommended** to use a hashing function +that provides the following properties: + +- **Collision resistance**: The hash function must be collision resistant. This + is needed in order for the inputs of the SMT to be unique. +- **Preimage resistance**: The hash function must be preimage resistant. This + is needed to protect against the Merkle tree construction attacks where + the attacker can modify unknown data. +- **Efficiency**: The hash function must be efficient, as it is used to compute + the hash of many nodes in the trie. + ## Roots The root of the tree is a slice of bytes. `MerkleRoot` is an alias for `[]byte`. diff --git a/proofs.go b/proofs.go index 12d3de8..6a09fe9 100644 --- a/proofs.go +++ b/proofs.go @@ -341,9 +341,9 @@ func VerifyClosestProof(proof *SparseMerkleClosestProof, root []byte, spec *Trie if err := proof.validateBasic(spec); err != nil { return false, errors.Join(ErrBadProof, err) } - // Create a new TrieSpec with a nil path hasher - as the ClosestProof - // already contains a hashed path, double hashing it will invalidate the - // proof. + // Create a new TrieSpec with a nil path hasher. + // Since the ClosestProof already contains a hashed path, double hashing it + // will invalidate the proof. nilSpec := &TrieSpec{ th: spec.th, ph: newNilPathHasher(spec.ph.PathSize()), diff --git a/smt.go b/smt.go index 7928c40..1cef322 100644 --- a/smt.go +++ b/smt.go @@ -177,7 +177,6 @@ func (smt *SMT) update( return newLeaf, nil } // We insert an "extension" representing multiple single-branch inner nodes - last := &node var newInner *innerNode if getPathBit(path, prefixlen) == left { newInner = &innerNode{ @@ -191,6 +190,7 @@ func (smt *SMT) update( } } // Determine if we need to insert an extension or a branch + last := &node if depth < prefixlen { // note: this keeps path slice alive - GC inefficiency? if depth > 0xff {