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 }