github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/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:   ContractKey(contractName),
    79  	}
    80  }
    81  
    82  func ContractKey(contractName string) string {
    83  	return CodeKeyPrefix + contractName
    84  }
    85  
    86  func IsContractKey(key string) bool {
    87  	return strings.HasPrefix(key, CodeKeyPrefix)
    88  }
    89  
    90  func KeyContractName(key string) string {
    91  	if !IsContractKey(key) {
    92  		return ""
    93  	}
    94  	return key[len(CodeKeyPrefix):]
    95  }
    96  
    97  func IsContractNamesRegisterID(registerID RegisterID) bool {
    98  	return registerID.Key == ContractNamesKey
    99  }
   100  
   101  func CadenceRegisterID(owner []byte, key []byte) RegisterID {
   102  	return RegisterID{
   103  		Owner: addressToOwner(BytesToAddress(owner)),
   104  		Key:   string(key),
   105  	}
   106  }
   107  
   108  // AddressToRegisterOwner converts 8-byte address to register owner.
   109  // If given address is ZeroAddress, register owner is "" (global register).
   110  func AddressToRegisterOwner(address Address) string {
   111  	// Global registers have address zero and an empty owner field
   112  	if address == EmptyAddress {
   113  		return ""
   114  	}
   115  
   116  	// All other registers have the account's address
   117  	return addressToOwner(address)
   118  }
   119  
   120  func NewRegisterID(owner Address, key string) RegisterID {
   121  	return RegisterID{
   122  		Owner: AddressToRegisterOwner(owner),
   123  		Key:   key,
   124  	}
   125  }
   126  
   127  // IsInternalState returns true if the register id is controlled by flow-go and
   128  // return false otherwise (key controlled by the cadence env).
   129  func (id RegisterID) IsInternalState() bool {
   130  	// check if is a service level key (owner is empty)
   131  	// cases:
   132  	//      - "", "uuid" (for shard index 0)
   133  	//      - "", "uuid_%d" (for shard index > 0)
   134  	//      - "", "account_address_state"
   135  	if len(id.Owner) == 0 {
   136  		return strings.HasPrefix(id.Key, UUIDKeyPrefix) ||
   137  			id.Key == AddressStateKey
   138  	}
   139  
   140  	// check account level keys
   141  	// cases:
   142  	//      - address, "contract_names"
   143  	//      - address, "code.%s" (contract name)
   144  	//      - address, "public_key_%d" (index)
   145  	//      - address, "a.s" (account status)
   146  	return strings.HasPrefix(id.Key, PublicKeyKeyPrefix) ||
   147  		id.Key == ContractNamesKey ||
   148  		strings.HasPrefix(id.Key, CodeKeyPrefix) ||
   149  		id.Key == AccountStatusKey
   150  }
   151  
   152  const SlabIndexPrefix = '$'
   153  
   154  // IsSlabIndex returns true if the key is a slab index for an account's ordered fields
   155  // map.
   156  //
   157  // In general, each account's regular fields are stored in ordered map known
   158  // only to cadence.  Cadence encodes this map into bytes and split the bytes
   159  // into slab chunks before storing the slabs into the ledger.
   160  func (id RegisterID) IsSlabIndex() bool {
   161  	return IsSlabIndexKey(id.Key)
   162  }
   163  
   164  func IsSlabIndexKey(key string) bool {
   165  	return len(key) == 9 && key[0] == SlabIndexPrefix
   166  }
   167  
   168  // String returns formatted string representation of the RegisterID.
   169  func (id RegisterID) String() string {
   170  	formattedKey := ""
   171  	if id.IsSlabIndex() {
   172  		i := binary.BigEndian.Uint64([]byte(id.Key[1:]))
   173  		formattedKey = fmt.Sprintf("%c%d", SlabIndexPrefix, i)
   174  	} else {
   175  		formattedKey = fmt.Sprintf("#%x", []byte(id.Key))
   176  	}
   177  
   178  	return fmt.Sprintf("%x/%s", id.Owner, formattedKey)
   179  }
   180  
   181  // Bytes returns a bytes representation of the RegisterID.
   182  //
   183  // The encoding uses the injective fingerprint module.
   184  func (r *RegisterID) Bytes() []byte {
   185  	return fingerprint.Fingerprint(r)
   186  }
   187  
   188  // RegisterValue (value part of Register)
   189  type RegisterValue = []byte
   190  
   191  type RegisterEntry struct {
   192  	Key   RegisterID
   193  	Value RegisterValue
   194  }
   195  
   196  // handy container for sorting
   197  // TODO(ramtin): add canonical encoding and fingerprint for RegisterEntries
   198  type RegisterEntries []RegisterEntry
   199  
   200  func (d RegisterEntries) Len() int {
   201  	return len(d)
   202  }
   203  
   204  func (d RegisterEntries) Less(i, j int) bool {
   205  	if d[i].Key.Owner != d[j].Key.Owner {
   206  		return d[i].Key.Owner < d[j].Key.Owner
   207  	}
   208  	return d[i].Key.Key < d[j].Key.Key
   209  }
   210  
   211  func (d RegisterEntries) Swap(i, j int) {
   212  	d[i], d[j] = d[j], d[i]
   213  }
   214  
   215  func (d RegisterEntries) IDs() []RegisterID {
   216  	r := make([]RegisterID, len(d))
   217  	for i, entry := range d {
   218  		r[i] = entry.Key
   219  	}
   220  	return r
   221  }
   222  
   223  func (d RegisterEntries) Values() []RegisterValue {
   224  	r := make([]RegisterValue, len(d))
   225  	for i, entry := range d {
   226  		r[i] = entry.Value
   227  	}
   228  	return r
   229  }
   230  
   231  // handy container for sorting
   232  type RegisterIDs []RegisterID
   233  
   234  func (d RegisterIDs) Len() int {
   235  	return len(d)
   236  }
   237  
   238  func (d RegisterIDs) Less(i, j int) bool {
   239  	if d[i].Owner != d[j].Owner {
   240  		return d[i].Owner < d[j].Owner
   241  	}
   242  	return d[i].Key < d[j].Key
   243  }
   244  
   245  func (d RegisterIDs) Swap(i, j int) {
   246  	d[i], d[j] = d[j], d[i]
   247  }
   248  
   249  // StorageProof (proof of a read or update to the state, Merkle path of some sort)
   250  type StorageProof = []byte
   251  
   252  // StateCommitment holds the root hash of the tree (Snapshot)
   253  // TODO: solve the circular dependency and define StateCommitment as ledger.State
   254  type StateCommitment hash.Hash
   255  
   256  // DummyStateCommitment is an arbitrary value used in function failure cases,
   257  // although it can represent a valid state commitment.
   258  var DummyStateCommitment = StateCommitment(hash.DummyHash)
   259  
   260  // ToStateCommitment converts a byte slice into a StateCommitment.
   261  // It returns an error if the slice has an invalid length.
   262  // The returned error indicates that the given byte slice is not a
   263  // valid root hash of an execution state.  As the function is
   264  // side-effect free, all failures are simply a no-op.
   265  func ToStateCommitment(stateBytes []byte) (StateCommitment, error) {
   266  	var state StateCommitment
   267  	if len(stateBytes) != len(state) {
   268  		return DummyStateCommitment, fmt.Errorf("expecting %d bytes but got %d bytes", len(state), len(stateBytes))
   269  	}
   270  	copy(state[:], stateBytes)
   271  	return state, nil
   272  }
   273  
   274  func (s StateCommitment) MarshalJSON() ([]byte, error) {
   275  	return json.Marshal(hex.EncodeToString(s[:]))
   276  }
   277  
   278  func (s *StateCommitment) UnmarshalJSON(data []byte) error {
   279  	// first, attempt to unmarshal assuming data is a hex string representation
   280  	err := s.unmarshalJSONHexString(data)
   281  	if err == nil {
   282  		return nil
   283  	}
   284  	// fallback to unmarshalling as [32]byte
   285  	return s.unmarshalJSONByteArr(data)
   286  }
   287  
   288  func (s *StateCommitment) unmarshalJSONHexString(data []byte) error {
   289  	var stateCommitmentHex string
   290  	if err := json.Unmarshal(data, &stateCommitmentHex); err != nil {
   291  		return err
   292  	}
   293  	b, err := hex.DecodeString(stateCommitmentHex)
   294  	if err != nil {
   295  		return err
   296  	}
   297  	h, err := hash.ToHash(b)
   298  	if err != nil {
   299  		return err
   300  	}
   301  	*s = StateCommitment(h)
   302  	return nil
   303  }
   304  
   305  func (s *StateCommitment) unmarshalJSONByteArr(data []byte) error {
   306  	var stateCommitment [32]byte
   307  	if err := json.Unmarshal(data, &stateCommitment); err != nil {
   308  		return err
   309  	}
   310  	*s = stateCommitment
   311  	return nil
   312  }