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  }