github.com/koko1123/flow-go-1@v0.29.6/ledger/common/pathfinder/pathfinder.go (about)

     1  // Package pathfinder computes the trie storage path for any given key/value pair
     2  package pathfinder
     3  
     4  import (
     5  	"crypto/sha256"
     6  	"fmt"
     7  
     8  	"github.com/koko1123/flow-go-1/ledger"
     9  	"github.com/onflow/flow-go/crypto/hash"
    10  )
    11  
    12  // PathByteSize captures number of bytes each path takes
    13  const PathByteSize = 32
    14  
    15  // KeyToPath converts key into a path
    16  // version zero applies sha2-256 on value of the key parts (in order ignoring types)
    17  func KeyToPath(key ledger.Key, version uint8) (ledger.Path, error) {
    18  	switch version {
    19  	case 0:
    20  		{
    21  			ret := make([]byte, 0)
    22  			for _, kp := range key.KeyParts {
    23  				ret = append(ret, kp.Value...)
    24  			}
    25  			h := sha256.New()
    26  			_, err := h.Write(ret)
    27  			if err != nil {
    28  				return ledger.DummyPath, err
    29  			}
    30  			path, err := ledger.ToPath(h.Sum(nil))
    31  			if err != nil {
    32  				return ledger.DummyPath, err
    33  			}
    34  			return path, nil
    35  		}
    36  	case 1:
    37  		{
    38  			var path ledger.Path
    39  			hash.ComputeSHA3_256((*[ledger.PathLen]byte)(&path), key.CanonicalForm())
    40  			return path, nil
    41  		}
    42  	}
    43  	return ledger.DummyPath, fmt.Errorf("unsupported key to path version")
    44  }
    45  
    46  // KeysToPaths converts an slice of keys into a paths
    47  func KeysToPaths(keys []ledger.Key, version uint8) ([]ledger.Path, error) {
    48  	paths := make([]ledger.Path, len(keys))
    49  	for i, k := range keys {
    50  		p, err := KeyToPath(k, version)
    51  		if err != nil {
    52  			return nil, err
    53  		}
    54  		paths[i] = p
    55  	}
    56  	return paths, nil
    57  }
    58  
    59  // UpdateToTrieUpdate converts an update into a trie update
    60  func UpdateToTrieUpdate(u *ledger.Update, version uint8) (*ledger.TrieUpdate, error) {
    61  
    62  	paths, err := KeysToPaths(u.Keys(), version)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	payloads, err := UpdateToPayloads(u)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	trieUpdate := &ledger.TrieUpdate{RootHash: ledger.RootHash(u.State()), Paths: paths, Payloads: payloads}
    73  
    74  	return trieUpdate, nil
    75  }
    76  
    77  // QueryToTrieRead converts a ledger query into a trie read
    78  func QueryToTrieRead(q *ledger.Query, version uint8) (*ledger.TrieRead, error) {
    79  
    80  	paths, err := KeysToPaths(q.Keys(), version)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	trieRead := &ledger.TrieRead{RootHash: ledger.RootHash(q.State()), Paths: paths}
    86  
    87  	return trieRead, nil
    88  }
    89  
    90  // PayloadsToValues extracts values from an slice of payload
    91  func PayloadsToValues(payloads []*ledger.Payload) ([]ledger.Value, error) {
    92  	ret := make([]ledger.Value, len(payloads))
    93  	for i, p := range payloads {
    94  		ret[i] = p.Value()
    95  	}
    96  	return ret, nil
    97  }
    98  
    99  // PathsFromPayloads constructs paths from an slice of payload
   100  func PathsFromPayloads(payloads []ledger.Payload, version uint8) ([]ledger.Path, error) {
   101  	paths := make([]ledger.Path, len(payloads))
   102  	for i, pay := range payloads {
   103  		k, err := pay.Key()
   104  		if err != nil {
   105  			return nil, err
   106  		}
   107  		p, err := KeyToPath(k, version)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		paths[i] = p
   112  	}
   113  	return paths, nil
   114  }
   115  
   116  // UpdateToPayloads constructs an slice of payloads given ledger update
   117  func UpdateToPayloads(update *ledger.Update) ([]*ledger.Payload, error) {
   118  	keys := update.Keys()
   119  	values := update.Values()
   120  	payloads := make([]*ledger.Payload, len(keys))
   121  	for i := range keys {
   122  		payload := ledger.NewPayload(keys[i], values[i])
   123  		payloads[i] = payload
   124  	}
   125  	return payloads, nil
   126  }