merge with 1.8.12 version

This commit is contained in:
vsmk98 2018-08-17 03:20:33 +00:00
commit 7e35574def
19 changed files with 1572 additions and 11 deletions

View File

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
)
// SignerFn is a signer function callback when a contract requires a method to
@ -183,6 +184,7 @@ func (c *BoundContract) Transfer(opts *TransactOpts) (*types.Transaction, error)
// transact executes an actual transaction invocation, first deriving any missing
// authorization fields, and then scheduling the transaction for execution.
func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
log.Info("Inside transact")
var err error
// Ensure a valid value field and resolve the account nonce
@ -238,6 +240,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if err != nil {
return nil, err
}
log.Info("calling SendTransaction in side transact")
if err := c.transactor.SendTransaction(ensureContext(opts.Context), signedTx); err != nil {
return nil, err
}

View File

@ -117,6 +117,8 @@ func main() {
}
}
var knownNodes []*discover.Node
if *runv5 {
if _, err := discv5.ListenUDP(nodeKey, conn, realaddr, "", restrictList); err != nil {
utils.Fatalf("%v", err)
@ -127,7 +129,7 @@ func main() {
AnnounceAddr: realaddr,
NetRestrict: restrictList,
}
if _, err := discover.ListenUDP(conn, cfg); err != nil {
if _, err := discover.ListenUDP(conn, cfg, knownNodes); err != nil {
utils.Fatalf("%v", err)
}
}

View File

@ -39,6 +39,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/permissions"
"gopkg.in/urfave/cli.v1"
)
@ -285,6 +286,14 @@ func startNode(ctx *cli.Context, stack *node.Node) {
events := make(chan accounts.WalletEvent, 16)
stack.AccountManager().Subscribe(events)
//START - QUORUM Permissioning
if permissioned := ctx.GlobalBool(utils.EnableNodePermissionFlag.Name); permissioned {
if err := permissions.QuorumPermissioning(ctx, stack); err != nil {
utils.Fatalf("Failed to start Quorum Permissioning: %v", err)
}
}
//END - QUORUM Permissioning
go func() {
// Create a chain state reader for self-derivation
rpcClient, err := stack.Attach()

View File

@ -82,6 +82,9 @@ var (
// ErrEtherValueUnsupported is returned if a transaction specifies an Ether Value
// for a private Quorum transaction.
ErrEtherValueUnsupported = errors.New("ether value is not supported for private transactions")
// ErrUnahorizedAccount is returned if the sender account is not authorized by the
// permissions module
ErrUnAuthorizedAccount = errors.New("Account not authorized for this operation")
)
var (
@ -261,6 +264,17 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
return pool
}
// Nonce returns the nonce for the given addr from the pending state.
// Can only be used for local transactions.
func (pool *TxPool) Nonce(addr common.Address) uint64 {
pool.mu.Lock()
defer pool.mu.Unlock()
if pool.pendingState == nil {
pool.lockedReset(nil, nil)
}
return pool.pendingState.GetNonce(addr)
}
// loop is the transaction pool's main event loop, waiting for and reacting to
// outside blockchain events as well as for various reporting and transaction
// eviction events.
@ -559,6 +573,7 @@ func (pool *TxPool) local() map[common.Address]types.Transactions {
// validateTx checks whether a transaction is valid according to the consensus
// rules and adheres to some heuristic limits of the local node (price and size).
func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
log.Info("Inside validateTx")
isQuorum := pool.chainconfig.IsQuorum
if isQuorum && tx.GasPrice().Cmp(common.Big0) != 0 {
@ -607,6 +622,15 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if tx.Gas() < intrGas {
return ErrIntrinsicGas
}
// Check if the sender account is authorized to perform the transaction
if isQuorum {
log.Info("Inside if before checkAccount")
if err := checkAccount(from, tx.To()); err != nil {
return ErrUnAuthorizedAccount
}
}
return nil
}
@ -619,6 +643,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// whitelisted, preventing any associated transaction from being dropped out of
// the pool due to pricing constraints.
func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
log.Info("Inside add")
// If the transaction is already known, discard it
hash := tx.Hash()
if pool.all.Get(hash) != nil {
@ -772,6 +797,7 @@ func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.T
// the sender as a local one in the mean time, ensuring it goes around the local
// pricing constraints.
func (pool *TxPool) AddLocal(tx *types.Transaction) error {
log.Info("inside AddLocal")
return pool.addTx(tx, !pool.config.NoLocals)
}
@ -798,6 +824,7 @@ func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error {
// addTx enqueues a single transaction into the pool if it is valid.
func (pool *TxPool) addTx(tx *types.Transaction, local bool) error {
log.Info("inside addTx")
pool.mu.Lock()
defer pool.mu.Unlock()
@ -1256,3 +1283,39 @@ func (t *txLookup) Remove(hash common.Hash) {
delete(t.all, hash)
}
// checks if the account is permissioned for transaction
func checkAccount(fromAcct common.Address, toAcct *common.Address) error {
log.Info("Inside checkAccount to validate")
access := types.GetAcctAccess(fromAcct)
switch access {
case types.FullAccess:
log.Info("Full Access so no issue")
return nil
case types.ReadOnly:
log.Info("Read only access cannot transact")
err := errors.New("Account Does not have transaction permissions")
return err
case types.Transact:
if toAcct == nil {
log.Info("Not entitled for contract create call ")
err := errors.New("Account Does not have contract create permissions")
return err
}else {
return nil
}
case types.ContractDeploy:
if toAcct != nil {
log.Info("Not entitled for transaction call ")
err := errors.New("Account Does not have transacte permissions")
return err
}else {
return nil
}
}
log.Info("returning nil")
return nil
}

View File

@ -0,0 +1,52 @@
package types
import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
type AccessType uint8
const (
FullAccess AccessType = iota
ReadOnly
Transact
ContractDeploy
)
type PermStruct struct {
AcctId common.Address
AcctAccess AccessType
}
type PermAccountsMap map[common.Address][] *PermStruct
var AcctMap = make(map[common.Address] *PermStruct)
func AddAccountAccess(acctId common.Address, access uint8) {
log.Info("Inside PutAcctmap adding :", "acctId", acctId, "access", access)
mu := sync.RWMutex{}
mu.Lock()
AcctMap[acctId] = &PermStruct {AcctId : acctId, AcctAccess : AccessType(access)}
mu.Unlock()
}
func GetAcctAccess(acctId common.Address) AccessType {
mu := sync.RWMutex{}
if len(AcctMap) != 0 {
if _, ok := AcctMap[acctId]; ok {
log.Info("Inside GetAcct sending :", "acctId", AcctMap[acctId].AcctId, "access", AcctMap[acctId].AcctAccess)
mu.RLock()
acctAccess := AcctMap[acctId].AcctAccess
mu.RUnlock()
return acctAccess
}
}
return FullAccess
}

View File

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/log"
)
// EthAPIBackend implements ethapi.Backend for full nodes
@ -173,6 +174,7 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri
}
func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
log.Info("inside SendTx")
return b.eth.txPool.AddLocal(signedTx)
}

View File

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/log"
)
// Client defines typed wrappers for the Ethereum RPC API.
@ -483,6 +484,7 @@ func (ec *Client) EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64
// If the transaction was a contract creation use the TransactionReceipt method to get the
// contract address after the transaction has been mined.
func (ec *Client) SendTransaction(ctx context.Context, tx *types.Transaction) error {
log.Info("Inside SendTransaction")
data, err := rlp.EncodeToBytes(tx)
if err != nil {
return err

View File

@ -415,6 +415,7 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
if err != nil {
return common.Hash{}, err
}
log.Info("Calling submitTransaction 1")
return submitTransaction(ctx, s.b, signed, isPrivate)
}
@ -1210,6 +1211,7 @@ func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
}
func (args *SendTxArgs) toTransaction() *types.Transaction {
log.Info("inside toTransaction")
var input []byte
if args.Data != nil {
input = *args.Data
@ -1217,13 +1219,16 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
input = *args.Input
}
if args.To == nil {
log.Info("Contract creation call")
return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
}
log.Info("New transaction callcreation call")
return types.NewTransaction(uint64(*args.Nonce), *args.To, (*big.Int)(args.Value), uint64(*args.Gas), (*big.Int)(args.GasPrice), input)
}
// submitTransaction is a helper function that submits tx to txPool and logs a message.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction, isPrivate bool) (common.Hash, error) {
log.Info("inside submitTransaction")
if isPrivate {
tx.SetPrivate()
}
@ -1304,6 +1309,7 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
if err != nil {
return common.Hash{}, err
}
log.Info("Calling submitTransaction 2")
return submitTransaction(ctx, s.b, signed, isPrivate)
}
@ -1314,6 +1320,7 @@ func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encod
if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
return common.Hash{}, err
}
log.Info("Calling submitTransaction 3")
return submitTransaction(ctx, s.b, tx, tx.IsPrivate())
}
@ -1648,6 +1655,7 @@ func (a *Async) save(ctx context.Context, s *PublicTransactionPoolAPI, args Send
return common.Hash{}, err
}
log.Info("Calling submitTransaction 4")
return submitTransaction(ctx, s.b, signed, args.PrivateFor != nil)
}

