github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/engine/accounts.go (about) 1 package engine 2 3 import ( 4 "fmt" 5 6 "github.com/hyperledger/burrow/acm" 7 "github.com/hyperledger/burrow/acm/acmstate" 8 "github.com/hyperledger/burrow/crypto" 9 "github.com/hyperledger/burrow/execution/errors" 10 "github.com/hyperledger/burrow/permission" 11 ) 12 13 type Maybe interface { 14 PushError(err error) bool 15 Error() error 16 } 17 18 func GetAccount(st acmstate.Reader, m Maybe, address crypto.Address) *acm.Account { 19 acc, err := st.GetAccount(address) 20 if err != nil { 21 m.PushError(err) 22 return nil 23 } 24 return acc 25 } 26 27 // Guaranteed to return a non-nil account, if the account does not exist returns a pointer to the zero-value of Account 28 // and pushes an error. 29 func MustGetAccount(st acmstate.Reader, m Maybe, address crypto.Address) *acm.Account { 30 acc := GetAccount(st, m, address) 31 if acc == nil { 32 m.PushError(errors.Errorf(errors.Codes.NonExistentAccount, "account %v does not exist", address)) 33 return &acm.Account{} 34 } 35 return acc 36 } 37 38 func EnsurePermission(callFrame *CallFrame, address crypto.Address, perm permission.PermFlag) error { 39 hasPermission, err := HasPermission(callFrame, address, perm) 40 if err != nil { 41 return err 42 } else if !hasPermission { 43 return errors.PermissionDenied{ 44 Address: address, 45 Perm: perm, 46 } 47 } 48 return nil 49 } 50 51 // CONTRACT: it is the duty of the contract writer to call known permissions 52 // we do not convey if a permission is not set 53 // (unlike in state/execution, where we guarantee HasPermission is called 54 // on known permissions and panics else) 55 // If the perm is not defined in the acc nor set by default in GlobalPermissions, 56 // this function returns false. 57 func HasPermission(st acmstate.Reader, address crypto.Address, perm permission.PermFlag) (bool, error) { 58 acc, err := st.GetAccount(address) 59 if err != nil { 60 return false, err 61 } 62 if acc == nil { 63 return false, fmt.Errorf("account %v does not exist", address) 64 } 65 globalPerms, err := acmstate.GlobalAccountPermissions(st) 66 if err != nil { 67 return false, err 68 } 69 perms := acc.Permissions.Base.Compose(globalPerms.Base) 70 value, err := perms.Get(perm) 71 if err != nil { 72 return false, err 73 } 74 return value, nil 75 } 76 77 func CreateAccount(st acmstate.ReaderWriter, address crypto.Address) error { 78 acc, err := st.GetAccount(address) 79 if err != nil { 80 return err 81 } 82 if acc != nil { 83 if acc.NativeName != "" { 84 return errors.Errorf(errors.Codes.ReservedAddress, 85 "cannot create account at %v because that address is reserved for a native contract '%s'", 86 address, acc.NativeName) 87 } 88 return errors.Errorf(errors.Codes.DuplicateAddress, 89 "tried to create an account at an address that already exists: %v", address) 90 } 91 return st.UpdateAccount(&acm.Account{Address: address}) 92 } 93 94 func AddressFromName(name string) (address crypto.Address) { 95 hash := crypto.Keccak256([]byte(name)) 96 copy(address[:], hash[len(hash)-crypto.AddressLength:]) 97 return 98 }