mirror of https://github.com/poanetwork/quorum.git
Code changes for populating the initial node list from static-nodes.json
This commit is contained in:
parent
4dc1f3376b
commit
5187dd9430
|
@ -7,15 +7,15 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
)
|
)
|
||||||
// Create an RPC client for the contract interface
|
// Create an RPC client for the contract interface
|
||||||
func CreateEthClient(stack *node.Node ) (*ethclient.Client, error){
|
func CreateEthClient(stack *node.Node ) (*ethclient.Client, *eth.Ethereum, error){
|
||||||
var e *eth.Ethereum
|
var e *eth.Ethereum
|
||||||
if err := stack.Service(&e); err != nil {
|
if err := stack.Service(&e); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcClient, err := stack.Attach()
|
rpcClient, err := stack.Attach()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return ethclient.NewClient(rpcClient), nil
|
return ethclient.NewClient(rpcClient), e, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
// the permissiones contract deployed as a precompile via genesis.json
|
// the permissiones contract deployed as a precompile via genesis.json
|
||||||
func ManageOrgKeys(ctx *cli.Context, stack *node.Node ) error {
|
func ManageOrgKeys(ctx *cli.Context, stack *node.Node ) error {
|
||||||
// Create a new ethclient to for interfacing with the contract
|
// Create a new ethclient to for interfacing with the contract
|
||||||
stateReader, err := controls.CreateEthClient(stack)
|
stateReader, _, err := controls.CreateEthClient(stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error ("Unable to create ethereum client for cluster check : ", "err" , err)
|
log.Error ("Unable to create ethereum client for cluster check : ", "err" , err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -30,6 +30,9 @@ contract Permissions {
|
||||||
// valid vote count
|
// valid vote count
|
||||||
mapping (uint => uint) private voteCount;
|
mapping (uint => uint) private voteCount;
|
||||||
|
|
||||||
|
// checks if firts time network boot up has happened or not
|
||||||
|
bool networkBoot = false;
|
||||||
|
|
||||||
// node permission events for new node propose
|
// node permission events for new node propose
|
||||||
event NodeProposed(string _enodeId);
|
event NodeProposed(string _enodeId);
|
||||||
event NodeApproved(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
event NodeApproved(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
||||||
|
@ -130,22 +133,34 @@ contract Permissions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// state change functions
|
// state change functions
|
||||||
|
// update the networ boot status as true
|
||||||
|
function updateNetworkBootStatus() external {
|
||||||
|
require (networkBoot == false, "Invalid call: Network boot up completed");
|
||||||
|
networkBoot = true;
|
||||||
|
}
|
||||||
|
|
||||||
// propose a new node to the network
|
// propose a new node to the network
|
||||||
function proposeNode(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort) external enodeNotInList(_enodeId)
|
function proposeNode(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort) external enodeNotInList(_enodeId)
|
||||||
{
|
{
|
||||||
if (checkVotingAccountExist()){
|
if (!(networkBoot)){
|
||||||
// increment node number, add node to the list
|
|
||||||
numberOfNodes++;
|
numberOfNodes++;
|
||||||
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
||||||
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.PendingApproval));
|
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.Approved));
|
||||||
// add voting status, numberOfNodes is the index of current proposed node
|
}
|
||||||
for (uint i = 0; i < accountList.length; i++){
|
else {
|
||||||
voteStatus[numberOfNodes][accountList[i]] = false;
|
if (checkVotingAccountExist()){
|
||||||
|
// increment node number, add node to the list
|
||||||
|
numberOfNodes++;
|
||||||
|
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
||||||
|
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.PendingApproval));
|
||||||
|
// add voting status, numberOfNodes is the index of current proposed node
|
||||||
|
for (uint i = 0; i < accountList.length; i++){
|
||||||
|
voteStatus[numberOfNodes][accountList[i]] = false;
|
||||||
|
}
|
||||||
|
voteCount[numberOfNodes] = 0;
|
||||||
|
// emit event
|
||||||
|
emit NodeProposed(_enodeId);
|
||||||
}
|
}
|
||||||
voteCount[numberOfNodes] = 0;
|
|
||||||
// emit event
|
|
||||||
emit NodeProposed(_enodeId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,18 +1,23 @@
|
||||||
package permissions
|
package permissions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/controls"
|
"github.com/ethereum/go-ethereum/controls"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
|
@ -36,7 +41,7 @@ const (
|
||||||
// the permissiones contract deployed as a precompile via genesis.json
|
// the permissiones contract deployed as a precompile via genesis.json
|
||||||
func QuorumPermissioning(ctx *cli.Context, stack *node.Node ) error {
|
func QuorumPermissioning(ctx *cli.Context, stack *node.Node ) error {
|
||||||
// Create a new ethclient to for interfacing with the contract
|
// Create a new ethclient to for interfacing with the contract
|
||||||
stateReader, err := controls.CreateEthClient(stack)
|
stateReader, e, err := controls.CreateEthClient(stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error ("Unable to create ethereum client for permissions check : ", "err" , err)
|
log.Error ("Unable to create ethereum client for permissions check : ", "err" , err)
|
||||||
return err
|
return err
|
||||||
|
@ -52,7 +57,7 @@ func QuorumPermissioning(ctx *cli.Context, stack *node.Node ) error {
|
||||||
consensusEngine = RAFT
|
consensusEngine = RAFT
|
||||||
}
|
}
|
||||||
// Monitors node addition and decativation from network
|
// Monitors node addition and decativation from network
|
||||||
manageNodePermissions(stack, stateReader, consensusEngine);
|
manageNodePermissions(ctx, stack, e, stateReader, consensusEngine);
|
||||||
|
|
||||||
// Monitors account level persmissions update from smart contarct
|
// Monitors account level persmissions update from smart contarct
|
||||||
manageAccountPermissions(stack, stateReader);
|
manageAccountPermissions(stack, stateReader);
|
||||||
|
@ -62,7 +67,11 @@ func QuorumPermissioning(ctx *cli.Context, stack *node.Node ) error {
|
||||||
|
|
||||||
|
|
||||||
// Manages node addition and decavtivation from network
|
// Manages node addition and decavtivation from network
|
||||||
func manageNodePermissions(stack *node.Node, stateReader *ethclient.Client, consensusEngine string) {
|
func manageNodePermissions(ctx *cli.Context, stack *node.Node, e *eth.Ethereum, stateReader *ethclient.Client, consensusEngine string) {
|
||||||
|
// populate the initial list of nodes into the smart contract
|
||||||
|
// from permissioned-nodes.json
|
||||||
|
populateNodesToContract(ctx, stack, e, stateReader)
|
||||||
|
|
||||||
//monitor for new nodes addition via smart contract
|
//monitor for new nodes addition via smart contract
|
||||||
go monitorNewNodeAdd(stack, stateReader, consensusEngine)
|
go monitorNewNodeAdd(stack, stateReader, consensusEngine)
|
||||||
|
|
||||||
|
@ -347,3 +356,95 @@ func formatEnodeId( enodeId , ipAddrPort, discPort, raftPort, consensusEngine st
|
||||||
}
|
}
|
||||||
return newEnodeId
|
return newEnodeId
|
||||||
}
|
}
|
||||||
|
//populates the nodes list from permissioned-nodes.json into the permissions
|
||||||
|
//smart contract
|
||||||
|
func populateNodesToContract(ctx *cli.Context, stack *node.Node, e *eth.Ethereum, stateReader *ethclient.Client){
|
||||||
|
|
||||||
|
log.Info("SMK - inside populateNodesToContract @363")
|
||||||
|
//Read the key file from key store. SHOULD WE MAKE IT CONFIG value
|
||||||
|
key := getKeyFromKeyStore(ctx)
|
||||||
|
|
||||||
|
permissionsContract, err := NewPermissions(params.QuorumPermissionsContract, stateReader)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to instantiate a Permissions contract: %v", err)
|
||||||
|
}
|
||||||
|
auth, err := bind.NewTransactor(strings.NewReader(key), "")
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to create authorized transactor: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
permissionsSession := &PermissionsSession{
|
||||||
|
Contract: permissionsContract,
|
||||||
|
CallOpts: bind.CallOpts{
|
||||||
|
Pending: true,
|
||||||
|
},
|
||||||
|
TransactOpts: bind.TransactOpts{
|
||||||
|
From: auth.From,
|
||||||
|
Signer: auth.Signer,
|
||||||
|
GasLimit: 3558096384,
|
||||||
|
GasPrice: big.NewInt(0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
datadir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||||
|
|
||||||
|
nodes := p2p.ParsePermissionedNodes(datadir)
|
||||||
|
for _, node := range nodes {
|
||||||
|
enodeID := fmt.Sprintf("%x", node.ID[:])
|
||||||
|
ipAddr := fmt.Sprintf("%v", node.IP)
|
||||||
|
port := fmt.Sprintf("%v", node.TCP)
|
||||||
|
discPort := fmt.Sprintf("%v", node.UDP)
|
||||||
|
raftPort := fmt.Sprintf("%v", node.RaftPort)
|
||||||
|
|
||||||
|
ipAddrPort := ipAddr + ":" + port
|
||||||
|
|
||||||
|
log.Info("SMK-values are : ", "enodeId", enodeID, "ipAddrPort", ipAddrPort, "discPort", discPort, "raftPort", raftPort)
|
||||||
|
|
||||||
|
log.Trace("Adding node to permissions contract", "enodeID", enodeID)
|
||||||
|
|
||||||
|
nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From)
|
||||||
|
permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce)
|
||||||
|
|
||||||
|
tx, err := permissionsSession.ProposeNode(enodeID, ipAddrPort, discPort, raftPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to propose node", "err", err)
|
||||||
|
}
|
||||||
|
log.Debug("Transaction pending", "tx hash", tx.Hash())
|
||||||
|
}
|
||||||
|
// update the network boot status to true
|
||||||
|
nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From)
|
||||||
|
permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce)
|
||||||
|
|
||||||
|
tx, err := permissionsSession.UpdateNetworkBootStatus()
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Failed to udpate network boot status ", "err", err)
|
||||||
|
}
|
||||||
|
log.Debug("Transaction pending", "tx hash", tx.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
//This functions reads the first file in key store directory, reads the key
|
||||||
|
//value and returns the same
|
||||||
|
func getKeyFromKeyStore(ctx *cli.Context) string {
|
||||||
|
datadir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||||
|
|
||||||
|
files, err := ioutil.ReadDir(filepath.Join(datadir, "keystore"))
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to read keystore directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: here we always use the first key as transactor
|
||||||
|
var keyPath string
|
||||||
|
for _, f := range files {
|
||||||
|
keyPath = filepath.Join(datadir, "keystore", f.Name())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
keyBlob, err := ioutil.ReadFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to read key file: %v", err)
|
||||||
|
}
|
||||||
|
// n := bytes.IndexByte(keyBlob, 0)
|
||||||
|
n := len(keyBlob)
|
||||||
|
|
||||||
|
return string(keyBlob[:n])
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue