github.com/onflow/flow-go@v0.33.17/ledger/trie.go (about)

     1  package ledger
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/fxamacker/cbor/v2"
    11  
    12  	cryptoHash "github.com/onflow/flow-go/crypto/hash"
    13  	"github.com/onflow/flow-go/ledger/common/bitutils"
    14  	"github.com/onflow/flow-go/ledger/common/hash"
    15  )
    16  
    17  // Path captures storage path of a payload;
    18  // where we store a payload in the ledger
    19  type Path hash.Hash
    20  
    21  func (p Path) MarshalJSON() ([]byte, error) {
    22  	return json.Marshal(hex.EncodeToString(p[:]))
    23  }
    24  
    25  // DummyPath is an arbitrary path value, used in function error returns.
    26  var DummyPath = Path(hash.DummyHash)
    27  
    28  // PathLen is the size of paths in bytes.
    29  const PathLen = 32
    30  
    31  // The node maximum height or the tree height.
    32  // It corresponds to the path size in bits.
    33  const NodeMaxHeight = PathLen * 8
    34  
    35  // we are currently supporting paths of a size equal to 32 bytes.
    36  // I.e. path length from the rootNode of a fully expanded tree to the leaf node is 256.
    37  // A path of length k is comprised of k+1 vertices. Hence, we need 257 default hashes.
    38  const defaultHashesNum = NodeMaxHeight + 1
    39  
    40  // array to store all default hashes
    41  var defaultHashes [defaultHashesNum]hash.Hash
    42  
    43  func init() {
    44  
    45  	// default value and default hash value for a default node
    46  	var defaultLeafHash hash.Hash
    47  	castedPointer := (*[hash.HashLen]byte)(&defaultLeafHash)
    48  	cryptoHash.ComputeSHA3_256(castedPointer, []byte("default:"))
    49  
    50  	// Creates the Default hashes from base to level height
    51  	defaultHashes[0] = defaultLeafHash
    52  	for i := 1; i < defaultHashesNum; i++ {
    53  		defaultHashes[i] = hash.HashInterNode(defaultHashes[i-1], defaultHashes[i-1])
    54  	}
    55  }
    56  
    57  // GetDefaultHashForHeight returns the default hashes of the SMT at a specified height.
    58  //
    59  // For each tree level N, there is a default hash equal to the chained
    60  // hashing of the default value N times.
    61  func GetDefaultHashForHeight(height int) hash.Hash {
    62  	return defaultHashes[height]
    63  }
    64  
    65  // ComputeCompactValue computes the value for the node considering the sub tree
    66  // to only include this value and default values. It writes the hash result to the result input.
    67  // UNCHECKED: payload!= nil
    68  func ComputeCompactValue(path hash.Hash, value []byte, nodeHeight int) hash.Hash {
    69  	// if register is unallocated: return default hash
    70  	if len(value) == 0 {
    71  		return GetDefaultHashForHeight(nodeHeight)
    72  	}
    73  
    74  	var out hash.Hash
    75  	out = hash.HashLeaf(path, value)   // we first compute the hash of the fully-expanded leaf
    76  	for h := 1; h <= nodeHeight; h++ { // then, we hash our way upwards towards the root until we hit the specified nodeHeight
    77  		// h is the height of the node, whose hash we are computing in this iteration.
    78  		// The hash is computed from the node's children at height h-1.
    79  		bit := bitutils.ReadBit(path[:], NodeMaxHeight-h)
    80  		if bit == 1 { // right branching
    81  			out = hash.HashInterNode(GetDefaultHashForHeight(h-1), out)
    82  		} else { // left branching
    83  			out = hash.HashInterNode(out, GetDefaultHashForHeight(h-1))
    84  		}
    85  	}
    86  	return out
    87  }
    88  
    89  // TrieRead captures a trie read query
    90  type TrieRead struct {
    91  	RootHash RootHash
    92  	Paths    []Path
    93  }
    94  
    95  // TrieReadSinglePayload contains trie read query for a single payload
    96  type TrieReadSingleValue struct {
    97  	RootHash RootHash
    98  	Path     Path
    99  }
   100  
   101  // TrieUpdate holds all data for a trie update
   102  type TrieUpdate struct {
   103  	RootHash RootHash
   104  	Paths    []Path
   105  	Payloads []*Payload
   106  }
   107  
   108  // Size returns number of paths in the trie update
   109  func (u *TrieUpdate) Size() int {
   110  	return len(u.Paths)
   111  }
   112  
   113  // IsEmpty returns true if key or value is not empty
   114  func (u *TrieUpdate) IsEmpty() bool {
   115  	return u.Size() == 0
   116  }
   117  
   118  func (u *TrieUpdate) String() string {
   119  	str := "Trie Update:\n "
   120  	str += "\t triehash : " + u.RootHash.String() + "\n"
   121  	for i, p := range u.Paths {
   122  		str += fmt.Sprintf("\t\t path %d : %s\n", i, p)
   123  	}
   124  	str += fmt.Sprintf("\t paths len: %d , bytesize: %d\n", len(u.Paths), len(u.Paths)*PathLen)
   125  	tp := 0
   126  	for _, p := range u.Payloads {
   127  		tp += p.Size()
   128  	}
   129  	str += fmt.Sprintf("\t total size of payloads : %d \n", tp)
   130  	return str
   131  }
   132  
   133  // Equals compares this trie update to another trie update
   134  func (u *TrieUpdate) Equals(other *TrieUpdate) bool {
   135  	if other == nil {
   136  		return false
   137  	}
   138  	if !u.RootHash.Equals(other.RootHash) {
   139  		return false
   140  	}
   141  	if len(u.Paths) != len(other.Paths) {
   142  		return false
   143  	}
   144  	for i := range u.Paths {
   145  		if !u.Paths[i].Equals(other.Paths[i]) {
   146  			return false
   147  		}
   148  	}
   149  
   150  	if len(u.Payloads) != len(other.Payloads) {
   151  		return false
   152  	}
   153  	for i := range u.Payloads {
   154  		if !u.Payloads[i].Equals(other.Payloads[i]) {
   155  			return false
   156  		}
   157  	}
   158  	return true
   159  }
   160  
   161  // RootHash captures the root hash of a trie
   162  type RootHash hash.Hash
   163  
   164  func (rh RootHash) MarshalJSON() ([]byte, error) {
   165  	return json.Marshal(rh.String())
   166  }
   167  
   168  func (rh RootHash) String() string {
   169  	return hex.EncodeToString(rh[:])
   170  }
   171  
   172  // Equals compares the root hash to another one
   173  func (rh RootHash) Equals(o RootHash) bool {
   174  	return rh == o
   175  }
   176  
   177  // ToRootHash converts a byte slice into a root hash.
   178  // It returns an error if the slice has an invalid length.
   179  func ToRootHash(rootHashBytes []byte) (RootHash, error) {
   180  	var rootHash RootHash
   181  	if len(rootHashBytes) != len(rootHash) {
   182  		return RootHash(hash.DummyHash), fmt.Errorf("expecting %d bytes but got %d bytes", len(rootHash), len(rootHashBytes))
   183  	}
   184  	copy(rootHash[:], rootHashBytes)
   185  	return rootHash, nil
   186  }
   187  
   188  func (p Path) String() string {
   189  	str := ""
   190  	for _, i := range p {
   191  		str += fmt.Sprintf("%08b", i)
   192  	}
   193  	str = str[0:8] + "..." + str[len(str)-8:]
   194  	return str
   195  }
   196  
   197  // Equals compares this path to another path
   198  func (p Path) Equals(o Path) bool {
   199  	return p == o
   200  }
   201  
   202  // ToPath converts a byte slice into a path.
   203  // It returns an error if the slice has an invalid length.
   204  func ToPath(pathBytes []byte) (Path, error) {
   205  	var path Path
   206  	if len(pathBytes) != len(path) {
   207  		return DummyPath, fmt.Errorf("expecting %d bytes but got %d bytes", len(path), len(pathBytes))
   208  	}
   209  	copy(path[:], pathBytes)
   210  	return path, nil
   211  }
   212  
   213  // encKey represents an encoded ledger key.
   214  type encKey []byte
   215  
   216  // Size returns the byte size of the encoded key.
   217  func (k encKey) Size() int {
   218  	return len(k)
   219  }
   220  
   221  // String returns the string representation of the encoded key.
   222  func (k encKey) String() string {
   223  	return hex.EncodeToString(k)
   224  }
   225  
   226  // Equals compares this encoded key to another encoded key.
   227  // A nil encoded key is equivalent to an empty encoded key.
   228  func (k encKey) Equals(other encKey) bool {
   229  	return bytes.Equal(k, other)
   230  }
   231  
   232  // DeepCopy returns a deep copy of the encoded key.
   233  func (k encKey) DeepCopy() encKey {
   234  	newK := make([]byte, len(k))
   235  	copy(newK, k)
   236  	return newK
   237  }
   238  
   239  // Payload is the smallest immutable storable unit in ledger
   240  type Payload struct {
   241  	// encKey is key encoded using PayloadVersion.
   242  	// Version and type data are not encoded to save 3 bytes.
   243  	// NOTE: encKey translates to Key{} when encKey is
   244  	//       one of these three values:
   245  	//       nil, []byte{}, []byte{0,0}.
   246  	encKey encKey
   247  	value  Value
   248  }
   249  
   250  // serializablePayload is used to serialize ledger.Payload.
   251  // Encoder only serializes exported fields and ledger.Payload's
   252  // key and value fields are not exported.  So it is necessary to
   253  // use serializablePayload for encoding.
   254  type serializablePayload struct {
   255  	Key   Key
   256  	Value Value
   257  }
   258  
   259  // MarshalJSON returns JSON encoding of p.
   260  func (p Payload) MarshalJSON() ([]byte, error) {
   261  	k, err := p.Key()
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  	sp := serializablePayload{Key: k, Value: p.value}
   266  	return json.Marshal(sp)
   267  }
   268  
   269  // UnmarshalJSON unmarshals a JSON value of payload.
   270  func (p *Payload) UnmarshalJSON(b []byte) error {
   271  	if p == nil {
   272  		return errors.New("UnmarshalJSON on nil Payload")
   273  	}
   274  	var sp serializablePayload
   275  	if err := json.Unmarshal(b, &sp); err != nil {
   276  		return err
   277  	}
   278  	p.encKey = encodeKey(&sp.Key, PayloadVersion)
   279  	p.value = sp.Value
   280  	return nil
   281  }
   282  
   283  // MarshalCBOR returns CBOR encoding of p.
   284  func (p Payload) MarshalCBOR() ([]byte, error) {
   285  	k, err := p.Key()
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  	sp := serializablePayload{Key: k, Value: p.value}
   290  	return cbor.Marshal(sp)
   291  }
   292  
   293  // UnmarshalCBOR unmarshals a CBOR value of payload.
   294  func (p *Payload) UnmarshalCBOR(b []byte) error {
   295  	if p == nil {
   296  		return errors.New("UnmarshalCBOR on nil payload")
   297  	}
   298  	var sp serializablePayload
   299  	if err := cbor.Unmarshal(b, &sp); err != nil {
   300  		return err
   301  	}
   302  	p.encKey = encodeKey(&sp.Key, PayloadVersion)
   303  	p.value = sp.Value
   304  	return nil
   305  }
   306  
   307  // Key returns payload key.
   308  // Error indicates that ledger.Key can't be created from payload key, so
   309  // migration and reporting (known callers) should abort.
   310  // CAUTION: do not modify returned key because it shares underlying data with payload key.
   311  func (p *Payload) Key() (Key, error) {
   312  	if p == nil || len(p.encKey) == 0 {
   313  		return Key{}, nil
   314  	}
   315  	k, err := decodeKey(p.encKey, true, PayloadVersion)
   316  	if err != nil {
   317  		return Key{}, err
   318  	}
   319  	return *k, nil
   320  }
   321  
   322  // EncodedKey returns payload key.
   323  // CAUTION: do not modify returned encoded key
   324  // because it shares underlying data with payload key.
   325  func (p *Payload) EncodedKey() []byte {
   326  	if p == nil {
   327  		return nil
   328  	}
   329  	return p.encKey
   330  }
   331  
   332  // Value returns payload value.
   333  // CAUTION: do not modify returned value because it shares underlying data with payload value.
   334  func (p *Payload) Value() Value {
   335  	if p == nil {
   336  		return Value{}
   337  	}
   338  	return p.value
   339  }
   340  
   341  // Size returns the size of the payload
   342  func (p *Payload) Size() int {
   343  	if p == nil {
   344  		return 0
   345  	}
   346  	return p.encKey.Size() + p.value.Size()
   347  }
   348  
   349  // IsEmpty returns true if payload is nil or value is empty
   350  func (p *Payload) IsEmpty() bool {
   351  	return p == nil || p.value.Size() == 0
   352  }
   353  
   354  // TODO fix me
   355  func (p *Payload) String() string {
   356  	// TODO improve this key, values
   357  	return p.encKey.String() + " " + p.value.String()
   358  }
   359  
   360  // Equals compares this payload to another payload
   361  // A nil payload is equivalent to an empty payload.
   362  func (p *Payload) Equals(other *Payload) bool {
   363  	if p == nil || (p.encKey.Size() == 0 && p.value.Size() == 0) {
   364  		return other == nil || (other.encKey.Size() == 0 && other.value.Size() == 0)
   365  	}
   366  	if other == nil {
   367  		return false
   368  	}
   369  	return p.encKey.Equals(other.encKey) && p.value.Equals(other.value)
   370  }
   371  
   372  // ValueEquals compares this payload value to another payload value.
   373  // A nil payload is equivalent to an empty payload.
   374  // NOTE: prefer using this function over payload.Value.Equals()
   375  // when comparing payload values.  payload.ValueEquals() handles
   376  // nil payload, while payload.Value.Equals() panics on nil payload.
   377  func (p *Payload) ValueEquals(other *Payload) bool {
   378  	pEmpty := p.IsEmpty()
   379  	otherEmpty := other.IsEmpty()
   380  	if pEmpty != otherEmpty {
   381  		// Only one payload is empty
   382  		return false
   383  	}
   384  	if pEmpty {
   385  		// Both payloads are empty
   386  		return true
   387  	}
   388  	// Compare values since both payloads are not empty.
   389  	return p.value.Equals(other.value)
   390  }
   391  
   392  // DeepCopy returns a deep copy of the payload
   393  func (p *Payload) DeepCopy() *Payload {
   394  	if p == nil {
   395  		return nil
   396  	}
   397  	k := p.encKey.DeepCopy()
   398  	v := p.value.DeepCopy()
   399  	return &Payload{encKey: k, value: v}
   400  }
   401  
   402  // NewPayload returns a new payload
   403  func NewPayload(key Key, value Value) *Payload {
   404  	ek := encodeKey(&key, PayloadVersion)
   405  	return &Payload{encKey: ek, value: value}
   406  }
   407  
   408  // EmptyPayload returns an empty payload
   409  func EmptyPayload() *Payload {
   410  	return &Payload{}
   411  }
   412  
   413  // TrieProof includes all the information needed to walk
   414  // through a trie branch from an specific leaf node (key)
   415  // up to the root of the trie.
   416  type TrieProof struct {
   417  	Path      Path        // path
   418  	Payload   *Payload    // payload
   419  	Interims  []hash.Hash // the non-default intermediate nodes in the proof
   420  	Inclusion bool        // flag indicating if this is an inclusion or exclusion proof
   421  	Flags     []byte      // The flags of the proofs (is set if an intermediate node has a non-default)
   422  	Steps     uint8       // number of steps for the proof (path len) // TODO: should this be a type allowing for larger values?
   423  }
   424  
   425  // NewTrieProof creates a new instance of Trie Proof
   426  func NewTrieProof() *TrieProof {
   427  	return &TrieProof{
   428  		Payload:   EmptyPayload(),
   429  		Interims:  make([]hash.Hash, 0),
   430  		Inclusion: false,
   431  		Flags:     make([]byte, PathLen),
   432  		Steps:     0,
   433  	}
   434  }
   435  
   436  func (p *TrieProof) String() string {
   437  	flagStr := ""
   438  	for _, f := range p.Flags {
   439  		flagStr += fmt.Sprintf("%08b", f)
   440  	}
   441  	proofStr := fmt.Sprintf("size: %d flags: %v\n", p.Steps, flagStr)
   442  	proofStr += fmt.Sprintf("\t path: %v payload: %v\n", p.Path, p.Payload)
   443  
   444  	if p.Inclusion {
   445  		proofStr += "\t inclusion proof:\n"
   446  	} else {
   447  		proofStr += "\t noninclusion proof:\n"
   448  	}
   449  	interimIndex := 0
   450  	for j := 0; j < int(p.Steps); j++ {
   451  		// if bit is set
   452  		if p.Flags[j/8]&(1<<(7-j%8)) != 0 {
   453  			proofStr += fmt.Sprintf("\t\t %d: [%x]\n", j, p.Interims[interimIndex])
   454  			interimIndex++
   455  		}
   456  	}
   457  	return proofStr
   458  }
   459  
   460  // Equals compares this proof to another payload
   461  func (p *TrieProof) Equals(o *TrieProof) bool {
   462  	if o == nil {
   463  		return false
   464  	}
   465  	if !p.Path.Equals(o.Path) {
   466  		return false
   467  	}
   468  	if !p.Payload.Equals(o.Payload) {
   469  		return false
   470  	}
   471  	if len(p.Interims) != len(o.Interims) {
   472  		return false
   473  	}
   474  	for i, inter := range p.Interims {
   475  		if inter != o.Interims[i] {
   476  			return false
   477  		}
   478  	}
   479  	if p.Inclusion != o.Inclusion {
   480  		return false
   481  	}
   482  	if !bytes.Equal(p.Flags, o.Flags) {
   483  		return false
   484  	}
   485  	if p.Steps != o.Steps {
   486  		return false
   487  	}
   488  	return true
   489  }
   490  
   491  // TrieBatchProof is a struct that holds the proofs for several keys
   492  //
   493  // so there is no need for two calls (read, proofs)
   494  type TrieBatchProof struct {
   495  	Proofs []*TrieProof
   496  }
   497  
   498  // NewTrieBatchProof creates a new instance of BatchProof
   499  func NewTrieBatchProof() *TrieBatchProof {
   500  	bp := new(TrieBatchProof)
   501  	bp.Proofs = make([]*TrieProof, 0)
   502  	return bp
   503  }
   504  
   505  // NewTrieBatchProofWithEmptyProofs creates an instance of Batchproof
   506  // filled with n newly created proofs (empty)
   507  func NewTrieBatchProofWithEmptyProofs(numberOfProofs int) *TrieBatchProof {
   508  	bp := new(TrieBatchProof)
   509  	bp.Proofs = make([]*TrieProof, numberOfProofs)
   510  	for i := 0; i < numberOfProofs; i++ {
   511  		bp.Proofs[i] = NewTrieProof()
   512  	}
   513  	return bp
   514  }
   515  
   516  // Size returns the number of proofs
   517  func (bp *TrieBatchProof) Size() int {
   518  	return len(bp.Proofs)
   519  }
   520  
   521  // Paths returns the slice of paths for this batch proof
   522  func (bp *TrieBatchProof) Paths() []Path {
   523  	paths := make([]Path, len(bp.Proofs))
   524  	for i, p := range bp.Proofs {
   525  		paths[i] = p.Path
   526  	}
   527  	return paths
   528  }
   529  
   530  // Payloads returns the slice of paths for this batch proof
   531  func (bp *TrieBatchProof) Payloads() []*Payload {
   532  	payloads := make([]*Payload, len(bp.Proofs))
   533  	for i, p := range bp.Proofs {
   534  		payloads[i] = p.Payload
   535  	}
   536  	return payloads
   537  }
   538  
   539  func (bp *TrieBatchProof) String() string {
   540  	res := fmt.Sprintf("trie batch proof includes %d proofs: \n", bp.Size())
   541  	for _, proof := range bp.Proofs {
   542  		res = res + "\n" + proof.String()
   543  	}
   544  	return res
   545  }
   546  
   547  // AppendProof adds a proof to the batch proof
   548  func (bp *TrieBatchProof) AppendProof(p *TrieProof) {
   549  	bp.Proofs = append(bp.Proofs, p)
   550  }
   551  
   552  // MergeInto adds all of its proofs into the dest batch proof
   553  func (bp *TrieBatchProof) MergeInto(dest *TrieBatchProof) {
   554  	for _, p := range bp.Proofs {
   555  		dest.AppendProof(p)
   556  	}
   557  }
   558  
   559  // Equals compares this batch proof to another batch proof
   560  func (bp *TrieBatchProof) Equals(o *TrieBatchProof) bool {
   561  	if o == nil {
   562  		return false
   563  	}
   564  	if len(bp.Proofs) != len(o.Proofs) {
   565  		return false
   566  	}
   567  	for i, proof := range bp.Proofs {
   568  		if !proof.Equals(o.Proofs[i]) {
   569  			return false
   570  		}
   571  	}
   572  	return true
   573  }