mirror of https://github.com/poanetwork/quorum.git
added function for event monitoring
This commit is contained in:
parent
1f4abe1ed4
commit
aaf0de899d
|
@ -255,7 +255,7 @@ func startNode(ctx *cli.Context, stack *node.Node) {
|
||||||
|
|
||||||
//START - QUORUM Permissioning
|
//START - QUORUM Permissioning
|
||||||
if permissioned := ctx.GlobalBool(utils.EnableNodePermissionFlag.Name); permissioned {
|
if permissioned := ctx.GlobalBool(utils.EnableNodePermissionFlag.Name); permissioned {
|
||||||
permissions.PopulateNodes(ctx, stack)
|
permissions.QuorumPermissioning(ctx, stack)
|
||||||
}
|
}
|
||||||
//END - QUORUM Permissioning
|
//END - QUORUM Permissioning
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package params
|
||||||
|
|
||||||
|
import "github.com/ethereum/go-ethereum/common"
|
||||||
|
|
||||||
|
var (
|
||||||
|
QuorumPermissionsContract = common.Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32}
|
||||||
|
)
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"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"
|
||||||
|
@ -17,60 +17,38 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//This function first adds the node list from permissioned-nodes.json to
|
||||||
|
//the permissiones contract deployed as a precompile via genesis.json
|
||||||
|
func QuorumPermissioning(ctx *cli.Context, stack *node.Node ){
|
||||||
|
|
||||||
|
//Create a new ethclient to for interfacing with the contract
|
||||||
|
e, stateReader := createEthClient(stack)
|
||||||
|
|
||||||
|
//call populate nodes to populate the nodes into contract
|
||||||
|
populateNodesToContract (ctx, stack, e, stateReader)
|
||||||
|
|
||||||
|
//monitor for new nodes addition via smart contract
|
||||||
|
go monitorNewNodeAdd(stateReader)
|
||||||
|
}
|
||||||
|
|
||||||
//populates the nodes list from permissioned-nodes.json into the permissions
|
//populates the nodes list from permissioned-nodes.json into the permissions
|
||||||
//smart contract
|
//smart contract
|
||||||
func PopulateNodes(ctx *cli.Context, stack *node.Node ){
|
func populateNodesToContract(ctx *cli.Context, stack *node.Node, e *eth.Ethereum, stateReader *ethclient.Client){
|
||||||
|
|
||||||
log.Trace("Quorum permissioning v2 started")
|
//Read the key file from key store. SHOULD WE MAKE IT CONFIG value
|
||||||
|
key := getKeyFromKeyStore(ctx)
|
||||||
|
|
||||||
var e *eth.Ethereum
|
permissionsContract, err := NewPermissions(params.QuorumPermissionsContract, stateReader)
|
||||||
if err := stack.Service(&e); err != nil {
|
|
||||||
utils.Fatalf("Ethereum service not running: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcClient, err := stack.Attach()
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Failed to attach to self: %v", err)
|
|
||||||
}
|
|
||||||
stateReader := ethclient.NewClient(rpcClient)
|
|
||||||
log.Trace("rpc connection to permissions contract established")
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
log.Trace("reading account keys...")
|
|
||||||
|
|
||||||
// (zekun) 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)
|
|
||||||
}
|
|
||||||
log.Debug("Finished reading key file", "keyPath", keyPath, "keyBlob", keyBlob)
|
|
||||||
// n := bytes.IndexByte(keyBlob, 0)
|
|
||||||
n := len(keyBlob)
|
|
||||||
log.Debug("Decoding keyBlob", "length", n)
|
|
||||||
key := string(keyBlob[:n])
|
|
||||||
log.Debug("Decoded key", "key", key)
|
|
||||||
|
|
||||||
contractAddr := common.HexToAddress("0x0000000000000000000000000000000000000020") // hard coded in genesis
|
|
||||||
permissionsContract, err := NewPermissions(contractAddr, stateReader)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to instantiate a Permissions contract: %v", err)
|
utils.Fatalf("Failed to instantiate a Permissions contract: %v", err)
|
||||||
}
|
}
|
||||||
log.Debug("Permissions contract instantiated")
|
|
||||||
auth, err := bind.NewTransactor(strings.NewReader(key), "")
|
auth, err := bind.NewTransactor(strings.NewReader(key), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to create authorized transactor: %v", err)
|
utils.Fatalf("Failed to create authorized transactor: %v", err)
|
||||||
}
|
}
|
||||||
log.Debug("Transactor created")
|
|
||||||
permissionsSession := &PermissionsSession{
|
permissionsSession := &PermissionsSession{
|
||||||
Contract: permissionsContract,
|
Contract: permissionsContract,
|
||||||
CallOpts: bind.CallOpts{
|
CallOpts: bind.CallOpts{
|
||||||
|
@ -84,6 +62,8 @@ func PopulateNodes(ctx *cli.Context, stack *node.Node ){
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
datadir := ctx.GlobalString(utils.DataDirFlag.Name)
|
||||||
|
|
||||||
nodes := p2p.ParsePermissionedNodes(datadir)
|
nodes := p2p.ParsePermissionedNodes(datadir)
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
enodeID := fmt.Sprintf("%x", node.ID[:])
|
enodeID := fmt.Sprintf("%x", node.ID[:])
|
||||||
|
@ -91,7 +71,6 @@ func PopulateNodes(ctx *cli.Context, stack *node.Node ){
|
||||||
|
|
||||||
nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From)
|
nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From)
|
||||||
permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce)
|
permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce)
|
||||||
log.Trace("Current Nonce", "nonce", nonce)
|
|
||||||
|
|
||||||
tx, err := permissionsSession.ProposeNode(enodeID, true, true)
|
tx, err := permissionsSession.ProposeNode(enodeID, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -100,3 +79,76 @@ func PopulateNodes(ctx *cli.Context, stack *node.Node ){
|
||||||
log.Debug("Transaction pending", "tx hash", tx.Hash())
|
log.Debug("Transaction pending", "tx hash", tx.Hash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This functions listens on the channel for new node approval via smart contract and
|
||||||
|
// adds the same into permissioned-nodes.json
|
||||||
|
func monitorNewNodeAdd(stateReader *ethclient.Client){
|
||||||
|
|
||||||
|
permissions, err := NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to instantiate a Permissions Filterer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan *PermissionsNewNodeProposed)
|
||||||
|
|
||||||
|
opts := &bind.WatchOpts{}
|
||||||
|
var blockNumber uint64 = 1
|
||||||
|
opts.Start = &blockNumber
|
||||||
|
|
||||||
|
log.Info("Inside the new func added")
|
||||||
|
|
||||||
|
for {
|
||||||
|
log.Info("Inside the new loop - addNewNode")
|
||||||
|
|
||||||
|
_, err = permissions.WatchNewNodeProposed(opts, ch)
|
||||||
|
if err != nil {
|
||||||
|
log.Info("Failed NewNodeProposed: %v", err)
|
||||||
|
}
|
||||||
|
// newEvent = <-ch
|
||||||
|
var newEvent *PermissionsNewNodeProposed = <-ch
|
||||||
|
log.Info("Found Node add event", "enodeId", newEvent.EnodeId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create an RPC client for the contract interface
|
||||||
|
func createEthClient(stack *node.Node ) (*eth.Ethereum, *ethclient.Client){
|
||||||
|
var e *eth.Ethereum
|
||||||
|
if err := stack.Service(&e); err != nil {
|
||||||
|
utils.Fatalf("Ethereum service not running: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcClient, err := stack.Attach()
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to attach to self: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, ethclient.NewClient(rpcClient)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// (zekun) 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])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue