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  }