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