Documentation ¶
Overview ¶
package trie implements an immutable Merkle Patricia Trie, used by the state package to store the chain state.
The code is based on the trie.go package by Evaldas Drasutis: https://github.com/iotaledger/trie.go
This is a simplified version, keeping only the features that are relevant for our use case. Namely:
- Arity is fixed at 16 - Hash size is fixed at 20 bytes - Hashing algorithm is blake2b - No mutable trie implementation
This file contains functions for verification of the proofs of inclusion or absence in the trie with trie_blake2b commitment model. The package only depends on the commitment model implementation and the proof format it defines. The verification package is completely independent on the implementation of the Merkle tree (the trie)
DISCLAIMER: THE FOLLOWING CODE IS SECURITY CRITICAL. ANY POTENTIAL BUG WHICH MAY LEAD TO FALSE POSITIVES OF PROOF VALIDITY CHECKS POTENTIALLY CREATES AN ATTACK VECTOR. THEREFORE, IT IS HIGHLY RECOMMENDED THE VERIFICATION CODE TO BE WRITTEN BY THE VERIFYING PARTY ITSELF, INSTEAD OF CLONING THIS PACKAGE. DO NOT TRUST ANYBODY BUT YOURSELF. IN ANY CASE, PERFORM A DETAILED AUDIT OF THE PROOF-VERIFYING CODE BEFORE USING IT
Index ¶
- Constants
- Variables
- func DebugDump(store KVStore, roots []Hash)
- func Diff(store KVStore, root1, root2 Hash) (onlyOn1, onlyOn2 map[Hash]*NodeData)
- type CommitStats
- type Hash
- type HiveKVStoreAdapter
- func (kvs *HiveKVStoreAdapter) Del(key []byte)
- func (kvs *HiveKVStoreAdapter) Get(key []byte) []byte
- func (kvs *HiveKVStoreAdapter) Has(key []byte) bool
- func (kvs *HiveKVStoreAdapter) Iterate(fun func(k []byte, v []byte) bool)
- func (kvs *HiveKVStoreAdapter) IterateKeys(fun func(k []byte) bool)
- func (kvs *HiveKVStoreAdapter) Set(key, value []byte)
- type IterateNodesAction
- type KVIterator
- type KVReader
- type KVStore
- type KVWriter
- type MerkleProof
- func (p *MerkleProof) IsProofOfAbsence() bool
- func (p *MerkleProof) MustKeyWithTerminal() ([]byte, []byte)
- func (p *MerkleProof) Validate(rootBytes []byte) error
- func (p *MerkleProof) ValidateValue(trieRoot Hash, value []byte) error
- func (p *MerkleProof) ValidateWithTerminal(rootBytes, terminalBytes []byte) error
- type MerkleProofElement
- type NodeData
- type PruneStats
- type Refcounts
- type Tcommitment
- func (t *Tcommitment) Bytes() []byte
- func (t *Tcommitment) Clone() *Tcommitment
- func (t *Tcommitment) Equals(o *Tcommitment) bool
- func (t *Tcommitment) ExtractValue() ([]byte, bool)
- func (t *Tcommitment) Read(r io.Reader) error
- func (t *Tcommitment) String() string
- func (t *Tcommitment) Write(w io.Writer) error
- type Traversable
- type TrieIterator
- type TrieReader
- func (tr *TrieReader) CopyToStore(snapshot KVStore)
- func (tr *TrieReader) DebugDump()
- func (tr *TrieReader) Get(key []byte) []byte
- func (tr *TrieReader) GetStr(key string) string
- func (tr *TrieReader) Has(key []byte) bool
- func (tr *TrieReader) HasStr(key string) bool
- func (tr *TrieReader) Iterate(f func(k []byte, v []byte) bool)
- func (tr *TrieReader) IterateKeys(f func(k []byte) bool)
- func (tr *TrieReader) IterateNodes(fun func(nodeKey []byte, n *NodeData, depth int) IterateNodesAction)
- func (tr *TrieReader) Iterator(prefix []byte) KVIterator
- func (tr *TrieReader) MerkleProof(key []byte) *MerkleProof
- func (tr *TrieReader) Root() Hash
- type TrieUpdatable
- func (tr *TrieUpdatable) Commit(store KVStore) (Hash, CommitStats)
- func (tr *TrieUpdatable) Delete(key []byte)
- func (tr *TrieUpdatable) DeletePrefix(pathPrefix []byte) bool
- func (tr *TrieUpdatable) DeleteStr(key interface{})
- func (tr *TrieUpdatable) SetRoot(h Hash) error
- func (tr *TrieUpdatable) Update(key []byte, value []byte)
- func (tr *TrieUpdatable) UpdateStr(key interface{}, value interface{})
Constants ¶
const ( HashSizeBits = 160 HashSizeBytes = HashSizeBits / 8 )
const KeyMaxLength = 256
const (
// NumChildren is the maximum amount of children for each trie node
NumChildren = 16
)
Variables ¶
Functions ¶
Types ¶
type CommitStats ¶
type Hash ¶
type Hash [HashSizeBytes]byte
Hash is a blake2b 160 bit (20 bytes) hash
func HashFromBytes ¶
type HiveKVStoreAdapter ¶
type HiveKVStoreAdapter struct {
// contains filtered or unexported fields
}
HiveKVStoreAdapter maps a partition of the Hive KVStore to trie_go.KVStore
func NewHiveKVStoreAdapter ¶
func NewHiveKVStoreAdapter(kvs kvstore.KVStore, prefix []byte) *HiveKVStoreAdapter
NewHiveKVStoreAdapter creates a new KVStore as a partition of hive.go KVStore
func (*HiveKVStoreAdapter) Del ¶
func (kvs *HiveKVStoreAdapter) Del(key []byte)
func (*HiveKVStoreAdapter) Get ¶
func (kvs *HiveKVStoreAdapter) Get(key []byte) []byte
func (*HiveKVStoreAdapter) Has ¶
func (kvs *HiveKVStoreAdapter) Has(key []byte) bool
func (*HiveKVStoreAdapter) Iterate ¶
func (kvs *HiveKVStoreAdapter) Iterate(fun func(k []byte, v []byte) bool)
func (*HiveKVStoreAdapter) IterateKeys ¶
func (kvs *HiveKVStoreAdapter) IterateKeys(fun func(k []byte) bool)
func (*HiveKVStoreAdapter) Set ¶
func (kvs *HiveKVStoreAdapter) Set(key, value []byte)
type IterateNodesAction ¶
type IterateNodesAction byte
const ( IterateStop IterateNodesAction = iota IterateContinue IterateSkipSubtree )
type KVIterator ¶
KVIterator is an interface to iterate through a set of key/value pairs. Order of iteration is NON-DETERMINISTIC in general
type KVReader ¶
type KVReader interface { // Get retrieves value by key. Returned nil means absence of the key Get(key []byte) []byte // Has checks presence of the key in the key/value store Has(key []byte) bool // for performance }
KVReader is a key/value reader
type KVStore ¶
type KVStore interface { KVReader KVWriter KVIterator }
KVStore is a compound interface
type KVWriter ¶
type KVWriter interface { // Set writes new or updates existing key with the value. // value == nil means deletion of the key from the store Set(key, value []byte) Del(key []byte) }
KVWriter is a key/value writer
type MerkleProof ¶
type MerkleProof struct { Key []byte Path []*MerkleProofElement }
MerkleProof is a proof of inclusion or absence
func (*MerkleProof) IsProofOfAbsence ¶
func (p *MerkleProof) IsProofOfAbsence() bool
IsProofOfAbsence checks if it is proof of absence. MerkleProof that the trie commits to something else in the place where it would commit to the key if it would be present
func (*MerkleProof) MustKeyWithTerminal ¶
func (p *MerkleProof) MustKeyWithTerminal() ([]byte, []byte)
MustKeyWithTerminal returns key and terminal commitment the proof is about. It returns: - key - terminal commitment. If it is nil, the proof is a proof of absence It does not verify the proof, so this function should be used only after Validate()
func (*MerkleProof) Validate ¶
func (p *MerkleProof) Validate(rootBytes []byte) error
Validate check the proof against the provided root commitments
func (*MerkleProof) ValidateValue ¶
func (p *MerkleProof) ValidateValue(trieRoot Hash, value []byte) error
func (*MerkleProof) ValidateWithTerminal ¶
func (p *MerkleProof) ValidateWithTerminal(rootBytes, terminalBytes []byte) error
ValidateWithTerminal checks the proof and checks if the proof commits to the specific value The check is dependent on the commitment model because of valueOptimisationThreshold
type MerkleProofElement ¶
type MerkleProofElement struct { PathExtension []byte Children [NumChildren]*Hash Terminal []byte ChildIndex int }
type NodeData ¶
type NodeData struct { // if PathExtension != nil, this is an extension node (i.e. if there are // no branching nodes along the PathExtension). // See https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/#optimization PathExtension []byte // if Terminal != nil, it contains the commitment to a value in the trie Terminal *Tcommitment // Children contains pointers to up to 16 other nodes, one for each // possible nibble Children [NumChildren]*Hash // Commitment is hash(pathExtension|terminal|children), which is persisted in the key Commitment Hash }
NodeData represents a node of the trie, which is stored in the trieStore with key = commitment.Bytes()
func (*NodeData) ChildrenCount ¶
type PruneStats ¶
type Tcommitment ¶
Tcommitment (short for terminal commitment) commits to data of arbitrary size.
func CommitToData ¶
func CommitToData(data []byte) *Tcommitment
func (*Tcommitment) Bytes ¶
func (t *Tcommitment) Bytes() []byte
func (*Tcommitment) Clone ¶
func (t *Tcommitment) Clone() *Tcommitment
func (*Tcommitment) Equals ¶
func (t *Tcommitment) Equals(o *Tcommitment) bool
func (*Tcommitment) ExtractValue ¶
func (t *Tcommitment) ExtractValue() ([]byte, bool)
func (*Tcommitment) String ¶
func (t *Tcommitment) String() string
type Traversable ¶
type Traversable interface {
Iterator(prefix []byte) KVIterator
}
Traversable is an interface which provides with partial iterators
type TrieIterator ¶
type TrieIterator struct {
// contains filtered or unexported fields
}
TrieIterator implements KVIterator interface for keys in the trie with given prefix
func (*TrieIterator) IterateKeys ¶
func (ti *TrieIterator) IterateKeys(fun func(k []byte) bool)
type TrieReader ¶
type TrieReader struct {
// contains filtered or unexported fields
}
TrieReader direct read-only access to trie
func NewTrieReader ¶
func NewTrieReader(store KVReader, root Hash) (*TrieReader, error)
func (*TrieReader) CopyToStore ¶
func (tr *TrieReader) CopyToStore(snapshot KVStore)
func (*TrieReader) DebugDump ¶
func (tr *TrieReader) DebugDump()
DebugDump prints the structure of the tree to stdout, for debugging purposes.
func (*TrieReader) Get ¶
func (tr *TrieReader) Get(key []byte) []byte
Get reads the trie with the key
func (*TrieReader) GetStr ¶
func (tr *TrieReader) GetStr(key string) string
func (*TrieReader) Has ¶
func (tr *TrieReader) Has(key []byte) bool
Has check existence of the key in the trie
func (*TrieReader) HasStr ¶
func (tr *TrieReader) HasStr(key string) bool
func (*TrieReader) Iterate ¶
func (tr *TrieReader) Iterate(f func(k []byte, v []byte) bool)
Iterate iterates all the key/value pairs in the trie
func (*TrieReader) IterateKeys ¶
func (tr *TrieReader) IterateKeys(f func(k []byte) bool)
IterateKeys iterates all the keys in the trie
func (*TrieReader) IterateNodes ¶
func (tr *TrieReader) IterateNodes(fun func(nodeKey []byte, n *NodeData, depth int) IterateNodesAction)
IterateNodes iterates nodes of the trie in the lexicographical order of trie keys in "depth first" order
func (*TrieReader) Iterator ¶
func (tr *TrieReader) Iterator(prefix []byte) KVIterator
Iterator returns iterator for the sub-trie
func (*TrieReader) MerkleProof ¶
func (tr *TrieReader) MerkleProof(key []byte) *MerkleProof
func (*TrieReader) Root ¶
func (tr *TrieReader) Root() Hash
type TrieUpdatable ¶
type TrieUpdatable struct { *TrieReader // contains filtered or unexported fields }
TrieUpdatable is an updatable trie implemented on top of the unpackedKey/value store. It is virtualized and optimized by caching of the trie update operation and keeping consistent trie in the cache
func NewTrieUpdatable ¶
func NewTrieUpdatable(store KVReader, root Hash) (*TrieUpdatable, error)
func (*TrieUpdatable) Commit ¶
func (tr *TrieUpdatable) Commit(store KVStore) (Hash, CommitStats)
Commit calculates a new mutatedRoot commitment value from the cache, commits all mutations and writes it into the store. The nodes and values are written into separate partitions The buffered nodes are garbage collected, except the mutated ones By default, it sets new root in the end and clears the trie reader cache. To override, use notSetNewRoot = true
func (*TrieUpdatable) Delete ¶
func (tr *TrieUpdatable) Delete(key []byte)
Delete deletes Key/value from the TrieUpdatable
func (*TrieUpdatable) DeletePrefix ¶
func (tr *TrieUpdatable) DeletePrefix(pathPrefix []byte) bool
DeletePrefix deletes all kv pairs with the prefix. It is a very fast operation, it modifies only one node and all children (any number) disappears from the next root
func (*TrieUpdatable) DeleteStr ¶
func (tr *TrieUpdatable) DeleteStr(key interface{})
DeleteStr removes key from trie
func (*TrieUpdatable) SetRoot ¶
func (tr *TrieUpdatable) SetRoot(h Hash) error
SetRoot overloaded for updatable trie
func (*TrieUpdatable) Update ¶
func (tr *TrieUpdatable) Update(key []byte, value []byte)
Update updates TrieUpdatable with the unpackedKey/value. Reorganizes and re-calculates trie, keeps cache consistent
func (*TrieUpdatable) UpdateStr ¶
func (tr *TrieUpdatable) UpdateStr(key interface{}, value interface{})
UpdateStr updates key/value pair in the trie