From aaf0de899dd8442104ffa0674c7dbf085516b94b Mon Sep 17 00:00:00 2001 From: vsmk98 Date: Sat, 14 Jul 2018 01:22:43 +0000 Subject: [PATCH] added function for event monitoring --- cmd/geth/main.go | 2 +- params/quorum.go | 7 ++ permissions/node_permissions.go | 198 ++++++++++++++++++++------------ 3 files changed, 133 insertions(+), 74 deletions(-) create mode 100644 params/quorum.go diff --git a/cmd/geth/main.go b/cmd/geth/main.go index c4287f3f0..1b47b93c0 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -255,7 +255,7 @@ func startNode(ctx *cli.Context, stack *node.Node) { //START - QUORUM Permissioning if permissioned := ctx.GlobalBool(utils.EnableNodePermissionFlag.Name); permissioned { - permissions.PopulateNodes(ctx, stack) + permissions.QuorumPermissioning(ctx, stack) } //END - QUORUM Permissioning diff --git a/params/quorum.go b/params/quorum.go new file mode 100644 index 000000000..dd16eaaee --- /dev/null +++ b/params/quorum.go @@ -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} +) diff --git a/permissions/node_permissions.go b/permissions/node_permissions.go index d35e42fac..8ef13f7b5 100644 --- a/permissions/node_permissions.go +++ b/permissions/node_permissions.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "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/ethclient" "github.com/ethereum/go-ethereum/log" @@ -17,86 +17,138 @@ import ( "github.com/ethereum/go-ethereum/p2p" "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 //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 - if err := stack.Service(&e); err != nil { - utils.Fatalf("Ethereum service not running: %v", err) - } + permissionsContract, err := NewPermissions(params.QuorumPermissionsContract, stateReader) - 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") + 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) + } - datadir := ctx.GlobalString(utils.DataDirFlag.Name) + permissionsSession := &PermissionsSession{ + Contract: permissionsContract, + CallOpts: bind.CallOpts{ + Pending: true, + }, + TransactOpts: bind.TransactOpts{ + From: auth.From, + Signer: auth.Signer, + GasLimit: 3558096384, + GasPrice: big.NewInt(0), + }, + } - 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...") + datadir := ctx.GlobalString(utils.DataDirFlag.Name) - // (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) + nodes := p2p.ParsePermissionedNodes(datadir) + for _, node := range nodes { + enodeID := fmt.Sprintf("%x", node.ID[:]) + log.Trace("Adding node to permissions contract", "enodeID", enodeID) - contractAddr := common.HexToAddress("0x0000000000000000000000000000000000000020") // hard coded in genesis - permissionsContract, err := NewPermissions(contractAddr, stateReader) - if err != nil { - utils.Fatalf("Failed to instantiate a Permissions contract: %v", err) - } - log.Debug("Permissions contract instantiated") - auth, err := bind.NewTransactor(strings.NewReader(key), "") - if err != nil { - utils.Fatalf("Failed to create authorized transactor: %v", err) - } - log.Debug("Transactor created") - permissionsSession := &PermissionsSession{ - Contract: permissionsContract, - CallOpts: bind.CallOpts{ - Pending: true, - }, - TransactOpts: bind.TransactOpts{ - From: auth.From, - Signer: auth.Signer, - GasLimit: 3558096384, - GasPrice: big.NewInt(0), - }, - } + nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From) + permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce) + + tx, err := permissionsSession.ProposeNode(enodeID, true, true) + if err != nil { + log.Warn("Failed to propose node", "err", err) + } + 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]) - nodes := p2p.ParsePermissionedNodes(datadir) - for _, node := range nodes { - enodeID := fmt.Sprintf("%x", node.ID[:]) - log.Trace("Adding node to permissions contract", "enodeID", enodeID) - - nonce := e.TxPool().Nonce(permissionsSession.TransactOpts.From) - permissionsSession.TransactOpts.Nonce = new(big.Int).SetUint64(nonce) - log.Trace("Current Nonce", "nonce", nonce) - - tx, err := permissionsSession.ProposeNode(enodeID, true, true) - if err != nil { - log.Warn("Failed to propose node", "err", err) - } - log.Debug("Transaction pending", "tx hash", tx.Hash()) - } }