From 3d709643d529b4995dbe21263036310ced460463 Mon Sep 17 00:00:00 2001
From: Silas Davis <silas@monax.io>
Date: Mon, 8 Jan 2018 17:08:40 +0000
Subject: [PATCH] Permissions: restructed permissions to make global constants
 accessible without import cycles. Added some support for building permissions
 from strings (for genesis).

Signed-off-by: Silas Davis <silas@monax.io>
---
 permission/constants.go                 |  10 +
 permission/{types => }/errors.go        |  21 +-
 permission/permissions.go               | 190 ++++++++++++++++
 permission/snatives.go                  |  88 ++++++++
 permission/types/account_permissions.go |  62 ++++++
 permission/types/base_permissions.go    |  86 ++++++++
 permission/types/permissions.go         | 277 ------------------------
 permission/types/snatives.go            | 120 ----------
 permission/{types => }/util.go          |  26 ++-
 permission/util_test.go                 |  16 ++
 10 files changed, 475 insertions(+), 421 deletions(-)
 create mode 100644 permission/constants.go
 rename permission/{types => }/errors.go (61%)
 create mode 100644 permission/permissions.go
 create mode 100644 permission/snatives.go
 create mode 100644 permission/types/account_permissions.go
 create mode 100644 permission/types/base_permissions.go
 delete mode 100644 permission/types/permissions.go
 delete mode 100644 permission/types/snatives.go
 rename permission/{types => }/util.go (75%)
 create mode 100644 permission/util_test.go

diff --git a/permission/constants.go b/permission/constants.go
new file mode 100644
index 00000000..c795fda0
--- /dev/null
+++ b/permission/constants.go
@@ -0,0 +1,10 @@
+package permission
+
+import (
+	"github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/binary"
+)
+
+var (
+	GlobalPermissionsAddress = account.Address(binary.Zero160)
+)
diff --git a/permission/types/errors.go b/permission/errors.go
similarity index 61%
rename from permission/types/errors.go
rename to permission/errors.go
index fe023ca8..795b621c 100644
--- a/permission/types/errors.go
+++ b/permission/errors.go
@@ -12,26 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package types
-
-import (
-	"fmt"
-)
+package permission
 
 //------------------------------------------------------------------------------------------------
 // Some errors
