mirror of https://github.com/poanetwork/quorum.git
merge with 1.8.12 version
This commit is contained in:
commit
7e35574def
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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"}]
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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("**************************************")
|
||||
}
|
Loading…
Reference in New Issue