github.com/onflow/flow-go@v0.33.17/model/flow/ledger.go (about) 1 package flow 2 3 import ( 4 "encoding/binary" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "strings" 9 10 "github.com/onflow/flow-go/ledger/common/hash" 11 "github.com/onflow/flow-go/model/fingerprint" 12 ) 13 14 const ( 15 // Service level keys (owner is empty): 16 UUIDKeyPrefix = "uuid" 17 AddressStateKey = "account_address_state" 18 19 // Account level keys 20 AccountKeyPrefix = "a." 21 AccountStatusKey = AccountKeyPrefix + "s" 22 CodeKeyPrefix = "code." 23 ContractNamesKey = "contract_names" 24 PublicKeyKeyPrefix = "public_key_" 25 ) 26 27 func addressToOwner(address Address) string { 28 return string(address.Bytes()) 29 } 30 31 type RegisterID struct { 32 Owner string 33 Key string 34 } 35 36 var AddressStateRegisterID = RegisterID{ 37 Owner: "", 38 Key: AddressStateKey, 39 } 40 41 func UUIDRegisterID(partition byte) RegisterID { 42 // NOTE: partition 0 uses "uuid" as key to maintain backwards compatibility. 43 key := UUIDKeyPrefix 44 if partition != 0 { 45 key = fmt.Sprintf("%s_%d", UUIDKeyPrefix, partition) 46 } 47 48 return RegisterID{ 49 Owner: "", 50 Key: key, 51 } 52 } 53 54 func AccountStatusRegisterID(address Address) RegisterID { 55 return RegisterID{ 56 Owner: addressToOwner(address), 57 Key: AccountStatusKey, 58 } 59 } 60 61 func PublicKeyRegisterID(address Address, index uint64) RegisterID { 62 return RegisterID{ 63 Owner: addressToOwner(address), 64 Key: fmt.Sprintf("public_key_%d", index), 65 } 66 } 67 68 func ContractNamesRegisterID(address Address) RegisterID { 69 return RegisterID{ 70 Owner: addressToOwner(address), 71 Key: ContractNamesKey, 72 } 73 } 74 75 func ContractRegisterID(address Address, contractName string) RegisterID { 76 return RegisterID{ 77 Owner: addressToOwner(address), 78 Key: CodeKeyPrefix + contractName, 79 } 80 } 81 82 func CadenceRegisterID(owner []byte, key []byte) RegisterID { 83 return RegisterID{ 84 Owner: addressToOwner(BytesToAddress(owner)), 85 Key: string(key), 86 } 87 } 88 89 func NewRegisterID(owner Address, key string) RegisterID { 90 // global registers have an empty owner field 91 ownerString := "" 92 93 // all other registers have the account's address 94 if owner != EmptyAddress { 95 ownerString = addressToOwner(owner) 96 } 97 98 return RegisterID{ 99 Owner: ownerString, 100 Key: key, 101 } 102 } 103 104 // IsInternalState returns true if the register id is controlled by flow-go and 105 // return false otherwise (key controlled by the cadence env). 106 func (id RegisterID) IsInternalState() bool { 107 // check if is a service level key (owner is empty) 108 // cases: 109 // - "", "uuid" (for shard index 0) 110 // - "", "uuid_%d" (for shard index > 0) 111 // - "", "account_address_state" 112 if len(id.Owner) == 0 { 113 return strings.HasPrefix(id.Key, UUIDKeyPrefix) || 114 id.Key == AddressStateKey 115 } 116 117 // check account level keys 118 // cases: 119 // - address, "contract_names" 120 // - address, "code.%s" (contract name) 121 // - address, "public_key_%d" (index) 122 // - address, "a.s" (account status) 123 return strings.HasPrefix(id.Key, PublicKeyKeyPrefix) || 124 id.Key == ContractNamesKey || 125 strings.HasPrefix(id.Key, CodeKeyPrefix) || 126 id.Key == AccountStatusKey 127 } 128 129 // IsSlabIndex returns true if the key is a slab index for an account's ordered fields 130 // map. 131 // 132 // In general, each account's regular fields are stored in ordered map known 133 // only to cadence. Cadence encodes this map into bytes and split the bytes 134 // into slab chunks before storing the slabs into the ledger. 135 func (id RegisterID) IsSlabIndex() bool { 136 return len(id.Key) == 9 && id.Key[0] == '$' 137 } 138 139 // String returns formatted string representation of the RegisterID. 140 func (id RegisterID) String() string { 141 formattedKey := "" 142 if id.IsSlabIndex() { 143 i := uint64(binary.BigEndian.Uint64([]byte(id.Key[1:]))) 144 formattedKey = fmt.Sprintf("$%d", i) 145 } else { 146 formattedKey = fmt.Sprintf("#%x", []byte(id.Key)) 147 } 148 149 return fmt.Sprintf("%x/%s", id.Owner, formattedKey) 150 } 151 152 // Bytes returns a bytes representation of the RegisterID. 153 // 154 // The encoding uses the injective fingerprint module. 155 func (r *RegisterID) Bytes() []byte { 156 return fingerprint.Fingerprint(r) 157 } 158 159 // RegisterValue (value part of Register) 160 type RegisterValue = []byte 161 162 type RegisterEntry struct { 163 Key RegisterID 164 Value RegisterValue 165 } 166 167 // handy container for sorting 168 // TODO(ramtin): add canonical encoding and fingerprint for RegisterEntries 169 type RegisterEntries []RegisterEntry 170 171 func (d RegisterEntries) Len() int { 172 return len(d) 173 } 174 175 func (d RegisterEntries) Less(i, j int) bool { 176 if d[i].Key.Owner != d[j].Key.Owner { 177 return d[i].Key.Owner < d[j].Key.Owner 178 } 179 return d[i].Key.Key < d[j].Key.Key 180 } 181 182 func (d RegisterEntries) Swap(i, j int) { 183 d[i], d[j] = d[j], d[i] 184 } 185 186 func (d RegisterEntries) IDs() []RegisterID { 187 r := make([]RegisterID, len(d)) 188 for i, entry := range d { 189 r[i] = entry.Key 190 } 191 return r 192 } 193 194 func (d RegisterEntries) Values() []RegisterValue { 195 r := make([]RegisterValue, len(d)) 196 for i, entry := range d { 197 r[i] = entry.Value 198 } 199 return r 200 } 201 202 // handy container for sorting 203 type RegisterIDs []RegisterID 204 205 func (d RegisterIDs) Len() int { 206 return len(d) 207 } 208 209 func (d RegisterIDs) Less(i, j int) bool { 210 if d[i].Owner != d[j].Owner { 211 return d[i].Owner < d[j].Owner 212 } 213 return d[i].Key < d[j].Key 214 } 215 216 func (d RegisterIDs) Swap(i, j int) { 217 d[i], d[j] = d[j], d[i] 218 } 219 220 // StorageProof (proof of a read or update to the state, Merkle path of some sort) 221 type StorageProof = []byte 222 223 // StateCommitment holds the root hash of the tree (Snapshot) 224 // TODO: solve the circular dependency and define StateCommitment as ledger.State 225 type StateCommitment hash.Hash 226 227 // DummyStateCommitment is an arbitrary value used in function failure cases, 228 // although it can represent a valid state commitment. 229 var DummyStateCommitment = StateCommitment(hash.DummyHash) 230 231 // ToStateCommitment converts a byte slice into a StateCommitment. 232 // It returns an error if the slice has an invalid length. 233 // The returned error indicates that the given byte slice is not a 234 // valid root hash of an execution state. As the function is 235 // side-effect free, all failures are simply a no-op. 236 func ToStateCommitment(stateBytes []byte) (StateCommitment, error) { 237 var state StateCommitment 238 if len(stateBytes) != len(state) { 239 return DummyStateCommitment, fmt.Errorf("expecting %d bytes but got %d bytes", len(state), len(stateBytes)) 240 } 241 copy(state[:], stateBytes) 242 return state, nil 243 } 244 245 func (s StateCommitment) MarshalJSON() ([]byte, error) { 246 return json.Marshal(hex.EncodeToString(s[:])) 247 } 248 249 func (s *StateCommitment) UnmarshalJSON(data []byte) error { 250 // first, attempt to unmarshal assuming data is a hex string representation 251 err := s.unmarshalJSONHexString(data) 252 if err == nil { 253 return nil 254 } 255 // fallback to unmarshalling as [32]byte 256 return s.unmarshalJSONByteArr(data) 257 } 258 259 func (s *StateCommitment) unmarshalJSONHexString(data []byte) error { 260 var stateCommitmentHex string 261 if err := json.Unmarshal(data, &stateCommitmentHex); err != nil { 262 return err 263 } 264 b, err := hex.DecodeString(stateCommitmentHex) 265 if err != nil { 266 return err 267 } 268 h, err := hash.ToHash(b) 269 if err != nil { 270 return err 271 } 272 *s = StateCommitment(h) 273 return nil 274 } 275 276 func (s *StateCommitment) unmarshalJSONByteArr(data []byte) error { 277 var stateCommitment [32]byte 278 if err := json.Unmarshal(data, &stateCommitment); err != nil { 279 return err 280 } 281 *s = stateCommitment 282 return nil 283 }