View File

@ -227,8 +227,9 @@ type Config struct {
}
// ListenUDP returns a new table that listens for UDP packets on laddr.
func ListenUDP(c conn, cfg Config) (*Table, error) {
tab, _, err := newUDP(c, cfg)
func ListenUDP(c conn, cfg Config, knownNodes []*Node) (*Table, error) {
tab, _, err := newUDP(c, cfg, knownNodes)
if err != nil {
return nil, err
}
@ -236,7 +237,8 @@ func ListenUDP(c conn, cfg Config) (*Table, error) {
return tab, nil
}
func newUDP(c conn, cfg Config) (*Table, *udp, error) {
func newUDP(c conn, cfg Config, knownNodes []*Node) (*Table, *udp, error) {
udp := &udp{
conn: c,
priv: cfg.PrivateKey,
@ -251,10 +253,18 @@ func newUDP(c conn, cfg Config) (*Table, *udp, error) {
}
// TODO: separate TCP port
udp.ourEndpoint = makeEndpoint(realaddr, uint16(realaddr.Port))
tab, err := newTable(udp, PubkeyID(&cfg.PrivateKey.PublicKey), realaddr, cfg.NodeDBPath, cfg.Bootnodes)
if err != nil {
return nil, nil, err
}
// prepopulate nodes database with the known nodes
if nodesLen := len(knownNodes); nodesLen > 0 {
log.Info("Adding predefined nodes to node database", "count", nodesLen)
tab.stuff(knownNodes)
}
udp.Table = tab
go udp.loop()

View File

@ -60,6 +60,7 @@ type udpTest struct {
sent [][]byte
localkey, remotekey *ecdsa.PrivateKey
remoteaddr *net.UDPAddr
knownNodes []*Node
}
func newUDPTest(t *testing.T) *udpTest {
@ -70,7 +71,7 @@ func newUDPTest(t *testing.T) *udpTest {
remotekey: newkey(),
remoteaddr: &net.UDPAddr{IP: net.IP{10, 0, 1, 99}, Port: 30303},
}
test.table, test.udp, _ = newUDP(test.pipe, Config{PrivateKey: test.localkey})
test.table, test.udp, _ = newUDP(test.pipe, Config{PrivateKey: test.localkey}, test.knownNodes)
// Wait for initial refresh so the table doesn't send unexpected findnode.
<-test.table.initDone
return test

View File

@ -16,11 +16,11 @@ const (
)
// check if a given node is permissioned to connect to the change
func isNodePermissioned(nodename string, currentNode string, datadir string, direction string) bool {
func isNodePermissioned(nodename string, currentNode string, datadir string, direction string, knownNodes []*discover.Node) bool {
var permissionedList []string
nodes := parsePermissionedNodes(datadir)
for _, v := range nodes {
for _, v := range knownNodes {
permissionedList = append(permissionedList, v.ID.String())
}
@ -39,7 +39,7 @@ func isNodePermissioned(nodename string, currentNode string, datadir string, dir
//this is a shameless copy from the config.go. It is a duplication of the code
//for the timebeing to allow reload of the permissioned nodes while the server is running
func parsePermissionedNodes(DataDir string) []*discover.Node {
func ParsePermissionedNodes(DataDir string) []*discover.Node {
log.Debug("parsePermissionedNodes", "DataDir", DataDir, "file", PERMISSIONED_CONFIG)

View File

@ -101,6 +101,10 @@ type Config struct {
// allowed to connect, even above the peer limit.
TrustedNodes []*discover.Node
// KnownNodes contains a list of nodes that are used to pre-populate the
// node database.
KnownNodes []*discover.Node
// Connectivity can be restricted to certain IP networks.
// If this option is set to a non-nil value, only hosts which match one of the
// IP networks contained in the list are considered.
@ -449,6 +453,13 @@ func (srv *Server) Start() (err error) {
sconn = &sharedUDPConn{conn, unhandled}
}
knownNodes := append([]*discover.Node(nil), srv.KnownNodes...)
if srv.EnableNodePermission {
knownNodes = append(knownNodes, ParsePermissionedNodes(srv.DataDir)...)
}
srv.KnownNodes = knownNodes
// node table
if !srv.NoDiscovery {
cfg := discover.Config{
@ -459,7 +470,9 @@ func (srv *Server) Start() (err error) {
Bootnodes: srv.BootstrapNodes,
Unhandled: unhandled,
}
ntab, err := discover.ListenUDP(conn, cfg)
log.Info("calling ListenUDP")
ntab, err := discover.ListenUDP(conn, cfg, knownNodes)
log.Info("after ListenUDP")
if err != nil {
return err
}
@ -848,7 +861,7 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *discover.Node) e
log.Trace("Node Permissioning", "Connection Direction", direction)
}
if !isNodePermissioned(node, currentNode, srv.DataDir, direction) {
if !isNodePermissioned(node, currentNode, srv.DataDir, direction, srv.KnownNodes) {
return nil
}
} else {

7
params/quorum.go Normal file
View File

@ -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}
)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,74 @@
pragma solidity ^0.4.23;
contract Permissions {
enum NodeStatus { NotInList, PendingApproval, Approved, PendingDeactivation, Deactivated }
enum AccountAccess {FullAccess, ReadOnly, Transact, ContractDeploy}
struct nodeDetails {
string enodeId;
//e.g. 127.0.0.1:20005
string ipAddrPort;
string discPort;
string raftPort;
bool canWrite;
bool canLead;
NodeStatus status;
}
mapping (bytes32 => nodeDetails) nodeList;
struct acctAccess {
address acctId;
AccountAccess access;
}
mapping (address => acctAccess) acctAccessList;
event NewNodeProposed (string _enodeId);
event NodeApproved(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
event NodePendingDeactivation (string _enodeId);
event NodeDeactivated(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
event AcctAccessModified (address acctId, AccountAccess access);
// Checks if the Node is already added. If yes then returns true
function updateAcctAccess (address _acctId, AccountAccess access) public {
acctAccessList[_acctId] = acctAccess(_acctId, access);
emit AcctAccessModified(_acctId, access);
}
// Checks if the Node is already added. If yes then returns true
function getNodeStatus (string _enodeId) public view returns (NodeStatus _status) {
return nodeList[keccak256(_enodeId)].status;
}
// Adds a node to the nodeList mapping and emits node added event if successfully and node exists event of node is already present
function ApproveNode(string _enodeId) public {
require(getNodeStatus(_enodeId) == NodeStatus.PendingApproval);
bytes32 i;
i = keccak256(_enodeId);
nodeList[i].status = NodeStatus.Approved;
emit NodeApproved(nodeList[i].enodeId, nodeList[i].ipAddrPort, nodeList[i].discPort, nodeList[i].raftPort);
}
function ProposeNode(string _enodeId, bool _canWrite, bool _canLead, string _ipAddrPort, string _discPort, string _raftPort) public {
require(getNodeStatus(_enodeId) == NodeStatus.NotInList, "New node cannot be in the list");
nodeList[keccak256(_enodeId)] = nodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, _canWrite, _canLead, NodeStatus.PendingApproval);
emit NewNodeProposed (_enodeId);
}
function ProposeDeactivation(string _enodeId) public {
require(getNodeStatus(_enodeId) == NodeStatus.Approved, "Node need to be in Approved status");
nodeList[keccak256(_enodeId)].status = NodeStatus.PendingDeactivation;
emit NodePendingDeactivation(_enodeId);
}
//deactivates a given Enode and emits the decativation event
function DeactivateNode (string _enodeId) public {
require(getNodeStatus(_enodeId) == NodeStatus.PendingDeactivation, "Node need to be in PendingDeactivation status");
bytes32 i;
i = keccak256(_enodeId);
nodeList[i].status = NodeStatus.Deactivated;
emit NodeDeactivated(nodeList[i].enodeId, nodeList[i].ipAddrPort, nodeList[i].discPort, nodeList[i].raftPort);
}
}

View File

@ -0,0 +1 @@
[{"constant":true,"inputs":[{"name":"_enodeId","type":"string"}],"name":"getNodeStatus","outputs":[{"name":"_status","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_enodeId","type":"string"}],"name":"ProposeDeactivation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_acctId","type":"address"},{"name":"access","type":"uint8"}],"name":"updateAcctAccess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_enodeId","type":"string"},{"name":"_canWrite","type":"bool"},{"name":"_canLead","type":"bool"}],"name":"ProposeNode","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_enodeId","type":"string"}],"name":"DeactivateNode","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_enodeId","type":"string"}],"name":"ApproveNode","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_enodeId","type":"string"},{"indexed":false,"name":"_canWrite","type":"bool"},{"indexed":false,"name":"_canLead","type":"bool"}],"name":"NewNodeProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_enodeId","type":"string"}],"name":"NodeApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_enodeId","type":"string"}],"name":"NodePendingDeactivation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_enodeId","type":"string"}],"name":"NodeDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"acctId","type":"address"},{"indexed":false,"name":"access","type":"uint8"}],"name":"AcctAccessModified","type":"event"}]

