github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/native/state.go (about) 1 package native 2 3 import ( 4 "github.com/hyperledger/burrow/acm" 5 "github.com/hyperledger/burrow/acm/acmstate" 6 "github.com/hyperledger/burrow/binary" 7 "github.com/hyperledger/burrow/crypto" 8 "github.com/hyperledger/burrow/execution/engine" 9 "github.com/hyperledger/burrow/execution/errors" 10 ) 11 12 // This wrapper provides a state that behaves 'as if' the natives were stored directly in state. 13 // TODO: we may want to actually store native account sentinel values (and their metadata) in on-disk state down the line 14 type State struct { 15 natives engine.Natives 16 backend acmstate.ReaderWriter 17 } 18 19 // Get a new state that wraps the backend but intercepts any calls to natives returning appropriate errors message 20 // or an Account sentinel for the particular native 21 func NewState(natives engine.Natives, backend acmstate.ReaderWriter) *State { 22 return &State{ 23 natives: natives, 24 backend: backend, 25 } 26 } 27 28 func (s *State) UpdateAccount(updatedAccount *acm.Account) error { 29 err := s.ensureNonNative(updatedAccount.Address, "update account") 30 if err != nil { 31 return err 32 } 33 return s.backend.UpdateAccount(updatedAccount) 34 } 35 36 func (s *State) GetAccount(address crypto.Address) (*acm.Account, error) { 37 contract := s.natives.GetByAddress(address) 38 if contract != nil { 39 return account(contract), nil 40 } 41 return s.backend.GetAccount(address) 42 } 43 44 func (s *State) RemoveAccount(address crypto.Address) error { 45 err := s.ensureNonNative(address, "remove account") 46 if err != nil { 47 return err 48 } 49 return s.backend.RemoveAccount(address) 50 } 51 52 func (s *State) GetStorage(address crypto.Address, key binary.Word256) ([]byte, error) { 53 err := s.ensureNonNative(address, "get storage") 54 if err != nil { 55 return nil, err 56 } 57 return s.backend.GetStorage(address, key) 58 } 59 60 func (s *State) SetStorage(address crypto.Address, key binary.Word256, value []byte) error { 61 err := s.ensureNonNative(address, "set storage") 62 if err != nil { 63 return err 64 } 65 return s.backend.SetStorage(address, key, value) 66 } 67 68 func (s *State) ensureNonNative(address crypto.Address, action string) error { 69 contract := s.natives.GetByAddress(address) 70 if contract != nil { 71 return errors.Errorf(errors.Codes.ReservedAddress, 72 "cannot %s at %v because that address is reserved for a native contract '%s'", 73 action, address, contract.FullName()) 74 } 75 return nil 76 } 77 78 func account(callable engine.Native) *acm.Account { 79 return &acm.Account{ 80 Address: callable.Address(), 81 NativeName: callable.FullName(), 82 // TODO: this is not populated yet, see FIXME note on native.Contract 83 ContractMeta: callable.ContractMeta(), 84 } 85 }