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"
2018-07-12 03:00:19 -07:00
"github.com/ethereum/go-ethereum/accounts/abi/bind"
2019-04-30 03:28:09 -07:00
"github.com/ethereum/go-ethereum/common"
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"
2019-04-30 03:28:09 -07:00
"github.com/ethereum/go-ethereum/p2p/enode"
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"
2019-04-30 03:28:09 -07:00
"io/ioutil"
"math/big"
"os"
"path/filepath"
"sync"
"time"
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
)
2019-03-31 23:33:44 -07:00
// permission config for bootstrapping
type PermissionLocalConfig struct {
UpgrdAddress string
InterfAddress string
ImplAddress string
NodeAddress string
AccountAddress string
RoleAddress string
VoterAddress string
OrgAddress string
NwAdminOrg string
NwAdminRole string
OrgAdminRole string
2019-04-14 21:32:06 -07:00
Accounts [ ] string //initial list of account that need full access
SubOrgBreadth string
SubOrgDepth string
2019-03-31 23:33:44 -07:00
}
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
}
2019-04-01 03:22:41 -07:00
func ( p * PermissionCtrl ) Interface ( ) * pbind . PermInterface {
return p . permInterf
}
2019-03-31 23:33:44 -07:00
// This function takes the local config data where all the information is in string
// converts that to address and populates the global permissions config
func populateConfig ( config PermissionLocalConfig ) types . PermissionConfig {
var permConfig types . PermissionConfig
permConfig . UpgrdAddress = common . HexToAddress ( config . UpgrdAddress )
permConfig . InterfAddress = common . HexToAddress ( config . InterfAddress )
permConfig . ImplAddress = common . HexToAddress ( config . ImplAddress )
permConfig . OrgAddress = common . HexToAddress ( config . OrgAddress )
permConfig . RoleAddress = common . HexToAddress ( config . RoleAddress )
permConfig . NodeAddress = common . HexToAddress ( config . NodeAddress )
permConfig . AccountAddress = common . HexToAddress ( config . AccountAddress )
permConfig . VoterAddress = common . HexToAddress ( config . VoterAddress )
permConfig . NwAdminOrg = config . NwAdminOrg
2019-04-01 20:37:09 -07:00
permConfig . NwAdminRole = config . NwAdminRole
2019-03-31 23:33:44 -07:00
permConfig . OrgAdminRole = config . OrgAdminRole
// populate the account list as passed in config
for _ , val := range config . Accounts {
permConfig . Accounts = append ( permConfig . Accounts , common . HexToAddress ( val ) )
}
2019-04-14 21:32:06 -07:00
permConfig . SubOrgBreadth . SetString ( config . SubOrgBreadth , 10 )
permConfig . SubOrgDepth . SetString ( config . SubOrgDepth , 10 )
2019-03-31 23:33:44 -07:00
return permConfig
}
2019-04-01 02:48:37 -07:00
// this function reads the permissions config file passed and populates the
// config structure accrodingly
2019-03-11 20:18:20 -07:00
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
}
2019-03-31 23:33:44 -07:00
var permlocConfig PermissionLocalConfig
err = json . Unmarshal ( blob , & permlocConfig )
2019-03-11 20:18:20 -07:00
if err != nil {
log . Error ( "error unmarshalling permission-config.json file" , err )
return types . PermissionConfig { } , err
}
2019-03-31 23:33:44 -07:00
permConfig := populateConfig ( permlocConfig )
2019-04-01 02:48:37 -07:00
if len ( permConfig . Accounts ) == 0 {
return types . PermissionConfig { } , errors . New ( "no accounts given in permission-config.json. Network cannot boot up" )
}
2019-03-31 23:33:44 -07:00
2019-04-14 21:32:06 -07:00
if permConfig . SubOrgDepth . Cmp ( big . NewInt ( 0 ) ) == 0 || permConfig . SubOrgBreadth . Cmp ( big . NewInt ( 0 ) ) == 0 {
return types . PermissionConfig { } , errors . New ( "sub org breadth depth not passed in permission-config.json. Network cannot boot up" )
}
2019-03-11 20:18:20 -07:00
return permConfig , nil
2018-10-25 21:33:23 -07:00
}
2019-04-30 03:28:09 -07:00
func waitForSync ( e * eth . Ethereum ) {
for ! types . GetSyncStatus ( ) {
time . Sleep ( 10 * time . Millisecond )
}
for e . Downloader ( ) . Synchronising ( ) {
time . Sleep ( 10 * time . Millisecond )
}
}
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 )
2019-04-30 03:28:09 -07:00
waitForSync ( e )
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-31 23:33:44 -07:00
log . Error ( "permission-config.json is missing contract address" )
return nil , errors . New ( "permission-config.json is missing contract address" )
2019-03-08 01:09:24 -08:00
}
2019-03-31 23:33:44 -07:00
pu , err := pbind . NewPermUpgr ( pconfig . UpgrdAddress , stateReader )
2019-03-26 08:20:06 -07:00
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-31 23:33:44 -07:00
pm , err := pbind . NewPermInterface ( pconfig . InterfAddress , stateReader )
2019-03-22 04:34:15 -07:00
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2019-03-31 23:33:44 -07:00
pmAcct , err := pbind . NewAcctManager ( 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-31 23:33:44 -07:00
pmNode , err := pbind . NewNodeManager ( pconfig . NodeAddress , stateReader )
2019-03-22 04:34:15 -07:00
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2019-03-27 04:07:01 -07:00
2019-03-31 23:33:44 -07:00
pmRole , err := pbind . NewRoleManager ( pconfig . RoleAddress , stateReader )
2019-03-27 04:07:01 -07:00
if err != nil {
log . Error ( "Permissions not enabled for the network" , "err" , err )
return nil , err
}
2019-03-31 23:33:44 -07:00
pmOrg , err := pbind . NewOrgManager ( pconfig . OrgAddress , stateReader )
2019-03-27 04:07:01 -07:00
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
2018-11-02 03:42:14 -07:00
}
2019-03-31 23:33:44 -07:00
// Starts the node permissioning and event monitoring for permissions
// smart contracts
2018-11-02 03:42:14 -07:00
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
}
2019-03-31 23:33:44 -07:00
// monitor org management related events
2019-04-01 02:48:37 -07:00
go p . manageOrgPermissions ( )
2019-03-31 23:33:44 -07:00
// monitor org level node management events
2019-04-01 23:13:23 -07:00
go p . manageNodePermissions ( )
2019-03-31 23:33:44 -07:00
// monitor org level role management events
2019-04-01 23:13:23 -07:00
go p . manageRolePermissions ( )
2019-03-31 23:33:44 -07:00
// monitor org level account management events
2019-04-01 23:13:23 -07:00
go 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 {
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
2019-02-11 17:54:13 -08:00
// set the default access to ReadOnly
types . SetDefaultAccess ( )
2019-04-23 23:40:28 -07:00
types . SetAdminRole ( p . permConfig . NwAdminRole , p . permConfig . OrgAdminRole )
2019-02-11 17:54:13 -08:00
2018-10-25 22:38:56 -07:00
return nil
}
2019-04-01 02:48:37 -07:00
// monitors org management related events happening via
// smart contracts
2019-03-28 03:00:17 -07:00
func ( p * PermissionCtrl ) manageOrgPermissions ( ) {
2019-04-01 02:48:37 -07:00
chPendingApproval := make ( chan * pbind . OrgManagerOrgPendingApproval , 1 )
chOrgApproved := make ( chan * pbind . OrgManagerOrgApproved , 1 )
chOrgSuspended := make ( chan * pbind . OrgManagerOrgSuspended , 1 )
chOrgReactivated := make ( chan * pbind . OrgManagerOrgSuspensionRevoked , 1 )
2019-03-28 03:00:17 -07:00
2019-04-01 02:48:37 -07:00
var evtPendingApproval * pbind . OrgManagerOrgPendingApproval
var evtOrgApproved * pbind . OrgManagerOrgApproved
var evtOrgSuspended * pbind . OrgManagerOrgSuspended
var evtOrgReactivated * pbind . OrgManagerOrgSuspensionRevoked
2019-03-28 03:00:17 -07:00
2019-04-01 02:48:37 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
if _ , err := p . permOrg . OrgManagerFilterer . WatchOrgPendingApproval ( opts , chPendingApproval ) ; err != nil {
log . Info ( "Failed WatchNodePendingApproval: %v" , err )
}
if _ , err := p . permOrg . OrgManagerFilterer . WatchOrgApproved ( opts , chOrgApproved ) ; err != nil {
log . Info ( "Failed WatchNodePendingApproval: %v" , err )
}
if _ , err := p . permOrg . OrgManagerFilterer . WatchOrgSuspended ( opts , chOrgSuspended ) ; err != nil {
log . Info ( "Failed WatchNodePendingApproval: %v" , err )
}
if _ , err := p . permOrg . OrgManagerFilterer . WatchOrgSuspensionRevoked ( opts , chOrgReactivated ) ; err != nil {
log . Info ( "Failed WatchNodePendingApproval: %v" , err )
}
for {
select {
case evtPendingApproval = <- chPendingApproval :
2019-04-09 02:52:06 -07:00
types . OrgInfoMap . UpsertOrg ( evtPendingApproval . OrgId , evtPendingApproval . PorgId , evtPendingApproval . UltParent , evtPendingApproval . Level , types . OrgStatus ( evtPendingApproval . Status . Uint64 ( ) ) )
2019-04-01 02:48:37 -07:00
case evtOrgApproved = <- chOrgApproved :
2019-04-09 02:52:06 -07:00
types . OrgInfoMap . UpsertOrg ( evtOrgApproved . OrgId , evtOrgApproved . PorgId , evtOrgApproved . UltParent , evtOrgApproved . Level , types . OrgApproved )
2019-04-01 02:48:37 -07:00
case evtOrgSuspended = <- chOrgSuspended :
2019-04-09 02:52:06 -07:00
types . OrgInfoMap . UpsertOrg ( evtOrgSuspended . OrgId , evtOrgSuspended . PorgId , evtOrgSuspended . UltParent , evtOrgSuspended . Level , types . OrgSuspended )
2019-04-01 02:48:37 -07:00
case evtOrgReactivated = <- chOrgReactivated :
2019-04-09 02:52:06 -07:00
types . OrgInfoMap . UpsertOrg ( evtOrgReactivated . OrgId , evtOrgReactivated . PorgId , evtOrgReactivated . UltParent , evtOrgReactivated . Level , types . OrgApproved )
2019-04-01 02:48:37 -07:00
}
2019-03-28 03:00:17 -07:00
}
}
2019-04-01 23:13:23 -07:00
// Monitors node management events and updates cache accordingly
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) manageNodePermissions ( ) {
2019-04-01 23:13:23 -07:00
chNodeApproved := make ( chan * pbind . NodeManagerNodeApproved , 1 )
chNodeProposed := make ( chan * pbind . NodeManagerNodeProposed , 1 )
chNodeDeactivated := make ( chan * pbind . NodeManagerNodeDeactivated , 1 )
chNodeActivated := make ( chan * pbind . NodeManagerNodeActivated , 1 )
chNodeBlacklisted := make ( chan * pbind . NodeManagerNodeBlacklisted )
var evtNodeApproved * pbind . NodeManagerNodeApproved
var evtNodeProposed * pbind . NodeManagerNodeProposed
var evtNodeDeactivated * pbind . NodeManagerNodeDeactivated
var evtNodeActivated * pbind . NodeManagerNodeActivated
var evtNodeBlacklisted * pbind . NodeManagerNodeBlacklisted
2018-07-13 18:22:43 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-04-01 23:13:23 -07:00
if _ , err := p . permNode . NodeManagerFilterer . WatchNodeApproved ( opts , chNodeApproved ) ; err != nil {
log . Info ( "Failed WatchNodeApproved" , "error" , err )
2019-03-28 03:00:17 -07:00
}
2019-03-29 02:49:46 -07:00
2019-04-01 23:13:23 -07:00
if _ , err := p . permNode . NodeManagerFilterer . WatchNodeProposed ( opts , chNodeProposed ) ; err != nil {
log . Info ( "Failed WatchNodeProposed" , "error" , err )
2019-03-28 03:00:17 -07:00
}
2018-07-26 00:46:53 -07:00
2019-04-01 23:13:23 -07:00
if _ , err := p . permNode . NodeManagerFilterer . WatchNodeDeactivated ( opts , chNodeDeactivated ) ; err != nil {
log . Info ( "Failed NodeDeactivated" , "error" , err )
2018-08-16 20:20:33 -07:00
}
2019-04-01 23:13:23 -07:00
if _ , err := p . permNode . NodeManagerFilterer . WatchNodeActivated ( opts , chNodeActivated ) ; err != nil {
log . Info ( "Failed WatchNodeActivated" , "error" , err )
2018-08-16 20:20:33 -07:00
}
2018-08-05 22:26:29 -07:00
2019-04-01 23:13:23 -07:00
if _ , err := p . permNode . NodeManagerFilterer . WatchNodeBlacklisted ( opts , chNodeBlacklisted ) ; err != nil {
log . Info ( "Failed NodeBlacklisting" , "error" , err )
2018-11-02 03:42:14 -07:00
}
2018-08-31 04:35:35 -07:00
for {
select {
2019-04-01 23:13:23 -07:00
case evtNodeApproved = <- chNodeApproved :
p . updatePermissionedNodes ( evtNodeApproved . EnodeId , NodeAdd )
types . NodeInfoMap . UpsertNode ( evtNodeApproved . OrgId , evtNodeApproved . EnodeId , types . NodeApproved )
case evtNodeProposed = <- chNodeProposed :
types . NodeInfoMap . UpsertNode ( evtNodeProposed . OrgId , evtNodeProposed . EnodeId , types . NodePendingApproval )
case evtNodeDeactivated = <- chNodeDeactivated :
p . updatePermissionedNodes ( evtNodeDeactivated . EnodeId , NodeDelete )
types . NodeInfoMap . UpsertNode ( evtNodeDeactivated . OrgId , evtNodeDeactivated . EnodeId , types . NodeDeactivated )
case evtNodeActivated = <- chNodeActivated :
p . updatePermissionedNodes ( evtNodeActivated . EnodeId , NodeAdd )
2019-04-26 01:35:51 -07:00
types . NodeInfoMap . UpsertNode ( evtNodeActivated . OrgId , evtNodeActivated . EnodeId , types . NodeApproved )
2019-04-01 23:13:23 -07:00
case evtNodeBlacklisted = <- chNodeBlacklisted :
p . updatePermissionedNodes ( evtNodeBlacklisted . EnodeId , NodeDelete )
p . updateDisallowedNodes ( evtNodeBlacklisted . EnodeId )
types . NodeInfoMap . UpsertNode ( evtNodeBlacklisted . OrgId , evtNodeBlacklisted . EnodeId , types . NodeBlackListed )
2018-08-31 04:35:35 -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
2019-03-28 03:00:17 -07:00
func ( p * PermissionCtrl ) updateDisallowedNodes ( url string ) {
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
}
}
2019-03-28 03:00:17 -07:00
nodelist = append ( nodelist , url )
2018-08-31 04:35:35 -07:00
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
2019-03-28 03:00:17 -07:00
p . disconnectNode ( url )
2018-08-31 04:35:35 -07:00
}
2019-04-01 23:13:23 -07:00
// Monitors account access related events and updates the cache accordingly
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) manageAccountPermissions ( ) {
2019-04-01 23:13:23 -07:00
chAccessModified := make ( chan * pbind . AcctManagerAccountAccessModified )
chAccessRevoked := make ( chan * pbind . AcctManagerAccountAccessRevoked )
2019-04-15 00:09:05 -07:00
chStatusChanged := make ( chan * pbind . AcctManagerAccountStatusChanged )
2019-04-01 23:13:23 -07:00
var evtAccessModified * pbind . AcctManagerAccountAccessModified
var evtAccessRevoked * pbind . AcctManagerAccountAccessRevoked
2019-04-15 00:09:05 -07:00
var evtStatusChanged * pbind . AcctManagerAccountStatusChanged
2019-04-01 23:13:23 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
if _ , err := p . permAcct . AcctManagerFilterer . WatchAccountAccessModified ( opts , chAccessModified ) ; err != nil {
log . Info ( "Failed NewNodeProposed" , "error" , err )
}
if _ , err := p . permAcct . AcctManagerFilterer . WatchAccountAccessRevoked ( opts , chAccessRevoked ) ; err != nil {
log . Info ( "Failed NewNodeProposed" , "error" , err )
}
2019-04-15 00:09:05 -07:00
if _ , err := p . permAcct . AcctManagerFilterer . WatchAccountStatusChanged ( opts , chStatusChanged ) ; err != nil {
log . Info ( "Failed NewNodeProposed" , "error" , err )
}
2019-04-01 23:13:23 -07:00
for {
select {
case evtAccessModified = <- chAccessModified :
types . AcctInfoMap . UpsertAccount ( evtAccessModified . OrgId , evtAccessModified . RoleId , evtAccessModified . Address , evtAccessModified . OrgAdmin , types . AcctStatus ( int ( evtAccessModified . Status . Uint64 ( ) ) ) )
case evtAccessRevoked = <- chAccessRevoked :
types . AcctInfoMap . UpsertAccount ( evtAccessRevoked . OrgId , evtAccessRevoked . RoleId , evtAccessRevoked . Address , evtAccessRevoked . OrgAdmin , types . AcctActive )
2019-04-15 00:09:05 -07:00
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 ( ) ) ) )
2019-04-01 23:13:23 -07:00
}
2019-03-26 08:20:06 -07:00
}
2018-08-12 19:00:35 -07:00
}
2018-10-29 19:41:01 -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
2019-03-31 23:33:44 -07:00
// Thus function checks if the its the initial network boot up status and if no
// populates permissioning model with details from permission-config.json
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.
log . Warn ( "Failed to retrieve network boot status " , "err" , err )
2019-03-27 21:44:47 -07:00
return err
2018-10-25 22:38:56 -07:00
}
2018-11-02 03:42:14 -07:00
2019-03-27 21:44:47 -07:00
if ! networkInitialized {
if err := p . bootupNetwork ( permInterfSession ) ; err != nil {
2018-11-02 03:42:14 -07:00
return err
}
2019-03-26 08:20:06 -07:00
} else {
2019-03-27 21:44:47 -07:00
//populate orgs, nodes, roles and accounts from contract
p . populateOrgsFromContract ( auth )
p . populateNodesFromContract ( auth )
p . populateRolesFromContract ( auth )
p . populateAccountsFromContract ( auth )
2019-03-26 08:20:06 -07:00
}
2019-02-06 20:45:29 -08:00
2019-03-27 21:44:47 -07:00
return nil
}
2019-03-31 23:33:44 -07:00
// initialize the permissions model and populate initial values
2019-03-27 21:44:47 -07:00
func ( p * PermissionCtrl ) bootupNetwork ( permInterfSession * pbind . PermInterfaceSession ) error {
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 {
2019-03-31 23:33:44 -07:00
log . Error ( "bootupNetwork SetPolicy failed" , "err" , err )
2019-03-27 21:44:47 -07:00
return err
}
permInterfSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permInterfSession . TransactOpts . From ) )
2019-04-14 21:32:06 -07:00
if _ , err := permInterfSession . Init ( p . permConfig . OrgAddress , p . permConfig . RoleAddress , p . permConfig . AccountAddress , p . permConfig . VoterAddress , p . permConfig . NodeAddress , & p . permConfig . SubOrgBreadth , & p . permConfig . SubOrgDepth ) ; err != nil {
2019-03-31 23:33:44 -07:00
log . Error ( "bootupNetwork init failed" , "err" , err )
2019-03-27 21:44:47 -07:00
return err
}
2019-04-09 02:52:06 -07:00
types . OrgInfoMap . UpsertOrg ( p . permConfig . NwAdminOrg , "" , "" , big . NewInt ( 1 ) , types . OrgApproved )
2019-04-26 01:35:51 -07:00
types . RoleInfoMap . UpsertRole ( p . permConfig . NwAdminOrg , p . permConfig . NwAdminRole , true , true , types . FullAccess , true )
2019-03-27 21:44:47 -07:00
// populate the initial node list from static-nodes.json
2019-04-01 02:48:37 -07:00
if err := p . populateStaticNodesToContract ( permInterfSession ) ; err != nil {
2019-03-27 21:44:47 -07:00
return err
}
// populate initial account access to full access
2019-04-01 02:48:37 -07:00
if err := p . populateInitAccountAccess ( permInterfSession ) ; err != nil {
2019-03-27 21:44:47 -07:00
return err
}
// update network status to boot completed
2019-04-01 02:48:37 -07:00
if err := p . updateNetworkStatus ( permInterfSession ) ; err != nil {
log . Error ( "failed to updated network boot status" , "error" , err )
2019-03-27 21:44:47 -07:00
return err
}
return nil
}
2019-04-01 23:13:23 -07:00
// populates the account access details from contract into cache
2019-03-27 21:44:47 -07:00
func ( p * PermissionCtrl ) populateAccountsFromContract ( auth * bind . TransactOpts ) {
//populate accounts
permAcctSession := & pbind . AcctManagerSession {
Contract : p . permAcct ,
2019-03-27 04:07:01 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
}
2019-04-01 02:48:37 -07:00
if numberOfRoles , err := permAcctSession . GetNumberOfAccounts ( ) ; err == nil {
2019-03-27 21:44:47 -07:00
iOrgNum := numberOfRoles . Uint64 ( )
2019-03-27 04:07:01 -07:00
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
2019-04-01 02:48:37 -07:00
if addr , org , role , status , orgAdmin , err := permAcctSession . GetAccountDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err == nil {
2019-03-28 21:28:11 -07:00
types . AcctInfoMap . UpsertAccount ( org , role , addr , orgAdmin , types . AcctStatus ( int ( status . Int64 ( ) ) ) )
2019-03-27 04:07:01 -07:00
}
}
}
2019-03-27 21:44:47 -07:00
}
2019-03-27 04:07:01 -07:00
2019-04-01 23:13:23 -07:00
// populates the role details from contract into cache
2019-03-27 21:44:47 -07:00
func ( p * PermissionCtrl ) populateRolesFromContract ( auth * bind . TransactOpts ) {
//populate roles
permRoleSession := & pbind . RoleManagerSession {
Contract : p . permRole ,
2019-03-27 04:07:01 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
}
2019-04-01 02:48:37 -07:00
if numberOfRoles , err := permRoleSession . GetNumberOfRoles ( ) ; err == nil {
2019-03-27 21:44:47 -07:00
iOrgNum := numberOfRoles . Uint64 ( )
2019-03-27 04:07:01 -07:00
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
2019-04-01 02:48:37 -07:00
if roleStruct , err := permRoleSession . GetRoleDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err == nil {
2019-04-26 01:35:51 -07:00
types . RoleInfoMap . UpsertRole ( roleStruct . OrgId , roleStruct . RoleId , roleStruct . Voter , roleStruct . Admin , types . AccessType ( int ( roleStruct . AccessType . Int64 ( ) ) ) , roleStruct . Active )
2019-03-27 04:07:01 -07:00
}
}
}
2019-03-27 21:44:47 -07:00
}
2019-03-27 04:07:01 -07:00
2019-04-01 23:13:23 -07:00
// populates the node details from contract into cache
2019-03-27 21:44:47 -07:00
func ( p * PermissionCtrl ) populateNodesFromContract ( auth * bind . TransactOpts ) {
//populate nodes
permNodeSession := & pbind . NodeManagerSession {
Contract : p . permNode ,
2019-03-27 04:07:01 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
}
2019-04-01 02:48:37 -07:00
if numberOfNodes , err := permNodeSession . GetNumberOfNodes ( ) ; err == nil {
2019-03-27 21:44:47 -07:00
iOrgNum := numberOfNodes . Uint64 ( )
2019-03-27 04:07:01 -07:00
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
2019-03-27 21:44:47 -07:00
permNodeSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( p . eth . TxPool ( ) . Nonce ( permNodeSession . TransactOpts . From ) )
2019-04-01 02:48:37 -07:00
if nodeStruct , err := permNodeSession . GetNodeDetailsFromIndex ( big . NewInt ( int64 ( k ) ) ) ; err == nil {
2019-03-28 21:28:11 -07:00
types . NodeInfoMap . UpsertNode ( nodeStruct . OrgId , nodeStruct . EnodeId , types . NodeStatus ( int ( nodeStruct . NodeStatus . Int64 ( ) ) ) )
2019-03-27 04:07:01 -07:00
}
}
}
2019-03-27 21:44:47 -07:00
}
2019-03-27 04:07:01 -07:00
2019-04-01 23:13:23 -07:00
// populates the org details from contract into cache
2019-03-27 21:44:47 -07:00
func ( p * PermissionCtrl ) populateOrgsFromContract ( auth * bind . TransactOpts ) {
//populate orgs
permOrgSession := & pbind . OrgManagerSession {
Contract : p . permOrg ,
2019-03-27 04:07:01 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
}
2019-04-01 02:48:37 -07:00
if numberOfOrgs , err := permOrgSession . GetNumberOfOrgs ( ) ; err == nil {
2019-03-27 21:44:47 -07:00
iOrgNum := numberOfOrgs . Uint64 ( )
2019-03-27 04:07:01 -07:00
for k := uint64 ( 0 ) ; k < iOrgNum ; k ++ {
2019-04-09 02:52:06 -07:00
if orgId , porgId , ultParent , level , status , err := permOrgSession . GetOrgInfo ( big . NewInt ( int64 ( k ) ) ) ; err == nil {
types . OrgInfoMap . UpsertOrg ( orgId , porgId , ultParent , level , types . OrgStatus ( int ( status . Int64 ( ) ) ) )
2019-03-27 04:07:01 -07:00
}
}
}
2018-11-02 03:42:14 -07:00
}
// 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-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-04-01 02:48:37 -07:00
_ , err := permissionsSession . AddAdminNodes ( node . String ( ) )
2018-11-02 03:42:14 -07:00
if err != nil {
2019-04-01 02:48:37 -07:00
log . Warn ( "Failed to propose node" , "err" , err , "enode" , enodeID )
2018-11-02 03:42:14 -07:00
return err
}
2019-03-27 21:44:47 -07:00
types . NodeInfoMap . UpsertNode ( p . permConfig . NwAdminOrg , node . String ( ) , 2 )
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
// 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-04-01 02:48:37 -07:00
for _ , a := range p . permConfig . Accounts {
nonce := p . eth . TxPool ( ) . Nonce ( permissionsSession . TransactOpts . From )
permissionsSession . TransactOpts . Nonce = new ( big . Int ) . SetUint64 ( nonce )
_ , er := permissionsSession . AddAdminAccounts ( a )
if er != nil {
log . Warn ( "Error adding permission initial account list" , "err" , er , "account" , a )
return er
2019-03-19 00:29:53 -07:00
}
2019-04-01 02:48:37 -07:00
types . AcctInfoMap . UpsertAccount ( p . permConfig . NwAdminOrg , p . permConfig . NwAdminRole , a , true , 2 )
2019-03-19 00:29:53 -07:00
}
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
}
2019-03-28 03:00:17 -07:00
2019-04-01 23:13:23 -07:00
// monitors role management related events and updated cache
2019-03-28 03:00:17 -07:00
func ( p * PermissionCtrl ) manageRolePermissions ( ) {
2019-04-01 23:13:23 -07:00
chRoleCreated := make ( chan * pbind . RoleManagerRoleCreated , 1 )
chRoleRevoked := make ( chan * pbind . RoleManagerRoleRevoked , 1 )
2019-03-28 03:00:17 -07:00
2019-04-01 23:13:23 -07:00
var evtRoleCreated * pbind . RoleManagerRoleCreated
var evtRoleRevoked * pbind . RoleManagerRoleRevoked
2019-03-28 03:00:17 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2019-04-01 23:13:23 -07:00
if _ , err := p . permRole . RoleManagerFilterer . WatchRoleCreated ( opts , chRoleCreated ) ; err != nil {
2019-03-28 03:00:17 -07:00
log . Info ( "Failed WatchRoleCreated: %v" , err )
}
2019-03-28 03:59:30 -07:00
2019-04-01 23:13:23 -07:00
if _ , err := p . permRole . RoleManagerFilterer . WatchRoleRevoked ( opts , chRoleRevoked ) ; err != nil {
2019-03-28 03:59:30 -07:00
log . Info ( "Failed WatchRoleRemoved: %v" , err )
}
2019-04-01 23:13:23 -07:00
2019-03-28 03:59:30 -07:00
for {
select {
2019-04-01 23:13:23 -07:00
case evtRoleCreated = <- chRoleCreated :
2019-04-26 01:35:51 -07:00
types . RoleInfoMap . UpsertRole ( evtRoleCreated . OrgId , evtRoleCreated . RoleId , evtRoleCreated . IsVoter , evtRoleCreated . IsAdmin , types . AccessType ( int ( evtRoleCreated . BaseAccess . Uint64 ( ) ) ) , true )
2019-04-01 23:13:23 -07:00
case evtRoleRevoked = <- chRoleRevoked :
if r := types . RoleInfoMap . GetRole ( evtRoleRevoked . OrgId , evtRoleRevoked . RoleId ) ; r != nil {
2019-04-26 01:35:51 -07:00
types . RoleInfoMap . UpsertRole ( evtRoleRevoked . OrgId , evtRoleRevoked . RoleId , r . IsVoter , r . IsAdmin , r . Access , false )
2019-03-28 21:28:11 -07:00
} else {
2019-04-01 23:13:23 -07:00
log . Error ( "Revoke role - cache is missing role" , "org" , evtRoleRevoked . OrgId , "role" , evtRoleRevoked . RoleId )
2019-03-28 21:28:11 -07:00
}
2019-03-28 03:59:30 -07:00
}
}
2019-03-28 03:00:17 -07:00
}