quorum/core/quorum/api.go

659 lines
19 KiB
Go
Raw Normal View History

package quorum
import (
2018-11-14 01:58:57 -08:00
"crypto/ecdsa"
2018-10-31 05:46:54 -07:00
"fmt"
2018-10-31 22:45:16 -07:00
"math/big"
2018-11-06 21:58:51 -08:00
"strconv"
"strings"
2018-10-31 22:45:16 -07:00
2018-10-31 05:46:54 -07:00
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
pbind "github.com/ethereum/go-ethereum/controls/bind"
"github.com/ethereum/go-ethereum/core"
2018-10-31 05:46:54 -07:00
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/ethapi"
2018-10-31 05:46:54 -07:00
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover"
2018-10-31 05:46:54 -07:00
"github.com/ethereum/go-ethereum/params"
)
2018-10-31 22:45:16 -07:00
//default gas limit to use if not passed in sendTxArgs
2018-10-31 05:46:54 -07:00
var defaultGasLimit = uint64(470000000)
2018-10-31 22:45:16 -07:00
//default gas price to use if not passed in sendTxArgs
var defaultGasPrice = big.NewInt(0)
2018-10-31 22:45:16 -07:00
// PermAction represents actions in permission contract
2018-10-31 05:46:54 -07:00
type PermAction int
const (
ProposeNode PermAction = iota
ApproveNode
2018-11-05 07:44:23 -08:00
ProposeNodeDeactivation
ApproveNodeDeactivation
ProposeNodeActivation
ApproveNodeActivation
ProposeNodeBlacklisting
ApproveNodeBlacklisting
2018-10-31 05:46:54 -07:00
AddVoter
RemoveVoter
2018-11-06 21:58:51 -08:00
SetAccountAccess
2018-10-31 05:46:54 -07:00
)
2018-10-31 22:45:16 -07:00
// OrgKeyAction represents an action in cluster contract
2018-10-31 05:46:54 -07:00
type OrgKeyAction int
const (
AddOrgKey OrgKeyAction = iota
RemoveOrgKey
)
2018-10-31 22:45:16 -07:00
// PermissionAPI provides an API to access Quorum's node permission and org key management related services
type PermissionAPI struct {
2018-10-31 00:15:34 -07:00
txPool *core.TxPool
ethClnt *ethclient.Client
2018-10-31 05:46:54 -07:00
acntMgr *accounts.Manager
txOpt *bind.TransactOpts
2018-10-31 00:15:34 -07:00
permContr *pbind.Permissions
2018-10-30 00:59:08 -07:00
clustContr *pbind.Cluster
2018-11-14 01:58:57 -08:00
key *ecdsa.PrivateKey
enabled bool
}
2018-10-31 22:45:16 -07:00
// txArgs holds arguments required for execute functions
2018-10-31 05:46:54 -07:00
type txArgs struct {
2018-11-12 00:16:56 -08:00
voter common.Address
nodeId string
orgId string
keyId string
txa ethapi.SendTxArgs
acctId common.Address
2018-11-06 21:58:51 -08:00
accessType string
2018-10-31 05:46:54 -07:00
}
2018-11-12 00:16:56 -08:00
type nodeStatus struct {
EnodeId string
Status string
2018-11-12 00:16:56 -08:00
}
2018-11-15 20:21:50 -08:00
type accountInfo struct {
Address string
Access string
}
2018-11-12 00:16:56 -08:00
type ExecStatus struct {
Status bool
Msg string
}
2018-11-15 20:21:50 -08:00
2018-11-15 19:07:10 -08:00
var (
2018-11-15 20:21:50 -08:00
ErrNoVoterAccount = ExecStatus{false, "No voter account registered. Add voter first"}
ErrInvalidNode = ExecStatus{false, "Invalid node id"}
ErrAccountNotAVoter = ExecStatus{false, "Account is not a voter. Action cannot be approved"}
ErrInvalidAccount = ExecStatus{false, "Invalid account id"}
ErrInvalidAccountAccess = ExecStatus{false, "Invalid account access type"}
2018-11-15 20:21:50 -08:00
ErrFailedExecution = ExecStatus{false, "Failed to execute permission action"}
ErrNodeDetailsMismatch = ExecStatus{false, "Node details mismatch"}
ErrPermissionDisabled = ExecStatus{false, "Permissions control not enabled"}
ErrAccountAccess = ExecStatus{false, "Account does not have sufficient access for operation"}
ErrVoterAccountAccess = ExecStatus{false, "Voter account does not have sufficient access"}
2018-11-15 20:21:50 -08:00
ExecSuccess = ExecStatus{true, "Action completed successfully"}
2018-11-15 19:07:10 -08:00
)
2018-11-15 20:21:50 -08:00
var (
nodeApproveStatus = map[uint8]string{
0: "Unknown",
1: "PendingApproval",
2: "Approved",
3: "PendingDeactivation",
4: "Deactivated",
5: "PendingActivation",
6: "PendingBlacklisting",
7: "Blacklisted",
}
2018-11-12 00:16:56 -08:00
2018-11-15 20:21:50 -08:00
accountPermMap = map[uint8]string{
0: "FullAccess",
1: "ReadOnly",
2: "Transact",
3: "ContractDeploy",
}
)
2018-11-14 20:32:11 -08:00
2018-10-31 22:45:16 -07:00
// NewPermissionAPI creates a new PermissionAPI to access quorum services
2018-10-31 00:15:34 -07:00
func NewPermissionAPI(tp *core.TxPool, am *accounts.Manager) *PermissionAPI {
return &PermissionAPI{tp, nil, am, nil, nil, nil, nil, false}
2018-11-14 01:58:57 -08:00
}
// helper function decodes the node status to string
func decodeNodeStatus(nodeStatus uint8) string {
2018-11-14 20:32:11 -08:00
if status, ok := nodeApproveStatus[nodeStatus]; ok {
return status
2018-11-14 01:58:57 -08:00
}
2018-11-14 20:32:11 -08:00
return "Unknown"
}
2018-10-31 22:45:16 -07:00
//Init initializes PermissionAPI with eth client, permission contract and org key management control
2018-11-14 02:03:50 -08:00
func (p *PermissionAPI) Init(ethClnt *ethclient.Client, key *ecdsa.PrivateKey) error {
p.ethClnt = ethClnt
2018-10-30 00:59:08 -07:00
permContr, err := pbind.NewPermissions(params.QuorumPermissionsContract, p.ethClnt)
if err != nil {
return err
}
p.permContr = permContr
2018-10-30 00:59:08 -07:00
clustContr, err := pbind.NewCluster(params.QuorumPrivateKeyManagementContract, p.ethClnt)
if err != nil {
return err
}
p.clustContr = clustContr
2018-11-14 01:58:57 -08:00
p.key = key
p.enabled = true
return nil
}
2018-11-14 02:24:28 -08:00
// Returns the list of Nodes and status of each
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) PermissionNodeList() []nodeStatus {
if !s.enabled {
nodeStatArr := make([]nodeStatus, 1)
nodeStatArr[0].EnodeId = "Permisssions control not enabled for network"
return nodeStatArr
}
2018-11-15 21:40:36 -08:00
ps := s.newPermSessionWithNodeKeySigner()
2018-11-14 01:58:57 -08:00
// get the total number of nodes on the contract
nodeCnt, err := ps.GetNumberOfNodes()
2018-11-15 19:07:10 -08:00
if err != nil {
return nil
}
2018-11-14 20:32:11 -08:00
nodeCntI := nodeCnt.Int64()
nodeStatArr := make([]nodeStatus, nodeCntI)
2018-11-14 01:58:57 -08:00
// loop for each index and get the node details from the contract
2018-11-15 19:07:10 -08:00
i := int64(0)
for i < nodeCntI {
nodeDtls, err := ps.GetNodeDetailsFromIndex(big.NewInt(i))
2018-11-15 20:21:50 -08:00
if err != nil {
log.Error("error getting node details", "err", err)
} else {
nodeStatArr[i].EnodeId = "enode://" + nodeDtls.EnodeId + "@" + nodeDtls.IpAddrPort
nodeStatArr[i].EnodeId += "?discport=" + nodeDtls.DiscPort
2018-11-15 20:21:50 -08:00
if len(nodeDtls.RaftPort) > 0 {
nodeStatArr[i].EnodeId += "&raftport=" + nodeDtls.RaftPort
2018-11-15 20:21:50 -08:00
}
nodeStatArr[i].Status = decodeNodeStatus(nodeDtls.NodeStatus)
2018-11-14 01:58:57 -08:00
}
2018-11-15 19:07:10 -08:00
i++
2018-11-12 00:16:56 -08:00
}
return nodeStatArr
}
2018-11-15 20:21:50 -08:00
func (s *PermissionAPI) PermissionAccountList() []accountInfo {
if !s.enabled {
acctInfoArr := make([]accountInfo, 1)
acctInfoArr[0].Address = "Account access control not enable for the network"
return acctInfoArr
}
2018-11-15 21:40:36 -08:00
ps := s.newPermSessionWithNodeKeySigner()
2018-11-15 20:21:50 -08:00
// get the total number of accounts with permissions
acctCnt, err := ps.GetNumberOfAccounts()
if err != nil {
return nil
}
acctCntI := acctCnt.Int64()
log.Debug("total permission accounts", "count", acctCntI)
acctInfoArr := make([]accountInfo, acctCntI)
// loop for each index and get the node details from the contract
i := int64(0)
for i < acctCntI {
a, err := ps.GetAccountDetails(big.NewInt(i))
if err != nil {
log.Error("error getting account info", "err", err)
} else {
acctInfoArr[i].Address = a.Acct.String()
acctInfoArr[i].Access = decodeAccountPermission(a.AcctAccess)
}
i++
}
return acctInfoArr
}
2018-11-15 21:40:36 -08:00
func (s *PermissionAPI) VoterList() []string {
if !s.enabled {
voterArr := make([]string, 1)
voterArr[0] = "Permissions control not enabled for the network"
return voterArr
}
2018-11-15 21:40:36 -08:00
ps := s.newPermSessionWithNodeKeySigner()
// get the total number of accounts with permissions
voterCnt, err := ps.GetNumberOfVoters()
if err != nil {
return nil
}
voterCntI := voterCnt.Int64()
log.Debug("total voters", "count", voterCntI)
voterArr := make([]string, voterCntI)
// loop for each index and get the node details from the contract
i := int64(0)
for i < voterCntI {
a, err := ps.GetVoter(big.NewInt(i))
if err != nil {
log.Error("error getting voter info", "err", err)
} else {
voterArr[i] = a.String()
}
i++
}
return voterArr
}
func (s *PermissionAPI) newPermSessionWithNodeKeySigner() *pbind.PermissionsSession {
auth := bind.NewKeyedTransactor(s.key)
ps := &pbind.PermissionsSession{
Contract: s.permContr,
CallOpts: bind.CallOpts{
Pending: true,
},
TransactOpts: bind.TransactOpts{
From: auth.From,
Signer: auth.Signer,
GasLimit: 4700000,
GasPrice: big.NewInt(0),
},
}
return ps
}
2018-11-15 20:21:50 -08:00
func decodeAccountPermission(access uint8) string {
if status, ok := accountPermMap[access]; ok {
return status
}
return "Unknown"
}
2018-10-31 22:45:16 -07:00
// AddVoter adds an account to the list of accounts that can approve nodes proposed or deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) AddVoter(vaddr common.Address, txa ethapi.SendTxArgs) ExecStatus {
return s.executePermAction(AddVoter, txArgs{voter: vaddr, txa: txa})
}
2018-10-31 22:45:16 -07:00
// RemoveVoter removes an account from the list of accounts that can approve nodes proposed or deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) RemoveVoter(vaddr common.Address, txa ethapi.SendTxArgs) ExecStatus {
return s.executePermAction(RemoveVoter, txArgs{voter: vaddr, txa: txa})
2018-10-31 05:46:54 -07:00
}
2018-10-31 00:15:34 -07:00
2018-10-31 22:45:16 -07:00
// ProposeNode proposes a node to join the network
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ProposeNode(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
return s.executePermAction(ProposeNode, txArgs{nodeId: nodeId, txa: txa})
2018-10-31 05:46:54 -07:00
}
2018-10-31 22:45:16 -07:00
// ApproveNode approves a proposed node to join the network
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ApproveNode(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
return s.executePermAction(ApproveNode, txArgs{nodeId: nodeId, txa: txa})
2018-10-31 05:46:54 -07:00
}
2018-10-31 22:45:16 -07:00
// DeactivateNode requests a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ProposeNodeDeactivation(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ProposeNodeDeactivation, txArgs{nodeId: nodeId, txa: txa})
}
2018-10-31 22:45:16 -07:00
// ApproveDeactivateNode approves a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ApproveNodeDeactivation(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ApproveNodeDeactivation, txArgs{nodeId: nodeId, txa: txa})
2018-10-31 05:46:54 -07:00
}
2018-11-05 07:44:23 -08:00
// DeactivateNode requests a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ProposeNodeActivation(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ProposeNodeActivation, txArgs{nodeId: nodeId, txa: txa})
}
// ApproveDeactivateNode approves a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ApproveNodeActivation(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ApproveNodeActivation, txArgs{nodeId: nodeId, txa: txa})
}
// DeactivateNode requests a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ProposeNodeBlacklisting(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ProposeNodeBlacklisting, txArgs{nodeId: nodeId, txa: txa})
}
// ApproveDeactivateNode approves a node to get deactivated
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) ApproveNodeBlacklisting(nodeId string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-05 07:44:23 -08:00
return s.executePermAction(ApproveNodeBlacklisting, txArgs{nodeId: nodeId, txa: txa})
}
2018-11-12 00:16:56 -08:00
2018-10-31 22:45:16 -07:00
// RemoveOrgKey removes an org key combination from the org key map
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) RemoveOrgKey(orgId string, pvtKey string, txa ethapi.SendTxArgs) ExecStatus {
return s.executeOrgKeyAction(RemoveOrgKey, txArgs{txa: txa, orgId: orgId, keyId: pvtKey})
}
2018-10-31 22:45:16 -07:00
// AddOrgKey adds an org key combination to the org key map
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) AddOrgKey(orgId string, pvtKey string, txa ethapi.SendTxArgs) ExecStatus {
return s.executeOrgKeyAction(AddOrgKey, txArgs{txa: txa, orgId: orgId, keyId: pvtKey})
}
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) SetAccountAccess(acct common.Address, access string, txa ethapi.SendTxArgs) ExecStatus {
2018-11-06 21:58:51 -08:00
return s.executePermAction(SetAccountAccess, txArgs{acctId: acct, accessType: access, txa: txa})
}
2018-10-31 22:45:16 -07:00
// executePermAction helps to execute an action in permission contract
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) executePermAction(action PermAction, args txArgs) ExecStatus {
if !s.enabled {
return ErrPermissionDisabled
}
2018-11-07 19:35:29 -08:00
var err error
var w accounts.Wallet
2018-11-12 00:16:56 -08:00
2018-11-07 19:35:29 -08:00
w, err = s.validateAccount(args.txa.From)
if err != nil {
2018-11-15 19:07:10 -08:00
return ErrInvalidAccount
}
ps := s.newPermSession(w, args.txa)
2018-10-31 05:46:54 -07:00
var tx *types.Transaction
2018-11-07 19:35:29 -08:00
var node *discover.Node
2018-10-31 05:46:54 -07:00
switch action {
case AddVoter:
if !checkVoterAccountAccess(args.voter){
return ErrVoterAccountAccess
}
2018-10-31 05:46:54 -07:00
tx, err = ps.AddVoter(args.voter)
2018-11-13 00:15:28 -08:00
2018-10-31 05:46:54 -07:00
case RemoveVoter:
tx, err = ps.RemoveVoter(args.voter)
2018-11-13 00:15:28 -08:00
2018-10-31 05:46:54 -07:00
case ProposeNode:
2018-11-14 02:24:28 -08:00
if !checkVoterExists(ps) {
2018-11-15 19:07:10 -08:00
return ErrNoVoterAccount
2018-11-13 00:15:28 -08:00
}
node, err = discover.ParseNode(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-11-05 07:44:23 -08:00
}
2018-11-13 00:15:28 -08:00
enodeID := node.ID.String()
ipAddr := node.IP.String()
port := fmt.Sprintf("%v", node.TCP)
discPort := fmt.Sprintf("%v", node.UDP)
raftPort := fmt.Sprintf("%v", node.RaftPort)
ipAddrPort := ipAddr + ":" + port
tx, err = ps.ProposeNode(enodeID, ipAddrPort, discPort, raftPort)
2018-11-05 07:44:23 -08:00
case ApproveNode:
2018-11-14 02:24:28 -08:00
if !checkIsVoter(ps, args.txa.From) {
2018-11-15 19:07:10 -08:00
return ErrAccountNotAVoter
2018-11-13 00:15:28 -08:00
}
2018-11-07 19:35:29 -08:00
node, err = discover.ParseNode(args.nodeId)
2018-10-31 05:46:54 -07:00
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-10-31 05:46:54 -07:00
}
enodeID := node.ID.String()
if !checkNodeDetails(ps, enodeID, node) {
return ErrNodeDetailsMismatch
}
2018-11-05 07:44:23 -08:00
tx, err = ps.ApproveNode(enodeID)
2018-11-13 00:15:28 -08:00
2018-11-05 07:44:23 -08:00
case ProposeNodeDeactivation:
2018-11-14 02:24:28 -08:00
if !checkVoterExists(ps) {
2018-11-15 19:07:10 -08:00
return ErrNoVoterAccount
2018-11-05 07:44:23 -08:00
}
2018-11-13 00:15:28 -08:00
node, err = discover.ParseNode(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-11-13 00:15:28 -08:00
}
enodeID := node.ID.String()
tx, err = ps.ProposeDeactivation(enodeID)
2018-11-05 07:44:23 -08:00
case ApproveNodeDeactivation:
2018-11-14 02:24:28 -08:00
if !checkIsVoter(ps, args.txa.From) {
2018-11-15 19:07:10 -08:00
return ErrAccountNotAVoter
2018-11-13 00:15:28 -08:00
}
2018-11-07 19:35:29 -08:00
node, err = discover.ParseNode(args.nodeId)
2018-10-31 05:46:54 -07:00
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-10-31 05:46:54 -07:00
}
enodeID := node.ID.String()
if !checkNodeDetails(ps, enodeID, node) {
return ErrNodeDetailsMismatch
}
2018-11-05 07:44:23 -08:00
tx, err = ps.DeactivateNode(enodeID)
2018-11-13 00:15:28 -08:00
2018-11-05 07:44:23 -08:00
case ProposeNodeActivation:
2018-11-14 02:24:28 -08:00
if !checkVoterExists(ps) {
2018-11-15 19:07:10 -08:00
return ErrNoVoterAccount
2018-11-13 00:15:28 -08:00
}
node, err = discover.ParseNode(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-11-05 07:44:23 -08:00
}
2018-11-13 00:15:28 -08:00
enodeID := node.ID.String()
tx, err = ps.ProposeNodeActivation(enodeID)
2018-11-05 07:44:23 -08:00
case ApproveNodeActivation:
2018-11-14 02:24:28 -08:00
if !checkIsVoter(ps, args.txa.From) {
2018-11-15 19:07:10 -08:00
return ErrAccountNotAVoter
2018-11-13 00:15:28 -08:00
}
2018-11-07 19:35:29 -08:00
node, err = discover.ParseNode(args.nodeId)
2018-10-31 05:46:54 -07:00
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-10-31 05:46:54 -07:00
}
enodeID := node.ID.String()
if !checkNodeDetails(ps, enodeID, node) {
return ErrNodeDetailsMismatch
}
2018-11-05 07:44:23 -08:00
tx, err = ps.ActivateNode(enodeID)
2018-11-13 00:15:28 -08:00
2018-11-05 07:44:23 -08:00
case ProposeNodeBlacklisting:
2018-11-14 02:24:28 -08:00
if !checkVoterExists(ps) {
2018-11-15 19:07:10 -08:00
return ErrNoVoterAccount
2018-11-13 00:15:28 -08:00
}
node, err = discover.ParseNode(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-11-05 07:44:23 -08:00
}
2018-11-13 00:15:28 -08:00
enodeID := node.ID.String()
ipAddr := node.IP.String()
port := fmt.Sprintf("%v", node.TCP)
discPort := fmt.Sprintf("%v", node.UDP)
raftPort := fmt.Sprintf("%v", node.RaftPort)
ipAddrPort := ipAddr + ":" + port
tx, err = ps.ProposeNodeBlacklisting(enodeID, ipAddrPort, discPort, raftPort)
2018-11-05 07:44:23 -08:00
case ApproveNodeBlacklisting:
2018-11-14 02:24:28 -08:00
if !checkIsVoter(ps, args.txa.From) {
2018-11-15 19:07:10 -08:00
return ErrAccountNotAVoter
2018-11-13 00:15:28 -08:00
}
2018-11-07 19:35:29 -08:00
node, err = discover.ParseNode(args.nodeId)
2018-10-31 05:46:54 -07:00
if err != nil {
log.Error("invalid node id: %v", err)
2018-11-15 19:07:10 -08:00
return ErrInvalidNode
2018-10-31 05:46:54 -07:00
}
enodeID := node.ID.String()
if !checkNodeDetails(ps, enodeID, node) {
return ErrNodeDetailsMismatch
}
2018-11-05 07:44:23 -08:00
tx, err = ps.BlacklistNode(enodeID)
2018-11-13 00:15:28 -08:00
2018-11-06 21:58:51 -08:00
case SetAccountAccess:
2018-11-07 19:35:29 -08:00
var access uint64
access, err = strconv.ParseUint(args.accessType, 10, 8)
2018-11-06 21:58:51 -08:00
if err != nil {
2018-11-15 19:07:10 -08:00
return ErrInvalidAccountAccess
2018-11-06 21:58:51 -08:00
}
if !checkAccountAccess(args.txa.From, uint8(access)) {
return ErrAccountAccess
}
2018-11-06 21:58:51 -08:00
tx, err = ps.UpdateAccountAccess(args.acctId, uint8(access))
2018-11-07 19:35:29 -08:00
}
2018-11-13 00:15:28 -08:00
2018-11-07 19:35:29 -08:00
if err != nil {
log.Error("Failed to execute permission action", "action", action, "err", err)
2018-11-15 19:07:10 -08:00
return ErrFailedExecution
}
2018-10-31 05:46:54 -07:00
log.Debug("executed permission action", "action", action, "tx", tx)
2018-11-15 19:07:10 -08:00
return ExecSuccess
}
2018-10-31 22:45:16 -07:00
// executeOrgKeyAction helps to execute an action in cluster contract
2018-11-12 00:16:56 -08:00
func (s *PermissionAPI) executeOrgKeyAction(action OrgKeyAction, args txArgs) ExecStatus {
if !s.enabled {
return ErrPermissionDisabled
}
w, err := s.validateAccount(args.txa.From)
if err != nil {
2018-11-12 00:16:56 -08:00
return ExecStatus{false, err.Error()}
}
ps := s.newClusterSession(w, args.txa)
2018-10-31 05:46:54 -07:00
var tx *types.Transaction
2018-10-31 05:46:54 -07:00
switch action {
case AddOrgKey:
tx, err = ps.AddOrgKey(args.orgId, args.keyId)
case RemoveOrgKey:
tx, err = ps.DeleteOrgKey(args.orgId, args.keyId)
}
if err != nil {
2018-10-31 05:46:54 -07:00
log.Error("Failed to execute orgKey action", "action", action, "err", err)
2018-11-12 00:16:56 -08:00
return ExecStatus{false, err.Error()}
}
2018-10-31 05:46:54 -07:00
log.Debug("executed orgKey action", "action", action, "tx", tx)
2018-11-12 00:16:56 -08:00
return ExecStatus{true, ""}
}
2018-10-31 22:45:16 -07:00
// validateAccount validates the account and returns the wallet associated with that for signing the transaction
func (s *PermissionAPI) validateAccount(from common.Address) (accounts.Wallet, error) {
2018-10-31 05:46:54 -07:00
acct := accounts.Account{Address: from}
w, err := s.acntMgr.Find(acct)
if err != nil {
return nil, err
}
return w, nil
}
2018-11-05 07:44:23 -08:00
// checkVoterExists checks if any vote accounts are there. If yes returns true, else false
func checkVoterExists(ps *pbind.PermissionsSession) bool {
tx, err := ps.GetNumberOfVoters()
2018-11-12 00:16:56 -08:00
log.Debug("number of voters", "count", tx)
2018-11-05 07:44:23 -08:00
if err == nil && tx.Cmp(big.NewInt(0)) > 0 {
return true
}
return false
}
2018-11-13 00:15:28 -08:00
// checks if any accounts is a valid voter to approve the action
func checkIsVoter(ps *pbind.PermissionsSession, acctId common.Address) bool {
tx, err := ps.IsVoter(acctId)
if err == nil && tx {
return true
}
return false
}
2018-11-14 02:24:28 -08:00
2018-10-31 22:45:16 -07:00
// newPermSession creates a new permission contract session
func (s *PermissionAPI) newPermSession(w accounts.Wallet, txa ethapi.SendTxArgs) *pbind.PermissionsSession {
frmAcct, transactOpts, gasLimit, gasPrice, nonce := s.getTxParams(txa, w)
2018-10-31 05:46:54 -07:00
ps := &pbind.PermissionsSession{
2018-10-31 00:15:34 -07:00
Contract: s.permContr,
CallOpts: bind.CallOpts{
Pending: true,
},
TransactOpts: bind.TransactOpts{
From: frmAcct.Address,
GasLimit: gasLimit,
GasPrice: gasPrice,
2018-10-31 05:46:54 -07:00
Signer: transactOpts.Signer,
Nonce: nonce,
2018-10-31 00:15:34 -07:00
},
}
2018-10-31 05:46:54 -07:00
return ps
2018-10-31 00:15:34 -07:00
}
2018-10-31 22:45:16 -07:00
// newClusterSession creates a new cluster contract session
func (s *PermissionAPI) newClusterSession(w accounts.Wallet, txa ethapi.SendTxArgs) *pbind.ClusterSession {
frmAcct, transactOpts, gasLimit, gasPrice, nonce := s.getTxParams(txa, w)
cs := &pbind.ClusterSession{
2018-10-30 00:59:08 -07:00
Contract: s.clustContr,
CallOpts: bind.CallOpts{
Pending: true,
},
TransactOpts: bind.TransactOpts{
From: frmAcct.Address,
GasLimit: gasLimit,
GasPrice: gasPrice,
2018-10-31 05:46:54 -07:00
Signer: transactOpts.Signer,
Nonce: nonce,
2018-10-30 00:59:08 -07:00
},
}
return cs
}
2018-10-31 22:45:16 -07:00
// getTxParams extracts the transaction related parameters
func (s *PermissionAPI) getTxParams(txa ethapi.SendTxArgs, w accounts.Wallet) (accounts.Account, *bind.TransactOpts, uint64, *big.Int, *big.Int) {
frmAcct := accounts.Account{Address: txa.From}
transactOpts := bind.NewWalletTransactor(w, frmAcct)
gasLimit := defaultGasLimit
gasPrice := defaultGasPrice
if txa.GasPrice != nil {
gasPrice = txa.GasPrice.ToInt()
}
if txa.Gas != nil {
gasLimit = uint64(*txa.Gas)
}
var nonce *big.Int
if txa.Nonce != nil {
nonce = new(big.Int).SetUint64(uint64(*txa.Nonce))
} else {
nonce = new(big.Int).SetUint64(s.txPool.Nonce(frmAcct.Address))
}
return frmAcct, transactOpts, gasLimit, gasPrice, nonce
2018-10-30 00:59:08 -07:00
}
// checks if the input node details for approval is matching with details stored
// in contract
func checkNodeDetails (ps *pbind.PermissionsSession, enodeID string, node *discover.Node ) bool {
ipAddr := node.IP.String()
port := fmt.Sprintf("%v", node.TCP)
discPort := fmt.Sprintf("%v", node.UDP)
raftPort := fmt.Sprintf("%v", node.RaftPort)
ipAddrPort := ipAddr + ":" + port
cnode, err := ps.GetNodeDetails(enodeID)
if err == nil {
if strings.Compare(ipAddrPort, cnode.IpAddrPort) == 0 && strings.Compare(discPort, cnode.DiscPort) == 0 && strings.Compare(raftPort, cnode.RaftPort) == 0 {
return true
}
}
return false
}
// checks if the account performing the operation has sufficient access privileges
func checkAccountAccess (from common.Address, accessType uint8) bool {
acctAccess := types.GetAcctAccess(from)
if acctAccess == types.FullAccess {
return true
} else if acctAccess == types.ContractDeploy && accessType != uint8(types.FullAccess) {
return true
} else if acctAccess == types.Transact && (accessType == uint8(types.Transact) || accessType == uint8(types.ReadOnly)) {
return true
}
return false
}
// checks if the account performing the operation has sufficient access privileges
func checkVoterAccountAccess (account common.Address) bool {
acctAccess := types.GetAcctAccess(account)
if acctAccess == types.ReadOnly {
return false
}
return true
}