View File

@ -0,0 +1,262 @@
package permissions
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"os"
"sync"
// "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"gopkg.in/urfave/cli.v1"
)
const (
PERMISSIONED_CONFIG = "permissioned-nodes.json"
)
type NodeOperation uint8
const (
NodeAdd NodeOperation = iota
NodeDelete
)
// 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 ) error {
// Create a new ethclient to for interfacing with the contract
stateReader, err := createEthClient(stack)
if err != nil {
log.Error ("Unable to create ethereum client for permissions check : ", "err" , err)
return err
}
// check if permissioning contract is there at address. If not return from here
if _ , err = NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader); err != nil {
log.Error ("Permissions not enabled for the network : ", "err" , err)
return nil
}
// Monitors node addition and decativation from network
manageNodePermissions(stack, stateReader);
// Monitors account level persmissions update from smart contarct
manageAccountPermissions(stack, stateReader);
return nil
}
// Create an RPC client for the contract interface
func createEthClient(stack *node.Node ) (*ethclient.Client, error){
var e *eth.Ethereum
if err := stack.Service(&e); err != nil {
return nil, err
}
rpcClient, err := stack.Attach()
if err != nil {
return nil, err
}
return ethclient.NewClient(rpcClient), nil
}
// Manages node addition and decavtivation from network
func manageNodePermissions(stack *node.Node, stateReader *ethclient.Client) {
//monitor for new nodes addition via smart contract
go monitorNewNodeAdd(stack)
//monitor for nodes deletiin via smart contract
go monitorNodeDelete(stack, stateReader)
}
// This functions listens on the channel for new node approval via smart contract and
// adds the same into permissioned-nodes.json
func monitorNewNodeAdd(stack *node.Node) {
stateReader, err := createEthClient(stack)
permissions, err := NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader)
if err != nil {
log.Error ("failed to monitor new node add : ", "err" , err)
}
datadir := stack.DataDir()
ch := make(chan *PermissionsNodeApproved, 1)
opts := &bind.WatchOpts{}
var blockNumber uint64 = 1
opts.Start = &blockNumber
var nodeAddEvent *PermissionsNodeApproved
_, err = permissions.WatchNodeApproved(opts, ch)
if err != nil {
log.Info("Failed WatchNodeApproved: %v", err)
}
for {
select {
case nodeAddEvent = <-ch:
updatePermissionedNodes(nodeAddEvent.EnodeId, nodeAddEvent.IpAddrPort, nodeAddEvent.DiscPort, nodeAddEvent.RaftPort, datadir, NodeAdd)
}
}
}
// This functions listens on the channel for new node approval via smart contract and
// adds the same into permissioned-nodes.json
func monitorNodeDelete(stack *node.Node, stateReader *ethclient.Client) {
permissions, err := NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader)
if err != nil {
log.Error ("Failed to monitor node delete: ", "err" , err)
}
datadir := stack.DataDir()
ch := make(chan *PermissionsNodeDeactivated)
opts := &bind.WatchOpts{}
var blockNumber uint64 = 1
opts.Start = &blockNumber
var newNodeDeleteEvent *PermissionsNodeDeactivated
_, err = permissions.WatchNodeDeactivated(opts, ch)
if err != nil {
log.Info("Failed NodeDeactivated: %v", err)
}
for {
select {
case newNodeDeleteEvent = <-ch:
updatePermissionedNodes(newNodeDeleteEvent.EnodeId, newNodeDeleteEvent.IpAddrPort, newNodeDeleteEvent.DiscPort, newNodeDeleteEvent.RaftPort, datadir, NodeDelete)
}
}
}
//this function populates the new node information into the permissioned-nodes.json file
func updatePermissionedNodes(enodeId , ipAddrPort, discPort, raftPort, dataDir string, operation NodeOperation){
log.Debug("updatePermissionedNodes", "DataDir", dataDir, "file", PERMISSIONED_CONFIG)
path := filepath.Join(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)
if err != nil {
log.Error("updatePermissionedNodes: Failed to access permissioned-nodes.json", "err", err)
return
}
nodelist := []string{}
if err := json.Unmarshal(blob, &nodelist); err != nil {
log.Error("parsePermissionedNodes: Failed to load nodes list", "err", err)
return
}
// HACK: currently the ip, discpot and raft port are hard coded. Need to enhance the
//contract to pass these variables as part of the event and change this
// newEnodeId := "enode://" + enodeId + "@127.0.0.1:21005?discport=0&raftport=50406"
newEnodeId := "enode://" + enodeId + "@" + ipAddrPort + "?discPort=" + discPort + "&raftport=" + raftPort
log.Info("Enode id is : " , "newEnodeId", newEnodeId)
if (operation == NodeAdd){
nodelist = append(nodelist, newEnodeId)
} else {
index := 0
for i, enodeId := range nodelist {
if (enodeId == newEnodeId){
index = i
break
}
}
nodelist = append(nodelist[:index], nodelist[index+1:]...)
}
mu := sync.RWMutex{}
blob, _ = json.Marshal(nodelist)
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()
}
// Manages account level permissions update
func manageAccountPermissions(stack *node.Node, stateReader *ethclient.Client) error {
//call populate nodes to populate the nodes into contract
if err := populateAcctPermissions (stack, stateReader); err != nil {
return err;
}
//monitor for nodes deletiin via smart contract
go monitorAccountPermissions(stack, stateReader)
return nil
}
// populates the nodes list from permissioned-nodes.json into the permissions
// smart contract
func populateAcctPermissions(stack *node.Node, stateReader *ethclient.Client) error{
permissions, err := NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader)
if err != nil {
log.Error ("Failed to monitor node delete: ", "err" , err)
return err
}
opts := &bind.FilterOpts{}
pastEvents, err := permissions.FilterAcctAccessModified(opts)
recExists := true
for recExists {
recExists = pastEvents.Next()
if recExists {
types.AddAccountAccess(pastEvents.Event.AcctId, pastEvents.Event.Access)
}
}
return nil
}
// Monitors permissions changes at acount level and uodate the global permissions
// map with the same
func monitorAccountPermissions(stack *node.Node, stateReader *ethclient.Client) {
log.Info("Inside monotorAccountPermissions")
permissions, err := NewPermissionsFilterer(params.QuorumPermissionsContract, stateReader)
if err != nil {
log.Error ("Failed to monitor Account permissions : ", "err" , err)
}
ch := make(chan *PermissionsAcctAccessModified)
opts := &bind.WatchOpts{}
var blockNumber uint64 = 1
opts.Start = &blockNumber
var newEvent *PermissionsAcctAccessModified
_, err = permissions.WatchAcctAccessModified(opts, ch)
if err != nil {
log.Info("Failed NewNodeProposed: %v", err)
}
for {
select {
case newEvent = <-ch:
types.AddAccountAccess(newEvent.AcctId, newEvent.Access)
}
}
}