-
-// permission number out of bounds
-type ErrInvalidPermission PermFlag
-
-func (e ErrInvalidPermission) Error() string {
-	return fmt.Sprintf("invalid permission %d", e)
-}
-
-// set=false. This error should be caught and the global
-// value fetched for the permission by the caller
-type ErrValueNotSet PermFlag
-
-func (e ErrValueNotSet) Error() string {
-	return fmt.Sprintf("the value for permission %d is not set", e)
-}
diff --git a/permission/permissions.go b/permission/permissions.go
new file mode 100644
index 00000000..599be2bf
--- /dev/null
+++ b/permission/permissions.go
@@ -0,0 +1,190 @@
+// Copyright 2017 Monax Industries Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package permission
+
+import (
+	"fmt"
+	"strings"
+
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/permission/types"
+)
+
+//------------------------------------------------------------------------------------------------
+
+// Base permission references are like unix (the index is already bit shifted)
+const (
+	// chain permissions
+	Root           types.PermFlag = 1 << iota // 1
+	Send                                      // 2
+	Call                                      // 4
+	CreateContract                            // 8
+	CreateAccount                             // 16
+	Bond                                      // 32
+	Name                                      // 64
+
+	// moderator permissions
+	HasBase
+	SetBase
+	UnsetBase
+	SetGlobal
+	HasRole
+	AddRole
+	RemoveRole
+
+	NumPermissions uint = 14 // NOTE Adjust this too. We can support upto 64
+
+	TopPermFlag      types.PermFlag = 1 << (NumPermissions - 1)
+	AllPermFlags     types.PermFlag = TopPermFlag | (TopPermFlag - 1)
+	DefaultPermFlags types.PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name | HasBase | HasRole
+
+	RootString           string = "root"
+	SendString                  = "send"
+	CallString                  = "call"
+	CreateContractString        = "createContract"
+	CreateAccountString         = "createAccount"
+	BondString                  = "bond"
+	NameString                  = "name"
+
+	// moderator permissions
+	HasBaseString    = "hasBase"
+	SetBaseString    = "setBase"
+	UnsetBaseString  = "unsetBase"
+	SetGlobalString  = "setGlobal"
+	HasRoleString    = "hasRole"
+	AddRoleString    = "addRole"
+	RemoveRoleString = "removeRole"
+	UnknownString    = "#-UNKNOWN-#"
+
+	AllString = "all"
+)
+
+var (
+	ZeroBasePermissions    = types.BasePermissions{0, 0}
+	ZeroAccountPermissions = types.AccountPermissions{
+		Base: ZeroBasePermissions,
+	}
+	DefaultAccountPermissions = types.AccountPermissions{
+		Base: types.BasePermissions{
+			Perms:  DefaultPermFlags,
+			SetBit: AllPermFlags,
+		},
+		Roles: []string{},
+	}
+	AllAccountPermissions = types.AccountPermissions{
+		Base: types.BasePermissions{
+			Perms:  AllPermFlags,
+			SetBit: AllPermFlags,
+		},
+		Roles: []string{},
+	}
+)
+
+//---------------------------------------------------------------------------------------------
+
+//--------------------------------------------------------------------------------
+// string utilities
+
+// PermFlagToString assumes the permFlag is valid, else returns "#-UNKNOWN-#"
+func PermFlagToString(pf types.PermFlag) (perm string) {
+	switch pf {
+	case AllPermFlags:
+		perm = AllString
+	case Root:
+		perm = RootString
+	case Send:
+		perm = SendString
+	case Call:
+		perm = CallString
+	case CreateContract:
+		perm = CreateContractString
+	case CreateAccount:
+		perm = CreateAccountString
+	case Bond:
+		perm = BondString
+	case Name:
+		perm = NameString
+	case HasBase:
+		perm = HasBaseString
+	case SetBase:
+		perm = SetBaseString
+	case UnsetBase:
+		perm = UnsetBaseString
+	case SetGlobal:
+		perm = SetGlobalString
+	case HasRole:
+		perm = HasRoleString
+	case AddRole:
+		perm = AddRoleString
+	case RemoveRole:
+		perm = RemoveRoleString
+	default:
+		perm = UnknownString
+	}
+	return
+}
+
+// PermStringToFlag maps camel- and snake case strings to the
+// the corresponding permission flag.
+func PermStringToFlag(perm string) (pf types.PermFlag, err error) {
+	switch strings.ToLower(perm) {
+	case AllString:
+		pf = AllPermFlags
+	case RootString:
+		pf = Root
+	case SendString:
+		pf = Send
+	case CallString:
+		pf = Call
+	case CreateContractString, "createcontract", "create_contract":
+		pf = CreateContract
+	case CreateAccountString, "createaccount", "create_account":
+		pf = CreateAccount
+	case BondString:
+		pf = Bond
+	case NameString:
+		pf = Name
+	case HasBaseString, "hasbase", "has_base":
+		pf = HasBase
+	case SetBaseString, "setbase", "set_base":
+		pf = SetBase
+	case UnsetBaseString, "unsetbase", "unset_base":
+		pf = UnsetBase
+	case SetGlobalString, "setglobal", "set_global":
+		pf = SetGlobal
+	case HasRoleString, "hasrole", "has_role":
+		pf = HasRole
+	case AddRoleString, "addrole", "add_role":
+		pf = AddRole
+	case RemoveRoleString, "removerole", "rmrole", "rm_role":
+		pf = RemoveRole
+	default:
+		err = fmt.Errorf("unknown permission %s", perm)
+	}
+	return
+}
+
+func GlobalPermissionsAccount(state acm.Getter) acm.Account {
+	acc, err := state.GetAccount(GlobalPermissionsAddress)
+	if err != nil {
+		panic("Could not get global permission account, but this must exist")
+	}
+	return acc
+}
+
+// Get global permissions from the account at GlobalPermissionsAddress
+func GlobalAccountPermissions(state acm.Getter) types.AccountPermissions {
+	return GlobalPermissionsAccount(state).Permissions()
+}
diff --git a/permission/snatives.go b/permission/snatives.go
new file mode 100644
index 00000000..53fa0eea
--- /dev/null
+++ b/permission/snatives.go
@@ -0,0 +1,88 @@
+// Copyright 2017 Monax Industries Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package permission
+
+import (
+	acm "github.com/hyperledger/burrow/account"
+	"github.com/hyperledger/burrow/permission/types"
+)
+
+//---------------------------------------------------------------------------------------------------
+// PermissionsTx.PermArgs interface and argument encoding
+
+type PermArgs struct {
+	PermFlag   types.PermFlag
+	Address    acm.Address    `json:",omitempty"`
+	Permission types.PermFlag `json:",omitempty"`
+	Role       string         `json:",omitempty"`
+	Value      bool           `json:",omitempty"`
+}
+
+func HasBaseArgs(address acm.Address, permission types.PermFlag) *PermArgs {
+	return &PermArgs{
+		PermFlag:   HasBase,
+		Address:    address,
+		Permission: permission,
+	}
+}
+
+func SetBaseArgs(address acm.Address, permission types.PermFlag, value bool) *PermArgs {
+	return &PermArgs{
+		PermFlag:   SetBase,
+		Address:    address,
+		Permission: permission,
+		Value:      value,
+	}
+}
+
+func UnsetBaseArgs(address acm.Address, permission types.PermFlag) *PermArgs {
+	return &PermArgs{
+		PermFlag:   UnsetBase,
+		Address:    address,
+		Permission: permission,
+	}
+}
+
+func SetGlobalArgs(permission types.PermFlag, value bool) *PermArgs {
+	return &PermArgs{
+		PermFlag:   SetGlobal,
+		Permission: permission,
+		Value:      value,
+	}
+}
+
+func HasRoleArgs(address acm.Address, role string) *PermArgs {
+	return &PermArgs{
+		PermFlag: HasRole,
+		Address:  address,
+		Role:     role,
+	}
+}
+
+func AddRoleArgs(address acm.Address, role string) *PermArgs {
+	return &PermArgs{
+		PermFlag: AddRole,
+		Address:  address,
+		Role:     role,
+	}
+}
+
+func RemoveRoleArgs(address acm.Address, role string) *PermArgs {
+	return &PermArgs{
+		PermFlag: RemoveRole,
+		Address:  address,
+		Role:     role,
+	}
+}
diff --git a/permission/types/account_permissions.go b/permission/types/account_permissions.go
new file mode 100644
index 00000000..91bee5f8
--- /dev/null
+++ b/permission/types/account_permissions.go
@@ -0,0 +1,62 @@
+package types
+
+import "github.com/hyperledger/burrow/binary"
+
+type AccountPermissions struct {
+	Base  BasePermissions
+	Roles []string
+}
+
+// Returns true if the role is found
+func (ap AccountPermissions) HasRole(role string) bool {
+	role = string(binary.RightPadBytes([]byte(role), 32))
+	for _, r := range ap.Roles {
+		if r == role {
+			return true
+		}
+	}
+	return false
+}
+
+// Returns true if the role is added, and false if it already exists
+func (ap *AccountPermissions) AddRole(role string) bool {
+	role = string(binary.RightPadBytes([]byte(role), 32))
+	for _, r := range ap.Roles {
+		if r == role {
+			return false
+		}
+	}
+	ap.Roles = append(ap.Roles, role)
+	return true
+}
+
+// Returns true if the role is removed, and false if it is not found
+func (ap *AccountPermissions) RmRole(role string) bool {
+	role = string(binary.RightPadBytes([]byte(role), 32))
+	for i, r := range ap.Roles {
+		if r == role {
+			post := []string{}
+			if len(ap.Roles) > i+1 {
+				post = ap.Roles[i+1:]
+			}
+			ap.Roles = append(ap.Roles[:i], post...)
+			return true
+		}
+	}
+	return false
+}
+
+// Clone clones the account permissions
+func (ap *AccountPermissions) Clone() AccountPermissions {
+	// clone base permissions
+	basePermissionsClone := ap.Base
+	// clone roles []string
+	rolesClone := make([]string, len(ap.Roles))
+	// strings are immutable so copy suffices
+	copy(rolesClone, ap.Roles)
+
+	return AccountPermissions{
+		Base:  basePermissionsClone,
+		Roles: rolesClone,
+	}
+}
diff --git a/permission/types/base_permissions.go b/permission/types/base_permissions.go
new file mode 100644
index 00000000..bc9d7039
--- /dev/null
+++ b/permission/types/base_permissions.go
@@ -0,0 +1,86 @@
+package types
+
+import "fmt"
+
+// A particular permission
+type PermFlag uint64
+
+// permission number out of bounds
+type ErrInvalidPermission PermFlag
+
+func (e ErrInvalidPermission) Error() string {
+	return fmt.Sprintf("invalid permission %d", e)
+}
+
+// set=false. This error should be caught and the global
+// value fetched for the permission by the caller
+type ErrValueNotSet PermFlag
+
+func (e ErrValueNotSet) Error() string {
+	return fmt.Sprintf("the value for permission %d is not set", e)
+}
+
+// Base chain permissions struct
+type BasePermissions struct {
+	// bit array with "has"/"doesn't have" for each permission
+	Perms PermFlag
+
+	// bit array with "set"/"not set" for each permission (not-set should fall back to global)
+	SetBit PermFlag
+}
+
+// Get a permission value. ty should be a power of 2.
+// ErrValueNotSet is returned if the permission's set bit is off,
+// and should be caught by caller so the global permission can be fetched
+func (p BasePermissions) Get(ty PermFlag) (bool, error) {
+	if ty == 0 {
+		return false, ErrInvalidPermission(ty)
+	}
+	if p.SetBit&ty == 0 {
+		return false, ErrValueNotSet(ty)
+	}
+	return p.Perms&ty > 0, nil
+}
+
+// Set a permission bit. Will set the permission's set bit to true.
+func (p *BasePermissions) Set(ty PermFlag, value bool) error {
+	if ty == 0 {
+		return ErrInvalidPermission(ty)
+	}
+	p.SetBit |= ty
+	if value {
+		p.Perms |= ty
+	} else {
+		p.Perms &= ^ty
+	}
+	return nil
+}
+
+// Set the permission's set bit to false
+func (p *BasePermissions) Unset(ty PermFlag) error {
+	if ty == 0 {
+		return ErrInvalidPermission(ty)
+	}
+	p.SetBit &= ^ty
+	return nil
+}
+
+// Check if the permission is set
+func (p BasePermissions) IsSet(ty PermFlag) bool {
+	if ty == 0 {
+		return false
+	}
+	return p.SetBit&ty > 0
+}
+
+// Returns the Perms PermFlag masked with SetBit bit field to give the resultant
+// permissions enabled by this BasePermissions
+func (p BasePermissions) ResultantPerms() PermFlag {
+	return p.Perms & p.SetBit
+}
+
+func (p BasePermissions) String() string {
+	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
+}
+
+//---------------------------------------------------------------------------------------------
diff --git a/permission/types/permissions.go b/permission/types/permissions.go
deleted file mode 100644
index c414a85d..00000000
--- a/permission/types/permissions.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package types
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/hyperledger/burrow/word256"
-)
-
-//------------------------------------------------------------------------------------------------
-
-var (
-	GlobalPermissionsAddress    = word256.Zero256[:20]
-	GlobalPermissionsAddress256 = word256.Zero256
-)
-
-// A particular permission
-type PermFlag uint64
-
-// Base permission references are like unix (the index is already bit shifted)
-const (
-	// chain permissions
-	Root           PermFlag = 1 << iota // 1
-	Send                                // 2
-	Call                                // 4
-	CreateContract                      // 8
-	CreateAccount                       // 16
-	Bond                                // 32
-	Name                                // 64
-
-	// moderator permissions
-	HasBase
-	SetBase
-	UnsetBase
-	SetGlobal
-	HasRole
-	AddRole
-	RmRole
-
-	NumPermissions uint = 14 // NOTE Adjust this too. We can support upto 64
-
-	TopPermFlag      PermFlag = 1 << (NumPermissions - 1)
-	AllPermFlags     PermFlag = TopPermFlag | (TopPermFlag - 1)
-	DefaultPermFlags PermFlag = Send | Call | CreateContract | CreateAccount | Bond | Name | HasBase | HasRole
-)
-
-var (
-	ZeroBasePermissions    = BasePermissions{0, 0}
-	ZeroAccountPermissions = AccountPermissions{
-		Base: ZeroBasePermissions,
-	}
-	DefaultAccountPermissions = AccountPermissions{
-		Base: BasePermissions{
-			Perms:  DefaultPermFlags,
-			SetBit: AllPermFlags,
-		},
-		Roles: []string{},
-	}
-)
-
-//---------------------------------------------------------------------------------------------
-
-// Base chain permissions struct
-type BasePermissions struct {
-	// bit array with "has"/"doesn't have" for each permission
-	Perms PermFlag `json:"perms"`
-
-	// bit array with "set"/"not set" for each permission (not-set should fall back to global)
-	SetBit PermFlag `json:"set"`
-}
-
-// Get a permission value. ty should be a power of 2.
-// ErrValueNotSet is returned if the permission's set bit is off,
-// and should be caught by caller so the global permission can be fetched
-func (p *BasePermissions) Get(ty PermFlag) (bool, error) {
-	if ty == 0 {
-		return false, ErrInvalidPermission(ty)
-	}
-	if p.SetBit&ty == 0 {
-		return false, ErrValueNotSet(ty)
-	}
-	return p.Perms&ty > 0, nil
-}
-
-// Set a permission bit. Will set the permission's set bit to true.
-func (p *BasePermissions) Set(ty PermFlag, value bool) error {
-	if ty == 0 {
-		return ErrInvalidPermission(ty)
-	}
-	p.SetBit |= ty
-	if value {
-		p.Perms |= ty
-	} else {
-		p.Perms &= ^ty
-	}
-	return nil
-}
-
-// Set the permission's set bit to false
-func (p *BasePermissions) Unset(ty PermFlag) error {
-	if ty == 0 {
-		return ErrInvalidPermission(ty)
-	}
-	p.SetBit &= ^ty
-	return nil
-}
-
-// Check if the permission is set
-func (p *BasePermissions) IsSet(ty PermFlag) bool {
-	if ty == 0 {
-		return false
-	}
-	return p.SetBit&ty > 0
-}
-
-// Returns the Perms PermFlag masked with SetBit bit field to give the resultant
-// permissions enabled by this BasePermissions
-func (p *BasePermissions) ResultantPerms() PermFlag {
-	return p.Perms & p.SetBit
-}
-
-func (p BasePermissions) String() string {
-	return fmt.Sprintf("Base: %b; Set: %b", p.Perms, p.SetBit)
-}
-
-//---------------------------------------------------------------------------------------------
-
-type AccountPermissions struct {
-	Base  BasePermissions `json:"base"`
-	Roles []string        `json:"roles"`
-}
-
-// Returns true if the role is found
-func (aP *AccountPermissions) HasRole(role string) bool {
-	role = string(word256.RightPadBytes([]byte(role), 32))
-	for _, r := range aP.Roles {
-		if r == role {
-			return true
-		}
-	}
-	return false
-}
-
-// Returns true if the role is added, and false if it already exists
-func (aP *AccountPermissions) AddRole(role string) bool {
-	role = string(word256.RightPadBytes([]byte(role), 32))
-	for _, r := range aP.Roles {
-		if r == role {
-			return false
-		}
-	}
-	aP.Roles = append(aP.Roles, role)
-	return true
-}
-
-// Returns true if the role is removed, and false if it is not found
-func (aP *AccountPermissions) RmRole(role string) bool {
-	role = string(word256.RightPadBytes([]byte(role), 32))
-	for i, r := range aP.Roles {
-		if r == role {
-			post := []string{}
-			if len(aP.Roles) > i+1 {
-				post = aP.Roles[i+1:]
-			}
-			aP.Roles = append(aP.Roles[:i], post...)
-			return true
-		}
-	}
-	return false
-}
-
-// Clone clones the account permissions
-func (accountPermissions *AccountPermissions) Clone() AccountPermissions {
-	// clone base permissions
-	basePermissionsClone := accountPermissions.Base
-	// clone roles []string
-	rolesClone := make([]string, len(accountPermissions.Roles))
-	// strings are immutable so copy suffices
-	copy(rolesClone, accountPermissions.Roles)
-
-	return AccountPermissions{
-		Base:  basePermissionsClone,
-		Roles: rolesClone,
-	}
-}
-
-//--------------------------------------------------------------------------------
-// string utilities
-
-// PermFlagToString assumes the permFlag is valid, else returns "#-UNKNOWN-#"
-func PermFlagToString(pf PermFlag) (perm string) {
-	switch pf {
-	case Root:
-		perm = "root"
-	case Send:
-		perm = "send"
-	case Call:
-		perm = "call"
-	case CreateContract:
-		perm = "create_contract"
-	case CreateAccount:
-		perm = "create_account"
-	case Bond:
-		perm = "bond"
-	case Name:
-		perm = "name"
-	case HasBase:
-		perm = "hasBase"
-	case SetBase:
-		perm = "setBase"
-	case UnsetBase:
-		perm = "unsetBase"
-	case SetGlobal:
-		perm = "setGlobal"
-	case HasRole:
-		perm = "hasRole"
-	case AddRole:
-		perm = "addRole"
-	case RmRole:
-		perm = "removeRole"
-	default:
-		perm = "#-UNKNOWN-#"
-	}
-	return
-}
-
-// PermStringToFlag maps camel- and snake case strings to the
-// the corresponding permission flag.
-func PermStringToFlag(perm string) (pf PermFlag, err error) {
-	switch strings.ToLower(perm) {
-	case "root":
-		pf = Root
-	case "send":
-		pf = Send
-	case "call":
-		pf = Call
-	case "createcontract", "create_contract":
-		pf = CreateContract
-	case "createaccount", "create_account":
-		pf = CreateAccount
-	case "bond":
-		pf = Bond
-	case "name":
-		pf = Name
-	case "hasbase", "has_base":
-		pf = HasBase
-	case "setbase", "set_base":
-		pf = SetBase
-	case "unsetbase", "unset_base":
-		pf = UnsetBase
-	case "setglobal", "set_global":
-		pf = SetGlobal
-	case "hasrole", "has_role":
-		pf = HasRole
-	case "addrole", "add_role":
-		pf = AddRole
-	case "removerole", "rmrole", "rm_role":
-		pf = RmRole
-	default:
-		err = fmt.Errorf("Unknown permission %s", perm)
-	}
-	return
-}
diff --git a/permission/types/snatives.go b/permission/types/snatives.go
deleted file mode 100644
index f7fe543a..00000000
--- a/permission/types/snatives.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2017 Monax Industries Limited
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package types
-
-import (
-	"github.com/tendermint/go-wire"
-)
-
-//---------------------------------------------------------------------------------------------------
-// PermissionsTx.PermArgs interface and argument encoding
-
-// Arguments are a registered interface in the PermissionsTx,
-// so binary handles the arguments and each permission function gets a type-byte
-// PermFlag() maps the type-byte to the permission
-// The account sending the PermissionsTx must have this PermFlag set
-type PermArgs interface {
-	PermFlag() PermFlag
-}
-
-const (
-	PermArgsTypeHasBase   = byte(0x01)
-	PermArgsTypeSetBase   = byte(0x02)
-	PermArgsTypeUnsetBase = byte(0x03)
-	PermArgsTypeSetGlobal = byte(0x04)
-	PermArgsTypeHasRole   = byte(0x05)
-	PermArgsTypeAddRole   = byte(0x06)
-	PermArgsTypeRmRole    = byte(0x07)
-)
-
-// TODO: [ben] this registration needs to be lifted up
-// and centralised in core; here it pulls in go-wire dependency
-// while it suffices to have the type bytes defined;
-// ---
-// for wire.readReflect
-var _ = wire.RegisterInterface(
-	struct{ PermArgs }{},
-	wire.ConcreteType{&HasBaseArgs{}, PermArgsTypeHasBase},
-	wire.ConcreteType{&SetBaseArgs{}, PermArgsTypeSetBase},
-	wire.ConcreteType{&UnsetBaseArgs{}, PermArgsTypeUnsetBase},
-	wire.ConcreteType{&SetGlobalArgs{}, PermArgsTypeSetGlobal},
-	wire.ConcreteType{&HasRoleArgs{}, PermArgsTypeHasRole},
-	wire.ConcreteType{&AddRoleArgs{}, PermArgsTypeAddRole},
-	wire.ConcreteType{&RmRoleArgs{}, PermArgsTypeRmRole},
-)
-
-type HasBaseArgs struct {
-	Address    []byte   `json:"address"`
-	Permission PermFlag `json:"permission"`
-}
-
-func (*HasBaseArgs) PermFlag() PermFlag {
-	return HasBase
-}
-
-type SetBaseArgs struct {
-	Address    []byte   `json:"address"`
-	Permission PermFlag `json:"permission"`
-	Value      bool     `json:"value"`
-}
-
-func (*SetBaseArgs) PermFlag() PermFlag {
-	return SetBase
-}
-
-type UnsetBaseArgs struct {
-	Address    []byte   `json:"address"`
-	Permission PermFlag `json:"permission"`
-}
-
-func (*UnsetBaseArgs) PermFlag() PermFlag {
-	return UnsetBase
-}
-
-type SetGlobalArgs struct {
-	Permission PermFlag `json:"permission"`
-	Value      bool     `json:"value"`
-}
-
-func (*SetGlobalArgs) PermFlag() PermFlag {
-	return SetGlobal
-}
-
-type HasRoleArgs struct {
-	Address []byte `json:"address"`
-	Role    string `json:"role"`
-}
-
-func (*HasRoleArgs) PermFlag() PermFlag {
-	return HasRole
-}
-
-type AddRoleArgs struct {
-	Address []byte `json:"address"`
-	Role    string `json:"role"`
-}
-
-func (*AddRoleArgs) PermFlag() PermFlag {
-	return AddRole
-}
-
-type RmRoleArgs struct {
-	Address []byte `json:"address"`
-	Role    string `json:"role"`
-}
-
-func (*RmRoleArgs) PermFlag() PermFlag {
-	return RmRole
-}
diff --git a/permission/types/util.go b/permission/util.go
similarity index 75%
rename from permission/types/util.go
rename to permission/util.go
index c7ceae90..7942eb92 100644
--- a/permission/types/util.go
+++ b/permission/util.go
@@ -12,16 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package types
+package permission
+
+import "github.com/hyperledger/burrow/permission/types"
 
 // ConvertMapStringIntToPermissions converts a map of string-bool pairs and a slice of
 // strings for the roles to an AccountPermissions type. If the value in the
 // permissions map is true for a particular permission string then the permission
 // will be set in the AccountsPermissions. For all unmentioned permissions the
 // ZeroBasePermissions is defaulted to.
