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