Merge remote-tracking branch 'remotes/quoeng/feature/permissioning-1.8.12' into feature/permissioning-1.8.18

# Conflicts:
#	cmd/bootnode/main.go
#	internal/web3ext/web3ext.go
#	p2p/discover/udp.go
#	p2p/discover/udp_test.go
#	p2p/permissions.go
#	p2p/server.go

poc to pass permission contract via command line
This commit is contained in:
amalraj.manigmail.com 2019-03-08 17:09:24 +08:00
parent d5e4ae7b87
commit a8c050df22
20 changed files with 104 additions and 84 deletions

View File

@ -22,12 +22,12 @@ import (
"io"
"io/ioutil"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/accounts"
)
)
// NewTransactor is a utility method to easily create a transaction signer from
// an encrypted json key stream and the associated passphrase.

View File

@ -40,8 +40,8 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
)
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
@ -388,6 +388,7 @@ func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethere
}
}), nil
}
// PreparePrivateTransaction replaces the payload data of the transaction with a
// commitment to turn it into a private tx.
func (b *SimulatedBackend) PreparePrivateTransaction(ctx context.Context, encodedTx hexutil.Bytes, privateFrom string, privateFor []string) (hexutil.Bytes, error) {

View File

@ -356,6 +356,7 @@ func (c *BoundContract) UnpackLog(out interface{}, event string, log types.Log)
}
return parseTopics(out, indexed, log.Topics[1:])
}
// PreparePrivateTransaction replaces the payload data of the transaction with a
// commitment to turn it into a private tx.
func (c *BoundContract) preparePrivateTransaction(ctx context.Context, tx *types.Transaction, privateFrom string, privateFor []string) (*types.Transaction, error) {

View File

@ -137,6 +137,7 @@ var (
utils.EVMInterpreterFlag,
configFileFlag,
utils.EnableNodePermissionFlag,
utils.PermissionContractAddressFlag,
utils.RaftModeFlag,
utils.RaftBlockTimeFlag,
utils.RaftJoinExistingFlag,
@ -383,7 +384,7 @@ func startQuorumPermissionService(ctx *cli.Context, stack *node.Node) {
var quorumApis []string
// start the permissions management service
pc, err := permission.NewQuorumPermissionCtrl(stack, ctx.GlobalBool(utils.EnableNodePermissionFlag.Name), ctx.GlobalBool(utils.RaftModeFlag.Name))
pc, err := permission.NewQuorumPermissionCtrl(stack, ctx.GlobalBool(utils.EnableNodePermissionFlag.Name), ctx.GlobalBool(utils.RaftModeFlag.Name), ctx.GlobalString(utils.PermissionContractAddressFlag.Name))
if err != nil {
log.Error("Failed to start Quorum Permission contract service: %v", err)
} else {

View File

@ -607,6 +607,13 @@ var (
Usage: "If enabled, the node will allow only a defined list of nodes to connect",
}
// Quorum permission contract
PermissionContractAddressFlag = cli.StringFlag{
Name: "permission.contract",
Usage: "If passed, the node will use this contract to bootstrap permission instead of contract from genesis.json",
Value: "0x",
}
// Istanbul settings
IstanbulRequestTimeoutFlag = cli.Uint64Flag{
Name: "istanbul.requesttimeout",

View File

@ -86,7 +86,7 @@ func (k *OrgKeyCtrl) checkIfContractExists() error {
func (k *OrgKeyCtrl) manageClusterKeys() {
//call populate nodes to populate the nodes into contract
if err := k.populatePrivateKeys(); err != nil {
return
return
}
//monitor for nodes deletiin via smart contract
k.monitorKeyChanges()

View File

@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
"io/ioutil"
"math/big"
"os"
@ -21,7 +23,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/raft"
)
@ -45,7 +46,7 @@ type PermissionCtrl struct {
}
// Creates the controls structure for permissions
func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode, isRaft bool) (*PermissionCtrl, error) {
func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode, isRaft bool, permissionCtrAddress string) (*PermissionCtrl, error) {
// Create a new ethclient to for interfacing with the contract
stateReader, e, err := controls.CreateEthClient(stack)
if err != nil {
@ -53,8 +54,17 @@ func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode, isRaft bool) (*
return nil, err
}
var permissionContractAddress common.Address
if permissionCtrAddress != "0x" {
log.Info("AJ-1bootstrapping permission via command line passed permission contract")
permissionContractAddress = common.HexToAddress(permissionCtrAddress)
} else {
log.Info("AJ-2bootstrapping permission via genesis.json permission contract")
permissionContractAddress = params.QuorumPermissionsContract
}
log.Info("AJ-3permission", "contract address", permissionContractAddress)
// check if permissioning contract is there at address. If not return from here
pm, err := pbind.NewPermissions(params.QuorumPermissionsContract, stateReader)
pm, err := pbind.NewPermissions(permissionContractAddress, stateReader)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
@ -398,7 +408,7 @@ func (p *PermissionCtrl) disconnectNode(enodeId string) {
// Istanbul - disconnect the peer
server := p.node.Server()
if server != nil {
node, err := discover.ParseNode(enodeId)
node, err := enode.ParseV4(enodeId)
if err == nil {
server.RemovePeer(node)
}
@ -487,8 +497,8 @@ func (p *PermissionCtrl) populateStaticNodesToContract(permissionsSession *pbind
nodes := p2p.ParsePermissionedNodes(p.dataDir)
for _, node := range nodes {
enodeID := node.ID.String()
ipAddr := node.IP.String()
enodeID := node.EnodeID()
ipAddr := node.IP().String()
port := fmt.Sprintf("%v", node.TCP)
discPort := fmt.Sprintf("%v", node.UDP)
raftPort := fmt.Sprintf("%v", node.RaftPort)

View File

@ -4,6 +4,7 @@ import (
"crypto/ecdsa"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/p2p/enode"
"math/big"
"strings"
@ -17,7 +18,6 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/params"
)
@ -461,13 +461,13 @@ func (s *QuorumControlsAPI) SetAccountAccess(acct common.Address, access uint8,
// returns node details given the enode id
func getNodeDetailsFromEnode(nodeId string) (string, string, string, string, error) {
node, err := discover.ParseNode(nodeId)
node, err := enode.ParseV4(nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return "", "", "", "", err
}
enodeID := node.ID.String()
ipAddr := node.IP.String()
enodeID := node.EnodeID()
ipAddr := node.IP().String()
port := fmt.Sprintf("%v", node.TCP)
discPort := fmt.Sprintf("%v", node.UDP)
raftPort := fmt.Sprintf("%v", node.RaftPort)
@ -586,7 +586,7 @@ func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) Ex
}
ps := s.newPermSession(w, args.txa)
var tx *types.Transaction
var node *discover.Node
var node *enode.Node
var execStatus ExecStatus
if action != SetAccountAccess && action != AddVoter && action != RemoveVoter {
@ -625,50 +625,50 @@ func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) Ex
tx, err = ps.ProposeNode(enodeID, ipAddrPort, discPort, raftPort)
case ApproveNode:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.ApproveNode(enodeID)
case ProposeNodeDeactivation:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.ProposeDeactivation(enodeID)
case ApproveNodeDeactivation:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.DeactivateNode(enodeID)
case ProposeNodeActivation:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.ProposeNodeActivation(enodeID)
case ApproveNodeActivation:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.ActivateNode(enodeID)
@ -680,12 +680,12 @@ func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) Ex
}
tx, err = ps.ProposeNodeBlacklisting(enodeID, ipAddrPort, discPort, raftPort)
case ApproveNodeBlacklisting:
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.BlacklistNode(enodeID)
@ -702,12 +702,12 @@ func (s *QuorumControlsAPI) executePermAction(action PermAction, args txArgs) Ex
if !checkIsVoter(ps, args.txa.From) {
return ErrAccountNotAVoter
}
node, err = discover.ParseNode(args.nodeId)
node, err = enode.ParseV4(args.nodeId)
if err != nil {
log.Error("invalid node id: %v", err)
return ErrInvalidNode
}
enodeID := node.ID.String()
enodeID := node.EnodeID()
tx, err = ps.CancelPendingOperation(enodeID)

View File

@ -602,6 +602,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
return ErrNegativeValue
}
// Ensure the transaction doesn't exceed the current block limit gas.
log.Info("AJ-current MAX GAS ", "gas", pool.currentMaxGas, "tx gas", tx.Gas())
if pool.currentMaxGas < tx.Gas() {
return ErrGasLimit
}
@ -1318,15 +1319,15 @@ func checkAccount(fromAcct common.Address, toAcct *common.Address) error {
case types.ContractDeploy:
return nil
case types.ReadOnly:
return errors.New("Account does not have transaction permissions")
/* case types.ReadOnly:
return errors.New("Account does not have transaction permissions")
case types.Transact:
if toAcct == nil {
return errors.New("Account does not have contract create permissions")
} else {
return nil
}
case types.Transact:
if toAcct == nil {
return errors.New("Account does not have contract create permissions")
} else {
return nil
}*/
}
return nil
}

View File

@ -184,8 +184,8 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
return nil
}
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
func (tx *Transaction) SetData(data []byte) {
tx.data.Payload = common.CopyBytes(data)
}

View File

@ -85,7 +85,7 @@ func toCallArgs(msg ethereum.CallMsg) ethapi.CallArgs {
To: msg.To,
From: msg.From,
Data: msg.Data,
Gas: hexutil.Uint64(msg.Gas),
Gas: hexutil.Uint64(msg.Gas),
}
if msg.GasPrice != nil {
args.GasPrice = hexutil.Big(*msg.GasPrice)

View File

@ -1356,12 +1356,12 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
privateFor := resolvePrivateFor(args.PrivateFor)
//Send private transaction to local Constellation node
if len(data) > 0 {
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", privateFor)
data, err = private.P.Send(data, args.PrivateFrom, privateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", privateFor)
if err != nil {
return common.Hash{}, err
}
log.Info("sending private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", privateFor)
data, err = private.P.Send(data, args.PrivateFrom, privateFor)
log.Info("sent private tx", "data", fmt.Sprintf("%x", data), "privatefrom", args.PrivateFrom, "privatefor", privateFor)
if err != nil {
return common.Hash{}, err
}
}
// zekun: HACK
d := hexutil.Bytes(data)
@ -1803,7 +1803,7 @@ func (s *PublicBlockChainAPI) GetQuorumPayload(digestHex string) (string, error)
//End-Quorum
func resolvePrivateFor(privateFor []string) []string{
func resolvePrivateFor(privateFor []string) []string {
var newPrivateFor []string

View File

@ -18,21 +18,21 @@
package web3ext
var Modules = map[string]string{
"admin": Admin_JS,
"chequebook": Chequebook_JS,
"clique": Clique_JS,
"ethash": Ethash_JS,
"debug": Debug_JS,
"eth": Eth_JS,
"miner": Miner_JS,
"net": Net_JS,
"personal": Personal_JS,
"rpc": RPC_JS,
"shh": Shh_JS,
"swarmfs": SWARMFS_JS,
"txpool": TxPool_JS,
"raft": Raft_JS,
"istanbul": Istanbul_JS,
"admin": Admin_JS,
"chequebook": Chequebook_JS,
"clique": Clique_JS,
"ethash": Ethash_JS,
"debug": Debug_JS,
"eth": Eth_JS,
"miner": Miner_JS,
"net": Net_JS,
"personal": Personal_JS,
"rpc": RPC_JS,
"shh": Shh_JS,
"swarmfs": SWARMFS_JS,
"txpool": TxPool_JS,
"raft": Raft_JS,
"istanbul": Istanbul_JS,
"quorumNodeMgmt": QUORUM_NODE_JS,
"quorumAcctMgmt": QUORUM_ACCT_JS,
"quorumOrgMgmt": QUORUM_ORG_JS,

View File

@ -237,16 +237,16 @@ type Config struct {
}
// ListenUDP returns a new table that listens for UDP packets on laddr.
func ListenUDP(c conn, cfg Config, knownNodes []*Node) (*Table, error) {
func ListenUDP(c conn, ln *enode.LocalNode, cfg Config, knownNodes []*enode.Node) (*Table, error) {
tab, _, err := newUDP(c, cfg, knownNodes)
tab, _, err := newUDP(c, ln, cfg, knownNodes)
if err != nil {
return nil, err
}
return tab, nil
}
func newUDP(c conn, ln *enode.LocalNode, cfg Config, knownNodes []*Node) (*Table, *udp, error) {
func newUDP(c conn, ln *enode.LocalNode, cfg Config, knownNodes []*enode.Node) (*Table, *udp, error) {
udp := &udp{
conn: c,
@ -266,7 +266,8 @@ func newUDP(c conn, ln *enode.LocalNode, cfg Config, knownNodes []*Node) (*Table
// 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)
//k := knownNodes[0]
tab.stuff(wrapNodes(knownNodes))
}
udp.tab = tab

View File

@ -61,7 +61,7 @@ type udpTest struct {
sent [][]byte
localkey, remotekey *ecdsa.PrivateKey
remoteaddr *net.UDPAddr
knownNodes []*Node
knownNodes []*enode.Node
}
func newUDPTest(t *testing.T) *udpTest {
@ -74,7 +74,7 @@ func newUDPTest(t *testing.T) *udpTest {
}
db, _ := enode.OpenDB("")
ln := enode.NewLocalNode(db, test.localkey)
test.table, test.udp, _ = newUDP(test.pipe, ln, Config{PrivateKey: test.localkey})
test.table, test.udp, _ = newUDP(test.pipe, ln, 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

@ -7,13 +7,13 @@ import (
"path/filepath"
"strings"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
)
const (
NODE_NAME_LENGTH = 32
NODE_NAME_LENGTH = 32
)
// check if a given node is permissioned to connect to the change
@ -29,7 +29,7 @@ func isNodePermissioned(nodename string, currentNode string, datadir string, dir
if v == nodename {
log.Debug("isNodePermissioned", "connection", direction, "nodename", nodename[:NODE_NAME_LENGTH], "ALLOWED-BY", currentNode[:NODE_NAME_LENGTH])
// check if the node is blacklisted
if isNodeBlackListed(nodename, datadir){
if isNodeBlackListed(nodename, datadir) {
return false
}
return true
@ -42,7 +42,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) []*enode.Node {
func ParsePermissionedNodes(DataDir string) []*enode.Node {
log.Debug("parsePermissionedNodes", "DataDir", DataDir, "file", params.PERMISSIONED_CONFIG)
@ -81,7 +81,7 @@ func parsePermissionedNodes(DataDir string) []*enode.Node {
}
// This function checks if the node is black-listed
func isNodeBlackListed (nodeName, dataDir string ) bool {
func isNodeBlackListed(nodeName, dataDir string) bool {
log.Debug("isNodeBlackListed", "DataDir", dataDir, "file", params.BLACKLIST_CONFIG)
path := filepath.Join(dataDir, params.BLACKLIST_CONFIG)

View File

@ -111,7 +111,7 @@ type Config struct {
// KnownNodes contains a list of nodes that are used to pre-populate the
// node database.
KnownNodes []*discover.Node
KnownNodes []*enode.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
@ -156,7 +156,6 @@ type Config struct {
DataDir string `toml:",omitempty"`
// Logger is a custom logger to use with the p2p.Server.
Logger log.Logger `toml:",omitempty"`
}
// Server manages all peer connections.
@ -542,14 +541,13 @@ func (srv *Server) setupDiscovery() error {
var unhandled chan discover.ReadPacket
var sconn *sharedUDPConn
knownNodes := append([]*discover.Node(nil), srv.KnownNodes...)
knownNodes := append([]*enode.Node(nil), srv.KnownNodes...)
if srv.EnableNodePermission {
knownNodes = append(knownNodes, ParsePermissionedNodes(srv.DataDir)...)
}
srv.KnownNodes = knownNodes
if !srv.NoDiscovery {
if srv.DiscoveryV5 {
unhandled = make(chan discover.ReadPacket, 100)
@ -561,7 +559,7 @@ func (srv *Server) setupDiscovery() error {
Bootnodes: srv.BootstrapNodes,
Unhandled: unhandled,
}
ntab, err := discover.ListenUDP(conn, knownNodes, cfg)
ntab, err := discover.ListenUDP(conn, srv.localnode, cfg, knownNodes)
if err != nil {
return err
}

View File

@ -9,5 +9,5 @@ var (
const (
PERMISSIONED_CONFIG = "permissioned-nodes.json"
BLACKLIST_CONFIG = "disallowed-nodes.json"
BLACKLIST_CONFIG = "disallowed-nodes.json"
)

View File

@ -44,6 +44,6 @@ func (s *PublicRaftAPI) Cluster() []*Address {
return append(nodeInfo.PeerAddresses, nodeInfo.Address)
}
func (s *PublicRaftAPI) GetRaftId (enodeId string) (uint16, error) {
func (s *PublicRaftAPI) GetRaftId(enodeId string) (uint16, error) {
return s.raftService.raftProtocolManager.FetchRaftId(enodeId)
}

View File

@ -932,13 +932,13 @@ func (pm *ProtocolManager) LeaderAddress() (*Address, error) {
}
// Returns the raft id for a given enodeId
func (pm *ProtocolManager) FetchRaftId (enodeId string) (uint16, error) {
node, err := discover.ParseNode(enodeId)
func (pm *ProtocolManager) FetchRaftId(enodeId string) (uint16, error) {
node, err := enode.ParseV4(enodeId)
if err != nil {
return 0, err
}
for raftId, peer := range pm.peers {
if peer.p2pNode.ID == node.ID {
if peer.p2pNode.ID() == node.ID() {
return raftId, nil
}
}