mirror of https://github.com/ethereum/go-ethereum
Overview of changes: - ClientIdentity has been removed, use discover.NodeID - Server now requires a private key to be set (instead of public key) - Server performs the encryption handshake before launching Peer - Dial logic takes peers from discover table - Encryption handshake code has been cleaned up a bit - baseProtocol is gone because we don't exchange peers anymore - Some parts of baseProtocol have moved into Peer insteadpull/292/head
parent
739066ec56
commit
5bdc115943
@ -1,68 +0,0 @@ |
||||
package p2p |
||||
|
||||
import ( |
||||
"fmt" |
||||
"runtime" |
||||
) |
||||
|
||||
// ClientIdentity represents the identity of a peer.
|
||||
type ClientIdentity interface { |
||||
String() string // human readable identity
|
||||
Pubkey() []byte // 512-bit public key
|
||||
} |
||||
|
||||
type SimpleClientIdentity struct { |
||||
clientIdentifier string |
||||
version string |
||||
customIdentifier string |
||||
os string |
||||
implementation string |
||||
privkey []byte |
||||
pubkey []byte |
||||
} |
||||
|
||||
func NewSimpleClientIdentity(clientIdentifier string, version string, customIdentifier string, pubkey []byte) *SimpleClientIdentity { |
||||
clientIdentity := &SimpleClientIdentity{ |
||||
clientIdentifier: clientIdentifier, |
||||
version: version, |
||||
customIdentifier: customIdentifier, |
||||
os: runtime.GOOS, |
||||
implementation: runtime.Version(), |
||||
pubkey: pubkey, |
||||
} |
||||
|
||||
return clientIdentity |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) init() { |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) String() string { |
||||
var id string |
||||
if len(c.customIdentifier) > 0 { |
||||
id = "/" + c.customIdentifier |
||||
} |
||||
|
||||
return fmt.Sprintf("%s/v%s%s/%s/%s", |
||||
c.clientIdentifier, |
||||
c.version, |
||||
id, |
||||
c.os, |
||||
c.implementation) |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) Privkey() []byte { |
||||
return c.privkey |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) Pubkey() []byte { |
||||
return c.pubkey |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) SetCustomIdentifier(customIdentifier string) { |
||||
c.customIdentifier = customIdentifier |
||||
} |
||||
|
||||
func (c *SimpleClientIdentity) GetCustomIdentifier() string { |
||||
return c.customIdentifier |
||||
} |
@ -1,35 +0,0 @@ |
||||
package p2p |
||||
|
||||
import ( |
||||
"bytes" |
||||
"fmt" |
||||
"runtime" |
||||
"testing" |
||||
) |
||||
|
||||
func TestClientIdentity(t *testing.T) { |
||||
clientIdentity := NewSimpleClientIdentity("Ethereum(G)", "0.5.16", "test", []byte("pubkey")) |
||||
key := clientIdentity.Pubkey() |
||||
if !bytes.Equal(key, []byte("pubkey")) { |
||||
t.Errorf("Expected Pubkey to be %x, got %x", key, []byte("pubkey")) |
||||
} |
||||
clientString := clientIdentity.String() |
||||
expected := fmt.Sprintf("Ethereum(G)/v0.5.16/test/%s/%s", runtime.GOOS, runtime.Version()) |
||||
if clientString != expected { |
||||
t.Errorf("Expected clientIdentity to be %v, got %v", expected, clientString) |
||||
} |
||||
customIdentifier := clientIdentity.GetCustomIdentifier() |
||||
if customIdentifier != "test" { |
||||
t.Errorf("Expected clientIdentity.GetCustomIdentifier() to be 'test', got %v", customIdentifier) |
||||
} |
||||
clientIdentity.SetCustomIdentifier("test2") |
||||
customIdentifier = clientIdentity.GetCustomIdentifier() |
||||
if customIdentifier != "test2" { |
||||
t.Errorf("Expected clientIdentity.GetCustomIdentifier() to be 'test2', got %v", customIdentifier) |
||||
} |
||||
clientString = clientIdentity.String() |
||||
expected = fmt.Sprintf("Ethereum(G)/v0.5.16/test2/%s/%s", runtime.GOOS, runtime.Version()) |
||||
if clientString != expected { |
||||
t.Errorf("Expected clientIdentity to be %v, got %v", expected, clientString) |
||||
} |
||||
} |
@ -1,167 +0,0 @@ |
||||
package p2p |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net" |
||||
"reflect" |
||||
"sync" |
||||
"testing" |
||||
|
||||
"github.com/ethereum/go-ethereum/crypto" |
||||
) |
||||
|
||||
type peerId struct { |
||||
privKey, pubkey []byte |
||||
} |
||||
|
||||
func (self *peerId) String() string { |
||||
return fmt.Sprintf("test peer %x", self.Pubkey()[:4]) |
||||
} |
||||
|
||||
func (self *peerId) Pubkey() (pubkey []byte) { |
||||
pubkey = self.pubkey |
||||
if len(pubkey) == 0 { |
||||
pubkey = crypto.GenerateNewKeyPair().PublicKey |
||||
self.pubkey = pubkey |
||||
} |
||||
return |
||||
} |
||||
|
||||
func (self *peerId) PrivKey() (privKey []byte) { |
||||
privKey = self.privKey |
||||
if len(privKey) == 0 { |
||||
privKey = crypto.GenerateNewKeyPair().PublicKey |
||||
self.privKey = privKey |
||||
} |
||||
return |
||||
} |
||||
|
||||
func newTestPeer() (peer *Peer) { |
||||
peer = NewPeer(&peerId{}, []Cap{}) |
||||
peer.pubkeyHook = func(*peerAddr) error { return nil } |
||||
peer.ourID = &peerId{} |
||||
peer.listenAddr = &peerAddr{} |
||||
peer.otherPeers = func() []*Peer { return nil } |
||||
return |
||||
} |
||||
|
||||
func TestBaseProtocolPeers(t *testing.T) { |
||||
peerList := []*peerAddr{ |
||||
{IP: net.ParseIP("1.2.3.4"), Port: 2222, Pubkey: []byte{}}, |
||||
{IP: net.ParseIP("5.6.7.8"), Port: 3333, Pubkey: []byte{}}, |
||||
} |
||||
listenAddr := &peerAddr{IP: net.ParseIP("1.3.5.7"), Port: 1111, Pubkey: []byte{}} |
||||
rw1, rw2 := MsgPipe() |
||||
defer rw1.Close() |
||||
wg := new(sync.WaitGroup) |
||||
|
||||
// run matcher, close pipe when addresses have arrived
|
||||
numPeers := len(peerList) + 1 |
||||
addrChan := make(chan *peerAddr) |
||||
wg.Add(1) |
||||
go func() { |
||||
i := 0 |
||||
for got := range addrChan { |
||||
var want *peerAddr |
||||
switch { |
||||
case i < len(peerList): |
||||
want = peerList[i] |
||||
case i == len(peerList): |
||||
want = listenAddr // listenAddr should be the last thing sent
|
||||
} |
||||
t.Logf("got peer %d/%d: %v", i+1, numPeers, got) |
||||
if !reflect.DeepEqual(want, got) { |
||||
t.Errorf("mismatch: got %+v, want %+v", got, want) |
||||
} |
||||
i++ |
||||
if i == numPeers { |
||||
break |
||||
} |
||||
} |
||||
if i != numPeers { |
||||
t.Errorf("wrong number of peers received: got %d, want %d", i, numPeers) |
||||
} |
||||
rw1.Close() |
||||
wg.Done() |
||||
}() |
||||
|
||||
// run first peer (in background)
|
||||
peer1 := newTestPeer() |
||||
peer1.ourListenAddr = listenAddr |
||||
peer1.otherPeers = func() []*Peer { |
||||
pl := make([]*Peer, len(peerList)) |
||||
for i, addr := range peerList { |
||||
pl[i] = &Peer{listenAddr: addr} |
||||
} |
||||
return pl |
||||
} |
||||
wg.Add(1) |
||||
go func() { |
||||
runBaseProtocol(peer1, rw1) |
||||
wg.Done() |
||||
}() |
||||
|
||||
// run second peer
|
||||
peer2 := newTestPeer() |
||||
peer2.newPeerAddr = addrChan // feed peer suggestions into matcher
|
||||
if err := runBaseProtocol(peer2, rw2); err != ErrPipeClosed { |
||||
t.Errorf("peer2 terminated with unexpected error: %v", err) |
||||
} |
||||
|
||||
// terminate matcher
|
||||
close(addrChan) |
||||
wg.Wait() |
||||
} |
||||
|
||||
func TestBaseProtocolDisconnect(t *testing.T) { |
||||
peer := NewPeer(&peerId{}, nil) |
||||
peer.ourID = &peerId{} |
||||
peer.pubkeyHook = func(*peerAddr) error { return nil } |
||||
|
||||
rw1, rw2 := MsgPipe() |
||||
done := make(chan struct{}) |
||||
go func() { |
||||
if err := expectMsg(rw2, handshakeMsg); err != nil { |
||||
t.Error(err) |
||||
} |
||||
err := EncodeMsg(rw2, handshakeMsg, |
||||
baseProtocolVersion, |
||||
"", |
||||
[]interface{}{}, |
||||
0, |
||||
make([]byte, 64), |
||||
) |
||||
if err != nil { |
||||
t.Error(err) |
||||
} |
||||
if err := expectMsg(rw2, getPeersMsg); err != nil { |
||||
t.Error(err) |
||||
} |
||||
if err := EncodeMsg(rw2, discMsg, DiscQuitting); err != nil { |
||||
t.Error(err) |
||||
} |
||||
|
||||
close(done) |
||||
}() |
||||
|
||||
if err := runBaseProtocol(peer, rw1); err == nil { |
||||
t.Errorf("base protocol returned without error") |
||||
} else if reason, ok := err.(discRequestedError); !ok || reason != DiscQuitting { |
||||
t.Errorf("base protocol returned wrong error: %v", err) |
||||
} |
||||
<-done |
||||
} |
||||
|
||||
func expectMsg(r MsgReader, code uint64) error { |
||||
msg, err := r.ReadMsg() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
if err := msg.Discard(); err != nil { |
||||
return err |
||||
} |
||||
if msg.Code != code { |
||||
return fmt.Errorf("wrong message code: got %d, expected %d", msg.Code, code) |
||||
} |
||||
return nil |
||||
} |
@ -1,40 +0,0 @@ |
||||
// +build none
|
||||
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"log" |
||||
"net" |
||||
"os" |
||||
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1" |
||||
"github.com/ethereum/go-ethereum/logger" |
||||
"github.com/ethereum/go-ethereum/p2p" |
||||
) |
||||
|
||||
func main() { |
||||
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.DebugLevel)) |
||||
|
||||
pub, _ := secp256k1.GenerateKeyPair() |
||||
srv := p2p.Server{ |
||||
MaxPeers: 10, |
||||
Identity: p2p.NewSimpleClientIdentity("test", "1.0", "", string(pub)), |
||||
ListenAddr: ":30303", |
||||
NAT: p2p.PMP(net.ParseIP("10.0.0.1")), |
||||
} |
||||
if err := srv.Start(); err != nil { |
||||
fmt.Println("could not start server:", err) |
||||
os.Exit(1) |
||||
} |
||||
|
||||
// add seed peers
|
||||
seed, err := net.ResolveTCPAddr("tcp", "poc-7.ethdev.com:30303") |
||||
if err != nil { |
||||
fmt.Println("couldn't resolve:", err) |
||||
os.Exit(1) |
||||
} |
||||
srv.SuggestPeer(seed.IP, seed.Port, nil) |
||||
|
||||
select {} |
||||
} |
Loading…
Reference in new issue