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"
2018-11-13 00:15:28 -08:00
"errors"
2018-11-14 02:24:28 -08:00
"fmt"
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"
2019-01-23 21:35:46 -08:00
"strings"
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-09-19 18:51:36 -07:00
"github.com/ethereum/go-ethereum/p2p/discover"
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-07-16 03:34:20 -07:00
const (
PERMISSIONED_CONFIG = "permissioned-nodes.json"
2018-10-29 19:41:01 -07:00
BLACKLIST_CONFIG = "disallowed-nodes.json"
2018-07-16 03:34:20 -07:00
)
2018-07-13 18:22:43 -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
pm * pbind . Permissions
2018-10-25 21:33:23 -07:00
}
2018-10-31 19:55:40 -07:00
// Creates the controls structure for permissions
2018-11-13 00:15:28 -08:00
func NewQuorumPermissionCtrl ( stack * node . Node , permissionedMode , isRaft bool ) ( * 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 {
2018-10-29 19:41:01 -07:00
log . Error ( "Unable to create ethereum client for permissions check : " , "err" , err )
return nil , err
2018-08-12 19:00:35 -07:00
}
2018-10-29 19:41:01 -07:00
// check if permissioning contract is there at address. If not return from here
2018-11-04 19:28:33 -08:00
pm , err := pbind . NewPermissions ( params . QuorumPermissionsContract , stateReader )
2018-11-02 03:42:14 -07:00
if err != nil {
2018-10-29 19:41:01 -07: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
2018-11-13 00:15:28 -08:00
return & PermissionCtrl { stack , stateReader , e , isRaft , permissionedMode , stack . GetNodeKey ( ) , stack . DataDir ( ) , pm } , 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 {
log . Error ( "Permissions init failed : " , "err" , err )
return err
}
2018-10-25 22:38:56 -07:00
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-08-12 19:00:35 -07:00
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
2018-10-25 22:38:56 -07:00
// This functions updates 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
if err := p . populateInitPermission ( ) ; err != nil {
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
2018-11-04 19:28:33 -08:00
// call populates the node details from contract to KnownNodes
2019-01-10 19:38:02 -08:00
// this is not required as the permissioned node info is persisted at
// file level
// if err := p.populatePermissionedNodes(); err != nil {
// return err
// }
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-10-24 03:21:21 -07:00
2018-07-13 18:22:43 -07:00
//monitor for new nodes addition via smart contract
2018-10-29 19:41:01 -07:00
go p . monitorNewNodeAdd ( )
2018-07-26 00:46:53 -07:00
//monitor for nodes deletiin via smart contract
2018-10-29 19:41:01 -07:00
go p . monitorNodeDeactivation ( )
2018-08-31 04:35:35 -07:00
2018-11-07 04:50:49 -08:00
//monitor for nodes activation from deactivation status
2018-11-02 03:42:14 -07:00
go p . monitorNodeActivation ( )
2018-08-31 04:35:35 -07:00
//monitor for nodes blacklisting via smart contract
2018-10-29 19:41:01 -07:00
go p . monitorNodeBlacklisting ( )
2018-07-13 18:22:43 -07:00
}
2018-08-12 19:00:35 -07:00
// This functions 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 ( ) {
2018-10-30 00:59:08 -07:00
ch := make ( chan * pbind . PermissionsNodeApproved , 1 )
2018-07-13 18:22:43 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2018-10-30 00:59:08 -07:00
var nodeAddEvent * pbind . PermissionsNodeApproved
2018-07-13 18:22:43 -07:00
2018-11-04 19:28:33 -08:00
_ , err := p . pm . PermissionsFilterer . WatchNodeApproved ( opts , ch )
2018-08-16 20:20:33 -07:00
if err != nil {
log . Info ( "Failed WatchNodeApproved: %v" , err )
}
for {
2018-08-12 23:55:58 -07:00
select {
case nodeAddEvent = <- ch :
2018-10-29 19:41:01 -07:00
p . updatePermissionedNodes ( nodeAddEvent . EnodeId , nodeAddEvent . IpAddrPort , nodeAddEvent . DiscPort , nodeAddEvent . RaftPort , 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
}
2018-08-12 19:00:35 -07:00
// This functions listens on the channel for new node approval via smart contract and
2018-07-26 00:46:53 -07:00
// adds the same into permissioned-nodes.json
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) monitorNodeDeactivation ( ) {
2018-10-30 00:59:08 -07:00
ch := make ( chan * pbind . PermissionsNodeDeactivated )
2018-07-26 00:46:53 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2018-10-30 00:59:08 -07:00
var newNodeDeleteEvent * pbind . PermissionsNodeDeactivated
2018-11-04 19:28:33 -08:00
_ , err := p . pm . PermissionsFilterer . 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 :
2018-10-29 19:41:01 -07:00
p . updatePermissionedNodes ( newNodeDeleteEvent . EnodeId , newNodeDeleteEvent . IpAddrPort , newNodeDeleteEvent . DiscPort , newNodeDeleteEvent . RaftPort , NodeDelete )
}
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
2018-08-31 04:35:35 -07:00
// This function listnes on the channel for any node blacklisting event via smart contract
// and adds the same disallowed-nodes.json
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) monitorNodeActivation ( ) {
ch := make ( chan * pbind . PermissionsNodeActivated , 1 )
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
var nodeActivatedEvent * pbind . PermissionsNodeActivated
2018-11-04 19:28:33 -08:00
_ , err := p . pm . PermissionsFilterer . 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 :
p . updatePermissionedNodes ( nodeActivatedEvent . EnodeId , nodeActivatedEvent . IpAddrPort , nodeActivatedEvent . DiscPort , nodeActivatedEvent . RaftPort , NodeAdd )
}
2018-08-31 04:35:35 -07:00
}
2018-11-02 03:42:14 -07:00
}
// This functions listens on the channel for node blacklisting via smart contract and
// adds the same into disallowed-nodes.json
func ( p * PermissionCtrl ) monitorNodeBlacklisting ( ) {
ch := make ( chan * pbind . PermissionsNodeBlacklisted )
2018-08-31 04:35:35 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2018-11-02 03:42:14 -07:00
var newNodeBlacklistEvent * pbind . PermissionsNodeBlacklisted
2018-08-31 04:35:35 -07:00
2018-11-04 19:28:33 -08:00
_ , err := p . pm . PermissionsFilterer . 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-01-10 19:38:02 -08:00
p . updatePermissionedNodes ( newNodeBlacklistEvent . EnodeId , newNodeBlacklistEvent . IpAddrPort , newNodeBlacklistEvent . DiscPort , newNodeBlacklistEvent . RaftPort , NodeDelete )
2018-11-02 03:42:14 -07:00
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
2018-07-16 03:34:20 -07:00
//this function populates the new node information into the permissioned-nodes.json file
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) updatePermissionedNodes ( enodeId , ipAddrPort , discPort , raftPort string , operation NodeOperation ) {
2018-11-19 23:43:56 -08:00
log . Debug ( "updatePermissionedNodes" , "DataDir" , p . dataDir , "file" , PERMISSIONED_CONFIG )
2018-07-16 03:34:20 -07:00
2018-11-19 23:43:56 -08:00
path := filepath . Join ( p . dataDir , PERMISSIONED_CONFIG )
if _ , err := os . Stat ( path ) ; err != nil {
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 )
return
}
// 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 )
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
newEnodeId := p . formatEnodeId ( enodeId , ipAddrPort , discPort , raftPort )
// logic to update the permissioned-nodes.json file based on action
2019-01-23 21:35:46 -08:00
index := 0
recExists := false
for i , enodeId := range nodelist {
if strings . EqualFold ( enodeId , newEnodeId ) {
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 {
nodelist = append ( nodelist , newEnodeId )
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 : ] ... )
}
2018-11-20 05:29:03 -08:00
p . disconnectNode ( newEnodeId )
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 ( )
if err := ioutil . WriteFile ( path , blob , 0644 ) ; err != nil {
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-01-10 19:38:02 -08:00
//this function populates the black listed node information into the permissioned-nodes.json file
2018-10-30 00:59:08 -07:00
func ( p * PermissionCtrl ) updateDisallowedNodes ( nodeBlacklistEvent * pbind . PermissionsNodeBlacklisted ) {
2018-11-02 03:42:14 -07:00
log . Debug ( "updateDisallowedNodes" , "DataDir" , p . dataDir , "file" , BLACKLIST_CONFIG )
2018-08-31 04:35:35 -07:00
2018-09-02 23:59:45 -07:00
fileExisted := true
2018-11-02 03:42:14 -07:00
path := filepath . Join ( p . dataDir , 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 {
2018-10-29 19:41:01 -07: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 {
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 ( ) {
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
2018-10-25 22:38:56 -07: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 { }
2018-11-04 19:28:33 -08:00
pastAddEvent , err := p . pm . PermissionsFilterer . 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 {
p . updatePermissionedNodes ( pastAddEvent . Event . EnodeId , pastAddEvent . Event . IpAddrPort , pastAddEvent . Event . DiscPort , pastAddEvent . Event . RaftPort , NodeAdd )
}
2018-10-25 22:38:56 -07:00
}
}
opts = & bind . FilterOpts { }
2018-11-04 19:28:33 -08:00
pastDelEvent , err := p . pm . PermissionsFilterer . 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 {
p . updatePermissionedNodes ( pastDelEvent . Event . EnodeId , pastDelEvent . Event . IpAddrPort , pastDelEvent . Event . DiscPort , pastDelEvent . Event . RaftPort , NodeDelete )
}
2018-10-25 22:38:56 -07:00
}
}
return nil
}
2018-08-12 19:00:35 -07: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 ) populateAcctPermissions ( ) error {
2018-08-12 19:00:35 -07:00
opts := & bind . FilterOpts { }
2018-11-04 19:28:33 -08:00
pastEvents , err := p . pm . PermissionsFilterer . 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 {
types . AddAccountAccess ( pastEvents . Event . Address , pastEvents . Event . Access )
}
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
}
// Monitors permissions changes at acount level and uodate the global permissions
// map with the same
2018-10-29 19:41:01 -07:00
func ( p * PermissionCtrl ) monitorAccountPermissions ( ) {
2018-10-30 00:59:08 -07:00
ch := make ( chan * pbind . PermissionsAccountAccessModified )
2018-08-12 19:00:35 -07:00
opts := & bind . WatchOpts { }
var blockNumber uint64 = 1
opts . Start = & blockNumber
2018-10-30 00:59:08 -07:00
var newEvent * pbind . PermissionsAccountAccessModified
2018-08-12 19:00:35 -07:00
2018-11-04 19:28:33 -08:00
_ , err := p . pm . PermissionsFilterer . WatchAccountAccessModified ( opts , ch )
2018-08-16 20:20:33 -07:00
if err != nil {
log . Info ( "Failed NewNodeProposed: %v" , err )
}
2018-08-12 19:00:35 -07:00
for {
2018-08-16 20:20:33 -07:00
select {
case newEvent = <- ch :
2018-09-05 19:40:21 -07:00
types . AddAccountAccess ( newEvent . Address , newEvent . Access )
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 {
node , err := discover . ParseNode ( enodeId )
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 {
2018-09-19 22:55:57 -07: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
2018-10-24 03:21:21 -07:00
//populates the nodes list from permissioned-nodes.json into the permissions
//smart contract
2018-11-02 03:42:14 -07:00
func ( p * PermissionCtrl ) populateInitPermission ( ) error {
2018-10-30 23:42:29 -07:00
auth := bind . NewKeyedTransactor ( p . key )
2018-10-30 00:59:08 -07:00
permissionsSession := & pbind . PermissionsSession {
2018-11-04 19:28:33 -08:00
Contract : p . pm ,
2018-10-24 03:21:21 -07:00
CallOpts : bind . CallOpts {
Pending : true ,
} ,
TransactOpts : bind . TransactOpts {
From : auth . From ,
Signer : auth . Signer ,
2018-10-25 22:38:56 -07:00
GasLimit : 4700000 ,
2018-10-24 03:21:21 -07:00
GasPrice : big . NewInt ( 0 ) ,
} ,
}
2018-10-25 22:38:56 -07:00
tx , err := permissionsSession . GetNetworkBootStatus ( )
if err != nil {
2019-01-21 00:18:59 -08:00
// handle the scenario of no contract code.
if err . Error ( ) == "no contract code at given address" {
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
2018-11-13 00:15:28 -08:00
if tx && ! p . permissionedMode {
// Network is initialized with permissions and node is joining in a non-permissioned
// option. stop the node from coming up
2018-11-20 06:51:49 -08:00
utils . Fatalf ( "Joining a permissioned network in non-permissioned mode. Bring up geth with --permissioned." )
2018-11-13 00:15:28 -08:00
}
2018-11-14 02:24:28 -08:00
if ! p . permissionedMode {
2018-11-13 00:15:28 -08:00
return errors . New ( "Node started in non-permissioned mode" )
}
2018-10-25 22:38:56 -07:00
if tx != true {
2018-11-04 19:28:33 -08:00
// populate initial account access to full access
err = p . populateInitAccountAccess ( permissionsSession )
2018-11-02 03:42:14 -07:00
if err != nil {
return err
}
2018-10-25 22:38:56 -07:00
2018-11-07 04:50:49 -08:00
// populate the initial node list from static-nodes.json
2018-11-04 19:28:33 -08:00
err := p . populateStaticNodesToContract ( permissionsSession )
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
}
// update network status to boot completed
err = p . updateNetworkStatus ( permissionsSession )
if err != nil {
return err
}
}
return nil
}
// Reads the node list from static-nodes.json and populates into the contract
2018-11-07 04:50:49 -08:00
func ( p * PermissionCtrl ) populateStaticNodesToContract ( permissionsSession * pbind . PermissionsSession ) error {
2018-11-02 03:42:14 -07:00
nodes := p2p . ParsePermissionedNodes ( p . dataDir )
for _ , node := range nodes {
enodeID := node . ID . String ( )
ipAddr := node . IP . String ( )
port := fmt . Sprintf ( "%v" , node . TCP )
discPort := fmt . Sprintf ( "%v" , node . UDP )
raftPort := fmt . Sprintf ( "%v" , node . RaftPort )
ipAddrPort := ipAddr + ":" + port
2018-10-24 03:21:21 -07:00
2018-11-02 03:42:14 -07:00
log . Trace ( "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
2018-11-02 03:42:14 -07:00
tx , err := permissionsSession . ProposeNode ( enodeID , ipAddrPort , discPort , raftPort )
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
2018-11-02 03:42:14 -07:00
// Reads the acount from geth keystore and grants full access to these accounts
func ( p * PermissionCtrl ) populateInitAccountAccess ( permissionsSession * pbind . PermissionsSession ) error {
2018-11-16 02:08:49 -08:00
_ , err := permissionsSession . InitAccounts ( )
if err != nil {
log . Error ( "calling init accounts failed" , "err" , err )
return err
2018-11-02 03:42:14 -07:00
}
return nil
}
2018-10-24 03:21:21 -07:00
2018-11-02 03:42:14 -07:00
// update network boot status to true
2018-11-07 04:50:49 -08:00
func ( p * PermissionCtrl ) updateNetworkStatus ( permissionsSession * pbind . PermissionsSession ) 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
}