github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/environment/accounts_status.go (about) 1 package environment 2 3 import ( 4 "encoding/binary" 5 "encoding/hex" 6 7 "github.com/onflow/atree" 8 9 "github.com/onflow/flow-go/fvm/errors" 10 ) 11 12 const ( 13 flagSize = 1 14 storageUsedSize = 8 15 storageIndexSize = 8 16 publicKeyCountsSize = 8 17 addressIdCounterSize = 8 18 19 // oldAccountStatusSize is the size of the account status before the address 20 // id counter was added. After v0.32.0 check if it can be removed as all accounts 21 // should then have the new status sile len. 22 oldAccountStatusSize = flagSize + 23 storageUsedSize + 24 storageIndexSize + 25 publicKeyCountsSize 26 27 accountStatusSize = flagSize + 28 storageUsedSize + 29 storageIndexSize + 30 publicKeyCountsSize + 31 addressIdCounterSize 32 33 flagIndex = 0 34 storageUsedStartIndex = flagIndex + flagSize 35 storageIndexStartIndex = storageUsedStartIndex + storageUsedSize 36 publicKeyCountsStartIndex = storageIndexStartIndex + storageIndexSize 37 addressIdCounterStartIndex = publicKeyCountsStartIndex + publicKeyCountsSize 38 ) 39 40 // AccountStatus holds meta information about an account 41 // 42 // currently modelled as a byte array with on-demand encoding/decoding of sub arrays 43 // the first byte captures flags 44 // the next 8 bytes (big-endian) captures storage used by an account 45 // the next 8 bytes (big-endian) captures the storage index of an account 46 // the next 8 bytes (big-endian) captures the number of public keys stored on this account 47 // the next 8 bytes (big-endian) captures the current address id counter 48 type AccountStatus [accountStatusSize]byte 49 50 // NewAccountStatus returns a new AccountStatus 51 // sets the storage index to the init value 52 func NewAccountStatus() *AccountStatus { 53 return &AccountStatus{ 54 0, // initial empty flags 55 0, 0, 0, 0, 0, 0, 0, 0, // init value for storage used 56 0, 0, 0, 0, 0, 0, 0, 1, // init value for storage index 57 0, 0, 0, 0, 0, 0, 0, 0, // init value for public key counts 58 0, 0, 0, 0, 0, 0, 0, 0, // init value for address id counter 59 } 60 } 61 62 // ToBytes converts AccountStatus to a byte slice 63 // 64 // this has been kept this way in case one day 65 // we decided to move on to use a struct to represent 66 // account status. 67 func (a *AccountStatus) ToBytes() []byte { 68 return a[:] 69 } 70 71 // AccountStatusFromBytes constructs an AccountStatus from the given byte slice 72 func AccountStatusFromBytes(inp []byte) (*AccountStatus, error) { 73 var as AccountStatus 74 75 if len(inp) == oldAccountStatusSize { 76 // pad the input with zeros 77 // this is to migrate old account status to new account status on the fly 78 // TODO: remove this whole block after v0.32.0, when a full migration will 79 // be made. 80 sizeIncrease := uint64(accountStatusSize - oldAccountStatusSize) 81 82 // But we also need to fix the storage used by the appropriate size because 83 // the storage used is part of the account status itself. 84 copy(as[:], inp) 85 used := as.StorageUsed() 86 as.SetStorageUsed(used + sizeIncrease) 87 return &as, nil 88 } 89 90 if len(inp) != accountStatusSize { 91 return &as, errors.NewValueErrorf(hex.EncodeToString(inp), "invalid account status size") 92 } 93 copy(as[:], inp) 94 return &as, nil 95 } 96 97 // SetStorageUsed updates the storage used by the account 98 func (a *AccountStatus) SetStorageUsed(used uint64) { 99 binary.BigEndian.PutUint64(a[storageUsedStartIndex:storageUsedStartIndex+storageUsedSize], used) 100 } 101 102 // StorageUsed returns the storage used by the account 103 func (a *AccountStatus) StorageUsed() uint64 { 104 return binary.BigEndian.Uint64(a[storageUsedStartIndex : storageUsedStartIndex+storageUsedSize]) 105 } 106 107 // SetStorageIndex updates the storage index of the account 108 func (a *AccountStatus) SetStorageIndex(index atree.SlabIndex) { 109 copy(a[storageIndexStartIndex:storageIndexStartIndex+storageIndexSize], index[:storageIndexSize]) 110 } 111 112 // StorageIndex returns the storage index of the account 113 func (a *AccountStatus) StorageIndex() atree.SlabIndex { 114 var index atree.SlabIndex 115 copy(index[:], a[storageIndexStartIndex:storageIndexStartIndex+storageIndexSize]) 116 return index 117 } 118 119 // SetPublicKeyCount updates the public key count of the account 120 func (a *AccountStatus) SetPublicKeyCount(count uint64) { 121 binary.BigEndian.PutUint64(a[publicKeyCountsStartIndex:publicKeyCountsStartIndex+publicKeyCountsSize], count) 122 } 123 124 // PublicKeyCount returns the public key count of the account 125 func (a *AccountStatus) PublicKeyCount() uint64 { 126 return binary.BigEndian.Uint64(a[publicKeyCountsStartIndex : publicKeyCountsStartIndex+publicKeyCountsSize]) 127 } 128 129 // SetAccountIdCounter updates id counter of the account 130 func (a *AccountStatus) SetAccountIdCounter(id uint64) { 131 binary.BigEndian.PutUint64(a[addressIdCounterStartIndex:addressIdCounterStartIndex+addressIdCounterSize], id) 132 } 133 134 // AccountIdCounter returns id counter of the account 135 func (a *AccountStatus) AccountIdCounter() uint64 { 136 return binary.BigEndian.Uint64(a[addressIdCounterStartIndex : addressIdCounterStartIndex+addressIdCounterSize]) 137 }