mirror of https://github.com/poanetwork/quorum.git
permission: implement permission as standard service of the node
This commit is contained in:
parent
9d844b9dbf
commit
7e4b3ff310
|
@ -20,6 +20,9 @@ import (
|
|||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/controls/permission"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
|
@ -159,14 +162,20 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
|||
|
||||
ethChan := utils.RegisterEthService(stack, &cfg.Eth)
|
||||
|
||||
ethereum := <-ethChan
|
||||
|
||||
if ctx.GlobalBool(utils.RaftModeFlag.Name) {
|
||||
RegisterRaftService(stack, ctx, cfg, ethChan)
|
||||
RegisterRaftService(stack, ctx, cfg, ethereum)
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
|
||||
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(utils.EnableNodePermissionFlag.Name) {
|
||||
RegisterPermissionService(ctx, stack, ethereum)
|
||||
}
|
||||
|
||||
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
|
||||
shhEnabled := enableWhisper(ctx)
|
||||
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
|
||||
|
@ -189,6 +198,27 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
|||
}
|
||||
return stack
|
||||
}
|
||||
func RegisterPermissionService(ctx *cli.Context, stack *node.Node, ethereum *eth.Ethereum) {
|
||||
if err := stack.Register(func(sctx *node.ServiceContext) (node.Service, error) {
|
||||
dataDir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||
var permissionConfig types.PermissionConfig
|
||||
var err error
|
||||
if permissionConfig, err = permission.ParsePermissionConifg(dataDir); err != nil {
|
||||
utils.Fatalf("loading of permission-config.json failed", "error")
|
||||
}
|
||||
|
||||
// start the permissions management service
|
||||
pc, err := permission.NewQuorumPermissionCtrl(stack, ctx.GlobalBool(utils.EnableNodePermissionFlag.Name), ctx.GlobalBool(utils.RaftModeFlag.Name), &permissionConfig)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to load the permission contracts as given in permissions-config.json %v", err)
|
||||
}
|
||||
log.Info("permission service created")
|
||||
return pc, nil
|
||||
}); err != nil {
|
||||
utils.Fatalf("Failed to register the permission service: %v", err)
|
||||
}
|
||||
log.Info("permission service registered")
|
||||
}
|
||||
|
||||
// dumpConfig is the dumpconfig command.
|
||||
func dumpConfig(ctx *cli.Context) error {
|
||||
|
@ -209,7 +239,7 @@ func dumpConfig(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, ethChan <-chan *eth.Ethereum) {
|
||||
func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, ethereum *eth.Ethereum) {
|
||||
blockTimeMillis := ctx.GlobalInt(utils.RaftBlockTimeFlag.Name)
|
||||
datadir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||
joinExistingId := ctx.GlobalInt(utils.RaftJoinExistingFlag.Name)
|
||||
|
@ -250,8 +280,6 @@ func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, eth
|
|||
}
|
||||
}
|
||||
|
||||
ethereum := <-ethChan
|
||||
|
||||
return raft.New(ctx, ethereum.ChainConfig(), myId, raftPort, joinExisting, blockTimeNanos, ethereum, peers, datadir)
|
||||
}); err != nil {
|
||||
utils.Fatalf("Failed to register the Raft service: %v", err)
|
||||
|
|
|
@ -19,7 +19,6 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"math"
|
||||
"os"
|
||||
godebug "runtime/debug"
|
||||
|
@ -33,8 +32,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/console"
|
||||
"github.com/ethereum/go-ethereum/controls/permission"
|
||||
"github.com/ethereum/go-ethereum/core/quorum"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/internal/debug"
|
||||
|
@ -137,7 +134,6 @@ var (
|
|||
utils.EVMInterpreterFlag,
|
||||
configFileFlag,
|
||||
utils.EnableNodePermissionFlag,
|
||||
utils.PermissionContractAddressFlag,
|
||||
utils.RaftModeFlag,
|
||||
utils.RaftBlockTimeFlag,
|
||||
utils.RaftJoinExistingFlag,
|
||||
|
@ -346,9 +342,6 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
|||
}
|
||||
}()
|
||||
|
||||
//START - QUORUM Permissioning
|
||||
go startQuorumPermissionService(ctx, stack)
|
||||
|
||||
// Start auxiliary services if enabled
|
||||
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
|
||||
// Mining only makes sense if a full Ethereum node is running
|
||||
|
@ -376,57 +369,3 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// Starts all permissioning services permissioning services will come up only when
|
||||
// geth is brought up in --permissioned mode
|
||||
func startQuorumPermissionService(ctx *cli.Context, stack *node.Node) {
|
||||
|
||||
var quorumApis []string
|
||||
dataDir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||
permEnabled := ctx.GlobalBool(utils.EnableNodePermissionFlag.Name)
|
||||
|
||||
var permissionConfig types.PermissionConfig
|
||||
var err error
|
||||
if permEnabled {
|
||||
if permissionConfig, err = permission.ParsePermissionConifg(dataDir); err != nil {
|
||||
log.Error("loading of permission-config.json failed", "error", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// permissions not enabled hence none of the services will be available.
|
||||
return
|
||||
}
|
||||
|
||||
// start the permissions management service
|
||||
pc, err := permission.NewQuorumPermissionCtrl(stack, ctx.GlobalBool(utils.EnableNodePermissionFlag.Name), ctx.GlobalBool(utils.RaftModeFlag.Name), &permissionConfig)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to load the permission contracts as given in permissions-config.json %v", err)
|
||||
}
|
||||
|
||||
if err = pc.Start(); err == nil {
|
||||
quorumApis = []string{"quorumPermission"}
|
||||
} else {
|
||||
utils.Fatalf("Failed to start Quorum Permission contract service %v", err)
|
||||
}
|
||||
|
||||
rpcClient, err := stack.Attach() /**/
|
||||
if err != nil {
|
||||
utils.Fatalf("Unable to connect to the node: %v", err)
|
||||
}
|
||||
stateReader := ethclient.NewClient(rpcClient)
|
||||
|
||||
for _, apiName := range quorumApis {
|
||||
v := stack.GetRPC(apiName)
|
||||
if v == nil {
|
||||
utils.Fatalf("Failed to start Quorum Permission API %s", apiName)
|
||||
}
|
||||
qapi := v.(*quorum.QuorumControlsAPI)
|
||||
|
||||
err = qapi.Init(stateReader, stack.GetNodeKey(), apiName, &permissionConfig, pc.Interface())
|
||||
if err != nil {
|
||||
log.Info("Failed to starts API", "apiName", apiName)
|
||||
} else {
|
||||
log.Info("API started", "apiName", apiName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -607,13 +607,6 @@ var (
|
|||
Usage: "If enabled, the node will allow only a defined list of nodes to connect",
|
||||
}
|
||||
|
||||
// Quorum permission contract
|
||||
PermissionContractAddressFlag = cli.StringFlag{
|
||||
Name: "permission.contract",
|
||||
Usage: "If passed, the node will use this contract to bootstrap permission instead of contract from genesis.json",
|
||||
Value: "0x",
|
||||
}
|
||||
|
||||
// Istanbul settings
|
||||
IstanbulRequestTimeoutFlag = cli.Uint64Flag{
|
||||
Name: "istanbul.requesttimeout",
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
package quorum
|
||||
package permission
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
obind "github.com/ethereum/go-ethereum/controls/bind/cluster"
|
||||
pbind "github.com/ethereum/go-ethereum/controls/bind/permission"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
|
@ -70,16 +67,10 @@ type PermissionContracts struct {
|
|||
|
||||
// QuorumControlsAPI provides an API to access Quorum's node permission and org key management related services
|
||||
type QuorumControlsAPI struct {
|
||||
txPool *core.TxPool
|
||||
ethClnt *ethclient.Client
|
||||
acntMgr *accounts.Manager
|
||||
txOpt *bind.TransactOpts
|
||||
clustContr *obind.Cluster
|
||||
key *ecdsa.PrivateKey
|
||||
permEnabled bool
|
||||
orgEnabled bool
|
||||
permConfig *types.PermissionConfig
|
||||
permInterf *pbind.PermInterface
|
||||
txPool *core.TxPool
|
||||
acctMgr *accounts.Manager
|
||||
permConfig *types.PermissionConfig
|
||||
permInterf *pbind.PermInterface
|
||||
}
|
||||
|
||||
// txArgs holds arguments required for execute functions
|
||||
|
@ -147,16 +138,15 @@ var (
|
|||
)
|
||||
|
||||
// NewQuorumControlsAPI creates a new QuorumControlsAPI to access quorum services
|
||||
func NewQuorumControlsAPI(tp *core.TxPool, am *accounts.Manager) *QuorumControlsAPI {
|
||||
return &QuorumControlsAPI{tp, nil, am, nil, nil, nil, false, false, nil, nil}
|
||||
func NewQuorumControlsAPI(tp *core.TxPool, am *accounts.Manager, pcfg *types.PermissionConfig, pc *pbind.PermInterface) *QuorumControlsAPI {
|
||||
return &QuorumControlsAPI{tp, am, pcfg, pc}
|
||||
}
|
||||
|
||||
//Init initializes QuorumControlsAPI with eth client, permission contract and org key management control
|
||||
func (p *QuorumControlsAPI) Init(ethClnt *ethclient.Client, key *ecdsa.PrivateKey, apiName string, pconfig *types.PermissionConfig, pc *pbind.PermInterface) error {
|
||||
/*//Init initializes QuorumControlsAPI with eth client, permission contract and org key management control
|
||||
func (p *QuorumControlsAPI) Init(ethClnt *ethclient.Client, key *ecdsa.PrivateKey, pc *pbind.PermInterface) error {
|
||||
// check if the interface contract is deployed or not. if not
|
||||
// permissions apis will not work. return error
|
||||
p.ethClnt = ethClnt
|
||||
p.permConfig = pconfig
|
||||
|
||||
if _, err := pbind.NewPermInterface(p.permConfig.InterfAddress, p.ethClnt); err != nil {
|
||||
return err
|
||||
|
@ -166,7 +156,7 @@ func (p *QuorumControlsAPI) Init(ethClnt *ethclient.Client, key *ecdsa.PrivateKe
|
|||
p.permInterf = pc
|
||||
|
||||
return nil
|
||||
}
|
||||
}*/
|
||||
|
||||
func (s *QuorumControlsAPI) OrgList() []types.OrgInfo {
|
||||
return types.OrgInfoMap.GetOrgList()
|
||||
|
@ -466,10 +456,6 @@ func (s *QuorumControlsAPI) valNodeDetails(url string) (ExecStatus, error) {
|
|||
|
||||
// executePermAction helps to execute an action in permission contract
|
||||
func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) ExecStatus {
|
||||
|
||||
if !s.permEnabled {
|
||||
return ErrPermissionDisabled
|
||||
}
|
||||
var err error
|
||||
var w accounts.Wallet
|
||||
|
||||
|
@ -762,7 +748,7 @@ func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) Ex
|
|||
// validateAccount validates the account and returns the wallet associated with that for signing the transaction
|
||||
func (s *QuorumControlsAPI) validateAccount(from common.Address) (accounts.Wallet, error) {
|
||||
acct := accounts.Account{Address: from}
|
||||
w, err := s.acntMgr.Find(acct)
|
||||
w, err := s.acctMgr.Find(acct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/raft"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
|
@ -66,6 +67,10 @@ type PermissionCtrl struct {
|
|||
permRole *pbind.RoleManager
|
||||
permOrg *pbind.OrgManager
|
||||
permConfig *types.PermissionConfig
|
||||
orgChan chan struct{}
|
||||
nodeChan chan struct{}
|
||||
roleChan chan struct{}
|
||||
acctChan chan struct{}
|
||||
}
|
||||
|
||||
func (p *PermissionCtrl) Interface() *pbind.PermInterface {
|
||||
|
@ -146,7 +151,7 @@ func waitForSync(e *eth.Ethereum) {
|
|||
// Creates the controls structure for permissions
|
||||
func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode, isRaft bool, pconfig *types.PermissionConfig) (*PermissionCtrl, error) {
|
||||
// Create a new ethclient to for interfacing with the contract
|
||||
stateReader, e, err := controls.CreateEthClient(stack)
|
||||
clnt, e, err := controls.CreateEthClient(stack)
|
||||
waitForSync(e)
|
||||
if err != nil {
|
||||
log.Error("Unable to create ethereum client for permissions check", "err", err)
|
||||
|
@ -157,47 +162,47 @@ func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode, isRaft bool, pc
|
|||
log.Error("permission-config.json is missing contract address")
|
||||
return nil, errors.New("permission-config.json is missing contract address")
|
||||
}
|
||||
pu, err := pbind.NewPermUpgr(pconfig.UpgrdAddress, stateReader)
|
||||
pu, err := pbind.NewPermUpgr(pconfig.UpgrdAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
// check if permissioning contract is there at address. If not return from here
|
||||
pm, err := pbind.NewPermInterface(pconfig.InterfAddress, stateReader)
|
||||
pm, err := pbind.NewPermInterface(pconfig.InterfAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmAcct, err := pbind.NewAcctManager(pconfig.AccountAddress, stateReader)
|
||||
pmAcct, err := pbind.NewAcctManager(pconfig.AccountAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmNode, err := pbind.NewNodeManager(pconfig.NodeAddress, stateReader)
|
||||
pmNode, err := pbind.NewNodeManager(pconfig.NodeAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmRole, err := pbind.NewRoleManager(pconfig.RoleAddress, stateReader)
|
||||
pmRole, err := pbind.NewRoleManager(pconfig.RoleAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmOrg, err := pbind.NewOrgManager(pconfig.OrgAddress, stateReader)
|
||||
pmOrg, err := pbind.NewOrgManager(pconfig.OrgAddress, clnt)
|
||||
if err != nil {
|
||||
log.Error("Permissions not enabled for the network", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
return &PermissionCtrl{stack, stateReader, e, isRaft, permissionedMode, stack.GetNodeKey(), stack.DataDir(), pu, pm, pmNode, pmAcct, pmRole, pmOrg, pconfig}, nil
|
||||
return &PermissionCtrl{stack, clnt, e, isRaft, permissionedMode, stack.GetNodeKey(), stack.DataDir(), pu, pm, pmNode, pmAcct, pmRole, pmOrg, pconfig, make(chan struct{}), make(chan struct{}), make(chan struct{}), make(chan struct{})}, nil
|
||||
}
|
||||
|
||||
// Starts the node permissioning and event monitoring for permissions
|
||||
// smart contracts
|
||||
func (p *PermissionCtrl) Start() error {
|
||||
func (p *PermissionCtrl) Start(srvr *p2p.Server) error {
|
||||
// Permissions initialization
|
||||
if err := p.init(); err != nil {
|
||||
log.Error("Permissions init failed", "err", err)
|
||||
|
@ -219,6 +224,32 @@ func (p *PermissionCtrl) Start() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *PermissionCtrl) APIs() []rpc.API {
|
||||
log.Info("permission rpc API called")
|
||||
return []rpc.API{
|
||||
{
|
||||
Namespace: "quorumPermission",
|
||||
Version: "1.0",
|
||||
Service: NewQuorumControlsAPI(s.eth.TxPool(), s.eth.AccountManager(), s.permConfig, s.permInterf),
|
||||
Public: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PermissionCtrl) Protocols() []p2p.Protocol {
|
||||
return []p2p.Protocol{}
|
||||
}
|
||||
|
||||
func (p *PermissionCtrl) Stop() error {
|
||||
log.Info("stopping permission service...")
|
||||
p.roleChan <- struct{}{}
|
||||
p.orgChan <- struct{}{}
|
||||
p.acctChan <- struct{}{}
|
||||
p.nodeChan <- struct{}{}
|
||||
log.Info("stopped permission service")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Sets the initial values for the network
|
||||
func (p *PermissionCtrl) init() error {
|
||||
// populate the initial list of permissioned nodes and account accesses
|
||||
|
@ -280,6 +311,8 @@ func (p *PermissionCtrl) manageOrgPermissions() {
|
|||
|
||||
case evtOrgReactivated = <-chOrgReactivated:
|
||||
types.OrgInfoMap.UpsertOrg(evtOrgReactivated.OrgId, evtOrgReactivated.PorgId, evtOrgReactivated.UltParent, evtOrgReactivated.Level, types.OrgApproved)
|
||||
case <-p.orgChan:
|
||||
log.Info("quit org contract watch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +375,9 @@ func (p *PermissionCtrl) manageNodePermissions() {
|
|||
p.updatePermissionedNodes(evtNodeBlacklisted.EnodeId, NodeDelete)
|
||||
p.updateDisallowedNodes(evtNodeBlacklisted.EnodeId)
|
||||
types.NodeInfoMap.UpsertNode(evtNodeBlacklisted.OrgId, evtNodeBlacklisted.EnodeId, types.NodeBlackListed)
|
||||
case <-p.nodeChan:
|
||||
log.Info("quit node contract watch")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,6 +516,8 @@ func (p *PermissionCtrl) manageAccountPermissions() {
|
|||
case evtStatusChanged = <-chStatusChanged:
|
||||
ac := types.AcctInfoMap.GetAccount(evtStatusChanged.Address)
|
||||
types.AcctInfoMap.UpsertAccount(evtStatusChanged.OrgId, ac.RoleId, evtStatusChanged.Address, ac.IsOrgAdmin, types.AcctStatus(int(evtStatusChanged.Status.Uint64())))
|
||||
case <-p.acctChan:
|
||||
log.Info("quit account contract watch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -738,6 +776,8 @@ func (p *PermissionCtrl) manageRolePermissions() {
|
|||
} else {
|
||||
log.Error("Revoke role - cache is missing role", "org", evtRoleRevoked.OrgId, "role", evtRoleRevoked.RoleId)
|
||||
}
|
||||
case <-p.roleChan:
|
||||
log.Info("quit role contract watch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import (
|
|||
istanbulBackend "github.com/ethereum/go-ethereum/consensus/istanbul/backend"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/bloombits"
|
||||
"github.com/ethereum/go-ethereum/core/quorum"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
@ -337,18 +336,6 @@ func (s *Ethereum) APIs() []rpc.API {
|
|||
Service: s.netRPCService,
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
Namespace: "quorumPermission",
|
||||
Version: "1.0",
|
||||
Service: quorum.NewQuorumControlsAPI(s.txPool, s.accountManager),
|
||||
Public: true,
|
||||
},
|
||||
{
|
||||
Namespace: "quorumOrgMgmt",
|
||||
Version: "1.0",
|
||||
Service: quorum.NewQuorumControlsAPI(s.txPool, s.accountManager),
|
||||
Public: true,
|
||||
},
|
||||
}...)
|
||||
return apis
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue