github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/native/permissions.go (about)

     1  package native
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hyperledger/burrow/execution/engine"
     7  
     8  	"github.com/hyperledger/burrow/acm"
     9  	"github.com/hyperledger/burrow/crypto"
    10  	"github.com/hyperledger/burrow/permission"
    11  )
    12  
    13  var Permissions = New().MustContract("Permissions",
    14  	`* Interface for managing Secure Native authorizations.
    15  		* @dev This interface describes the functions exposed by the native permissions layer in burrow.
    16  		`,
    17  	Function{
    18  		Comment: `
    19  			* @notice Adds a role to an account
    20  			* @param _account account address
    21  			* @param _role role name
    22  			* @return _result whether role was added
    23  			`,
    24  		PermFlag: permission.AddRole,
    25  		F:        addRole,
    26  	},
    27  	Function{
    28  		Comment: `
    29  			* @notice Removes a role from an account
    30  			* @param _account account address
    31  			* @param _role role name
    32  			* @return _result whether role was removed
    33  			`,
    34  		PermFlag: permission.RemoveRole,
    35  		F:        removeRole,
    36  	},
    37  	Function{
    38  		Comment: `
    39  			* @notice Indicates whether an account has a role
    40  			* @param _account account address
    41  			* @param _role role name
    42  			* @return _result whether account has role
    43  			`,
    44  		PermFlag: permission.HasRole,
    45  		F:        hasRole,
    46  	},
    47  	Function{
    48  		Comment: `
    49  			* @notice Sets the permission flags for an account. Makes them explicitly set (on or off).
    50  			* @param _account account address
    51  			* @param _permission the base permissions flags to set for the account
    52  			* @param _set whether to set or unset the permissions flags at the account level
    53  			* @return _result is the permission flag that was set as uint64
    54  			`,
    55  		PermFlag: permission.SetBase,
    56  		F:        setBase,
    57  	},
    58  	Function{
    59  		Comment: `
    60  			* @notice Unsets the permissions flags for an account. Causes permissions being unset to fall through to global permissions.
    61        		* @param _account account address
    62        		* @param _permission the permissions flags to unset for the account
    63  			* @return _result is the permission flag that was unset as uint64
    64        `,
    65  		PermFlag: permission.UnsetBase,
    66  		F:        unsetBase,
    67  	},
    68  	Function{
    69  		Comment: `
    70  			* @notice Indicates whether an account has a subset of permissions set
    71  			* @param _account account address
    72  			* @param _permission the permissions flags (mask) to check whether enabled against base permissions for the account
    73  			* @return _result is whether account has the passed permissions flags set
    74  			`,
    75  		PermFlag: permission.HasBase,
    76  		F:        hasBase,
    77  	},
    78  	Function{Comment: `
    79  			* @notice Sets the global (default) permissions flags for the entire chain
    80  			* @param _permission the permissions flags to set
    81  			* @param _set whether to set (or unset) the permissions flags
    82  			* @return _result is the permission flag that was set as uint64
    83  			`,
    84  		PermFlag: permission.SetGlobal,
    85  		F:        setGlobal,
    86  	},
    87  )
    88  
    89  type hasBaseArgs struct {
    90  	Account    crypto.Address
    91  	Permission uint64
    92  }
    93  
    94  type hasBaseRets struct {
    95  	Result bool
    96  }
    97  
    98  func hasBase(ctx Context, args hasBaseArgs) (hasBaseRets, error) {
    99  	permN := permission.PermFlag(args.Permission) // already shifted
   100  	if !permN.IsValid() {
   101  		return hasBaseRets{}, permission.ErrInvalidPermission(permN)
   102  	}
   103  	hasPermission, err := engine.HasPermission(ctx.State, args.Account, permN)
   104  	if err != nil {
   105  		return hasBaseRets{}, err
   106  	}
   107  	ctx.Logger.Trace.Log("function", "hasBase",
   108  		"address", args.Account.String(),
   109  		"perm_flag", fmt.Sprintf("%b", permN),
   110  		"has_permission", hasPermission)
   111  	return hasBaseRets{Result: hasPermission}, nil
   112  }
   113  
   114  type setBaseArgs struct {
   115  	Account    crypto.Address
   116  	Permission uint64
   117  	Set        bool
   118  }
   119  
   120  type setBaseRets struct {
   121  	Result uint64
   122  }
   123  
   124  func setBase(ctx Context, args setBaseArgs) (setBaseRets, error) {
   125  	permFlag := permission.PermFlag(args.Permission)
   126  	if !permFlag.IsValid() {
   127  		return setBaseRets{}, permission.ErrInvalidPermission(permFlag)
   128  	}
   129  	err := engine.UpdateAccount(ctx.State, args.Account, func(acc *acm.Account) error {
   130  		err := acc.Permissions.Base.Set(permFlag, args.Set)
   131  		return err
   132  	})
   133  	if err != nil {
   134  		return setBaseRets{}, err
   135  	}
   136  	ctx.Logger.Trace.Log("function", "setBase", "address", args.Account.String(),
   137  		"permission_flag", fmt.Sprintf("%b", permFlag),
   138  		"permission_value", args.Permission)
   139  	return setBaseRets{Result: uint64(permFlag)}, nil
   140  }
   141  
   142  type unsetBaseArgs struct {
   143  	Account    crypto.Address
   144  	Permission uint64
   145  }
   146  
   147  type unsetBaseRets struct {
   148  	Result uint64
   149  }
   150  
   151  func unsetBase(ctx Context, args unsetBaseArgs) (unsetBaseRets, error) {
   152  	permFlag := permission.PermFlag(args.Permission)
   153  	if !permFlag.IsValid() {
   154  		return unsetBaseRets{}, permission.ErrInvalidPermission(permFlag)
   155  	}
   156  	err := engine.UpdateAccount(ctx.State, args.Account, func(acc *acm.Account) error {
   157  		return acc.Permissions.Base.Unset(permFlag)
   158  	})
   159  	if err != nil {
   160  		return unsetBaseRets{}, err
   161  	}
   162  	ctx.Logger.Trace.Log("function", "unsetBase", "address", args.Account.String(),
   163  		"perm_flag", fmt.Sprintf("%b", permFlag),
   164  		"permission_flag", fmt.Sprintf("%b", permFlag))
   165  
   166  	return unsetBaseRets{Result: uint64(permFlag)}, nil
   167  }
   168  
   169  type setGlobalArgs struct {
   170  	Permission uint64
   171  	Set        bool
   172  }
   173  
   174  type setGlobalRets struct {
   175  	Result uint64
   176  }
   177  
   178  func setGlobal(ctx Context, args setGlobalArgs) (setGlobalRets, error) {
   179  	permFlag := permission.PermFlag(args.Permission)
   180  	if !permFlag.IsValid() {
   181  		return setGlobalRets{}, permission.ErrInvalidPermission(permFlag)
   182  	}
   183  	err := engine.UpdateAccount(ctx.State, acm.GlobalPermissionsAddress, func(acc *acm.Account) error {
   184  		return acc.Permissions.Base.Set(permFlag, args.Set)
   185  	})
   186  	if err != nil {
   187  		return setGlobalRets{}, err
   188  	}
   189  	ctx.Logger.Trace.Log("function", "setGlobal",
   190  		"permission_flag", fmt.Sprintf("%b", permFlag),
   191  		"permission_value", args.Set)
   192  	return setGlobalRets{Result: uint64(permFlag)}, nil
   193  }
   194  
   195  type hasRoleArgs struct {
   196  	Account crypto.Address
   197  	Role    string
   198  }
   199  
   200  type hasRoleRets struct {
   201  	Result bool
   202  }
   203  
   204  func hasRole(ctx Context, args hasRoleArgs) (hasRoleRets, error) {
   205  	acc, err := engine.MustAccount(ctx.State, args.Account)
   206  	if err != nil {
   207  		return hasRoleRets{}, err
   208  	}
   209  	hasRole := acc.Permissions.HasRole(args.Role)
   210  	ctx.Logger.Trace.Log("function", "hasRole", "address", args.Account.String(),
   211  		"role", args.Role,
   212  		"has_role", hasRole)
   213  	return hasRoleRets{Result: hasRole}, nil
   214  }
   215  
   216  type addRoleArgs struct {
   217  	Account crypto.Address
   218  	Role    string
   219  }
   220  
   221  type addRoleRets struct {
   222  	Result bool
   223  }
   224  
   225  func addRole(ctx Context, args addRoleArgs) (addRoleRets, error) {
   226  	ret := addRoleRets{}
   227  	err := engine.UpdateAccount(ctx.State, args.Account, func(account *acm.Account) error {
   228  		ret.Result = account.Permissions.AddRole(args.Role)
   229  		return nil
   230  	})
   231  	if err != nil {
   232  		return ret, err
   233  	}
   234  	ctx.Logger.Trace.Log("function", "addRole", "address", args.Account.String(),
   235  		"role", args.Role,
   236  		"role_added", ret.Result)
   237  	return ret, nil
   238  }
   239  
   240  type removeRoleArgs struct {
   241  	Account crypto.Address
   242  	Role    string
   243  }
   244  
   245  type removeRoleRets struct {
   246  	Result bool
   247  }
   248  
   249  func removeRole(ctx Context, args removeRoleArgs) (removeRoleRets, error) {
   250  	ret := removeRoleRets{}
   251  	err := engine.UpdateAccount(ctx.State, args.Account, func(account *acm.Account) error {
   252  		ret.Result = account.Permissions.RemoveRole(args.Role)
   253  		return nil
   254  	})
   255  	if err != nil {
   256  		return ret, err
   257  	}
   258  	ctx.Logger.Trace.Log("function", "removeRole", "address", args.Account.String(),
   259  		"role", args.Role,
   260  		"role_removed", ret.Result)
   261  	return ret, nil
   262  }