-func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bool, roles []string) (*AccountPermissions, error) {
+func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bool,
+	roles []string) (*types.AccountPermissions, error) {
 	var err error
-	accountPermissions := &AccountPermissions{}
+	accountPermissions := &types.AccountPermissions{}
 	accountPermissions.Base, err = convertPermissionsMapStringIntToBasePermissions(permissions)
 	if err != nil {
 		return nil, err
@@ -32,7 +35,7 @@ func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]bo
 
 // convertPermissionsMapStringIntToBasePermissions converts a map of string-bool
 // pairs to BasePermissions.
-func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool) (BasePermissions, error) {
+func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool) (types.BasePermissions, error) {
 	// initialise basePermissions as ZeroBasePermissions
 	basePermissions := ZeroBasePermissions
 
@@ -47,3 +50,18 @@ func convertPermissionsMapStringIntToBasePermissions(permissions map[string]bool
 
 	return basePermissions, nil
 }
+
+func BasePermissionsFromStringList(permissions []string) (types.BasePermissions, error) {
+	var permFlag types.PermFlag
+	for _, perm := range permissions {
+		flag, err := PermStringToFlag(perm)
+		if err != nil {
+			return ZeroBasePermissions, err
+		}
+		permFlag |= flag
+	}
+	return types.BasePermissions{
+		Perms:  permFlag,
+		SetBit: permFlag,
+	}, nil
+}
diff --git a/permission/util_test.go b/permission/util_test.go
new file mode 100644
index 00000000..54dad954
--- /dev/null
+++ b/permission/util_test.go
@@ -0,0 +1,16 @@
+package permission
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestBasePermissionsFromStringList(t *testing.T) {
+	basePerms, err := BasePermissionsFromStringList([]string{HasRoleString, CreateContractString, SendString})
+	require.NoError(t, err)
+	permFlag := HasRole | CreateContract | Send
+	assert.Equal(t, permFlag, basePerms.Perms)
+	assert.Equal(t, permFlag, basePerms.SetBit)
+}
-- 
GitLab