View File

@ -0,0 +1,908 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package permissions
import (
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// PermissionsABI is the input ABI used to generate the binding from.
const PermissionsABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"getNodeStatus\",\"outputs\":[{\"name\":\"_status\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_enodeId\",\"type\":\"string\"},{\"name\":\"_canWrite\",\"type\":\"bool\"},{\"name\":\"_canLead\",\"type\":\"bool\"},{\"name\":\"_ipAddrPort\",\"type\":\"string\"},{\"name\":\"_discPort\",\"type\":\"string\"},{\"name\":\"_raftPort\",\"type\":\"string\"}],\"name\":\"ProposeNode\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"ProposeDeactivation\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_acctId\",\"type\":\"address\"},{\"name\":\"access\",\"type\":\"uint8\"}],\"name\":\"updateAcctAccess\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"DeactivateNode\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"ApproveNode\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"NewNodeProposed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_enodeId\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_ipAddrPort\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_discPort\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_raftPort\",\"type\":\"string\"}],\"name\":\"NodeApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_enodeId\",\"type\":\"string\"}],\"name\":\"NodePendingDeactivation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_enodeId\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_ipAddrPort\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_discPort\",\"type\":\"string\"},{\"indexed\":false,\"name\":\"_raftPort\",\"type\":\"string\"}],\"name\":\"NodeDeactivated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"acctId\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"access\",\"type\":\"uint8\"}],\"name\":\"AcctAccessModified\",\"type\":\"event\"}]"
// Permissions is an auto generated Go binding around an Ethereum contract.
type Permissions struct {
PermissionsCaller // Read-only binding to the contract
PermissionsTransactor // Write-only binding to the contract
PermissionsFilterer // Log filterer for contract events
}
// PermissionsCaller is an auto generated read-only Go binding around an Ethereum contract.
type PermissionsCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PermissionsTransactor is an auto generated write-only Go binding around an Ethereum contract.
type PermissionsTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PermissionsFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type PermissionsFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// PermissionsSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type PermissionsSession struct {
Contract *Permissions // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// PermissionsCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type PermissionsCallerSession struct {
Contract *PermissionsCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// PermissionsTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type PermissionsTransactorSession struct {
Contract *PermissionsTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// PermissionsRaw is an auto generated low-level Go binding around an Ethereum contract.
type PermissionsRaw struct {
Contract *Permissions // Generic contract binding to access the raw methods on
}
// PermissionsCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type PermissionsCallerRaw struct {
Contract *PermissionsCaller // Generic read-only contract binding to access the raw methods on
}
// PermissionsTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type PermissionsTransactorRaw struct {
Contract *PermissionsTransactor // Generic write-only contract binding to access the raw methods on
}
// NewPermissions creates a new instance of Permissions, bound to a specific deployed contract.
func NewPermissions(address common.Address, backend bind.ContractBackend) (*Permissions, error) {
contract, err := bindPermissions(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &Permissions{PermissionsCaller: PermissionsCaller{contract: contract}, PermissionsTransactor: PermissionsTransactor{contract: contract}, PermissionsFilterer: PermissionsFilterer{contract: contract}}, nil
}
// NewPermissionsCaller creates a new read-only instance of Permissions, bound to a specific deployed contract.
func NewPermissionsCaller(address common.Address, caller bind.ContractCaller) (*PermissionsCaller, error) {
contract, err := bindPermissions(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &PermissionsCaller{contract: contract}, nil
}
// NewPermissionsTransactor creates a new write-only instance of Permissions, bound to a specific deployed contract.
func NewPermissionsTransactor(address common.Address, transactor bind.ContractTransactor) (*PermissionsTransactor, error) {
contract, err := bindPermissions(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &PermissionsTransactor{contract: contract}, nil
}
// NewPermissionsFilterer creates a new log filterer instance of Permissions, bound to a specific deployed contract.
func NewPermissionsFilterer(address common.Address, filterer bind.ContractFilterer) (*PermissionsFilterer, error) {
contract, err := bindPermissions(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &PermissionsFilterer{contract: contract}, nil
}
// bindPermissions binds a generic wrapper to an already deployed contract.
func bindPermissions(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(PermissionsABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Permissions *PermissionsRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _Permissions.Contract.PermissionsCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Permissions *PermissionsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Permissions.Contract.PermissionsTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Permissions *PermissionsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Permissions.Contract.PermissionsTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Permissions *PermissionsCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _Permissions.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Permissions *PermissionsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Permissions.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Permissions *PermissionsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Permissions.Contract.contract.Transact(opts, method, params...)
}
// GetNodeStatus is a free data retrieval call binding the contract method 0x397eeccb.
//
// Solidity: function getNodeStatus(_enodeId string) constant returns(_status uint8)
func (_Permissions *PermissionsCaller) GetNodeStatus(opts *bind.CallOpts, _enodeId string) (uint8, error) {
var (
ret0 = new(uint8)
)
out := ret0
err := _Permissions.contract.Call(opts, out, "getNodeStatus", _enodeId)
return *ret0, err
}
// GetNodeStatus is a free data retrieval call binding the contract method 0x397eeccb.
//
// Solidity: function getNodeStatus(_enodeId string) constant returns(_status uint8)
func (_Permissions *PermissionsSession) GetNodeStatus(_enodeId string) (uint8, error) {
return _Permissions.Contract.GetNodeStatus(&_Permissions.CallOpts, _enodeId)
}
// GetNodeStatus is a free data retrieval call binding the contract method 0x397eeccb.
//
// Solidity: function getNodeStatus(_enodeId string) constant returns(_status uint8)
func (_Permissions *PermissionsCallerSession) GetNodeStatus(_enodeId string) (uint8, error) {
return _Permissions.Contract.GetNodeStatus(&_Permissions.CallOpts, _enodeId)
}
// ApproveNode is a paid mutator transaction binding the contract method 0xc1dd1d92.
//
// Solidity: function ApproveNode(_enodeId string) returns()
func (_Permissions *PermissionsTransactor) ApproveNode(opts *bind.TransactOpts, _enodeId string) (*types.Transaction, error) {
return _Permissions.contract.Transact(opts, "ApproveNode", _enodeId)
}
// ApproveNode is a paid mutator transaction binding the contract method 0xc1dd1d92.
//
// Solidity: function ApproveNode(_enodeId string) returns()
func (_Permissions *PermissionsSession) ApproveNode(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.ApproveNode(&_Permissions.TransactOpts, _enodeId)
}
// ApproveNode is a paid mutator transaction binding the contract method 0xc1dd1d92.
//
// Solidity: function ApproveNode(_enodeId string) returns()
func (_Permissions *PermissionsTransactorSession) ApproveNode(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.ApproveNode(&_Permissions.TransactOpts, _enodeId)
}
// DeactivateNode is a paid mutator transaction binding the contract method 0xbc67f80b.
//
// Solidity: function DeactivateNode(_enodeId string) returns()
func (_Permissions *PermissionsTransactor) DeactivateNode(opts *bind.TransactOpts, _enodeId string) (*types.Transaction, error) {
return _Permissions.contract.Transact(opts, "DeactivateNode", _enodeId)
}
// DeactivateNode is a paid mutator transaction binding the contract method 0xbc67f80b.
//
// Solidity: function DeactivateNode(_enodeId string) returns()
func (_Permissions *PermissionsSession) DeactivateNode(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.DeactivateNode(&_Permissions.TransactOpts, _enodeId)
}
// DeactivateNode is a paid mutator transaction binding the contract method 0xbc67f80b.
//
// Solidity: function DeactivateNode(_enodeId string) returns()
func (_Permissions *PermissionsTransactorSession) DeactivateNode(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.DeactivateNode(&_Permissions.TransactOpts, _enodeId)
}
// ProposeDeactivation is a paid mutator transaction binding the contract method 0x6dcd03e0.
//
// Solidity: function ProposeDeactivation(_enodeId string) returns()
func (_Permissions *PermissionsTransactor) ProposeDeactivation(opts *bind.TransactOpts, _enodeId string) (*types.Transaction, error) {
return _Permissions.contract.Transact(opts, "ProposeDeactivation", _enodeId)
}
// ProposeDeactivation is a paid mutator transaction binding the contract method 0x6dcd03e0.
//
// Solidity: function ProposeDeactivation(_enodeId string) returns()
func (_Permissions *PermissionsSession) ProposeDeactivation(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.ProposeDeactivation(&_Permissions.TransactOpts, _enodeId)
}
// ProposeDeactivation is a paid mutator transaction binding the contract method 0x6dcd03e0.
//
// Solidity: function ProposeDeactivation(_enodeId string) returns()
func (_Permissions *PermissionsTransactorSession) ProposeDeactivation(_enodeId string) (*types.Transaction, error) {
return _Permissions.Contract.ProposeDeactivation(&_Permissions.TransactOpts, _enodeId)
}
// ProposeNode is a paid mutator transaction binding the contract method 0x6b4b4867.
//
// Solidity: function ProposeNode(_enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) returns()
func (_Permissions *PermissionsTransactor) ProposeNode(opts *bind.TransactOpts, _enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) (*types.Transaction, error) {
return _Permissions.contract.Transact(opts, "ProposeNode", _enodeId, _canWrite, _canLead, _ipAddrPort, _discPort, _raftPort)
}
// ProposeNode is a paid mutator transaction binding the contract method 0x6b4b4867.
//
// Solidity: function ProposeNode(_enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) returns()
func (_Permissions *PermissionsSession) ProposeNode(_enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) (*types.Transaction, error) {
return _Permissions.Contract.ProposeNode(&_Permissions.TransactOpts, _enodeId, _canWrite, _canLead, _ipAddrPort, _discPort, _raftPort)
}
// ProposeNode is a paid mutator transaction binding the contract method 0x6b4b4867.
//
// Solidity: function ProposeNode(_enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) returns()
func (_Permissions *PermissionsTransactorSession) ProposeNode(_enodeId string, _canWrite bool, _canLead bool, _ipAddrPort string, _discPort string, _raftPort string) (*types.Transaction, error) {
return _Permissions.Contract.ProposeNode(&_Permissions.TransactOpts, _enodeId, _canWrite, _canLead, _ipAddrPort, _discPort, _raftPort)
}
// UpdateAcctAccess is a paid mutator transaction binding the contract method 0x913fc7d7.
//
// Solidity: function updateAcctAccess(_acctId address, access uint8) returns()
func (_Permissions *PermissionsTransactor) UpdateAcctAccess(opts *bind.TransactOpts, _acctId common.Address, access uint8) (*types.Transaction, error) {
return _Permissions.contract.Transact(opts, "updateAcctAccess", _acctId, access)
}
// UpdateAcctAccess is a paid mutator transaction binding the contract method 0x913fc7d7.
//
// Solidity: function updateAcctAccess(_acctId address, access uint8) returns()
func (_Permissions *PermissionsSession) UpdateAcctAccess(_acctId common.Address, access uint8) (*types.Transaction, error) {
return _Permissions.Contract.UpdateAcctAccess(&_Permissions.TransactOpts, _acctId, access)
}
// UpdateAcctAccess is a paid mutator transaction binding the contract method 0x913fc7d7.
//
// Solidity: function updateAcctAccess(_acctId address, access uint8) returns()
func (_Permissions *PermissionsTransactorSession) UpdateAcctAccess(_acctId common.Address, access uint8) (*types.Transaction, error) {
return _Permissions.Contract.UpdateAcctAccess(&_Permissions.TransactOpts, _acctId, access)
}
// PermissionsAcctAccessModifiedIterator is returned from FilterAcctAccessModified and is used to iterate over the raw logs and unpacked data for AcctAccessModified events raised by the Permissions contract.
type PermissionsAcctAccessModifiedIterator struct {
Event *PermissionsAcctAccessModified // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *PermissionsAcctAccessModifiedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(PermissionsAcctAccessModified)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(PermissionsAcctAccessModified)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *PermissionsAcctAccessModifiedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *PermissionsAcctAccessModifiedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// PermissionsAcctAccessModified represents a AcctAccessModified event raised by the Permissions contract.
type PermissionsAcctAccessModified struct {
AcctId common.Address
Access uint8
Raw types.Log // Blockchain specific contextual infos
}
// FilterAcctAccessModified is a free log retrieval operation binding the contract event 0xb9f8d88def106a1a167b617a197bee4323d3997cb1fa46b785c1a7b9af6e82a8.
//
// Solidity: e AcctAccessModified(acctId address, access uint8)
func (_Permissions *PermissionsFilterer) FilterAcctAccessModified(opts *bind.FilterOpts) (*PermissionsAcctAccessModifiedIterator, error) {
logs, sub, err := _Permissions.contract.FilterLogs(opts, "AcctAccessModified")
if err != nil {
return nil, err
}
return &PermissionsAcctAccessModifiedIterator{contract: _Permissions.contract, event: "AcctAccessModified", logs: logs, sub: sub}, nil
}
// WatchAcctAccessModified is a free log subscription operation binding the contract event 0xb9f8d88def106a1a167b617a197bee4323d3997cb1fa46b785c1a7b9af6e82a8.
//
// Solidity: e AcctAccessModified(acctId address, access uint8)
func (_Permissions *PermissionsFilterer) WatchAcctAccessModified(opts *bind.WatchOpts, sink chan<- *PermissionsAcctAccessModified) (event.Subscription, error) {
logs, sub, err := _Permissions.contract.WatchLogs(opts, "AcctAccessModified")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(PermissionsAcctAccessModified)
if err := _Permissions.contract.UnpackLog(event, "AcctAccessModified", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// PermissionsNewNodeProposedIterator is returned from FilterNewNodeProposed and is used to iterate over the raw logs and unpacked data for NewNodeProposed events raised by the Permissions contract.
type PermissionsNewNodeProposedIterator struct {
Event *PermissionsNewNodeProposed // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *PermissionsNewNodeProposedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(PermissionsNewNodeProposed)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(PermissionsNewNodeProposed)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *PermissionsNewNodeProposedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *PermissionsNewNodeProposedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// PermissionsNewNodeProposed represents a NewNodeProposed event raised by the Permissions contract.
type PermissionsNewNodeProposed struct {
EnodeId string
Raw types.Log // Blockchain specific contextual infos
}
// FilterNewNodeProposed is a free log retrieval operation binding the contract event 0xe370df14cec622d932b6c03454042c48c2815c9f96d22ab2bdb2e7171d96eb00.
//
// Solidity: e NewNodeProposed(_enodeId string)
func (_Permissions *PermissionsFilterer) FilterNewNodeProposed(opts *bind.FilterOpts) (*PermissionsNewNodeProposedIterator, error) {
logs, sub, err := _Permissions.contract.FilterLogs(opts, "NewNodeProposed")
if err != nil {
return nil, err
}
return &PermissionsNewNodeProposedIterator{contract: _Permissions.contract, event: "NewNodeProposed", logs: logs, sub: sub}, nil
}
// WatchNewNodeProposed is a free log subscription operation binding the contract event 0xe370df14cec622d932b6c03454042c48c2815c9f96d22ab2bdb2e7171d96eb00.
//
// Solidity: e NewNodeProposed(_enodeId string)
func (_Permissions *PermissionsFilterer) WatchNewNodeProposed(opts *bind.WatchOpts, sink chan<- *PermissionsNewNodeProposed) (event.Subscription, error) {
logs, sub, err := _Permissions.contract.WatchLogs(opts, "NewNodeProposed")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(PermissionsNewNodeProposed)
if err := _Permissions.contract.UnpackLog(event, "NewNodeProposed", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// PermissionsNodeApprovedIterator is returned from FilterNodeApproved and is used to iterate over the raw logs and unpacked data for NodeApproved events raised by the Permissions contract.
type PermissionsNodeApprovedIterator struct {
Event *PermissionsNodeApproved // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *PermissionsNodeApprovedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(PermissionsNodeApproved)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(PermissionsNodeApproved)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *PermissionsNodeApprovedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *PermissionsNodeApprovedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// PermissionsNodeApproved represents a NodeApproved event raised by the Permissions contract.
type PermissionsNodeApproved struct {
EnodeId string
IpAddrPort string
DiscPort string
RaftPort string
Raw types.Log // Blockchain specific contextual infos
}
// FilterNodeApproved is a free log retrieval operation binding the contract event 0xc6d86deaa3b3cf7c374cfd405aae9f08571fce2bf6ccfe8f98a399cda8960a98.
//
// Solidity: e NodeApproved(_enodeId string, _ipAddrPort string, _discPort string, _raftPort string)
func (_Permissions *PermissionsFilterer) FilterNodeApproved(opts *bind.FilterOpts) (*PermissionsNodeApprovedIterator, error) {
logs, sub, err := _Permissions.contract.FilterLogs(opts, "NodeApproved")
if err != nil {
return nil, err
}
return &PermissionsNodeApprovedIterator{contract: _Permissions.contract, event: "NodeApproved", logs: logs, sub: sub}, nil
}
// WatchNodeApproved is a free log subscription operation binding the contract event 0xc6d86deaa3b3cf7c374cfd405aae9f08571fce2bf6ccfe8f98a399cda8960a98.
//
// Solidity: e NodeApproved(_enodeId string, _ipAddrPort string, _discPort string, _raftPort string)
func (_Permissions *PermissionsFilterer) WatchNodeApproved(opts *bind.WatchOpts, sink chan<- *PermissionsNodeApproved) (event.Subscription, error) {
logs, sub, err := _Permissions.contract.WatchLogs(opts, "NodeApproved")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(PermissionsNodeApproved)
if err := _Permissions.contract.UnpackLog(event, "NodeApproved", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// PermissionsNodeDeactivatedIterator is returned from FilterNodeDeactivated and is used to iterate over the raw logs and unpacked data for NodeDeactivated events raised by the Permissions contract.
type PermissionsNodeDeactivatedIterator struct {
Event *PermissionsNodeDeactivated // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *PermissionsNodeDeactivatedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(PermissionsNodeDeactivated)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(PermissionsNodeDeactivated)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *PermissionsNodeDeactivatedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *PermissionsNodeDeactivatedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// PermissionsNodeDeactivated represents a NodeDeactivated event raised by the Permissions contract.
type PermissionsNodeDeactivated struct {
EnodeId string
IpAddrPort string
DiscPort string
RaftPort string
Raw types.Log // Blockchain specific contextual infos
}
// FilterNodeDeactivated is a free log retrieval operation binding the contract event 0xd5fa0ecdea15b332dd0a270c65234bc4aee212edf2ed62eb2fd182ef55ca98a1.
//
// Solidity: e NodeDeactivated(_enodeId string, _ipAddrPort string, _discPort string, _raftPort string)
func (_Permissions *PermissionsFilterer) FilterNodeDeactivated(opts *bind.FilterOpts) (*PermissionsNodeDeactivatedIterator, error) {
logs, sub, err := _Permissions.contract.FilterLogs(opts, "NodeDeactivated")
if err != nil {
return nil, err
}
return &PermissionsNodeDeactivatedIterator{contract: _Permissions.contract, event: "NodeDeactivated", logs: logs, sub: sub}, nil
}
// WatchNodeDeactivated is a free log subscription operation binding the contract event 0xd5fa0ecdea15b332dd0a270c65234bc4aee212edf2ed62eb2fd182ef55ca98a1.
//
// Solidity: e NodeDeactivated(_enodeId string, _ipAddrPort string, _discPort string, _raftPort string)
func (_Permissions *PermissionsFilterer) WatchNodeDeactivated(opts *bind.WatchOpts, sink chan<- *PermissionsNodeDeactivated) (event.Subscription, error) {
logs, sub, err := _Permissions.contract.WatchLogs(opts, "NodeDeactivated")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(PermissionsNodeDeactivated)
if err := _Permissions.contract.UnpackLog(event, "NodeDeactivated", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// PermissionsNodePendingDeactivationIterator is returned from FilterNodePendingDeactivation and is used to iterate over the raw logs and unpacked data for NodePendingDeactivation events raised by the Permissions contract.
type PermissionsNodePendingDeactivationIterator struct {
Event *PermissionsNodePendingDeactivation // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *PermissionsNodePendingDeactivationIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(PermissionsNodePendingDeactivation)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(PermissionsNodePendingDeactivation)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *PermissionsNodePendingDeactivationIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *PermissionsNodePendingDeactivationIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// PermissionsNodePendingDeactivation represents a NodePendingDeactivation event raised by the Permissions contract.
type PermissionsNodePendingDeactivation struct {
EnodeId string
Raw types.Log // Blockchain specific contextual infos
}
// FilterNodePendingDeactivation is a free log retrieval operation binding the contract event 0x2b5689b33f48f1dcbda2084e130a9bee7b3bf14dc767ea74cbdf3e5fffb118e4.
//
// Solidity: e NodePendingDeactivation(_enodeId string)
func (_Permissions *PermissionsFilterer) FilterNodePendingDeactivation(opts *bind.FilterOpts) (*PermissionsNodePendingDeactivationIterator, error) {
logs, sub, err := _Permissions.contract.FilterLogs(opts, "NodePendingDeactivation")
if err != nil {
return nil, err
}
return &PermissionsNodePendingDeactivationIterator{contract: _Permissions.contract, event: "NodePendingDeactivation", logs: logs, sub: sub}, nil
}
// WatchNodePendingDeactivation is a free log subscription operation binding the contract event 0x2b5689b33f48f1dcbda2084e130a9bee7b3bf14dc767ea74cbdf3e5fffb118e4.
//
// Solidity: e NodePendingDeactivation(_enodeId string)
func (_Permissions *PermissionsFilterer) WatchNodePendingDeactivation(opts *bind.WatchOpts, sink chan<- *PermissionsNodePendingDeactivation) (event.Subscription, error) {
logs, sub, err := _Permissions.contract.WatchLogs(opts, "NodePendingDeactivation")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(PermissionsNodePendingDeactivation)
if err := _Permissions.contract.UnpackLog(event, "NodePendingDeactivation", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}

View File

@ -0,0 +1,143 @@
package permissions
import (
"fmt"
"math/big"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
const key = `{"address":"ed9d02e382b34818e88b88a309c7fe71e65f419d","crypto":{"cipher":"aes-128-ctr","ciphertext":"4e77046ba3f699e744acb4a89c36a3ea1158a1bd90a076d36675f4c883864377","cipherparams":{"iv":"a8932af2a3c0225ee8e872bc0e462c11"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"8ca49552b3e92f79c51f2cd3d38dfc723412c212e702bd337a3724e8937aff0f"},"mac":"6d1354fef5aa0418389b1a5d1f5ee0050d7273292a1171c51fd02f9ecff55264"},"id":"a65d1ac3-db7e-445d-a1cc-b6c5eeaa05e0","version":3}`
//const enode1 = "ac6b1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef"
const enode1 = "abhb1096ca56b9f6d004b779ae3728bf83f8e22453404cc3cef16a3d9b96608bc67c4b30db88e0a5a6c6390213f7acbe1153ff6d23ce57380104288ae19373ef"
const enode2 = "0ba6b9f606a43a95edc6247cdb1c1e105145817be7bcafd6b2c0ba15d58145f0dc1a194f70ba73cd6f4cdd6864edc7687f311254c7555cc32e4d45aeb1b80416"
// const addr = "0x9d13c6d3afe1721beef56b55d303b09e021e27ab"
const addr = "0x0000000000000000000000000000000000000020"
// function to test proposeNode
func TestContract_ProposeNode(t *testing.T) {
conn, err := ethclient.Dial("/home/vagrant/quorum-examples/examples/7nodes/qdata/dd1/geth.ipc")
if err != nil {
t.Errorf("Failed to connect to the Ethereum client: %v", err)
}
var contractAddr = common.HexToAddress(addr)
permissions, err := NewPermissions(contractAddr, conn)
if err != nil {
t.Errorf("Failed to instantiate a Permissions contract: %v", err)
}
auth, err := bind.NewTransactor(strings.NewReader(key), "")
if err != nil {
t.Errorf("Failed to create authorized transactor: %v", err)
}
session := &PermissionsSession{
Contract: permissions,
CallOpts: bind.CallOpts{
Pending: true,
},
TransactOpts: bind.TransactOpts{
From: auth.From,
Signer: auth.Signer,
GasLimit: 3558096384,
GasPrice: big.NewInt(0),
},
}
tx, err := session.ProposeNode(enode1, true, true)
if err != nil {
t.Errorf("Failed to propose node: %v", err)
}
fmt.Printf("Transaction pending: 0x%x\n", tx.Hash())
}
// function to test getNodeIndex for a given enode
func TestContract_GetNodeStatus(t *testing.T) {
conn, err := ethclient.Dial("/home/vagrant/quorum-examples/examples/7nodes/qdata/dd1/geth.ipc")
if err != nil {
t.Errorf("Failed to connect to the Ethereum client: %v", err)
}
var contractAddr = common.HexToAddress(addr)
permissions, err := NewPermissions(contractAddr, conn)
if err != nil {
t.Errorf("Failed to instantiate a Permissions contract: %v", err)
}
status, err := permissions.GetNodeStatus(nil, enode1)
if err != nil {
t.Errorf("Failed to create authorized transactor: %v", err)
} else {
fmt.Printf("node status: %v\n", status)
}
}
// function to test filterNewNodeProposed. Returns list of all nodes added
func TestContract_filterNewNodeProposed(t *testing.T) {
conn, err := ethclient.Dial("/home/vagrant/quorum-examples/examples/7nodes/qdata/dd1/geth.ipc")
if err != nil {
t.Errorf("Failed to connect to the Ethereum client: %v", err)
}
var contractAddr = common.HexToAddress(addr)
permissions, err := NewPermissionsFilterer(contractAddr, conn)
if err != nil {
t.Errorf("some error")
}
opts := &bind.FilterOpts{}
past, err := permissions.FilterNewNodeProposed(opts)
notEmpty := true
for notEmpty {
notEmpty = past.Next()
if notEmpty {
fmt.Printf("Enode Id - %v, Can Write - %v, Can Lead - %v\n", past.Event.EnodeId, past.Event.CanWrite, past.Event.CanLead)
fmt.Println("********************************************************")
}
}
}
// function to test watch new node proposed. wats on the channel for new node add event
func TestContract_watchNewNodeProposed(t *testing.T) {
conn, err := ethclient.Dial("/home/vagrant/quorum-examples/examples/7nodes/qdata/dd1/geth.ipc")
if err != nil {
t.Errorf("Failed to connect to the Ethereum client: %v", err)
}
var contractAddr = common.HexToAddress(addr)
permissions, err := NewPermissionsFilterer(contractAddr, conn)
if err != nil {
t.Errorf("some error")
} else {
fmt.Printf("value is %v", permissions)
}
ch := make(chan *PermissionsNewNodeProposed)
// nodeIndex := []uint32{}
opts := &bind.WatchOpts{}
var blockNumber uint64 = 1
opts.Start = &blockNumber
_, err = permissions.WatchNewNodeProposed(opts, ch)
if err != nil {
t.Error("Failed NewNodeProposed: %v", err)
}
var newEvent *PermissionsNewNodeProposed = <-ch
fmt.Printf("Found event: Enode Id - %v, Can Write - %v, Can Lead - %v\n", newEvent.EnodeId, newEvent.CanWrite, newEvent.CanLead)
fmt.Println("**************************************")
}