github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/acm/acmstate/state.go (about) 1 package acmstate 2 3 import ( 4 "fmt" 5 6 "github.com/hyperledger/burrow/acm" 7 "github.com/hyperledger/burrow/binary" 8 "github.com/hyperledger/burrow/crypto" 9 "golang.org/x/crypto/sha3" 10 11 "github.com/hyperledger/burrow/permission" 12 "github.com/tmthrgd/go-hex" 13 ) 14 15 // MetadataHash is the keccak hash for the metadata. This is to make the metadata content-addressed 16 type MetadataHash [32]byte 17 18 func (h *MetadataHash) Bytes() []byte { 19 b := make([]byte, 32) 20 copy(b, h[:]) 21 return b 22 } 23 24 func (ch *MetadataHash) UnmarshalText(hexBytes []byte) error { 25 bs, err := hex.DecodeString(string(hexBytes)) 26 if err != nil { 27 return err 28 } 29 copy(ch[:], bs) 30 return nil 31 } 32 33 func (ch MetadataHash) MarshalText() ([]byte, error) { 34 return []byte(ch.String()), nil 35 } 36 37 func (ch MetadataHash) String() string { 38 return hex.EncodeUpperToString(ch[:]) 39 } 40 41 func GetMetadataHash(metadata string) (metahash MetadataHash) { 42 hash := sha3.NewLegacyKeccak256() 43 hash.Write([]byte(metadata)) 44 copy(metahash[:], hash.Sum(nil)) 45 return 46 } 47 48 // CodeHash is the keccak hash for the code for an account. This is used for the EVM CODEHASH opcode, and to find the 49 // correct Metadata for a contract 50 type CodeHash [32]byte 51 52 func (h *CodeHash) Bytes() []byte { 53 b := make([]byte, 32) 54 copy(b, h[:]) 55 return b 56 } 57 58 func (ch *CodeHash) UnmarshalText(hexBytes []byte) error { 59 bs, err := hex.DecodeString(string(hexBytes)) 60 if err != nil { 61 return err 62 } 63 copy(ch[:], bs) 64 return nil 65 } 66 67 func (ch CodeHash) MarshalText() ([]byte, error) { 68 return []byte(ch.String()), nil 69 } 70 71 func (ch CodeHash) String() string { 72 return hex.EncodeUpperToString(ch[:]) 73 } 74 75 type AccountGetter interface { 76 // Get an account by its address return nil if it does not exist (which should not be an error) 77 GetAccount(address crypto.Address) (*acm.Account, error) 78 } 79 80 type AccountIterable interface { 81 // Iterates through accounts calling passed function once per account, if the consumer 82 // returns true the iteration breaks and returns true to indicate it iteration 83 // was escaped 84 IterateAccounts(consumer func(*acm.Account) error) (err error) 85 } 86 87 type AccountUpdater interface { 88 // Updates the fields of updatedAccount by address, creating the account 89 // if it does not exist 90 UpdateAccount(updatedAccount *acm.Account) error 91 // Remove the account at address 92 RemoveAccount(address crypto.Address) error 93 } 94 95 type StorageGetter interface { 96 // Retrieve a 32-byte value stored at key for the account at address, return Zero256 if key does not exist but 97 // error if address does not 98 GetStorage(address crypto.Address, key binary.Word256) (value []byte, err error) 99 } 100 101 type StorageSetter interface { 102 // Store a 32-byte value at key for the account at address, setting to Zero256 removes the key 103 SetStorage(address crypto.Address, key binary.Word256, value []byte) error 104 } 105 106 type StorageIterable interface { 107 // Iterates through the storage of account ad address calling the passed function once per account, 108 // if the iterator function returns true the iteration breaks and returns true to indicate it iteration 109 // was escaped 110 IterateStorage(address crypto.Address, consumer func(key binary.Word256, value []byte) error) (err error) 111 } 112 113 type MetadataReader interface { 114 // Get an Metadata by its hash. This is content-addressed 115 GetMetadata(metahash MetadataHash) (string, error) 116 } 117 118 type MetadataWriter interface { 119 // Set an Metadata according to it keccak-256 hash. 120 SetMetadata(metahash MetadataHash, metadata string) error 121 } 122 123 type AccountStats struct { 124 AccountsWithCode uint64 125 AccountsWithoutCode uint64 126 } 127 128 type AccountStatsGetter interface { 129 GetAccountStats() AccountStats 130 } 131 132 // Compositions 133 134 // Read-only account and storage state 135 type Reader interface { 136 AccountGetter 137 StorageGetter 138 } 139 140 type Iterable interface { 141 AccountIterable 142 StorageIterable 143 } 144 145 // Read and list account and storage state 146 type IterableReader interface { 147 Iterable 148 Reader 149 } 150 151 type IterableStatsReader interface { 152 Iterable 153 Reader 154 AccountStatsGetter 155 } 156 157 type Writer interface { 158 AccountUpdater 159 StorageSetter 160 } 161 162 // Read and write account and storage state 163 type ReaderWriter interface { 164 Reader 165 Writer 166 } 167 168 type MetadataReaderWriter interface { 169 MetadataReader 170 MetadataWriter 171 } 172 173 type IterableReaderWriter interface { 174 Iterable 175 Reader 176 Writer 177 } 178 179 // Get global permissions from the account at GlobalPermissionsAddress 180 func GlobalAccountPermissions(getter AccountGetter) (permission.AccountPermissions, error) { 181 acc, err := getter.GetAccount(acm.GlobalPermissionsAddress) 182 if err != nil { 183 return permission.AccountPermissions{}, err 184 } 185 if acc == nil { 186 return permission.AccountPermissions{}, fmt.Errorf("global permissions account is not defined but must be") 187 } 188 return acc.Permissions, nil 189 }