diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 2c522a9a3..8c2b26feb 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -26,13 +26,13 @@ import ( "time" "unicode" - cli "gopkg.in/urfave/cli.v1" + "gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/dashboard" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/raft" whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" @@ -218,7 +218,7 @@ func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, eth if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { privkey := cfg.Node.NodeKey() - strId := discover.PubkeyID(&privkey.PublicKey).String() + strId := enode.PubkeyToIDV4(&privkey.PublicKey).String() blockTimeNanos := time.Duration(blockTimeMillis) * time.Millisecond peers := cfg.Node.StaticNodes() @@ -238,7 +238,7 @@ func RegisterRaftService(stack *node.Node, ctx *cli.Context, cfg gethConfig, eth utils.Fatalf("raftport querystring parameter not specified in static-node enode ID: %v. please check your static-nodes.json file.", peer.String()) } - peerId := peer.ID.String() + peerId := peer.ID().String() peerIds[peerIdx] = peerId if peerId == strId { myId = uint16(peerIdx) + 1 diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index cfb37d986..97eaef706 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -673,7 +673,7 @@ func (ethash *Ethash) SetThreads(threads int) { // Note the returned hashrate includes local hashrate, but also includes the total // hashrate of all remote miner. func (ethash *Ethash) Hashrate() float64 { - if(ethash.hashrate == nil){ + if ethash.hashrate == nil { return 0 } // Short circuit if we are run the ethash in normal/test mode. diff --git a/core/blockchain.go b/core/blockchain.go index 09ae601a0..ee9feb6a8 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -155,21 +155,21 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par badBlocks, _ := lru.New(badBlockLimit) bc := &BlockChain{ - chainConfig: chainConfig, - cacheConfig: cacheConfig, - db: db, - triegc: prque.New(nil), - stateCache: state.NewDatabase(db), - quit: make(chan struct{}), - shouldPreserve: shouldPreserve, - bodyCache: bodyCache, - bodyRLPCache: bodyRLPCache, - receiptsCache: receiptsCache, - blockCache: blockCache, - futureBlocks: futureBlocks, - engine: engine, - vmConfig: vmConfig, - badBlocks: badBlocks, + chainConfig: chainConfig, + cacheConfig: cacheConfig, + db: db, + triegc: prque.New(nil), + stateCache: state.NewDatabase(db), + quit: make(chan struct{}), + shouldPreserve: shouldPreserve, + bodyCache: bodyCache, + bodyRLPCache: bodyRLPCache, + receiptsCache: receiptsCache, + blockCache: blockCache, + futureBlocks: futureBlocks, + engine: engine, + vmConfig: vmConfig, + badBlocks: badBlocks, privateStateCache: state.NewDatabase(db), } bc.SetValidator(NewBlockValidator(chainConfig, bc, engine)) diff --git a/core/vm/evm.go b/core/vm/evm.go index 3f5e4c45e..aaebfb5ce 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -428,6 +428,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, return nil, common.Address{}, gas, ErrInsufficientBalance } + // Quorum // Get the right state in case of a dual state environment. If a sender // is a transaction (depth == 0) use the public state to derive the address // and increment the nonce of the public state. If the sender is a contract @@ -447,16 +448,15 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, creatorStateDb.SetNonce(caller.Address(), nonce+1) // Ensure there's no existing contract already at the designated address - contractAddr := crypto.CreateAddress(caller.Address(), nonce) - contractHash := evm.StateDB.GetCodeHash(contractAddr) - if evm.StateDB.GetNonce(contractAddr) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { + contractHash := evm.StateDB.GetCodeHash(address) + if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { return nil, common.Address{}, 0, ErrContractAddressCollision } // Create a new account on the state snapshot := evm.StateDB.Snapshot() - evm.StateDB.CreateAccount(contractAddr) + evm.StateDB.CreateAccount(address) if evm.ChainConfig().IsEIP158(evm.BlockNumber) { - evm.StateDB.SetNonce(contractAddr, 1) + evm.StateDB.SetNonce(address, 1) } if evm.ChainConfig().IsQuorum { // skip transfer if value /= 0 (see note: Quorum, States, and Value Transfer) @@ -464,10 +464,10 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if evm.quorumReadOnly { return nil, common.Address{}, gas, ErrReadOnlyValueTransfer } - evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value) + evm.Transfer(evm.StateDB, caller.Address(), address, value) } } else { - evm.Transfer(evm.StateDB, caller.Address(), contractAddr, value) + evm.Transfer(evm.StateDB, caller.Address(), address, value) } // initialise a new contract and set the code that is to be used by the @@ -477,7 +477,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, contract.SetCodeOptionalHash(&address, codeAndHash) if evm.vmConfig.NoRecursion && evm.depth > 0 { - return nil, contractAddr, gas, nil + return nil, address, gas, nil } if evm.vmConfig.Debug && evm.depth == 0 { @@ -496,7 +496,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if err == nil && !maxCodeSizeExceeded { createDataGas := uint64(len(ret)) * params.CreateDataGas if contract.UseGas(createDataGas) { - evm.StateDB.SetCode(contractAddr, ret) + evm.StateDB.SetCode(address, ret) } else { err = ErrCodeStoreOutOfGas } @@ -518,13 +518,31 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, if evm.vmConfig.Debug && evm.depth == 0 { evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) } - return ret, contractAddr, contract.Gas, err + return ret, address, contract.Gas, err } // Create creates a new contract using code as deployment code. func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { - contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) + // Quorum + // Get the right state in case of a dual state environment. If a sender + // is a transaction (depth == 0) use the public state to derive the address + // and increment the nonce of the public state. If the sender is a contract + // (depth > 0) use the private state to derive the nonce and increment the + // nonce on the private state only. + // + // If the transaction went to a public contract the private and public state + // are the same. + var creatorStateDb StateDB + if evm.depth > 0 { + creatorStateDb = evm.privateState + } else { + creatorStateDb = evm.publicState + } + + // Ensure there's no existing contract already at the designated address + nonce := creatorStateDb.GetNonce(caller.Address()) + contractAddr = crypto.CreateAddress(caller.Address(), nonce) return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr) } @@ -582,6 +600,8 @@ func (env *EVM) Pop() { env.StateDB = env.states[env.currentStateDepth-1] } +func (env *EVM) Depth() int { return env.depth } + // We only need to revert the current state because when we call from private // public state it's read only, there wouldn't be anything to reset. // (A)->(B)->C->(B): A failure in (B) wouldn't need to reset C, as C was flagged diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 61d8dc42e..191a50396 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -34,9 +34,9 @@ type twoOperandTest struct { func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)) { var ( - env = NewEVM(Context{}, nil,nil, params.TestChainConfig, Config{}) - stack = newstack() - pc = uint64(0) + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() + pc = uint64(0) evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -75,8 +75,8 @@ func testTwoOperandOp(t *testing.T, tests []twoOperandTest, opFn func(pc *uint64 func TestByteOp(t *testing.T) { var ( - env = NewEVM(Context{}, nil, nil,params.TestChainConfig, Config{}) - stack = newstack() + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -210,8 +210,8 @@ func TestSLT(t *testing.T) { func opBenchmark(bench *testing.B, op func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error), args ...string) { var ( - env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) - stack = newstack() + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -445,9 +445,9 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(Context{}, nil, nil,params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() + mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) @@ -471,9 +471,9 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) - stack = newstack() - mem = NewMemory() + env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{}) + stack = newstack() + mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.vmConfig) ) diff --git a/core/vm/interface.go b/core/vm/interface.go index 3420a8f3c..6267bf000 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -20,6 +20,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" ) @@ -30,6 +31,11 @@ type MinimalApiState interface { GetCode(addr common.Address) []byte GetState(a common.Address, b common.Hash) common.Hash GetNonce(addr common.Address) uint64 + GetProof(common.Address) ([][]byte, error) + GetStorageProof(common.Address, common.Hash) ([][]byte, error) + StorageTrie(addr common.Address) state.Trie + Error() error + GetCodeHash(common.Address) common.Hash } // StateDB is an EVM database for full state querying. @@ -44,7 +50,7 @@ type StateDB interface { //GetNonce(common.Address) uint64 SetNonce(common.Address, uint64) - GetCodeHash(common.Address) common.Hash + //GetCodeHash(common.Address) common.Hash //GetCode(common.Address) []byte SetCode(common.Address, []byte) GetCodeSize(common.Address) int diff --git a/eth/api.go b/eth/api.go index 6e4fa3eaa..3fe04717c 100644 --- a/eth/api.go +++ b/eth/api.go @@ -89,6 +89,7 @@ func (s *PublicEthereumAPI) StorageRoot(addr common.Address, blockNr *rpc.BlockN } return pub.GetStorageRoot(addr) } + // Hashrate returns the POW hashrate func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 { return hexutil.Uint64(api.e.Miner().HashRate()) diff --git a/eth/api_backend.go b/eth/api_backend.go index ab47e5809..72f763837 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -255,6 +255,7 @@ func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.Ma } } +// used by Quorum type EthAPIState struct { state, privateState *state.StateDB } @@ -287,4 +288,25 @@ func (s EthAPIState) GetNonce(addr common.Address) uint64 { return s.state.GetNonce(addr) } +// TODO: implement the following methods for Quorum +func (s EthAPIState) GetProof(common.Address) ([][]byte, error) { + return nil, nil +} + +func (s EthAPIState) GetStorageProof(common.Address, common.Hash) ([][]byte, error) { + return nil, nil +} + +func (s EthAPIState) StorageTrie(addr common.Address) state.Trie { + return nil +} + +func (s EthAPIState) Error() error { + return nil +} + +func (s EthAPIState) GetCodeHash(common.Address) common.Hash { + return common.Hash{} +} + //func (s MinimalApiState) Error diff --git a/eth/handler.go b/eth/handler.go index 89e92f4fa..5800d7ec0 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -360,10 +360,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { return nil } } else if handler, ok := pm.engine.(consensus.Handler); ok { - pubKey, err := p.ID().Pubkey() - if err != nil { - return err - } + pubKey := p.Node().Pubkey() addr := crypto.PubkeyToAddress(*pubKey) handled, err := handler.HandleMsg(addr, msg) if handled { @@ -777,7 +774,6 @@ func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) { } } - // BroadcastTxs will propagate a batch of transactions to all peers which are not known to // already have the given transaction. func (pm *ProtocolManager) BroadcastTxs(txs types.Transactions) { @@ -852,10 +848,7 @@ func (pm *ProtocolManager) NodeInfo() *NodeInfo { func (self *ProtocolManager) FindPeers(targets map[common.Address]bool) map[common.Address]consensus.Peer { m := make(map[common.Address]consensus.Peer) for _, p := range self.peers.Peers() { - pubKey, err := p.ID().Pubkey() - if err != nil { - continue - } + pubKey := p.Node().Pubkey() addr := crypto.PubkeyToAddress(*pubKey) if targets[addr] { m[addr] = p diff --git a/eth/handler_test.go b/eth/handler_test.go index a4762b239..529ee22da 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -246,10 +246,10 @@ func testGetBlockBodies(t *testing.T, protocol int) { available []bool // Availability of explicitly requested blocks expected int // Total number of existing blocks to expect }{ - {1, nil, nil, 1}, // A single random block should be retrievable - {10, nil, nil, 10}, // Multiple random blocks should be retrievable - {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable - {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned + {1, nil, nil, 1}, // A single random block should be retrievable + {10, nil, nil, 10}, // Multiple random blocks should be retrievable + {limit, nil, nil, limit}, // The maximum possible blocks should be retrievable + {limit + 1, nil, nil, limit}, // No more than the possible block count should be returned {0, []common.Hash{pm.blockchain.Genesis().Hash()}, []bool{true}, 1}, // The genesis block should be retrievable {0, []common.Hash{pm.blockchain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned diff --git a/les/serverpool.go b/les/serverpool.go index 0fe6e49b6..12688f62f 100644 --- a/les/serverpool.go +++ b/les/serverpool.go @@ -191,7 +191,7 @@ func (pool *serverPool) discoverNodes() { if err != nil { continue } - pool.discNodes <- enode.NewV4(pubkey, n.IP, int(n.TCP), int(n.UDP)) + pool.discNodes <- enode.NewV4(pubkey, n.IP, int(n.TCP), int(n.UDP), 0) } } @@ -667,7 +667,7 @@ func (e *poolEntry) DecodeRLP(s *rlp.Stream) error { return err } addr := &poolEntryAddress{ip: entry.IP, port: entry.Port, fails: entry.Fails, lastSeen: mclock.Now()} - e.node = enode.NewV4(pubkey, entry.IP, int(entry.Port), int(entry.Port)) + e.node = enode.NewV4(pubkey, entry.IP, int(entry.Port), int(entry.Port), 0) e.addr = make(map[string]*poolEntryAddress) e.addr[addr.strKey()] = addr e.addrSelect = *newWeightedRandomSelect() diff --git a/node/config.go b/node/config.go index 8d045a167..e54f3a9d8 100644 --- a/node/config.go +++ b/node/config.go @@ -368,7 +368,9 @@ func (c *Config) parsePersistentNodes(path string) []*enode.Node { if url == "" { continue } + log.Info("AJ-parsePersistentNodes1", "url", url) node, err := enode.ParseV4(url) + log.Info("AJ-parsePersistentNodes2", "url", url, "ID", node.ID().String(), "EnodeID", node.EnodeID()) if err != nil { log.Error(fmt.Sprintf("Node URL %s: %v\n", url, err)) continue diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index 6b4cd2d18..d8431209b 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -57,7 +57,7 @@ func testPingReplace(t *testing.T, newNodeIsResponding, lastInBucketIsResponding // Fill up the sender's bucket. pingKey, _ := crypto.HexToECDSA("45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8") - pingSender := wrapNode(enode.NewV4(&pingKey.PublicKey, net.IP{}, 99, 99)) + pingSender := wrapNode(enode.NewV4(&pingKey.PublicKey, net.IP{}, 99, 99, 0)) last := fillBucket(tab, pingSender) // Add the sender as if it just pinged us. Revalidate should replace the last node in @@ -289,7 +289,7 @@ func TestTable_Lookup(t *testing.T) { } // seed table with initial node (otherwise lookup will terminate immediately) seedKey, _ := decodePubkey(lookupTestnet.dists[256][0]) - seed := wrapNode(enode.NewV4(seedKey, net.IP{}, 0, 256)) + seed := wrapNode(enode.NewV4(seedKey, net.IP{}, 0, 256, 0)) tab.stuff([]*node{seed}) results := tab.lookup(lookupTestnet.target, true) @@ -524,7 +524,7 @@ func (tn *preminedTestnet) findnode(toid enode.ID, toaddr *net.UDPAddr, target e var result []*node for i, ekey := range tn.dists[toaddr.Port] { key, _ := decodePubkey(ekey) - node := wrapNode(enode.NewV4(key, net.ParseIP("127.0.0.1"), i, next)) + node := wrapNode(enode.NewV4(key, net.ParseIP("127.0.0.1"), i, next, 0)) result = append(result, node) } return result, nil diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index 37a044902..cb1e67387 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -141,7 +141,7 @@ func (t *udp) nodeFromRPC(sender *net.UDPAddr, rn rpcNode) (*node, error) { if err != nil { return nil, err } - n := wrapNode(enode.NewV4(key, rn.IP, int(rn.TCP), int(rn.UDP))) + n := wrapNode(enode.NewV4(key, rn.IP, int(rn.TCP), int(rn.UDP), 0)) err = n.ValidateComplete() return n, err } @@ -628,7 +628,7 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromKey encPubkey, mac []byte ReplyTok: mac, Expiration: uint64(time.Now().Add(expiration).Unix()), }) - n := wrapNode(enode.NewV4(key, from.IP, int(req.From.TCP), from.Port)) + n := wrapNode(enode.NewV4(key, from.IP, int(req.From.TCP), from.Port, 0)) t.handleReply(n.ID(), pingPacket, req) if time.Since(t.db.LastPongReceived(n.ID())) > bondExpiration { t.sendPing(n.ID(), from, func() { t.tab.addThroughPing(n) }) diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go index a4ddaf750..84c3dd16f 100644 --- a/p2p/discover/udp_test.go +++ b/p2p/discover/udp_test.go @@ -244,7 +244,7 @@ func TestUDP_findnode(t *testing.T) { nodes := &nodesByDistance{target: testTarget.id()} for i := 0; i < bucketSize; i++ { key := newkey() - n := wrapNode(enode.NewV4(&key.PublicKey, net.IP{10, 13, 0, 1}, 0, i)) + n := wrapNode(enode.NewV4(&key.PublicKey, net.IP{10, 13, 0, 1}, 0, i, 0)) nodes.push(n, bucketSize) } test.table.stuff(nodes.entries) diff --git a/p2p/enode/node.go b/p2p/enode/node.go index b454ab255..3ca1d54f2 100644 --- a/p2p/enode/node.go +++ b/p2p/enode/node.go @@ -82,6 +82,20 @@ func (n *Node) UDP() int { return int(port) } +// RAFTPORT returns the RAFT PORT of the node +func (n *Node) RAFTPORT() int { + var port enr.RAFTPORT + err := n.Load(&port) + if err != nil { + return 0 + } + return int(port) +} + +func (n *Node) HasRaftPort() bool { + return n.RAFTPORT() > 0 +} + // UDP returns the TCP port of the node. func (n *Node) TCP() int { var port enr.TCP diff --git a/p2p/enode/nodedb_test.go b/p2p/enode/nodedb_test.go index 96794827c..9e1cb86d6 100644 --- a/p2p/enode/nodedb_test.go +++ b/p2p/enode/nodedb_test.go @@ -105,6 +105,7 @@ func TestDBFetchStore(t *testing.T) { net.IP{192, 168, 0, 1}, 30303, 30303, + 0, ) inst := time.Now() num := 314 @@ -168,6 +169,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 3}, 30303, 30303, + 0, ), pong: time.Now().Add(-3 * time.Hour), }, @@ -179,6 +181,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 3}, 30303, 30303, + 0, ), pong: time.Now().Add(-4 * time.Second), }, @@ -190,6 +193,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 1}, 30303, 30303, + 0, ), pong: time.Now().Add(-2 * time.Second), }, @@ -199,6 +203,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 2}, 30303, 30303, + 0, ), pong: time.Now().Add(-3 * time.Second), }, @@ -208,6 +213,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 3}, 30303, 30303, + 0, ), pong: time.Now().Add(-1 * time.Second), }, @@ -217,6 +223,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 3}, 30303, 30303, + 0, ), pong: time.Now().Add(-2 * time.Second), }, @@ -226,6 +233,7 @@ var nodeDBSeedQueryNodes = []struct { net.IP{127, 0, 0, 3}, 30303, 30303, + 0, ), pong: time.Now().Add(-2 * time.Second), }, @@ -331,6 +339,7 @@ var nodeDBExpirationNodes = []struct { net.IP{127, 0, 0, 1}, 30303, 30303, + 0, ), pong: time.Now().Add(-dbNodeExpiration + time.Minute), exp: false, @@ -340,6 +349,7 @@ var nodeDBExpirationNodes = []struct { net.IP{127, 0, 0, 2}, 30303, 30303, + 0, ), pong: time.Now().Add(-dbNodeExpiration - time.Minute), exp: true, diff --git a/p2p/enode/urlv4.go b/p2p/enode/urlv4.go index 50e9485d0..ecd6e2df3 100644 --- a/p2p/enode/urlv4.go +++ b/p2p/enode/urlv4.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p/enr" ) @@ -72,14 +73,14 @@ func ParseV4(rawurl string) (*Node, error) { if err != nil { return nil, fmt.Errorf("invalid node ID (%v)", err) } - return NewV4(id, nil, 0, 0), nil + return NewV4(id, nil, 0, 0, 0), nil } return parseComplete(rawurl) } // NewV4 creates a node from discovery v4 node information. The record // contained in the node has a zero-length signature. -func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp int) *Node { +func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp, raftPort int) *Node { var r enr.Record if ip != nil { r.Set(enr.IP(ip)) @@ -90,11 +91,17 @@ func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp int) *Node { if tcp != 0 { r.Set(enr.TCP(tcp)) } + + if raftPort != 0 { + r.Set(enr.RAFTPORT(tcp)) + } + signV4Compat(&r, pubkey) n, err := New(v4CompatID{}, &r) if err != nil { panic(err) } + log.Info("NewV4", "raftPort", raftPort, "nodeId", n.ID().String(), "NodeId.bytes", n.ID().Bytes()) return n } @@ -115,9 +122,11 @@ func parseComplete(rawurl string) (*Node, error) { if u.User == nil { return nil, errors.New("does not contain node ID") } + log.Info("AJ-parseComplete1", "u.User", u.User.String()) if id, err = parsePubkey(u.User.String()); err != nil { return nil, fmt.Errorf("invalid node ID (%v)", err) } + log.Info("AJ-parseComplete2", "id", id) // Parse the IP address. host, port, err := net.SplitHostPort(u.Host) if err != nil { @@ -142,7 +151,28 @@ func parseComplete(rawurl string) (*Node, error) { return nil, errors.New("invalid discport in query") } } - return NewV4(id, ip, int(tcpPort), int(udpPort)), nil + + var node *Node + + if qv.Get("raftport") != "" { + raftPort, err := strconv.ParseUint(qv.Get("raftport"), 10, 16) + if err != nil { + return nil, errors.New("invalid raftport in query") + } + node = NewV4(id, ip, int(tcpPort), int(udpPort), int(raftPort)) + } else { + node = NewV4(id, ip, int(tcpPort), int(udpPort), 0) + } + return node, nil + +} + +func HexPubkey(h string) (*ecdsa.PublicKey, error) { + k, err := parsePubkey(h) + if err != nil { + return nil, err + } + return k, err } // parsePubkey parses a hex-encoded secp256k1 public key. @@ -157,7 +187,8 @@ func parsePubkey(in string) (*ecdsa.PublicKey, error) { return crypto.UnmarshalPubkey(b) } -func (n *Node) v4URL() string { +// TODO: Amal to review it - added for RAFT +func (n *Node) EnodeID() string { var ( scheme enr.ID nodeid string @@ -171,6 +202,25 @@ func (n *Node) v4URL() string { default: nodeid = fmt.Sprintf("%s.%x", scheme, n.id[:]) } + return nodeid +} + +func (n *Node) v4URL() string { + var ( + scheme enr.ID + nodeid string + key ecdsa.PublicKey + ) + n.Load(&scheme) + n.Load((*Secp256k1)(&key)) + switch { + case scheme == "v4" || key != ecdsa.PublicKey{}: + log.Info("AJ-schemeV4") + nodeid = fmt.Sprintf("%x", crypto.FromECDSAPub(&key)[1:]) + default: + log.Info("AJ-NOT schemeV4") + nodeid = fmt.Sprintf("%s.%x", scheme, n.id[:]) + } u := url.URL{Scheme: "enode"} if n.Incomplete() { u.Host = nodeid @@ -181,6 +231,15 @@ func (n *Node) v4URL() string { if n.UDP() != n.TCP() { u.RawQuery = "discport=" + strconv.Itoa(n.UDP()) } + raftPort := n.RAFTPORT() + if raftPort != 0 { + raftQuery := "raftport=" + strconv.Itoa(raftPort) + if len(u.RawQuery) > 0 { + u.RawQuery = u.RawQuery + "&" + raftQuery + } else { + u.RawQuery = raftQuery + } + } } return u.String() } diff --git a/p2p/enode/urlv4_test.go b/p2p/enode/urlv4_test.go index 3680ab6b7..f6b9278c1 100644 --- a/p2p/enode/urlv4_test.go +++ b/p2p/enode/urlv4_test.go @@ -60,6 +60,7 @@ var parseNodeTests = []struct { net.IP{0x7f, 0x0, 0x0, 0x1}, 52150, 52150, + 0, ), }, { @@ -69,6 +70,7 @@ var parseNodeTests = []struct { net.ParseIP("::"), 52150, 52150, + 0, ), }, { @@ -78,6 +80,7 @@ var parseNodeTests = []struct { net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 52150, 52150, + 0, ), }, { @@ -87,6 +90,7 @@ var parseNodeTests = []struct { net.IP{0x7f, 0x0, 0x0, 0x1}, 52150, 22334, + 0, ), }, // Incomplete nodes with no address. @@ -94,14 +98,14 @@ var parseNodeTests = []struct { rawurl: "1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", wantResult: NewV4( hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - nil, 0, 0, + nil, 0, 0, 0, ), }, { rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", wantResult: NewV4( hexPubkey("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - nil, 0, 0, + nil, 0, 0, 0, ), }, // Invalid URLs diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index 444820c15..21671c2f3 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -40,6 +40,7 @@ import ( "io" "sort" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -120,6 +121,7 @@ func (r *Record) Load(e Entry) error { if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil { return &KeyError{Key: e.ENRKey(), Err: err} } + log.Info("AJ-Load", "key", e.ENRKey(), "value", r.pairs[i].v) return nil } return &KeyError{Key: e.ENRKey(), Err: errNotFound} diff --git a/p2p/enr/entries.go b/p2p/enr/entries.go index 347990ab6..d81f55ce2 100644 --- a/p2p/enr/entries.go +++ b/p2p/enr/entries.go @@ -77,6 +77,11 @@ type IP net.IP func (v IP) ENRKey() string { return "ip" } +// RaftPort is the "raftport" key, which holds the raftport of the node +type RAFTPORT uint16 + +func (v RAFTPORT) ENRKey() string { return "raftport" } + // EncodeRLP implements rlp.Encoder. func (v IP) EncodeRLP(w io.Writer) error { if ip4 := net.IP(v).To4(); ip4 != nil { diff --git a/p2p/permissions.go b/p2p/permissions.go index 824bb110a..1941b6c82 100644 --- a/p2p/permissions.go +++ b/p2p/permissions.go @@ -7,7 +7,7 @@ import ( "path/filepath" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/p2p/enode" ) const ( @@ -21,7 +21,7 @@ func isNodePermissioned(nodename string, currentNode string, datadir string, dir var permissionedList []string nodes := parsePermissionedNodes(datadir) for _, v := range nodes { - permissionedList = append(permissionedList, v.ID.String()) + permissionedList = append(permissionedList, v.ID().String()) } log.Debug("isNodePermissioned", "permissionedList", permissionedList) @@ -38,7 +38,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) []*enode.Node { log.Debug("parsePermissionedNodes", "DataDir", DataDir, "file", PERMISSIONED_CONFIG) @@ -60,13 +60,13 @@ func parsePermissionedNodes(DataDir string) []*discover.Node { return nil } // Interpret the list as a discovery node array - var nodes []*discover.Node + var nodes []*enode.Node for _, url := range nodelist { if url == "" { log.Error("parsePermissionedNodes: Node URL blank") continue } - node, err := discover.ParseNode(url) + node, err := enode.ParseV4(url) if err != nil { log.Error("parsePermissionedNodes: Node URL", "url", url, "err", err) continue diff --git a/p2p/server.go b/p2p/server.go index 91c18af47..f3d270334 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -360,7 +360,7 @@ func (srv *Server) Self() *enode.Node { srv.lock.Unlock() if ln == nil { - return enode.NewV4(&srv.PrivateKey.PublicKey, net.ParseIP("0.0.0.0"), 0, 0) + return enode.NewV4(&srv.PrivateKey.PublicKey, net.ParseIP("0.0.0.0"), 0, 0, 0) } return ln.Node() } @@ -916,6 +916,17 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro return err } + if dialDest != nil { + // For dialed connections, check that the remote public key matches. + if dialPubkey.X.Cmp(remotePubkey.X) != 0 || dialPubkey.Y.Cmp(remotePubkey.Y) != 0 { + return DiscUnexpectedIdentity + } + c.node = dialDest + } else { + c.node = nodeFromConn(remotePubkey, c.fd) + } + log.Info("AJ-setupConn1", "remotePubkey", remotePubkey) + log.Info("AJ-setupConn2", "c.node.ID", c.node.ID(), "c.node.ID.Bytes", c.node.ID().Bytes(), "node", c.node.String()) clog := srv.log.New("id", c.node.ID(), "addr", c.fd.RemoteAddr(), "conn", c.flags) //START - QUORUM Permissioning @@ -949,16 +960,6 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro //END - QUORUM Permissioning - if dialDest != nil { - // For dialed connections, check that the remote public key matches. - if dialPubkey.X.Cmp(remotePubkey.X) != 0 || dialPubkey.Y.Cmp(remotePubkey.Y) != 0 { - return DiscUnexpectedIdentity - } - c.node = dialDest - } else { - c.node = nodeFromConn(remotePubkey, c.fd) - } - if conn, ok := c.fd.(*meteredConn); ok { conn.handshakeDone(c.node.ID()) } @@ -997,7 +998,7 @@ func nodeFromConn(pubkey *ecdsa.PublicKey, conn net.Conn) *enode.Node { ip = tcp.IP port = tcp.Port } - return enode.NewV4(pubkey, ip, port, port) + return enode.NewV4(pubkey, ip, port, port, 0) } func truncateName(s string) string { diff --git a/p2p/server_test.go b/p2p/server_test.go index 7e11577d6..22430730d 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -147,7 +147,7 @@ func TestServerDial(t *testing.T) { // tell the server to connect tcpAddr := listener.Addr().(*net.TCPAddr) - node := enode.NewV4(remid, tcpAddr.IP, tcpAddr.Port, 0) + node := enode.NewV4(remid, tcpAddr.IP, tcpAddr.Port, 0, 0) srv.AddPeer(node) select { @@ -417,7 +417,7 @@ func TestServerAtCap(t *testing.T) { func TestServerPeerLimits(t *testing.T) { srvkey := newkey() clientkey := newkey() - clientnode := enode.NewV4(&clientkey.PublicKey, nil, 0, 0) + clientnode := enode.NewV4(&clientkey.PublicKey, nil, 0, 0, 0) var tp = &setupTransport{ pubkey: &clientkey.PublicKey, @@ -507,21 +507,21 @@ func TestServerSetupConn(t *testing.T) { }, { tt: &setupTransport{pubkey: clientpub}, - dialDest: enode.NewV4(&newkey().PublicKey, nil, 0, 0), + dialDest: enode.NewV4(&newkey().PublicKey, nil, 0, 0, 0), flags: dynDialedConn, wantCalls: "doEncHandshake,close,", wantCloseErr: DiscUnexpectedIdentity, }, { tt: &setupTransport{pubkey: clientpub, phs: protoHandshake{ID: randomID().Bytes()}}, - dialDest: enode.NewV4(clientpub, nil, 0, 0), + dialDest: enode.NewV4(clientpub, nil, 0, 0, 0), flags: dynDialedConn, wantCalls: "doEncHandshake,doProtoHandshake,close,", wantCloseErr: DiscUnexpectedIdentity, }, { tt: &setupTransport{pubkey: clientpub, protoHandshakeErr: errors.New("foo")}, - dialDest: enode.NewV4(clientpub, nil, 0, 0), + dialDest: enode.NewV4(clientpub, nil, 0, 0, 0), flags: dynDialedConn, wantCalls: "doEncHandshake,doProtoHandshake,close,", wantCloseErr: errors.New("foo"), diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go index 6681726e4..f03eec545 100644 --- a/p2p/simulations/adapters/types.go +++ b/p2p/simulations/adapters/types.go @@ -165,7 +165,7 @@ func (n *NodeConfig) UnmarshalJSON(data []byte) error { // Node returns the node descriptor represented by the config. func (n *NodeConfig) Node() *enode.Node { - return enode.NewV4(&n.PrivateKey.PublicKey, net.IP{127, 0, 0, 1}, int(n.Port), int(n.Port)) + return enode.NewV4(&n.PrivateKey.PublicKey, net.IP{127, 0, 0, 1}, int(n.Port), int(n.Port), 0) } // RandomNodeConfig returns node configuration with a randomly generated ID and diff --git a/params/config.go b/params/config.go index b25894e3a..19a3256e9 100644 --- a/params/config.go +++ b/params/config.go @@ -338,10 +338,10 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int, isQuor if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) { return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block) } - if isQuorumEIP155Activated && c.ChainID!=nil && isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) { + if isQuorumEIP155Activated && c.ChainID != nil && isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) { return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block) } - if isQuorumEIP155Activated && c.ChainID!=nil && c.IsEIP155(head) && !configNumEqual(c.ChainID, newcfg.ChainID) { + if isQuorumEIP155Activated && c.ChainID != nil && c.IsEIP155(head) && !configNumEqual(c.ChainID, newcfg.ChainID) { return newCompatError("EIP155 chain ID", c.ChainID, newcfg.ChainID) } if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) { diff --git a/raft/backend.go b/raft/backend.go index 9b95283cc..d9e54fb5b 100644 --- a/raft/backend.go +++ b/raft/backend.go @@ -14,7 +14,7 @@ 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/p2p/enode" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) @@ -28,7 +28,7 @@ type RaftService struct { downloader *downloader.Downloader raftProtocolManager *ProtocolManager - startPeers []*discover.Node + startPeers []*enode.Node // we need an event mux to instantiate the blockchain eventMux *event.TypeMux @@ -36,7 +36,7 @@ type RaftService struct { nodeKey *ecdsa.PrivateKey } -func New(ctx *node.ServiceContext, chainConfig *params.ChainConfig, raftId, raftPort uint16, joinExisting bool, blockTime time.Duration, e *eth.Ethereum, startPeers []*discover.Node, datadir string) (*RaftService, error) { +func New(ctx *node.ServiceContext, chainConfig *params.ChainConfig, raftId, raftPort uint16, joinExisting bool, blockTime time.Duration, e *eth.Ethereum, startPeers []*enode.Node, datadir string) (*RaftService, error) { service := &RaftService{ eventMux: ctx.EventMux, chainDb: e.ChainDb(), diff --git a/raft/handler.go b/raft/handler.go index 692483e85..b31eb902a 100755 --- a/raft/handler.go +++ b/raft/handler.go @@ -21,14 +21,17 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" - "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/rlp" + "crypto/ecdsa" "github.com/coreos/etcd/etcdserver/stats" raftTypes "github.com/coreos/etcd/pkg/types" etcdRaft "github.com/coreos/etcd/raft" "github.com/coreos/etcd/raft/raftpb" "github.com/coreos/etcd/rafthttp" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/syndtr/goleveldb/leveldb" "gopkg.in/fatih/set.v0" ) @@ -40,7 +43,7 @@ type ProtocolManager struct { // Static configuration joinExisting bool // Whether to join an existing cluster when a WAL doesn't already exist - bootstrapNodes []*discover.Node + bootstrapNodes []*enode.Node raftId uint16 raftPort uint16 @@ -95,7 +98,7 @@ type ProtocolManager struct { // Public interface // -func NewProtocolManager(raftId uint16, raftPort uint16, blockchain *core.BlockChain, mux *event.TypeMux, bootstrapNodes []*discover.Node, joinExisting bool, datadir string, minter *minter, downloader *downloader.Downloader) (*ProtocolManager, error) { +func NewProtocolManager(raftId uint16, raftPort uint16, blockchain *core.BlockChain, mux *event.TypeMux, bootstrapNodes []*enode.Node, joinExisting bool, datadir string, minter *minter, downloader *downloader.Downloader) (*ProtocolManager, error) { waldir := fmt.Sprintf("%s/raft-wal", datadir) snapdir := fmt.Sprintf("%s/raft-snap", datadir) quorumRaftDbLoc := fmt.Sprintf("%s/quorum-raft-state", datadir) @@ -274,7 +277,7 @@ func (pm *ProtocolManager) isRaftIdUsed(raftId uint16) bool { return pm.peers[raftId] != nil } -func (pm *ProtocolManager) isNodeAlreadyInCluster(node *discover.Node) error { +func (pm *ProtocolManager) isNodeAlreadyInCluster(node *enode.Node) error { pm.mu.RLock() defer pm.mu.RUnlock() @@ -282,15 +285,15 @@ func (pm *ProtocolManager) isNodeAlreadyInCluster(node *discover.Node) error { peerRaftId := peer.address.RaftId peerNode := peer.p2pNode - if peerNode.ID == node.ID { + if peerNode.ID() == node.ID() { return fmt.Errorf("node with this enode has already been added to the cluster: %v", node.ID) } - if peerNode.IP.Equal(node.IP) { - if peerNode.TCP == node.TCP { + if peerNode.IP().Equal(node.IP()) { + if peerNode.TCP() == node.TCP() { return fmt.Errorf("existing node %v with raft ID %v is already using eth p2p at %v:%v", peerNode.ID, peerRaftId, node.IP, node.TCP) - } else if peer.address.RaftPort == node.RaftPort { - return fmt.Errorf("existing node %v with raft ID %v is already using raft at %v:%v", peerNode.ID, peerRaftId, node.IP, node.RaftPort) + } else if peer.address.RaftPort == enr.RAFTPORT(node.RAFTPORT()) { + return fmt.Errorf("existing node %v with raft ID %v is already using raft at %v:%v", peerNode.ID, peerRaftId, node.IP, node.RAFTPORT()) } } } @@ -299,13 +302,13 @@ func (pm *ProtocolManager) isNodeAlreadyInCluster(node *discover.Node) error { } func (pm *ProtocolManager) ProposeNewPeer(enodeId string) (uint16, error) { - node, err := discover.ParseNode(enodeId) + node, err := enode.ParseV4(enodeId) if err != nil { return 0, err } - if len(node.IP) != 4 { - return 0, fmt.Errorf("expected IPv4 address (with length 4), but got IP of length %v", len(node.IP)) + if len(node.IP()) != 4 { + return 0, fmt.Errorf("expected IPv4 address (with length 4), but got IP of length %v", len(node.IP())) } if !node.HasRaftPort() { @@ -317,7 +320,7 @@ func (pm *ProtocolManager) ProposeNewPeer(enodeId string) (uint16, error) { } raftId := pm.nextRaftId() - address := newAddress(raftId, node.RaftPort, node) + address := newAddress(raftId, node.RAFTPORT(), node) pm.confChangeProposalC <- raftpb.ConfChange{ Type: raftpb.ConfChangeAddNode, @@ -638,14 +641,31 @@ func raftUrl(address *Address) string { return fmt.Sprintf("http://%s:%d", address.Ip, address.RaftPort) } +func decodePubkey64(b []byte) (*ecdsa.PublicKey, error) { + return crypto.UnmarshalPubkey(append([]byte{0x04}, b...)) +} + func (pm *ProtocolManager) addPeer(address *Address) { pm.mu.Lock() defer pm.mu.Unlock() raftId := address.RaftId + log.Info("AJ-addPeer:", "raftId", raftId, "nodeId", address.NodeId.String(), "bytes", address.NodeId.Bytes(), "address", address) + + //TODO: Amal to confirm if this decoding is correct + //pubKey, err := decodePubkey64(address.NodeId.Bytes()) + + /*if err != nil { + log.Error("AJ-error decoding pub key", "nodeId", address.NodeId.String(), "err", err) + return + }*/ + + log.Info("addPeer: decoded pub key", "pubKey", address.PubKey) + // Add P2P connection: - p2pNode := discover.NewNode(address.NodeId, address.Ip, 0, uint16(address.P2pPort)) + p2pNode := enode.NewV4(address.PubKey, address.Ip, 0, int(address.P2pPort), 0) + log.Info("AJ-p2pNode", "ID1", address.NodeId.String(), "ID2", p2pNode.ID().String()) pm.p2pServer.AddPeer(p2pNode) // Add raft transport connection: @@ -837,7 +857,7 @@ func (pm *ProtocolManager) makeInitialRaftPeers() (raftPeers []etcdRaft.Peer, pe // We initially get the raftPort from the enode ID's query string. As an alternative, we can move away from // requiring the use of static peers for the initial set, and load them from e.g. another JSON file which // contains pairs of enodes and raft ports, or we can get this initial peer list from commandline flags. - address := newAddress(raftId, node.RaftPort, node) + address := newAddress(raftId, node.RAFTPORT(), node) raftPeers[i] = etcdRaft.Peer{ ID: uint64(raftId), diff --git a/raft/peer.go b/raft/peer.go index 84aac4521..b13268745 100644 --- a/raft/peer.go +++ b/raft/peer.go @@ -7,34 +7,43 @@ import ( "fmt" "log" - "github.com/ethereum/go-ethereum/p2p/discover" + "crypto/ecdsa" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/p2p/enr" "github.com/ethereum/go-ethereum/rlp" ) +const nodeIDBits = 512 + +type EnodeID [nodeIDBits / 8]byte + // Serializable information about a Peer. Sufficient to build `etcdRaft.Peer` // or `discover.Node`. type Address struct { - RaftId uint16 `json:"raftId"` - NodeId discover.NodeID `json:"nodeId"` - Ip net.IP `json:"ip"` - P2pPort uint16 `json:"p2pPort"` - RaftPort uint16 `json:"raftPort"` + RaftId uint16 `json:"raftId"` + NodeId [64]byte `json:"nodeId"` + Ip net.IP `json:"ip"` + P2pPort enr.TCP `json:"p2pPort"` + RaftPort enr.RAFTPORT `json:"raftPort"` + PubKey *ecdsa.PublicKey } -func newAddress(raftId uint16, raftPort uint16, node *discover.Node) *Address { +func newAddress(raftId uint16, raftPort int, node *enode.Node) *Address { + node.ID().Bytes() return &Address{ RaftId: raftId, - NodeId: node.ID, - Ip: node.IP, - P2pPort: node.TCP, - RaftPort: raftPort, + NodeId: []byte(node.EnodeID()), + Ip: node.IP(), + P2pPort: enr.TCP(node.TCP()), + RaftPort: enr.RAFTPORT(raftPort), + PubKey: node.Pubkey(), } } // A peer that we're connected to via both raft's http transport, and ethereum p2p type Peer struct { - address *Address // For raft transport - p2pNode *discover.Node // For ethereum transport + address *Address // For raft transport + p2pNode *enode.Node // For ethereum transport } func (addr *Address) EncodeRLP(w io.Writer) error { @@ -45,10 +54,10 @@ func (addr *Address) DecodeRLP(s *rlp.Stream) error { // These fields need to be public: var temp struct { RaftId uint16 - NodeId discover.NodeID + NodeId enode.ID Ip net.IP - P2pPort uint16 - RaftPort uint16 + P2pPort enr.TCP + RaftPort enr.RAFTPORT } if err := s.Decode(&temp); err != nil { diff --git a/raft/snapshot.go b/raft/snapshot.go index 3bec72418..5ce04ec4c 100644 --- a/raft/snapshot.go +++ b/raft/snapshot.go @@ -37,6 +37,8 @@ func (pm *ProtocolManager) buildSnapshot() *Snapshot { defer pm.mu.RUnlock() numNodes := len(pm.confState.Nodes) + log.Info("AJ-numNodes", "nodesSize", numNodes, "nodes", pm.confState.Nodes) + log.Info("AJ-peers", "pm.peers", pm.peers) numRemovedNodes := pm.removedPeers.Size() snapshot := &Snapshot{ @@ -298,8 +300,8 @@ func (pm *ProtocolManager) syncBlockchainUntil(hash common.Hash) { for peerId, peer := range peerMap { log.Info("synchronizing with peer", "peer id", peerId, "hash", hash) - peerId := peer.p2pNode.ID.String() - peerIdPrefix := fmt.Sprintf("%x", peer.p2pNode.ID[:8]) + peerId := peer.p2pNode.ID().String() + peerIdPrefix := fmt.Sprintf("%x", peer.p2pNode.ID().Bytes()[:8]) if err := pm.downloader.Synchronise(peerIdPrefix, hash, big.NewInt(0), downloader.BoundedFullSync); err != nil { log.Info("failed to synchronize with peer", "peer id", peerId) diff --git a/swarm/network/protocol.go b/swarm/network/protocol.go index 66ae94a88..32c18c597 100644 --- a/swarm/network/protocol.go +++ b/swarm/network/protocol.go @@ -378,7 +378,7 @@ func RandomAddr() *BzzAddr { if err != nil { panic("unable to generate key") } - node := enode.NewV4(&key.PublicKey, net.IP{127, 0, 0, 1}, 30303, 30303) + node := enode.NewV4(&key.PublicKey, net.IP{127, 0, 0, 1}, 30303, 30303, 0) return NewAddr(node) } diff --git a/whisper/whisperv5/peer_test.go b/whisper/whisperv5/peer_test.go index 35616aaaf..8c54e0ada 100644 --- a/whisper/whisperv5/peer_test.go +++ b/whisper/whisperv5/peer_test.go @@ -146,7 +146,7 @@ func initialize(t *testing.T) { peerNodeId := nodes[j].id address, _ := net.ResolveTCPAddr("tcp", nodes[j].server.ListenAddr) peerPort := uint16(address.Port) - peer := enode.NewV4(&peerNodeId.PublicKey, address.IP, int(peerPort), int(peerPort)) + peer := enode.NewV4(&peerNodeId.PublicKey, address.IP, int(peerPort), int(peerPort), 0) node.server.AddPeer(peer) } diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 65e62d96c..5ac53b9c4 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -223,7 +223,7 @@ func initialize(t *testing.T) { for j := 0; j < i; j++ { peerNodeId := nodes[j].id address, _ := net.ResolveTCPAddr("tcp", nodes[j].server.ListenAddr) - peer := enode.NewV4(&peerNodeId.PublicKey, address.IP, address.Port, address.Port) + peer := enode.NewV4(&peerNodeId.PublicKey, address.IP, address.Port, address.Port, 0) nodes[i].server.AddPeer(peer) } }