github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/state/accounts.go (about) 1 package state 2 3 import ( 4 "fmt" 5 6 "github.com/hyperledger/burrow/storage" 7 8 "github.com/hyperledger/burrow/acm" 9 "github.com/hyperledger/burrow/acm/acmstate" 10 "github.com/hyperledger/burrow/binary" 11 "github.com/hyperledger/burrow/crypto" 12 "github.com/hyperledger/burrow/encoding" 13 ) 14 15 // Returns nil if account does not exist with given address. 16 func (s *ImmutableState) GetAccount(address crypto.Address) (*acm.Account, error) { 17 tree, err := s.Forest.Reader(keys.Account.Prefix()) 18 if err != nil { 19 return nil, err 20 } 21 accBytes, err := tree.Get(keys.Account.KeyNoPrefix(address)) 22 if err != nil { 23 return nil, err 24 } else if accBytes == nil { 25 return nil, nil 26 } 27 account := new(acm.Account) 28 err = encoding.Decode(accBytes, account) 29 if err != nil { 30 return nil, fmt.Errorf("could not decode Account: %v", err) 31 } 32 return account, nil 33 } 34 35 func (ws *writeState) statsAddAccount(acc *acm.Account) { 36 if acc != nil { 37 if len(acc.EVMCode) > 0 || len(acc.WASMCode) > 0 { 38 ws.accountStats.AccountsWithCode++ 39 } else { 40 ws.accountStats.AccountsWithoutCode++ 41 } 42 } 43 } 44 45 func (ws *writeState) statsRemoveAccount(acc *acm.Account) { 46 if acc != nil { 47 if len(acc.EVMCode) > 0 || len(acc.WASMCode) > 0 { 48 ws.accountStats.AccountsWithCode-- 49 } else { 50 ws.accountStats.AccountsWithoutCode-- 51 } 52 } 53 } 54 55 func (ws *writeState) UpdateAccount(account *acm.Account) error { 56 if account == nil { 57 return fmt.Errorf("UpdateAccount passed nil account in State") 58 } 59 bs, err := encoding.Encode(account) 60 if err != nil { 61 return fmt.Errorf("UpdateAccount could not encode account: %v", err) 62 } 63 return ws.forest.Write(keys.Account.Prefix(), func(tree *storage.RWTree) error { 64 updated := tree.Set(keys.Account.KeyNoPrefix(account.Address), bs) 65 if updated { 66 ws.statsAddAccount(account) 67 } 68 return nil 69 }) 70 } 71 72 func (ws *writeState) RemoveAccount(address crypto.Address) error { 73 return ws.forest.Write(keys.Account.Prefix(), func(tree *storage.RWTree) error { 74 accBytes, deleted := tree.Delete(keys.Account.KeyNoPrefix(address)) 75 if deleted { 76 account := new(acm.Account) 77 err := encoding.Decode(accBytes, account) 78 if err != nil { 79 return err 80 } 81 ws.statsRemoveAccount(account) 82 // Delete storage associated with account too 83 _, err = ws.forest.Delete(keys.Storage.Key(address)) 84 if err != nil { 85 return err 86 } 87 } 88 return nil 89 }) 90 } 91 92 func (s *ImmutableState) IterateAccounts(consumer func(*acm.Account) error) error { 93 tree, err := s.Forest.Reader(keys.Account.Prefix()) 94 if err != nil { 95 return err 96 } 97 return tree.Iterate(nil, nil, true, func(key []byte, value []byte) error { 98 account := new(acm.Account) 99 err := encoding.Decode(value, account) 100 if err != nil { 101 return fmt.Errorf("IterateAccounts could not decode account: %v", err) 102 } 103 return consumer(account) 104 }) 105 } 106 107 func (s *State) GetAccountStats() acmstate.AccountStats { 108 return s.writeState.accountStats 109 } 110 111 // Storage 112 113 func (s *ImmutableState) GetStorage(address crypto.Address, key binary.Word256) ([]byte, error) { 114 keyFormat := keys.Storage.Fix(address) 115 tree, err := s.Forest.Reader(keyFormat.Prefix()) 116 if err != nil { 117 return []byte{}, err 118 } 119 return tree.Get(keyFormat.KeyNoPrefix(key)) 120 } 121 122 func (ws *writeState) SetStorage(address crypto.Address, key binary.Word256, value []byte) error { 123 keyFormat := keys.Storage.Fix(address) 124 return ws.forest.Write(keyFormat.Prefix(), func(tree *storage.RWTree) error { 125 zero := true 126 for _, b := range value { 127 if b != 0 { 128 zero = false 129 break 130 } 131 } 132 if zero { 133 tree.Delete(keyFormat.KeyNoPrefix(key)) 134 } else { 135 tree.Set(keyFormat.KeyNoPrefix(key), value) 136 } 137 return nil 138 }) 139 } 140 141 func (s *ImmutableState) IterateStorage(address crypto.Address, consumer func(key binary.Word256, value []byte) error) error { 142 keyFormat := keys.Storage.Fix(address) 143 tree, err := s.Forest.Reader(keyFormat.Prefix()) 144 if err != nil { 145 return err 146 } 147 return tree.Iterate(nil, nil, true, 148 func(key []byte, value []byte) error { 149 150 if len(key) != binary.Word256Bytes { 151 return fmt.Errorf("key '%X' stored for account %s is not a %v-byte word", 152 key, address, binary.Word256Bytes) 153 } 154 if len(value) != binary.Word256Bytes { 155 return fmt.Errorf("value '%X' stored for account %s is not a %v-byte word", 156 key, address, binary.Word256Bytes) 157 } 158 return consumer(binary.LeftPadWord256(key), value) 159 }) 160 }