2018-10-29 19:41:01 -07:00
package permission
2018-07-12 03:00:19 -07:00
import (
2018-10-30 23:42:29 -07:00
"crypto/ecdsa"
2018-07-16 03:34:20 -07:00
"encoding/json"
2019-03-26 08:20:06 -07:00
"errors"
2019-03-08 01:09:24 -08:00
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
2018-07-12 03:00:19 -07:00
"io/ioutil"
2018-10-24 03:21:21 -07:00
"math/big"
2018-07-16 03:34:20 -07:00
"os"
2018-10-31 22:45:16 -07:00
"path/filepath"
2018-08-12 23:55:58 -07:00
"sync"
2018-07-12 03:00:19 -07:00
"github.com/ethereum/go-ethereum/accounts/abi/bind"
2018-11-16 02:08:49 -08:00
"github.com/ethereum/go-ethereum/cmd/utils"
2018-10-31 22:45:16 -07:00
"github.com/ethereum/go-ethereum/controls"
2019-01-07 22:40:57 -08:00
pbind "github.com/ethereum/go-ethereum/controls/bind/permission"
2018-10-31 22:45:16 -07:00
"github.com/ethereum/go-ethereum/core/types"
2018-10-24 03:21:21 -07:00
"github.com/ethereum/go-ethereum/eth"
2018-07-12 03:00:19 -07:00
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
2018-10-24 03:21:21 -07:00
"github.com/ethereum/go-ethereum/p2p"
2018-10-31 22:45:16 -07:00
"github.com/ethereum/go-ethereum/params"
2018-09-18 23:55:41 -07:00
"github.com/ethereum/go-ethereum/raft"
2018-07-12 03:00:19 -07:00
)
2018-10-29 19:41:01 -07:00
2018-08-12 19:00:35 -07:00
type NodeOperation uint8
2018-10-29 19:41:01 -07:00
2018-08-12 19:00:35 -07:00
const (
NodeAdd NodeOperation = iota
NodeDelete
)
2018-10-29 19:41:01 -07:00
type PermissionCtrl struct {
2018-11-14 02:24:28 -08:00
node * node . Node
ethClnt * ethclient . Client
eth * eth . Ethereum
isRaft bool
2018-11-13 00:15:28 -08:00
permissionedMode bool
2018-11-14 02:24:28 -08:00
key * ecdsa . PrivateKey
dataDir string
2019-03-26 08:20:06 -07:00
permUpgr * pbind . PermUpgr
2019-03-22 04:34:15 -07:00
permInterf * pbind . PermInterface
permNode * pbind . NodeManager
permAcct * pbind . AcctManager
2019-03-27 04:07:01 -07:00
permRole * pbind . RoleManager
permOrg * pbind . OrgManager
2019-03-11 20:18:20 -07:00
permConfig * types . PermissionConfig
}
func ParsePermissionConifg ( dir string ) ( types . PermissionConfig , error ) {
fileName := "permission-config.json"
fullPath := filepath . Join ( dir , fileName )
if _ , err := os . Stat ( fullPath ) ; err != nil {
2019-03-13 23:26:17 -07:00
log . Warn ( "permission-config.json file is missing" , err )
2019-03-22 04:34:15 -07:00
return types . PermissionConfig { } , err
2019-03-11 20:18:20 -07:00
}
blob , err := ioutil . ReadFile ( fullPath )
if err != nil {
log . Error ( "error reading permission-config.json file" , err )
return types . PermissionConfig { } , err
}
var permConfig types . PermissionConfig
err = json . Unmarshal ( blob , & permConfig )
if err != nil {
log . Error ( "error unmarshalling permission-config.json file" , err )
return types . PermissionConfig { } , err
}
return permConfig , nil
2018-10-25 21:33:23 -07:00
}
2018-10-31 19:55:40 -07:00
// Creates the controls structure for permissions
2019-03-11 20:18:20 -07:00
func NewQuorumPermissionCtrl ( stack * node . Node , permissionedMode , isRaft bool , pconfig * types . PermissionConfig ) ( * PermissionCtrl , error ) {
2018-08-05 22:26:29 -07:00
// Create a new ethclient to for interfacing with the contract
2018-10-24 03:21:21 -07:00
stateReader , e , err := controls . CreateEthClient ( stack )
2018-08-05 22:26:29 -07:00
if err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Unable to create ethereum client for permissions check" , "err" , err )
2018-10-29 19:41:01 -07:00
return nil , err
2018-08-12 19:00:35 -07:00
}
2018-10-29 19:41:01 -07:00
2019-03-26 08:20:06 -07:00
if pconfig . IsEmpty ( ) && permissionedMode {
2019-03-22 04:34:15 -07:00
utils . Fatalf ( "permission-config.json is missing contract address" )
2019-03-08 01:09:24 -08:00
}
2019-03-26 08:20:06 -07:00
if ! permissionedMode {
2019-03-27 04:07:01 -07:00
return & PermissionCtrl { stack , stateReader , e , isRaft , permissionedMode , stack . GetNodeKey ( ) , stack . DataDir ( ) , nil , nil , nil , nil , nil , nil , pconfig } , nil
2019-03-26 08:20:06 -07:00
}
pu , err := pbind . NewPermUpgr ( common . HexToAddress ( pconfig . UpgrdAddress ) , stateReader )
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2018-10-29 19:41:01 -07:00
// check if permissioning contract is there at address. If not return from here
2019-03-22 04:34:15 -07:00
pm , err := pbind . NewPermInterface ( common . HexToAddress ( pconfig . InterfAddress ) , stateReader )
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
pmAcct , err := pbind . NewAcctManager ( common . HexToAddress ( pconfig . AccountAddress ) , stateReader )
2018-11-02 03:42:14 -07:00
if err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Permissions not enabled for the network" , "err" , err )
2018-11-02 03:42:14 -07:00
return nil , err
2018-10-29 19:41:01 -07:00
}
2018-10-25 22:38:56 -07:00
2019-03-22 04:34:15 -07:00
pmNode , err := pbind . NewNodeManager ( common . HexToAddress ( pconfig . NodeAddress ) , stateReader )
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2019-03-27 04:07:01 -07:00
pmRole , err := pbind . NewRoleManager ( common . HexToAddress ( pconfig . RoleAddress ) , stateReader )
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
pmOrg , err := pbind . NewOrgManager ( common . HexToAddress ( pconfig . OrgAddress ) , stateReader )
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-permission contracts initialized" )
2019-03-27 04:07:01 -07:00
return & PermissionCtrl { stack , stateReader , e , isRaft , permissionedMode , stack . GetNodeKey ( ) , stack . DataDir ( ) , pu , pm , pmNode , pmAcct , pmRole , pmOrg , pconfig } , nil
2018-11-02 03:42:14 -07:00
}
// Starts the node permissioning and account access control monitoring
func ( p * PermissionCtrl ) Start ( ) error {
2018-10-25 22:38:56 -07:00
// Permissions initialization
2018-11-02 03:42:14 -07:00
if err := p . init ( ) ; err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Permissions init failed" , "err" , err )
2018-11-02 03:42:14 -07:00
return err
}
2018-08-12 19:00:35 -07:00
// Monitors node addition and decativation from network
2018-10-29 19:41:01 -07:00
p . manageNodePermissions ( )
2018-10-31 22:45:16 -07:00
// Monitors account level persmissions update from smart contarct
2018-10-29 19:41:01 -07:00
p . manageAccountPermissions ( )
2018-11-02 03:42:14 -07:00
2018-08-12 19:00:35 -07:00
return nil
}
2018-07-13 18:22:43 -07:00
2019-02-12 20:31:11 -08:00
// Sets the initial values for the network
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) init ( ) error {
2019-03-26 08:20:06 -07:00
if ! p . permissionedMode {
return nil
}
2018-11-02 03:42:14 -07:00
// populate the initial list of permissioned nodes and account accesses
2019-03-26 08:20:06 -07:00
if err := p . populateInitPermissions ( ) ; err != nil {
2018-11-02 03:42:14 -07:00
return err
}
2018-10-25 22:38:56 -07:00
2018-11-04 19:28:33 -08:00
// call populates the account permissions based on past history
if err := p . populateAcctPermissions ( ) ; err != nil {
2018-10-25 22:38:56 -07:00
return err
}
2018-11-02 03:42:14 -07:00
2019-02-11 17:54:13 -08:00
// set the default access to ReadOnly
types . SetDefaultAccess ( )
2018-10-25 22:38:56 -07:00
return nil
}
2018-11-02 03:42:14 -07:00
// Manages node addition, decavtivation and activation from network
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) manageNodePermissions ( ) {
2018-07-26 00:46:53 -07:00
2019-03-26 08:20:06 -07:00
if p . permissionedMode {
log . Info ( "AJ-permission start" )
//monitor for new nodes addition via smart contract
go p . monitorNewNodeAdd ( )
2018-08-31 04:35:35 -07:00
2019-03-26 08:20:06 -07:00
//monitor for nodes deletion via smart contract
go p . monitorNodeDeactivation ( )
2018-11-02 03:42:14 -07:00
2019-03-26 08:20:06 -07:00
//monitor for nodes activation from deactivation status
go p . monitorNodeActivation ( )
//monitor for nodes blacklisting via smart contract
go p . monitorNodeBlacklisting ( )
}
2018-07-13 18:22:43 -07:00
}
2019-02-12 20:31:11 -08:00
// Listens on the channel for new node approval via smart contract and
2018-07-13 18:22:43 -07:00
// adds the same into permissioned-nodes.json
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) monitorNewNodeAdd ( ) {
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-new node approved" )
ch := make ( chan * pbind . NodeManagerNodeApproved , 1 )
2018-07-13 18:22:43 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-03-22 04:34:15 -07:00
var nodeAddEvent * pbind . NodeManagerNodeApproved
2018-07-13 18:22:43 -07:00
2019-03-22 04:34:15 -07:00
_ , err := p . permNode . NodeManagerFilterer . WatchNodeApproved ( opts , ch )
2018-08-16 20:20:33 -07:00
if err != nil {
log . Info ( "Failed WatchNodeApproved: %v" , err )
}
for {
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-new node approved waiting for events..." )
2018-08-12 23:55:58 -07:00
select {
case nodeAddEvent = <- ch :
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-newNodeApproved" , "node" , nodeAddEvent . EnodeId )
p . updatePermissionedNodes ( nodeAddEvent . EnodeId , NodeAdd )
2018-08-12 23:55:58 -07:00
}
2018-10-29 19:41:01 -07:00
}
2018-07-13 18:22:43 -07:00
}
2019-02-12 20:31:11 -08:00
// Listens on the channel for new node deactivation via smart contract
// and removes the same from permissioned-nodes.json
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) monitorNodeDeactivation ( ) {
2019-03-22 04:34:15 -07:00
ch := make ( chan * pbind . NodeManagerNodeDeactivated )
2018-07-26 00:46:53 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-03-22 04:34:15 -07:00
var newNodeDeleteEvent * pbind . NodeManagerNodeDeactivated
_ , err := p . permNode . NodeManagerFilterer . WatchNodeDeactivated ( opts , ch )
2018-08-16 20:20:33 -07:00
if err != nil {
log . Info ( "Failed NodeDeactivated: %v" , err )
}
for {
select {
case newNodeDeleteEvent = <- ch :
2019-03-22 04:34:15 -07:00
p . updatePermissionedNodes ( newNodeDeleteEvent . EnodeId , NodeDelete )
2018-10-29 19:41:01 -07:00
}
2018-07-26 00:46:53 -07:00
2018-08-16 20:20:33 -07:00
}
2018-07-26 00:46:53 -07:00
}
2018-08-05 22:26:29 -07:00
2019-02-12 20:31:11 -08:00
// Listnes on the channel for any node activation via smart contract
// and adds the same permissioned-nodes.json
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) monitorNodeActivation ( ) {
2019-03-22 04:34:15 -07:00
ch := make ( chan * pbind . NodeManagerNodeActivated , 1 )
2018-11-02 03:42:14 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-03-22 04:34:15 -07:00
var nodeActivatedEvent * pbind . NodeManagerNodeActivated
2018-11-02 03:42:14 -07:00
2019-03-22 04:34:15 -07:00
_ , err := p . permNode . NodeManagerFilterer . WatchNodeActivated ( opts , ch )
2018-08-31 04:35:35 -07:00
if err != nil {
2018-11-02 03:42:14 -07:00
log . Info ( "Failed WatchNodeActivated: %v" , err )
}
for {
select {
case nodeActivatedEvent = <- ch :
2019-03-22 04:34:15 -07:00
p . updatePermissionedNodes ( nodeActivatedEvent . EnodeId , NodeAdd )
2018-11-02 03:42:14 -07:00
}
2018-08-31 04:35:35 -07:00
}
2018-11-02 03:42:14 -07:00
}
2019-02-12 20:31:11 -08:00
// Listens on the channel for node blacklisting via smart contract and
2018-11-02 03:42:14 -07:00
// adds the same into disallowed-nodes.json
func ( p * PermissionCtrl ) monitorNodeBlacklisting ( ) {
2019-03-22 04:34:15 -07:00
ch := make ( chan * pbind . NodeManagerNodeBlacklisted )
2018-08-31 04:35:35 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-03-22 04:34:15 -07:00
var newNodeBlacklistEvent * pbind . NodeManagerNodeBlacklisted
2018-08-31 04:35:35 -07:00
2019-03-22 04:34:15 -07:00
_ , err := p . permNode . NodeManagerFilterer . WatchNodeBlacklisted ( opts , ch )
2018-08-31 04:35:35 -07:00
if err != nil {
2018-11-02 03:42:14 -07:00
log . Info ( "Failed NodeBlacklisting: %v" , err )
2018-08-31 04:35:35 -07:00
}
for {
select {
2018-11-02 03:42:14 -07:00
case newNodeBlacklistEvent = <- ch :
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-nodeBlackListed" , "event" , newNodeBlacklistEvent )
//p.updatePermissionedNodes(newNodeBlacklistEvent., newNodeBlacklistEvent.IpAddrPort, newNodeBlacklistEvent.DiscPort, newNodeBlacklistEvent.RaftPort, NodeDelete)
//p.updateDisallowedNodes(newNodeBlacklistEvent)
2018-08-31 04:35:35 -07:00
}
2018-11-02 03:42:14 -07:00
2018-10-29 19:41:01 -07:00
}
2018-08-31 04:35:35 -07:00
}
2018-11-07 04:50:49 -08:00
2019-02-12 20:31:11 -08:00
// Populates the new node information into the permissioned-nodes.json file
2019-03-22 04:34:15 -07:00
func ( p * PermissionCtrl ) updatePermissionedNodes ( enodeId string , operation NodeOperation ) {
2019-02-13 18:24:32 -08:00
log . Debug ( "updatePermissionedNodes" , "DataDir" , p . dataDir , "file" , params . PERMISSIONED_CONFIG )
2018-07-16 03:34:20 -07:00
2019-02-13 18:24:32 -08:00
path := filepath . Join ( p . dataDir , params . PERMISSIONED_CONFIG )
2018-11-19 23:43:56 -08:00
if _ , err := os . Stat ( path ) ; err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Read Error for permissioned-nodes.json file. This is because 'permissioned' flag is specified but no permissioned-nodes.json file is present" , "err" , err )
2019-02-11 17:54:13 -08:00
return
2018-11-19 23:43:56 -08:00
}
// Load the nodes from the config file
blob , err := ioutil . ReadFile ( path )
2018-10-25 22:38:56 -07:00
if err != nil {
2018-11-19 23:43:56 -08:00
log . Error ( "updatePermissionedNodes: Failed to access permissioned-nodes.json" , "err" , err )
return
}
nodelist := [ ] string { }
if err := json . Unmarshal ( blob , & nodelist ) ; err != nil {
log . Error ( "updatePermissionedNodes: Failed to load nodes list" , "err" , err )
2019-02-11 17:54:13 -08:00
return
2018-07-16 03:34:20 -07:00
}
2018-08-12 23:55:58 -07:00
2018-11-19 23:43:56 -08:00
// logic to update the permissioned-nodes.json file based on action
2019-01-23 21:35:46 -08:00
index := 0
recExists := false
2019-03-22 04:34:15 -07:00
for i , eid := range nodelist {
if eid == enodeId {
2019-01-23 21:35:46 -08:00
index = i
recExists = true
break
}
}
2018-11-20 05:29:03 -08:00
if operation == NodeAdd {
2019-01-23 21:35:46 -08:00
if ! recExists {
2019-03-22 04:34:15 -07:00
nodelist = append ( nodelist , enodeId )
2018-08-16 20:20:33 -07:00
}
2019-01-23 21:35:46 -08:00
} else {
2019-01-10 19:38:02 -08:00
if recExists {
nodelist = append ( nodelist [ : index ] , nodelist [ index + 1 : ] ... )
}
2019-03-22 04:34:15 -07:00
p . disconnectNode ( enodeId )
2018-07-26 00:46:53 -07:00
}
2018-11-19 23:43:56 -08:00
mu := sync . RWMutex { }
blob , _ = json . Marshal ( nodelist )
2018-07-16 03:34:20 -07:00
2018-11-19 23:43:56 -08:00
mu . Lock ( )
2019-02-11 17:54:13 -08:00
if err := ioutil . WriteFile ( path , blob , 0644 ) ; err != nil {
2018-11-19 23:43:56 -08:00
log . Error ( "updatePermissionedNodes: Error writing new node info to file" , "err" , err )
}
mu . Unlock ( )
2018-08-12 19:00:35 -07:00
}
2018-08-31 04:35:35 -07:00
2019-02-12 20:31:11 -08:00
//this function populates the black listed node information into the disallowed-nodes.json file
2018-10-30 00:59:08 -07:00
func ( p * PermissionCtrl ) updateDisallowedNodes ( nodeBlacklistEvent * pbind . PermissionsNodeBlacklisted ) {
2019-02-13 18:24:32 -08:00
log . Debug ( "updateDisallowedNodes" , "DataDir" , p . dataDir , "file" , params . BLACKLIST_CONFIG )
2018-08-31 04:35:35 -07:00
2018-09-02 23:59:45 -07:00
fileExisted := true
2019-02-13 18:24:32 -08:00
path := filepath . Join ( p . dataDir , params . BLACKLIST_CONFIG )
2018-09-02 23:59:45 -07:00
// Check if the file is existing. If the file is not existing create the file
2018-08-31 04:35:35 -07:00
if _ , err := os . Stat ( path ) ; err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Read Error for disallowed-nodes.json file" , "err" , err )
2018-08-31 04:35:35 -07:00
if _ , err := os . OpenFile ( path , os . O_CREATE | os . O_RDWR , 0644 ) ; err != nil {
2019-02-13 01:42:59 -08:00
log . Error ( "Failed to create disallowed-nodes.json file" , "err" , err )
2018-10-29 19:41:01 -07:00
return
2018-08-31 04:35:35 -07:00
}
2018-09-02 23:59:45 -07:00
fileExisted = false
2018-08-31 04:35:35 -07:00
}
nodelist := [ ] string { }
2018-09-02 23:59:45 -07:00
// Load the nodes from the config file
if fileExisted == true {
blob , err := ioutil . ReadFile ( path )
if err != nil {
log . Error ( "updateDisallowedNodes Failed to access disallowed-nodes.json" , "err" , err )
return
}
2018-10-31 22:45:16 -07:00
if blob != nil {
2018-09-02 23:59:45 -07:00
if err := json . Unmarshal ( blob , & nodelist ) ; err != nil {
log . Error ( "updateDisallowedNodes: Failed to load nodes list" , "err" , err )
2018-10-29 19:41:01 -07:00
return
2018-09-02 23:59:45 -07:00
}
2018-08-31 04:35:35 -07:00
}
}
2018-11-02 03:42:14 -07:00
newEnodeId := p . formatEnodeId ( nodeBlacklistEvent . EnodeId , nodeBlacklistEvent . IpAddrPort , nodeBlacklistEvent . DiscPort , nodeBlacklistEvent . RaftPort )
2018-08-31 04:35:35 -07:00
nodelist = append ( nodelist , newEnodeId )
mu := sync . RWMutex { }
2018-09-02 23:59:45 -07:00
blob , _ := json . Marshal ( nodelist )
2018-08-31 04:35:35 -07:00
mu . Lock ( )
2018-10-29 19:41:01 -07:00
if err := ioutil . WriteFile ( path , blob , 0644 ) ; err != nil {
2018-08-31 04:35:35 -07:00
log . Error ( "updateDisallowedNodes: Error writing new node info to file" , "err" , err )
}
mu . Unlock ( )
2018-09-17 22:52:46 -07:00
// Disconnect the peer if it is already connected
2018-10-29 19:41:01 -07:00
p . disconnectNode ( newEnodeId )
2018-08-31 04:35:35 -07:00
}
2018-08-12 19:00:35 -07:00
// Manages account level permissions update
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) manageAccountPermissions ( ) {
2019-03-26 08:20:06 -07:00
if ! p . permissionedMode {
return
}
2018-08-12 19:00:35 -07:00
//monitor for nodes deletiin via smart contract
2018-10-29 19:41:01 -07:00
go p . monitorAccountPermissions ( )
2018-11-02 03:42:14 -07:00
return
2018-08-12 19:00:35 -07:00
}
2018-10-29 19:41:01 -07:00
2019-02-12 20:31:11 -08:00
// populates the nodes list from permissioned-nodes.json into the permissions smart contract
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) populatePermissionedNodes ( ) error {
2018-10-25 22:38:56 -07:00
opts := & bind . FilterOpts { }
2019-03-22 04:34:15 -07:00
pastAddEvent , err := p . permNode . NodeManagerFilterer . FilterNodeApproved ( opts )
2018-10-25 22:38:56 -07:00
2018-11-05 07:44:23 -08:00
if err == nil {
2018-11-02 03:42:14 -07:00
recExists := true
for recExists {
recExists = pastAddEvent . Next ( )
if recExists {
2019-03-22 04:34:15 -07:00
p . updatePermissionedNodes ( pastAddEvent . Event . EnodeId , NodeAdd )
2018-11-02 03:42:14 -07:00
}
2018-10-25 22:38:56 -07:00
}
}
opts = & bind . FilterOpts { }
2019-03-22 04:34:15 -07:00
pastDelEvent , err := p . permNode . NodeManagerFilterer . FilterNodeDeactivated ( opts )
2018-11-05 07:44:23 -08:00
if err == nil {
2018-11-02 03:42:14 -07:00
recExists := true
for recExists {
recExists = pastDelEvent . Next ( )
if recExists {
2019-03-22 04:34:15 -07:00
p . updatePermissionedNodes ( pastDelEvent . Event . EnodeId , NodeDelete )
2018-11-02 03:42:14 -07:00
}
2018-10-25 22:38:56 -07:00
}
}
return nil
}
2018-08-12 19:00:35 -07:00
2019-02-12 20:31:11 -08:00
// populates the account permissions cache from past account access update events
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) populateAcctPermissions ( ) error {
2019-03-26 08:20:06 -07:00
2018-08-12 19:00:35 -07:00
opts := & bind . FilterOpts { }
2019-03-22 04:34:15 -07:00
pastEvents , err := p . permAcct . AcctManagerFilterer . FilterAccountAccessModified ( opts )
2018-08-12 19:00:35 -07:00
2018-11-04 19:28:33 -08:00
if err == nil {
2018-11-02 03:42:14 -07:00
recExists := true
for recExists {
recExists = pastEvents . Next ( )
if recExists {
2019-03-26 08:20:06 -07:00
log . Info ( "AJ-added account " , "acct" , pastEvents . Event . Address , "roleId" , pastEvents . Event . RoleId )
2019-03-22 04:34:15 -07:00
types . AddAccountAccess ( pastEvents . Event . Address , pastEvents . Event . RoleId )
2018-11-02 03:42:14 -07:00
}
2018-08-12 19:00:35 -07:00
}
}
2018-11-02 03:42:14 -07:00
2018-08-12 19:00:35 -07:00
return nil
}
2019-02-12 20:31:11 -08:00
// Monitors permissions changes at acount level and uodate the account permissions cache
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) monitorAccountPermissions ( ) {
2019-03-22 04:34:15 -07:00
ch := make ( chan * pbind . AcctManagerAccountAccessModified )
2018-08-12 19:00:35 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-03-22 04:34:15 -07:00
var newEvent * pbind . AcctManagerAccountAccessModified
2018-08-12 19:00:35 -07:00
2019-03-22 04:34:15 -07:00
_ , err := p . permAcct . AcctManagerFilterer . WatchAccountAccessModified ( opts , ch )
2018-08-16 20:20:33 -07:00
if err != nil {
2019-03-27 04:07:01 -07:00
log . Info ( "AJ-Failed NewNodeProposed: %v" , err )
2018-08-16 20:20:33 -07:00
}
2018-08-12 19:00:35 -07:00
for {
2018-08-16 20:20:33 -07:00
select {
case newEvent = <- ch :
2019-03-22 04:34:15 -07:00
log . Info ( "AJ-AccountAccessModified" , "address" , newEvent . Address , "role" , newEvent . RoleId )
types . AddAccountAccess ( newEvent . Address , newEvent . RoleId )
2018-08-12 19:00:35 -07:00
}
2018-10-29 19:41:01 -07:00
}
2018-07-16 03:34:20 -07:00
}
2018-09-19 18:51:36 -07:00
// Disconnect the node from the network
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) disconnectNode ( enodeId string ) {
if p . isRaft {
2018-09-19 18:51:36 -07:00
var raftService * raft . RaftService
2018-10-29 19:41:01 -07:00
if err := p . node . Service ( & raftService ) ; err == nil {
2018-09-19 18:51:36 -07:00
raftApi := raft . NewPublicRaftAPI ( raftService )
//get the raftId for the given enodeId
raftId , err := raftApi . GetRaftId ( enodeId )
if err == nil {
raftApi . RemovePeer ( raftId )
}
}
} else {
// Istanbul - disconnect the peer
2018-10-29 19:41:01 -07:00
server := p . node . Server ( )
2018-09-19 18:51:36 -07:00
if server != nil {
2019-03-08 01:09:24 -08:00
node , err := enode . ParseV4 ( enodeId )
2018-09-19 18:51:36 -07:00
if err == nil {
server . RemovePeer ( node )
}
}
}
}
2018-09-19 22:55:57 -07:00
// helper function to format EnodeId
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) formatEnodeId ( enodeId , ipAddrPort , discPort , raftPort string ) string {
2019-01-28 21:52:58 -08:00
newEnodeId := "enode://" + enodeId + "@" + ipAddrPort + "?discport=" + discPort
2018-11-02 03:42:14 -07:00
if p . isRaft {
2018-10-29 19:41:01 -07:00
newEnodeId += "&raftport=" + raftPort
2018-09-19 22:55:57 -07:00
}
return newEnodeId
}
2018-10-29 19:41:01 -07:00
2019-02-12 20:31:11 -08:00
// Thus function checks if the its the initial network boot up and if yes
// populates the initial network enode details from static-nodes.json into
// smart contracts. Sets the accounts access to full access for the initial
// initial list of accounts as given in genesis.json file
2019-03-26 08:20:06 -07:00
func ( p * PermissionCtrl ) populateInitPermissions ( ) error {
auth := bind . NewKeyedTransactor ( p . key )
permInterfSession := & pbind . PermInterfaceSession {
2019-03-22 04:34:15 -07:00
Contract : p . permInterf ,
2018-10-24 03:21:21 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
2019-03-22 04:34:15 -07:00
GasLimit : 47000000 ,
2018-10-24 03:21:21 -07:00
GasPrice : big . NewInt ( 0 ) ,
} ,
}
2019-03-26 08:20:06 -07:00
networkInitialized , err := permInterfSession . GetNetworkBootStatus ( )
2018-10-25 22:38:56 -07:00
if err != nil {
2019-01-21 00:18:59 -08:00
// handle the scenario of no contract code.
2019-02-11 17:54:13 -08:00
if err . Error ( ) == "no contract code at given address" {
2019-01-21 00:18:59 -08:00
return err
}
log . Warn ( "Failed to retrieve network boot status " , "err" , err )
2018-10-25 22:38:56 -07:00
}
2018-11-02 03:42:14 -07:00
2019-03-22 04:34:15 -07:00
if networkInitialized && ! p . permissionedMode {
2018-11-13 00:15:28 -08:00
// Network is initialized with permissions and node is joining in a non-permissioned
// option. stop the node from coming up
2019-03-26 08:20:06 -07:00
utils . Fatalf ( "Joining a permissioned network in non-permissioned mode is not permitted. Bring up geth with --permissioned." )
2018-11-13 00:15:28 -08:00
}
2018-11-14 02:24:28 -08:00
if ! p . permissionedMode {
2019-03-26 08:20:06 -07:00
log . Info ( "Node started in non-permissioned mode" )
2018-11-13 00:15:28 -08:00
return errors . New ( "Node started in non-permissioned mode" )
}
2019-03-22 04:34:15 -07:00
if ! networkInitialized {
2019-02-06 22:31:19 -08:00
// Ensure that there is at least one account given as a part of genesis.json
// which will have full access. If not throw a fatal error
// Do not want a network with no access
2019-03-26 08:20:06 -07:00
log . Info ( "AJ-network not initialized" )
2019-02-06 22:31:19 -08:00
2019-03-26 08:20:06 -07:00
permInterfSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permInterfSession . TransactOpts . From ) )
if _ , err := permInterfSession . SetPolicy ( p . permConfig . NwAdminOrg , p . permConfig . NwAdminRole , p . permConfig . OrgAdminRole ) ; err != nil {
log . Error ( "AJ-permIntr.setPolicy failed" , "err" , err )
2018-11-02 03:42:14 -07:00
return err
}
2019-03-27 04:07:01 -07:00
log . Info ( "AJ-permInter setPolicy done" )
2019-03-26 08:20:06 -07:00
permInterfSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permInterfSession . TransactOpts . From ) )
if _ , err := permInterfSession . Init ( common . HexToAddress ( p . permConfig . OrgAddress ) , common . HexToAddress ( p . permConfig . RoleAddress ) , common . HexToAddress ( p . permConfig . AccountAddress ) , common . HexToAddress ( p . permConfig . VoterAddress ) , common . HexToAddress ( p . permConfig . NodeAddress ) ) ; err != nil {
log . Error ( "AJ-permIntr.init failed" , "err" , err )
return err
2019-03-19 00:29:53 -07:00
}
2019-03-27 04:07:01 -07:00
log . Info ( "AJ-permInter init done" )
2018-11-07 04:50:49 -08:00
// populate the initial node list from static-nodes.json
2019-03-26 08:20:06 -07:00
err = p . populateStaticNodesToContract ( permInterfSession )
if err != nil {
return err
}
2019-03-27 04:07:01 -07:00
log . Info ( "AJ-permInter init node population done" )
2019-03-26 08:20:06 -07:00
// populate initial account access to full access
err = p . populateInitAccountAccess ( permInterfSession )
2018-11-02 03:42:14 -07:00
if err != nil {
2018-11-16 02:08:49 -08:00
return err
2018-11-02 03:42:14 -07:00
}
2019-03-27 04:07:01 -07:00
log . Info ( "AJ-permInter init account population done" )
2019-03-26 08:20:06 -07:00
if err == nil && len ( p . permConfig . Accounts ) == 0 {
//utils.Fatalf("Permissioned network being brought up with zero accounts having full access. Add permissioned full access accounts in genesis.json and bring up the network")
}
2018-11-02 03:42:14 -07:00
// update network status to boot completed
2019-03-26 08:20:06 -07:00
err = p . updateNetworkStatus ( permInterfSession )
2018-11-02 03:42:14 -07:00
if err != nil {
2019-03-26 08:20:06 -07:00
log . Info ( "AJ-failed to updated network boot status" )
2018-11-02 03:42:14 -07:00
return err
}
2019-03-26 08:20:06 -07:00
log . Info ( "AJ-network boot completed" )
} else {
log . Info ( "AJ-network already booted" )
}
2019-02-06 20:45:29 -08:00
2019-03-27 04:07:01 -07:00
//populate orgs, nodes, roles and accounts from contract
//populate orgs
permOrgSession := & pbind . OrgManagerSession {
Contract : p . permOrg ,
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
GasLimit : 47000000 ,
GasPrice : big . NewInt ( 0 ) ,
} ,
}
permOrgSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permOrgSession . TransactOpts . From ) )
if numberOfOrgs , err := permOrgSession . GetNumberOfOrgs ( ) ; err != nil {
log . Error ( "AJ-reading org num failed" )
} else {
log . Info ( "AJ-org num " , "num" , numberOfOrgs . Int64 ( ) )
iOrgNum := numberOfOrgs . Uint64 ( )
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
permOrgSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permOrgSession . TransactOpts . From ) )
if o , s , err := permOrgSession . GetOrgInfo ( big . NewInt ( int64 ( k ) ) ) ; err != nil {
log . Error ( "AJ-Org reading org info failed" )
} else {
types . OrgInfoMap . UpsertOrg ( o , int ( s . Int64 ( ) ) )
}
}
}
//populate nodes
permNodeSession := & pbind . NodeManagerSession {
Contract : p . permNode ,
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
GasLimit : 47000000 ,
GasPrice : big . NewInt ( 0 ) ,
} ,
}
permNodeSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permNodeSession . TransactOpts . From ) )
if numberOfNodes , err := permNodeSession . GetNumberOfNodes ( ) ; err != nil {
log . Error ( "AJ-reading node num failed" )
} else {
log . Info ( "AJ-node num " , "num" , numberOfNodes . Int64 ( ) )
iOrgNum := numberOfNodes . Uint64 ( )
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
permNodeSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permNodeSession . TransactOpts . From ) )
if nodeStruct , err := permNodeSession . GetNodeDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err != nil {
log . Error ( "AJ-node reading org info failed" )
} else {
types . NodeInfoMap . UpsertNode ( nodeStruct . OrgId , nodeStruct . EnodeId , int ( nodeStruct . NodeStatus . Int64 ( ) ) )
}
}
}
//populate roles
permRoleSession := & pbind . RoleManagerSession {
Contract : p . permRole ,
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
GasLimit : 47000000 ,
GasPrice : big . NewInt ( 0 ) ,
} ,
}
permRoleSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permRoleSession . TransactOpts . From ) )
if numberOfRoles , err := permRoleSession . GetNumberOfRoles ( ) ; err != nil {
log . Error ( "AJ-reading role num failed" )
} else {
log . Info ( "AJ-role num " , "num" , numberOfRoles . Int64 ( ) )
iOrgNum := numberOfRoles . Uint64 ( )
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
permRoleSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permRoleSession . TransactOpts . From ) )
if roleStruct , err := permRoleSession . GetRoleDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err != nil {
2019-03-27 20:01:33 -07:00
log . Error ( "AJ-role reading org info failed" )
2019-03-27 04:07:01 -07:00
} else {
types . RoleInfoMap . UpsertRole ( roleStruct . OrgId , roleStruct . RoleId , roleStruct . Voter , int ( roleStruct . AccessType . Int64 ( ) ) , roleStruct . Active )
}
}
}
//populate accounts
permAcctSession := & pbind . AcctManagerSession {
Contract : p . permAcct ,
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
GasLimit : 47000000 ,
GasPrice : big . NewInt ( 0 ) ,
} ,
}
permAcctSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permAcctSession . TransactOpts . From ) )
if numberOfRoles , err := permAcctSession . GetNumberOfAccounts ( ) ; err != nil {
log . Error ( "AJ-reading acct num failed" )
} else {
log . Info ( "AJ-acct num " , "num" , numberOfRoles . Int64 ( ) )
iOrgNum := numberOfRoles . Uint64 ( )
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
permAcctSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permAcctSession . TransactOpts . From ) )
if addr , org , role , status , orgAdmin , err := permAcctSession . GetAccountDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err != nil {
log . Error ( "AJ-Org reading org info failed" )
} else {
types . AcctInfoMap . UpsertAccount ( org , role , addr , orgAdmin , int ( status . Int64 ( ) ) )
}
}
}
log . Info ( "AJ-all data loaded" )
types . OrgInfoMap . Show ( )
log . Info ( "============" )
types . NodeInfoMap . Show ( )
log . Info ( "============" )
types . RoleInfoMap . Show ( )
log . Info ( "============" )
types . AcctInfoMap . Show ( )
log . Info ( "============" )
2018-11-02 03:42:14 -07:00
return nil
}
// Reads the node list from static-nodes.json and populates into the contract
2019-03-26 08:20:06 -07:00
func ( p * PermissionCtrl ) populateStaticNodesToContract ( permissionsSession * pbind . PermInterfaceSession ) error {
2018-11-02 03:42:14 -07:00
nodes := p2p . ParsePermissionedNodes ( p . dataDir )
for _ , node := range nodes {
2019-03-08 01:09:24 -08:00
enodeID := node . EnodeID ( )
2018-10-24 03:21:21 -07:00
2019-03-26 08:20:06 -07:00
log . Info ( "AJ-Adding node to permissions contract" , "enodeID" , enodeID )
2018-10-24 03:21:21 -07:00
2018-11-02 03:42:14 -07:00
nonce := p . eth . TxPool ( ) . Nonce ( permissionsSession . TransactOpts . From )
permissionsSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( nonce )
2018-10-24 03:21:21 -07:00
2019-03-26 08:20:06 -07:00
tx , err := permissionsSession . AddAdminNodes ( node . String ( ) )
2018-11-02 03:42:14 -07:00
if err != nil {
log . Warn ( "Failed to propose node" , "err" , err )
return err
}
log . Debug ( "Transaction pending" , "tx hash" , tx . Hash ( ) )
}
return nil
}
2018-10-24 03:21:21 -07:00
2019-02-12 20:31:11 -08:00
// Invokes the initAccounts function of smart contract to set the initial
// set of accounts access to full access
2019-03-26 08:20:06 -07:00
func ( p * PermissionCtrl ) populateInitAccountAccess ( permissionsSession * pbind . PermInterfaceSession ) error {
2019-03-19 00:29:53 -07:00
if ! p . permConfig . IsEmpty ( ) {
log . Info ( "AJ-add initial account list ..." )
for _ , a := range p . permConfig . Accounts {
log . Info ( "AJ-adding account " , "A" , a )
nonce := p . eth . TxPool ( ) . Nonce ( permissionsSession . TransactOpts . From )
permissionsSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( nonce )
2019-03-26 08:20:06 -07:00
_ , er := permissionsSession . AddAdminAccounts ( common . HexToAddress ( a ) )
2019-03-19 00:29:53 -07:00
if er != nil {
utils . Fatalf ( "error adding permission initial account list account: %s, error:%v" , a , er )
}
}
log . Info ( "AJ-add initial account list ...done" )
}
2018-11-02 03:42:14 -07:00
return nil
}
2018-10-24 03:21:21 -07:00
2019-02-12 20:31:11 -08:00
// updates network boot status to true
2019-03-26 08:20:06 -07:00
func ( p * PermissionCtrl ) updateNetworkStatus ( permissionsSession * pbind . PermInterfaceSession ) error {
2018-11-02 03:42:14 -07:00
nonce := p . eth . TxPool ( ) . Nonce ( permissionsSession . TransactOpts . From )
permissionsSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( nonce )
_ , err := permissionsSession . UpdateNetworkBootStatus ( )
if err != nil {
log . Warn ( "Failed to udpate network boot status " , "err" , err )
return err
2018-10-24 03:21:21 -07:00
}
2018-11-02 03:42:14 -07:00
return nil
2018-10-24 03:21:21 -07:00
}