Browse Source

P2P now works with Amino

pull/1347/head
Jae Kwon 7 years ago
parent
commit
901b456151
22 changed files with 193 additions and 200 deletions
  1. +14
    -20
      Gopkg.lock
  2. +7
    -7
      Gopkg.toml
  3. +2
    -2
      config/config.go
  4. +1
    -1
      config/toml.go
  5. +31
    -35
      p2p/conn/connection.go
  6. +29
    -11
      p2p/conn/connection_test.go
  7. +3
    -10
      p2p/conn/secret_connection.go
  8. +0
    -5
      p2p/conn/secret_connection_test.go
  9. +1
    -2
      p2p/conn/wire.go
  10. +3
    -4
      p2p/key.go
  11. +1
    -2
      p2p/netaddress.go
  12. +28
    -35
      p2p/peer.go
  13. +1
    -1
      p2p/peer_set_test.go
  14. +5
    -5
      p2p/peer_test.go
  15. +12
    -22
      p2p/pex/pex_reactor.go
  16. +11
    -12
      p2p/pex/pex_reactor_test.go
  17. +11
    -0
      p2p/pex/wire.go
  18. +6
    -8
      p2p/switch.go
  19. +9
    -10
      p2p/switch_test.go
  20. +2
    -2
      p2p/test_util.go
  21. +4
    -6
      p2p/upnp/probe.go
  22. +12
    -0
      p2p/wire.go

+ 14
- 20
Gopkg.lock View File

@ -229,7 +229,6 @@
revision = "169b1b37be738edb2813dab48c97a549bcf99bb5" revision = "169b1b37be738edb2813dab48c97a549bcf99bb5"
[[projects]] [[projects]]
branch = "develop"
name = "github.com/tendermint/abci" name = "github.com/tendermint/abci"
packages = [ packages = [
"client", "client",
@ -239,7 +238,8 @@
"server", "server",
"types" "types"
] ]
revision = "4e0218467649fecf17ebc5e8161f1c888fc8ff22"
revision = "c62aed95f2ce399ec815b0cafe478af002cdc4e6"
version = "v0.10.3-dev"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -252,16 +252,16 @@
revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057"
[[projects]] [[projects]]
branch = "develop"
name = "github.com/tendermint/go-amino" name = "github.com/tendermint/go-amino"
packages = ["."] packages = ["."]
revision = "b1f32ee20e73716d8bfe695365c0a812b2bd8ef9"
revision = "f55c3351f30e5987500020631f00e87a035ed415"
version = "0.9.3"
[[projects]] [[projects]]
branch = "develop"
name = "github.com/tendermint/go-crypto" name = "github.com/tendermint/go-crypto"
packages = ["."] packages = ["."]
revision = "a3800da0a15c8272cbd3c155e024bff28fe9692c"
revision = "a04f2ae5c6ba037014531241ed973116290b029e"
version = "v0.6.0"
[[projects]] [[projects]]
name = "github.com/tendermint/go-wire" name = "github.com/tendermint/go-wire"
@ -273,7 +273,6 @@
version = "v0.7.3" version = "v0.7.3"
[[projects]] [[projects]]
branch = "develop"
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
packages = [ packages = [
"autofile", "autofile",
@ -289,7 +288,8 @@
"pubsub/query", "pubsub/query",
"test" "test"
] ]
revision = "4e5c655944c9a636eaed549e6ad8fd8011fb4d42"
revision = "e9cf47606cfcbdc28a7c16671b4a70b459e9d4cc"
version = "v0.8.0-dev"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -304,7 +304,7 @@
"ripemd160", "ripemd160",
"salsa20/salsa" "salsa20/salsa"
] ]
revision = "c3a3ad6d03f7a915c0f7e194b7152974bb73d287"
revision = "88942b9c40a4c9d203b82b3731787b672d6e809b"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -324,7 +324,7 @@
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix"] packages = ["unix"]
revision = "7ceb54c8418b8f9cdf0177b511d5cbb06e9fae39"
revision = "91ee8cde435411ca3f1cd365e8f20131aed4d0a1"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@ -351,20 +351,16 @@
branch = "master" branch = "master"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"] packages = ["googleapis/rpc/status"]
revision = "f8c8703595236ae70fdf8789ecb656ea0bcdcf46"
revision = "ab0870e398d5dd054b868c0db1481ab029b9a9f2"
[[projects]] [[projects]]
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
"balancer", "balancer",
"balancer/base",
"balancer/roundrobin",
"codes", "codes",
"connectivity", "connectivity",
"credentials", "credentials",
"encoding",
"encoding/proto",
"grpclb/grpc_lb_v1/messages", "grpclb/grpc_lb_v1/messages",
"grpclog", "grpclog",
"internal", "internal",
@ -373,15 +369,13 @@
"naming", "naming",
"peer", "peer",
"resolver", "resolver",
"resolver/dns",
"resolver/passthrough",
"stats", "stats",
"status", "status",
"tap", "tap",
"transport" "transport"
] ]
revision = "8e4536a86ab602859c20df5ebfd0bd4228d08655"
version = "v1.10.0"
revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e"
version = "v1.7.5"
[[projects]] [[projects]]
name = "gopkg.in/yaml.v2" name = "gopkg.in/yaml.v2"
@ -392,6 +386,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "6da81f319b092e227b5d2c9de3b10296e9bb7287c02adb38fe547147e9e5e447"
inputs-digest = "9aace7a292e5402f97327860531e13b77f036c19843b698566ee958773404f48"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

+ 7
- 7
Gopkg.toml View File

@ -26,12 +26,12 @@
[[constraint]] [[constraint]]
branch = "master"
name = "github.com/ebuchman/fail-test" name = "github.com/ebuchman/fail-test"
branch = "master"
[[constraint]] [[constraint]]
branch = "master"
name = "github.com/fortytw2/leaktest" name = "github.com/fortytw2/leaktest"
branch = "master"
[[constraint]] [[constraint]]
name = "github.com/go-kit/kit" name = "github.com/go-kit/kit"
@ -54,8 +54,8 @@
version = "0.8.0" version = "0.8.0"
[[constraint]] [[constraint]]
branch = "master"
name = "github.com/rcrowley/go-metrics" name = "github.com/rcrowley/go-metrics"
branch = "master"
[[constraint]] [[constraint]]
name = "github.com/spf13/cobra" name = "github.com/spf13/cobra"
@ -71,19 +71,19 @@
[[constraint]] [[constraint]]
name = "github.com/tendermint/abci" name = "github.com/tendermint/abci"
branch = "develop"
version = "0.10.3-dev"
[[constraint]] [[constraint]]
name = "github.com/tendermint/go-crypto" name = "github.com/tendermint/go-crypto"
branch = "develop"
version = "0.6.0"
[[constraint]] [[constraint]]
name = "github.com/tendermint/go-amino" name = "github.com/tendermint/go-amino"
branch = "develop"
version = "0.9.3"
[[constraint]] [[constraint]]
name = "github.com/tendermint/tmlibs" name = "github.com/tendermint/tmlibs"
branch = "develop"
version = "0.8.0-dev"
[[constraint]] [[constraint]]
name = "google.golang.org/grpc" name = "google.golang.org/grpc"


+ 2
- 2
config/config.go View File

@ -270,7 +270,7 @@ type P2PConfig struct {
FlushThrottleTimeout int `mapstructure:"flush_throttle_timeout"` FlushThrottleTimeout int `mapstructure:"flush_throttle_timeout"`
// Maximum size of a message packet payload, in bytes // Maximum size of a message packet payload, in bytes
MaxMsgPacketPayloadSize int `mapstructure:"max_msg_packet_payload_size"`
MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"`
// Rate at which packets can be sent, in bytes/second // Rate at which packets can be sent, in bytes/second
SendRate int64 `mapstructure:"send_rate"` SendRate int64 `mapstructure:"send_rate"`
@ -299,7 +299,7 @@ func DefaultP2PConfig() *P2PConfig {
AddrBookStrict: true, AddrBookStrict: true,
MaxNumPeers: 50, MaxNumPeers: 50,
FlushThrottleTimeout: 100, FlushThrottleTimeout: 100,
MaxMsgPacketPayloadSize: 1024, // 1 kB
MaxPacketMsgPayloadSize: 1024, // 1 kB
SendRate: 512000, // 500 kB/s SendRate: 512000, // 500 kB/s
RecvRate: 512000, // 500 kB/s RecvRate: 512000, // 500 kB/s
PexReactor: true, PexReactor: true,


+ 1
- 1
config/toml.go View File

@ -142,7 +142,7 @@ flush_throttle_timeout = {{ .P2P.FlushThrottleTimeout }}
max_num_peers = {{ .P2P.MaxNumPeers }} max_num_peers = {{ .P2P.MaxNumPeers }}
# Maximum size of a message packet payload, in bytes # Maximum size of a message packet payload, in bytes
max_msg_packet_payload_size = {{ .P2P.MaxMsgPacketPayloadSize }}
max_packet_msg_payload_size = {{ .P2P.MaxPacketMsgPayloadSize }}
# Rate at which packets can be sent, in bytes/second # Rate at which packets can be sent, in bytes/second
send_rate = {{ .P2P.SendRate }} send_rate = {{ .P2P.SendRate }}


+ 31
- 35
p2p/conn/connection.go View File

@ -8,7 +8,6 @@ import (
"math" "math"
"net" "net"
"reflect" "reflect"
"runtime/debug"
"sync/atomic" "sync/atomic"
"time" "time"
@ -19,8 +18,8 @@ import (
) )
const ( const (
packetMsgMaxPayloadSizeDefault = 1024
packetMsgMaxOverheadSize = 10 // It's actually lower but good enough
maxPacketMsgPayloadSizeDefault = 1024
maxPacketMsgOverheadSize = 14
numBatchPacketMsgs = 10 numBatchPacketMsgs = 10
minReadBufferSize = 1024 minReadBufferSize = 1024
@ -57,15 +56,15 @@ The byte id and the relative priorities of each `Channel` are configured upon
initialization of the connection. initialization of the connection.
There are two methods for sending messages: There are two methods for sending messages:
func (m MConnection) Send(chID byte, msg interface{}) bool {}
func (m MConnection) TrySend(chID byte, msg interface{}) bool {}
func (m MConnection) Send(chID byte, msgBytes []byte) bool {}
func (m MConnection) TrySend(chID byte, msgBytes []byte}) bool {}
`Send(chID, msg)` is a blocking call that waits until `msg` is successfully queued
for the channel with the given id byte `chID`, or until the request times out.
The message `msg` is serialized using Go-Amino.
`Send(chID, msgBytes)` is a blocking call that waits until `msg` is
successfully queued for the channel with the given id byte `chID`, or until the
request times out. The message `msg` is serialized using Go-Amino.
`TrySend(chID, msg)` is a nonblocking call that returns false if the channel's
queue is full.
`TrySend(chID, msgBytes)` is a nonblocking call that returns false if the
channel's queue is full.
Inbound message bytes are handled with an onReceive callback function. Inbound message bytes are handled with an onReceive callback function.
*/ */
@ -105,7 +104,7 @@ type MConnConfig struct {
RecvRate int64 `mapstructure:"recv_rate"` RecvRate int64 `mapstructure:"recv_rate"`
// Maximum payload size // Maximum payload size
PacketMsgMaxPayloadSize int `mapstructure:"packet_msg_max_payload_size"`
MaxPacketMsgPayloadSize int `mapstructure:"max_packet_msg_payload_size"`
// Interval to flush writes (throttled) // Interval to flush writes (throttled)
FlushThrottle time.Duration `mapstructure:"flush_throttle"` FlushThrottle time.Duration `mapstructure:"flush_throttle"`
@ -118,7 +117,7 @@ type MConnConfig struct {
} }
func (cfg *MConnConfig) maxPacketMsgTotalSize() int { func (cfg *MConnConfig) maxPacketMsgTotalSize() int {
return cfg.PacketMsgMaxPayloadSize + packetMsgMaxOverheadSize
return cfg.MaxPacketMsgPayloadSize + maxPacketMsgOverheadSize
} }
// DefaultMConnConfig returns the default config. // DefaultMConnConfig returns the default config.
@ -126,7 +125,7 @@ func DefaultMConnConfig() *MConnConfig {
return &MConnConfig{ return &MConnConfig{
SendRate: defaultSendRate, SendRate: defaultSendRate,
RecvRate: defaultRecvRate, RecvRate: defaultRecvRate,
PacketMsgMaxPayloadSize: packetMsgMaxPayloadSizeDefault,
MaxPacketMsgPayloadSize: maxPacketMsgPayloadSizeDefault,
FlushThrottle: defaultFlushThrottle, FlushThrottle: defaultFlushThrottle,
PingInterval: defaultPingInterval, PingInterval: defaultPingInterval,
PongTimeout: defaultPongTimeout, PongTimeout: defaultPongTimeout,
@ -233,8 +232,7 @@ func (c *MConnection) flush() {
// Catch panics, usually caused by remote disconnects. // Catch panics, usually caused by remote disconnects.
func (c *MConnection) _recover() { func (c *MConnection) _recover() {
if r := recover(); r != nil { if r := recover(); r != nil {
stack := debug.Stack()
err := cmn.StackError{r, stack}
err := cmn.ErrorWrap(r, "recovered panic in MConnection")
c.stopForError(err) c.stopForError(err)
} }
} }
@ -249,12 +247,12 @@ func (c *MConnection) stopForError(r interface{}) {
} }
// Queues a message to be sent to channel. // Queues a message to be sent to channel.
func (c *MConnection) Send(chID byte, msg interface{}) bool {
func (c *MConnection) Send(chID byte, msgBytes []byte) bool {
if !c.IsRunning() { if !c.IsRunning() {
return false return false
} }
c.Logger.Debug("Send", "channel", chID, "conn", c, "msg", msg)
c.Logger.Debug("Send", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes))
// Send message to channel. // Send message to channel.
channel, ok := c.channelsIdx[chID] channel, ok := c.channelsIdx[chID]
@ -263,7 +261,7 @@ func (c *MConnection) Send(chID byte, msg interface{}) bool {
return false return false
} }
success := channel.sendBytes(cdc.MustMarshalBinary(msg))
success := channel.sendBytes(msgBytes)
if success { if success {
// Wake up sendRoutine if necessary // Wake up sendRoutine if necessary
select { select {
@ -271,19 +269,19 @@ func (c *MConnection) Send(chID byte, msg interface{}) bool {
default: default:
} }
} else { } else {
c.Logger.Error("Send failed", "channel", chID, "conn", c, "msg", msg)
c.Logger.Error("Send failed", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes))
} }
return success return success
} }
// Queues a message to be sent to channel. // Queues a message to be sent to channel.
// Nonblocking, returns true if successful. // Nonblocking, returns true if successful.
func (c *MConnection) TrySend(chID byte, msg interface{}) bool {
func (c *MConnection) TrySend(chID byte, msgBytes []byte) bool {
if !c.IsRunning() { if !c.IsRunning() {
return false return false
} }
c.Logger.Debug("TrySend", "channel", chID, "conn", c, "msg", msg)
c.Logger.Debug("TrySend", "channel", chID, "conn", c, "msgBytes", fmt.Sprintf("%X", msgBytes))
// Send message to channel. // Send message to channel.
channel, ok := c.channelsIdx[chID] channel, ok := c.channelsIdx[chID]
@ -292,7 +290,7 @@ func (c *MConnection) TrySend(chID byte, msg interface{}) bool {
return false return false
} }
ok = channel.trySendBytes(cdc.MustMarshalBinary(msg))
ok = channel.trySendBytes(msgBytes)
if ok { if ok {
// Wake up sendRoutine if necessary // Wake up sendRoutine if necessary
select { select {
@ -462,18 +460,17 @@ FOR_LOOP:
// Block until .recvMonitor says we can read. // Block until .recvMonitor says we can read.
c.recvMonitor.Limit(c.config.maxPacketMsgTotalSize(), atomic.LoadInt64(&c.config.RecvRate), true) c.recvMonitor.Limit(c.config.maxPacketMsgTotalSize(), atomic.LoadInt64(&c.config.RecvRate), true)
// Peek into bufConnReader for debugging
/* /*
// Peek into bufConnReader for debugging
if numBytes := c.bufConnReader.Buffered(); numBytes > 0 { if numBytes := c.bufConnReader.Buffered(); numBytes > 0 {
log.Info("Peek connection buffer", "numBytes", numBytes, "bytes", log15.Lazy{func() []byte {
bytes, err := c.bufConnReader.Peek(cmn.MinInt(numBytes, 100))
if err == nil {
return bytes
} else {
log.Warn("Error peeking connection buffer", "err", err)
return nil
}
}})
bz, err := c.bufConnReader.Peek(cmn.MinInt(numBytes, 100))
if err == nil {
// return
} else {
c.Logger.Debug("Error peeking connection buffer", "err", err)
// return nil
}
c.Logger.Info("Peek connection buffer", "numBytes", numBytes, "bz", bz)
} }
*/ */
@ -639,7 +636,7 @@ func newChannel(conn *MConnection, desc ChannelDescriptor) *Channel {
desc: desc, desc: desc,
sendQueue: make(chan []byte, desc.SendQueueCapacity), sendQueue: make(chan []byte, desc.SendQueueCapacity),
recving: make([]byte, 0, desc.RecvBufferCapacity), recving: make([]byte, 0, desc.RecvBufferCapacity),
maxPacketMsgPayloadSize: conn.config.PacketMsgMaxPayloadSize,
maxPacketMsgPayloadSize: conn.config.MaxPacketMsgPayloadSize,
} }
} }
@ -719,7 +716,6 @@ func (ch *Channel) nextPacketMsg() PacketMsg {
// Not goroutine-safe // Not goroutine-safe
func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) { func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) {
var packet = ch.nextPacketMsg() var packet = ch.nextPacketMsg()
ch.Logger.Debug("Write Msg Packet", "conn", ch.conn, "packet", packet)
n, err = cdc.MarshalBinaryWriter(w, packet) n, err = cdc.MarshalBinaryWriter(w, packet)
ch.recentlySent += n ch.recentlySent += n
return return
@ -729,7 +725,7 @@ func (ch *Channel) writePacketMsgTo(w io.Writer) (n int64, err error) {
// complete. NOTE message bytes may change on next call to recvPacketMsg. // complete. NOTE message bytes may change on next call to recvPacketMsg.
// Not goroutine-safe // Not goroutine-safe
func (ch *Channel) recvPacketMsg(packet PacketMsg) ([]byte, error) { func (ch *Channel) recvPacketMsg(packet PacketMsg) ([]byte, error) {
ch.Logger.Debug("Read Msg Packet", "conn", ch.conn, "packet", packet)
ch.Logger.Debug("Read PacketMsg", "conn", ch.conn, "packet", packet)
var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Bytes) var recvCap, recvReceived = ch.desc.RecvMessageCapacity, len(ch.recving) + len(packet.Bytes)
if recvCap < recvReceived { if recvCap < recvReceived {
return nil, fmt.Errorf("Received message exceeds available capacity: %v < %v", recvCap, recvReceived) return nil, fmt.Errorf("Received message exceeds available capacity: %v < %v", recvCap, recvReceived)


+ 29
- 11
p2p/conn/connection_test.go View File

@ -1,6 +1,7 @@
package conn package conn
import ( import (
"bytes"
"net" "net"
"testing" "testing"
"time" "time"
@ -41,7 +42,7 @@ func TestMConnectionSend(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
defer mconn.Stop() defer mconn.Stop()
msg := "Ant-Man"
msg := []byte("Ant-Man")
assert.True(t, mconn.Send(0x01, msg)) assert.True(t, mconn.Send(0x01, msg))
// Note: subsequent Send/TrySend calls could pass because we are reading from // Note: subsequent Send/TrySend calls could pass because we are reading from
// the send queue in a separate goroutine. // the send queue in a separate goroutine.
@ -51,7 +52,7 @@ func TestMConnectionSend(t *testing.T) {
} }
assert.True(t, mconn.CanSend(0x01)) assert.True(t, mconn.CanSend(0x01))
msg = "Spider-Man"
msg = []byte("Spider-Man")
assert.True(t, mconn.TrySend(0x01, msg)) assert.True(t, mconn.TrySend(0x01, msg))
_, err = server.Read(make([]byte, len(msg))) _, err = server.Read(make([]byte, len(msg)))
if err != nil { if err != nil {
@ -59,7 +60,7 @@ func TestMConnectionSend(t *testing.T) {
} }
assert.False(t, mconn.CanSend(0x05), "CanSend should return false because channel is unknown") assert.False(t, mconn.CanSend(0x05), "CanSend should return false because channel is unknown")
assert.False(t, mconn.Send(0x05, "Absorbing Man"), "Send should return false because channel is unknown")
assert.False(t, mconn.Send(0x05, []byte("Absorbing Man")), "Send should return false because channel is unknown")
} }
func TestMConnectionReceive(t *testing.T) { func TestMConnectionReceive(t *testing.T) {
@ -85,12 +86,12 @@ func TestMConnectionReceive(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
defer mconn2.Stop() defer mconn2.Stop()
msg := "Cyclops"
msg := []byte("Cyclops")
assert.True(t, mconn2.Send(0x01, msg)) assert.True(t, mconn2.Send(0x01, msg))
select { select {
case receivedBytes := <-receivedCh: case receivedBytes := <-receivedCh:
assert.Equal(t, []byte(msg), receivedBytes[2:]) // first 3 bytes are internal
assert.Equal(t, []byte(msg), receivedBytes)
case err := <-errorsCh: case err := <-errorsCh:
t.Fatalf("Expected %s, got %+v", msg, err) t.Fatalf("Expected %s, got %+v", msg, err)
case <-time.After(500 * time.Millisecond): case <-time.After(500 * time.Millisecond):
@ -386,7 +387,7 @@ func TestMConnectionReadErrorUnknownChannel(t *testing.T) {
defer mconnClient.Stop() defer mconnClient.Stop()
defer mconnServer.Stop() defer mconnServer.Stop()
msg := "Ant-Man"
msg := []byte("Ant-Man")
// fail to send msg on channel unknown by client // fail to send msg on channel unknown by client
assert.False(t, mconnClient.Send(0x03, msg)) assert.False(t, mconnClient.Send(0x03, msg))
@ -413,23 +414,40 @@ func TestMConnectionReadErrorLongMessage(t *testing.T) {
// send msg thats just right // send msg thats just right
var err error var err error
var buf = new(bytes.Buffer)
// - Uvarint length of MustMarshalBinary(packet) = 1 or 2 bytes
// (as long as it's less than 16,384 bytes)
// - Prefix bytes = 4 bytes
// - ChannelID field key + byte = 2 bytes
// - EOF field key + byte = 2 bytes
// - Bytes field key = 1 bytes
// - Uvarint length of MustMarshalBinary(bytes) = 1 or 2 bytes
// - Struct terminator = 1 byte
// = up to 14 bytes overhead for the packet.
var packet = PacketMsg{ var packet = PacketMsg{
ChannelID: 0x01, ChannelID: 0x01,
Bytes: make([]byte, mconnClient.config.maxPacketMsgTotalSize()-12),
EOF: 1, EOF: 1,
Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize),
} }
_, err = cdc.MarshalBinaryWriter(client, packet)
_, err = cdc.MarshalBinaryWriter(buf, packet)
assert.Nil(t, err)
_, err = client.Write(buf.Bytes())
assert.Nil(t, err) assert.Nil(t, err)
assert.True(t, expectSend(chOnRcv), "msg just right") assert.True(t, expectSend(chOnRcv), "msg just right")
assert.False(t, expectSend(chOnErr), "msg just right")
// send msg thats too long // send msg thats too long
buf = new(bytes.Buffer)
packet = PacketMsg{ packet = PacketMsg{
ChannelID: 0x01, ChannelID: 0x01,
Bytes: make([]byte, mconnClient.config.maxPacketMsgTotalSize()-11),
EOF: 1, EOF: 1,
Bytes: make([]byte, mconnClient.config.MaxPacketMsgPayloadSize+1),
} }
_, err = cdc.MarshalBinaryWriter(client, packet)
_, err = cdc.MarshalBinaryWriter(buf, packet)
assert.Nil(t, err) assert.Nil(t, err)
_, err = client.Write(buf.Bytes())
assert.NotNil(t, err)
assert.False(t, expectSend(chOnRcv), "msg too long")
assert.True(t, expectSend(chOnErr), "msg too long") assert.True(t, expectSend(chOnErr), "msg too long")
} }
@ -458,7 +476,7 @@ func TestMConnectionTrySend(t *testing.T) {
require.Nil(t, err) require.Nil(t, err)
defer mconn.Stop() defer mconn.Stop()
msg := "Semicolon-Woman"
msg := []byte("Semicolon-Woman")
resultCh := make(chan string, 2) resultCh := make(chan string, 2)
assert.True(t, mconn.TrySend(0x01, msg)) assert.True(t, mconn.TrySend(0x01, msg))
server.Read(make([]byte, len(msg))) server.Read(make([]byte, len(msg)))


+ 3
- 10
p2p/conn/secret_connection.go View File

@ -12,7 +12,6 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"net" "net"
"time" "time"
@ -145,8 +144,8 @@ func (sc *SecretConnection) Write(data []byte) (n int, err error) {
// CONTRACT: data smaller than dataMaxSize is read atomically. // CONTRACT: data smaller than dataMaxSize is read atomically.
func (sc *SecretConnection) Read(data []byte) (n int, err error) { func (sc *SecretConnection) Read(data []byte) (n int, err error) {
if 0 < len(sc.recvBuffer) { if 0 < len(sc.recvBuffer) {
n_ := copy(data, sc.recvBuffer)
sc.recvBuffer = sc.recvBuffer[n_:]
n = copy(data, sc.recvBuffer)
sc.recvBuffer = sc.recvBuffer[n:]
return return
} }
@ -193,7 +192,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) {
var err error var err error
ephPub, ephPriv, err = box.GenerateKey(crand.Reader) ephPub, ephPriv, err = box.GenerateKey(crand.Reader)
if err != nil { if err != nil {
cmn.PanicCrisis("Could not generate ephemeral keypairs")
panic("Could not generate ephemeral keypairs")
} }
return return
} }
@ -225,9 +224,6 @@ func shareEphPubKey(conn io.ReadWriteCloser, locEphPub *[32]byte) (remEphPub *[3
if trs.FirstError() != nil { if trs.FirstError() != nil {
err = trs.FirstError() err = trs.FirstError()
return return
} else if trs.FirstPanic() != nil {
err = fmt.Errorf("Panic: %v", trs.FirstPanic())
return
} }
// Otherwise: // Otherwise:
@ -309,9 +305,6 @@ func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature cr
if trs.FirstError() != nil { if trs.FirstError() != nil {
err = trs.FirstError() err = trs.FirstError()
return return
} else if trs.FirstPanic() != nil {
err = fmt.Errorf("Panic: %v", trs.FirstPanic())
return
} }
var _recvMsg = trs.FirstValue().(authSigMessage) var _recvMsg = trs.FirstValue().(authSigMessage)


+ 0
- 5
p2p/conn/secret_connection_test.go View File

@ -73,7 +73,6 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection
return nil, nil, false return nil, nil, false
}, },
) )
require.Nil(tb, trs.FirstPanic())
require.Nil(tb, trs.FirstError()) require.Nil(tb, trs.FirstError())
require.True(tb, ok, "Unexpected task abortion") require.True(tb, ok, "Unexpected task abortion")
@ -158,9 +157,6 @@ func TestSecretConnectionReadWrite(t *testing.T) {
// If error: // If error:
if trs.FirstError() != nil { if trs.FirstError() != nil {
return nil, trs.FirstError(), true return nil, trs.FirstError(), true
} else if trs.FirstPanic() != nil {
err = fmt.Errorf("Panic in task: %v", trs.FirstPanic())
return nil, err, true
} }
// Otherwise: // Otherwise:
@ -173,7 +169,6 @@ func TestSecretConnectionReadWrite(t *testing.T) {
genNodeRunner("foo", fooConn, fooWrites, &fooReads), genNodeRunner("foo", fooConn, fooWrites, &fooReads),
genNodeRunner("bar", barConn, barWrites, &barReads), genNodeRunner("bar", barConn, barWrites, &barReads),
) )
require.Nil(t, trs.FirstPanic())
require.Nil(t, trs.FirstError()) require.Nil(t, trs.FirstError())
require.True(t, ok, "unexpected task abortion") require.True(t, ok, "unexpected task abortion")


+ 1
- 2
p2p/conn/wire.go View File

@ -5,10 +5,9 @@ import (
"github.com/tendermint/go-crypto" "github.com/tendermint/go-crypto"
) )
var cdc *amino.Codec
var cdc *amino.Codec = amino.NewCodec()
func init() { func init() {
cdc = amino.NewCodec()
crypto.RegisterAmino(cdc) crypto.RegisterAmino(cdc)
RegisterPacket(cdc) RegisterPacket(cdc)
} }

+ 3
- 4
p2p/key.go View File

@ -3,7 +3,6 @@ package p2p
import ( import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -64,7 +63,7 @@ func loadNodeKey(filePath string) (*NodeKey, error) {
return nil, err return nil, err
} }
nodeKey := new(NodeKey) nodeKey := new(NodeKey)
err = json.Unmarshal(jsonBytes, nodeKey)
err = cdc.UnmarshalJSON(jsonBytes, nodeKey)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error reading NodeKey from %v: %v\n", filePath, err) return nil, fmt.Errorf("Error reading NodeKey from %v: %v\n", filePath, err)
} }
@ -72,12 +71,12 @@ func loadNodeKey(filePath string) (*NodeKey, error) {
} }
func genNodeKey(filePath string) (*NodeKey, error) { func genNodeKey(filePath string) (*NodeKey, error) {
privKey := crypto.GenPrivKeyEd25519().Wrap()
privKey := crypto.GenPrivKeyEd25519()
nodeKey := &NodeKey{ nodeKey := &NodeKey{
PrivKey: privKey, PrivKey: privKey,
} }
jsonBytes, err := json.Marshal(nodeKey)
jsonBytes, err := cdc.MarshalJSON(nodeKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }


+ 1
- 2
p2p/netaddress.go View File

@ -13,7 +13,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
) )
@ -66,7 +65,7 @@ func NewNetAddressString(addr string) (*NetAddress, error) {
idStr := spl[0] idStr := spl[0]
idBytes, err := hex.DecodeString(idStr) idBytes, err := hex.DecodeString(idStr)
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Address (%s) contains invalid ID", addr))
return nil, cmn.ErrorWrap(err, fmt.Sprintf("Address (%s) contains invalid ID", addr))
} }
if len(idBytes) != IDByteLength { if len(idBytes) != IDByteLength {
return nil, fmt.Errorf("Address (%s) contains ID of invalid length (%d). Should be %d hex-encoded bytes", return nil, fmt.Errorf("Address (%s) contains ID of invalid length (%d). Should be %d hex-encoded bytes",


+ 28
- 35
p2p/peer.go View File

@ -5,10 +5,7 @@ import (
"net" "net"
"time" "time"
"github.com/pkg/errors"
crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-crypto"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
@ -25,8 +22,8 @@ type Peer interface {
NodeInfo() NodeInfo // peer's info NodeInfo() NodeInfo // peer's info
Status() tmconn.ConnectionStatus Status() tmconn.ConnectionStatus
Send(byte, interface{}) bool
TrySend(byte, interface{}) bool
Send(byte, []byte) bool
TrySend(byte, []byte) bool
Set(string, interface{}) Set(string, interface{})
Get(string) interface{} Get(string) interface{}
@ -114,13 +111,13 @@ func newOutboundPeerConn(addr *NetAddress, config *PeerConfig, persistent bool,
conn, err := dial(addr, config) conn, err := dial(addr, config)
if err != nil { if err != nil {
return pc, errors.Wrap(err, "Error creating peer")
return pc, cmn.ErrorWrap(err, "Error creating peer")
} }
pc, err = newPeerConn(conn, config, true, persistent, ourNodePrivKey) pc, err = newPeerConn(conn, config, true, persistent, ourNodePrivKey)
if err != nil { if err != nil {
if err2 := conn.Close(); err2 != nil { if err2 := conn.Close(); err2 != nil {
return pc, errors.Wrap(err, err2.Error())
return pc, cmn.ErrorWrap(err, err2.Error())
} }
return pc, err return pc, err
} }
@ -128,7 +125,7 @@ func newOutboundPeerConn(addr *NetAddress, config *PeerConfig, persistent bool,
// ensure dialed ID matches connection ID // ensure dialed ID matches connection ID
if config.AuthEnc && addr.ID != pc.ID() { if config.AuthEnc && addr.ID != pc.ID() {
if err2 := conn.Close(); err2 != nil { if err2 := conn.Close(); err2 != nil {
return pc, errors.Wrap(err, err2.Error())
return pc, cmn.ErrorWrap(err, err2.Error())
} }
return pc, ErrSwitchAuthenticationFailure{addr, pc.ID()} return pc, ErrSwitchAuthenticationFailure{addr, pc.ID()}
} }
@ -157,13 +154,13 @@ func newPeerConn(rawConn net.Conn,
if config.AuthEnc { if config.AuthEnc {
// Set deadline for secret handshake // Set deadline for secret handshake
if err := conn.SetDeadline(time.Now().Add(config.HandshakeTimeout * time.Second)); err != nil { if err := conn.SetDeadline(time.Now().Add(config.HandshakeTimeout * time.Second)); err != nil {
return pc, errors.Wrap(err, "Error setting deadline while encrypting connection")
return pc, cmn.ErrorWrap(err, "Error setting deadline while encrypting connection")
} }
// Encrypt connection // Encrypt connection
conn, err = tmconn.MakeSecretConnection(conn, ourNodePrivKey) conn, err = tmconn.MakeSecretConnection(conn, ourNodePrivKey)
if err != nil { if err != nil {
return pc, errors.Wrap(err, "Error creating peer")
return pc, cmn.ErrorWrap(err, "Error creating peer")
} }
} }
@ -228,9 +225,9 @@ func (p *peer) Status() tmconn.ConnectionStatus {
return p.mconn.Status() return p.mconn.Status()
} }
// Send msg to the channel identified by chID byte. Returns false if the send
// queue is full after timeout, specified by MConnection.
func (p *peer) Send(chID byte, msg interface{}) bool {
// Send msg bytes to the channel identified by chID byte. Returns false if the
// send queue is full after timeout, specified by MConnection.
func (p *peer) Send(chID byte, msgBytes []byte) bool {
if !p.IsRunning() { if !p.IsRunning() {
// see Switch#Broadcast, where we fetch the list of peers and loop over // see Switch#Broadcast, where we fetch the list of peers and loop over
// them - while we're looping, one peer may be removed and stopped. // them - while we're looping, one peer may be removed and stopped.
@ -238,18 +235,18 @@ func (p *peer) Send(chID byte, msg interface{}) bool {
} else if !p.hasChannel(chID) { } else if !p.hasChannel(chID) {
return false return false
} }
return p.mconn.Send(chID, msg)
return p.mconn.Send(chID, msgBytes)
} }
// TrySend msg to the channel identified by chID byte. Immediately returns
// TrySend msg bytes to the channel identified by chID byte. Immediately returns
// false if the send queue is full. // false if the send queue is full.
func (p *peer) TrySend(chID byte, msg interface{}) bool {
func (p *peer) TrySend(chID byte, msgBytes []byte) bool {
if !p.IsRunning() { if !p.IsRunning() {
return false return false
} else if !p.hasChannel(chID) { } else if !p.hasChannel(chID) {
return false return false
} }
return p.mconn.TrySend(chID, msg)
return p.mconn.TrySend(chID, msgBytes)
} }
// Get the data for a given key. // Get the data for a given key.
@ -290,30 +287,26 @@ func (pc *peerConn) CloseConn() {
func (pc *peerConn) HandshakeTimeout(ourNodeInfo NodeInfo, timeout time.Duration) (peerNodeInfo NodeInfo, err error) { func (pc *peerConn) HandshakeTimeout(ourNodeInfo NodeInfo, timeout time.Duration) (peerNodeInfo NodeInfo, err error) {
// Set deadline for handshake so we don't block forever on conn.ReadFull // Set deadline for handshake so we don't block forever on conn.ReadFull
if err := pc.conn.SetDeadline(time.Now().Add(timeout)); err != nil { if err := pc.conn.SetDeadline(time.Now().Add(timeout)); err != nil {
return peerNodeInfo, errors.Wrap(err, "Error setting deadline")
return peerNodeInfo, cmn.ErrorWrap(err, "Error setting deadline")
} }
var err1 error
var err2 error
cmn.Parallel(
func() {
var n int
wire.WriteBinary(&ourNodeInfo, pc.conn, &n, &err1)
var trs, _ = cmn.Parallel(
func(_ int) (val interface{}, err error, abort bool) {
_, err = cdc.MarshalBinaryWriter(pc.conn, ourNodeInfo)
return
}, },
func() {
var n int
wire.ReadBinary(&peerNodeInfo, pc.conn, MaxNodeInfoSize(), &n, &err2)
})
if err1 != nil {
return peerNodeInfo, errors.Wrap(err1, "Error during handshake/write")
}
if err2 != nil {
return peerNodeInfo, errors.Wrap(err2, "Error during handshake/read")
func(_ int) (val interface{}, err error, abort bool) {
_, err = cdc.UnmarshalBinaryReader(pc.conn, &peerNodeInfo, int64(MaxNodeInfoSize()))
return
},
)
if err := trs.FirstError(); err != nil {
return peerNodeInfo, cmn.ErrorWrap(err, "Error during handshake")
} }
// Remove deadline // Remove deadline
if err := pc.conn.SetDeadline(time.Time{}); err != nil { if err := pc.conn.SetDeadline(time.Time{}); err != nil {
return peerNodeInfo, errors.Wrap(err, "Error removing deadline")
return peerNodeInfo, cmn.ErrorWrap(err, "Error removing deadline")
} }
return peerNodeInfo, nil return peerNodeInfo, nil


+ 1
- 1
p2p/peer_set_test.go View File

@ -13,7 +13,7 @@ import (
// Returns an empty kvstore peer // Returns an empty kvstore peer
func randPeer() *peer { func randPeer() *peer {
pubKey := crypto.GenPrivKeyEd25519().Wrap().PubKey()
pubKey := crypto.GenPrivKeyEd25519().PubKey()
return &peer{ return &peer{
nodeInfo: NodeInfo{ nodeInfo: NodeInfo{
ListenAddr: cmn.Fmt("%v.%v.%v.%v:46656", rand.Int()%256, rand.Int()%256, rand.Int()%256, rand.Int()%256), ListenAddr: cmn.Fmt("%v.%v.%v.%v:46656", rand.Int()%256, rand.Int()%256, rand.Int()%256, rand.Int()%256),


+ 5
- 5
p2p/peer_test.go View File

@ -20,7 +20,7 @@ func TestPeerBasic(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -47,7 +47,7 @@ func TestPeerWithoutAuthEnc(t *testing.T) {
config.AuthEnc = false config.AuthEnc = false
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: config}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: config}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -68,7 +68,7 @@ func TestPeerSend(t *testing.T) {
config.AuthEnc = false config.AuthEnc = false
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: config}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: config}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -81,7 +81,7 @@ func TestPeerSend(t *testing.T) {
defer p.Stop() defer p.Stop()
assert.True(p.CanSend(testCh)) assert.True(p.CanSend(testCh))
assert.True(p.Send(testCh, "Asylum"))
assert.True(p.Send(testCh, []byte("Asylum")))
} }
func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig) (*peer, error) { func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig) (*peer, error) {
@ -89,7 +89,7 @@ func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig)
{ID: testCh, Priority: 1}, {ID: testCh, Priority: 1},
} }
reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)} reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)}
pk := crypto.GenPrivKeyEd25519().Wrap()
pk := crypto.GenPrivKeyEd25519()
pc, err := newOutboundPeerConn(addr, config, false, pk) pc, err := newOutboundPeerConn(addr, config, false, pk)
if err != nil { if err != nil {
return nil, err return nil, err


+ 12
- 22
p2p/pex/pex_reactor.go View File

@ -1,7 +1,6 @@
package pex package pex
import ( import (
"bytes"
"fmt" "fmt"
"math/rand" "math/rand"
"reflect" "reflect"
@ -9,8 +8,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/pkg/errors"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/go-amino"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
@ -165,7 +163,7 @@ func (r *PEXReactor) RemovePeer(p Peer, reason interface{}) {
// Receive implements Reactor by handling incoming PEX messages. // Receive implements Reactor by handling incoming PEX messages.
func (r *PEXReactor) Receive(chID byte, src Peer, msgBytes []byte) { func (r *PEXReactor) Receive(chID byte, src Peer, msgBytes []byte) {
_, msg, err := DecodeMessage(msgBytes)
msg, err := DecodeMessage(msgBytes)
if err != nil { if err != nil {
r.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) r.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes)
r.Switch.StopPeerForError(src, err) r.Switch.StopPeerForError(src, err)
@ -235,7 +233,7 @@ func (r *PEXReactor) RequestAddrs(p Peer) {
return return
} }
r.requestsSent.Set(id, struct{}{}) r.requestsSent.Set(id, struct{}{})
p.Send(PexChannel, struct{ PexMessage }{&pexRequestMessage{}})
p.Send(PexChannel, cdc.MustMarshalBinary(&pexRequestMessage{}))
} }
// ReceiveAddrs adds the given addrs to the addrbook if theres an open // ReceiveAddrs adds the given addrs to the addrbook if theres an open
@ -245,7 +243,7 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
id := string(src.ID()) id := string(src.ID())
if !r.requestsSent.Has(id) { if !r.requestsSent.Has(id) {
return errors.New("Received unsolicited pexAddrsMessage")
return cmn.NewError("Received unsolicited pexAddrsMessage")
} }
r.requestsSent.Delete(id) r.requestsSent.Delete(id)
@ -261,7 +259,7 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error {
// SendAddrs sends addrs to the peer. // SendAddrs sends addrs to the peer.
func (r *PEXReactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) { func (r *PEXReactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) {
p.Send(PexChannel, struct{ PexMessage }{&pexAddrsMessage{Addrs: netAddrs}})
p.Send(PexChannel, cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: netAddrs}))
} }
// SetEnsurePeersPeriod sets period to ensure peers connected. // SetEnsurePeersPeriod sets period to ensure peers connected.
@ -583,27 +581,19 @@ func (r *PEXReactor) attemptDisconnects() {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Messages // Messages
const (
msgTypeRequest = byte(0x01)
msgTypeAddrs = byte(0x02)
)
// PexMessage is a primary type for PEX messages. Underneath, it could contain // PexMessage is a primary type for PEX messages. Underneath, it could contain
// either pexRequestMessage, or pexAddrsMessage messages. // either pexRequestMessage, or pexAddrsMessage messages.
type PexMessage interface{} type PexMessage interface{}
var _ = wire.RegisterInterface(
struct{ PexMessage }{},
wire.ConcreteType{&pexRequestMessage{}, msgTypeRequest},
wire.ConcreteType{&pexAddrsMessage{}, msgTypeAddrs},
)
func RegisterPexMessage(cdc *amino.Codec) {
cdc.RegisterInterface((*PexMessage)(nil), nil)
cdc.RegisterConcrete(&pexRequestMessage{}, "tendermint/p2p/PexRequestMessage", nil)
cdc.RegisterConcrete(&pexAddrsMessage{}, "tendermint/p2p/PexAddrsMessage", nil)
}
// DecodeMessage implements interface registered above. // DecodeMessage implements interface registered above.
func DecodeMessage(bz []byte) (msgType byte, msg PexMessage, err error) {
msgType = bz[0]
n := new(int)
r := bytes.NewReader(bz)
msg = wire.ReadBinary(struct{ PexMessage }{}, r, maxPexMessageSize, n, &err).(struct{ PexMessage }).PexMessage
func DecodeMessage(bz []byte) (msg PexMessage, err error) {
err = cdc.UnmarshalBinary(bz, &msg)
return return
} }


+ 11
- 12
p2p/pex/pex_reactor_test.go View File

@ -12,7 +12,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/p2p/conn" "github.com/tendermint/tendermint/p2p/conn"
@ -114,12 +113,12 @@ func TestPEXReactorReceive(t *testing.T) {
size := book.Size() size := book.Size()
addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()}
msg := wire.BinaryBytes(struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}})
msg := cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: addrs})
r.Receive(PexChannel, peer, msg) r.Receive(PexChannel, peer, msg)
assert.Equal(t, size+1, book.Size()) assert.Equal(t, size+1, book.Size())
msg = wire.BinaryBytes(struct{ PexMessage }{&pexRequestMessage{}})
r.Receive(PexChannel, peer, msg)
msg = cdc.MustMarshalBinary(&pexRequestMessage{})
r.Receive(PexChannel, peer, msg) // should not panic.
} }
func TestPEXReactorRequestMessageAbuse(t *testing.T) { func TestPEXReactorRequestMessageAbuse(t *testing.T) {
@ -133,7 +132,7 @@ func TestPEXReactorRequestMessageAbuse(t *testing.T) {
assert.True(t, sw.Peers().Has(peer.ID())) assert.True(t, sw.Peers().Has(peer.ID()))
id := string(peer.ID()) id := string(peer.ID())
msg := wire.BinaryBytes(struct{ PexMessage }{&pexRequestMessage{}})
msg := cdc.MustMarshalBinary(&pexRequestMessage{})
// first time creates the entry // first time creates the entry
r.Receive(PexChannel, peer, msg) r.Receive(PexChannel, peer, msg)
@ -169,7 +168,7 @@ func TestPEXReactorAddrsMessageAbuse(t *testing.T) {
assert.True(t, sw.Peers().Has(peer.ID())) assert.True(t, sw.Peers().Has(peer.ID()))
addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()}
msg := wire.BinaryBytes(struct{ PexMessage }{&pexAddrsMessage{Addrs: addrs}})
msg := cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: addrs})
// receive some addrs. should clear the request // receive some addrs. should clear the request
r.Receive(PexChannel, peer, msg) r.Receive(PexChannel, peer, msg)
@ -302,7 +301,7 @@ func newMockPeer() mockPeer {
_, netAddr := p2p.CreateRoutableAddr() _, netAddr := p2p.CreateRoutableAddr()
mp := mockPeer{ mp := mockPeer{
addr: netAddr, addr: netAddr,
pubKey: crypto.GenPrivKeyEd25519().Wrap().PubKey(),
pubKey: crypto.GenPrivKeyEd25519().PubKey(),
} }
mp.BaseService = cmn.NewBaseService(nil, "MockPeer", mp) mp.BaseService = cmn.NewBaseService(nil, "MockPeer", mp)
mp.Start() mp.Start()
@ -318,11 +317,11 @@ func (mp mockPeer) NodeInfo() p2p.NodeInfo {
ListenAddr: mp.addr.DialString(), ListenAddr: mp.addr.DialString(),
} }
} }
func (mp mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} }
func (mp mockPeer) Send(byte, interface{}) bool { return false }
func (mp mockPeer) TrySend(byte, interface{}) bool { return false }
func (mp mockPeer) Set(string, interface{}) {}
func (mp mockPeer) Get(string) interface{} { return nil }
func (mp mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} }
func (mp mockPeer) Send(byte, []byte) bool { return false }
func (mp mockPeer) TrySend(byte, []byte) bool { return false }
func (mp mockPeer) Set(string, interface{}) {}
func (mp mockPeer) Get(string) interface{} { return nil }
func assertPeersWithTimeout( func assertPeersWithTimeout(
t *testing.T, t *testing.T,


+ 11
- 0
p2p/pex/wire.go View File

@ -0,0 +1,11 @@
package pex
import (
"github.com/tendermint/go-amino"
)
var cdc *amino.Codec = amino.NewCodec()
func init() {
RegisterPexMessage(cdc)
}

+ 6
- 8
p2p/switch.go View File

@ -8,8 +8,6 @@ import (
"sync" "sync"
"time" "time"
"github.com/pkg/errors"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/p2p/conn" "github.com/tendermint/tendermint/p2p/conn"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
@ -85,7 +83,7 @@ func NewSwitch(config *cfg.P2PConfig) *Switch {
sw.peerConfig.MConfig.FlushThrottle = time.Duration(config.FlushThrottleTimeout) * time.Millisecond sw.peerConfig.MConfig.FlushThrottle = time.Duration(config.FlushThrottleTimeout) * time.Millisecond
sw.peerConfig.MConfig.SendRate = config.SendRate sw.peerConfig.MConfig.SendRate = config.SendRate
sw.peerConfig.MConfig.RecvRate = config.RecvRate sw.peerConfig.MConfig.RecvRate = config.RecvRate
sw.peerConfig.MConfig.MaxMsgPacketPayloadSize = config.MaxMsgPacketPayloadSize
sw.peerConfig.MConfig.MaxPacketMsgPayloadSize = config.MaxPacketMsgPayloadSize
sw.peerConfig.AuthEnc = config.AuthEnc sw.peerConfig.AuthEnc = config.AuthEnc
sw.BaseService = *cmn.NewBaseService(nil, "P2P Switch", sw) sw.BaseService = *cmn.NewBaseService(nil, "P2P Switch", sw)
@ -171,7 +169,7 @@ func (sw *Switch) OnStart() error {
for _, reactor := range sw.reactors { for _, reactor := range sw.reactors {
err := reactor.Start() err := reactor.Start()
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to start %v", reactor)
return cmn.ErrorWrap(err, "failed to start %v", reactor)
} }
} }
// Start listeners // Start listeners
@ -206,18 +204,18 @@ func (sw *Switch) OnStop() {
// Broadcast runs a go routine for each attempted send, which will block trying // Broadcast runs a go routine for each attempted send, which will block trying
// to send for defaultSendTimeoutSeconds. Returns a channel which receives // to send for defaultSendTimeoutSeconds. Returns a channel which receives
// success values for each attempted send (false if times out). Channel will be // success values for each attempted send (false if times out). Channel will be
// closed once msg send to all peers.
// closed once msg bytes are sent to all peers (or time out).
// //
// NOTE: Broadcast uses goroutines, so order of broadcast may not be preserved. // NOTE: Broadcast uses goroutines, so order of broadcast may not be preserved.
func (sw *Switch) Broadcast(chID byte, msg interface{}) chan bool {
func (sw *Switch) Broadcast(chID byte, msgBytes []byte) chan bool {
successChan := make(chan bool, len(sw.peers.List())) successChan := make(chan bool, len(sw.peers.List()))
sw.Logger.Debug("Broadcast", "channel", chID, "msg", msg)
sw.Logger.Debug("Broadcast", "channel", chID, "msgBytes", fmt.Sprintf("%X", msgBytes))
var wg sync.WaitGroup var wg sync.WaitGroup
for _, peer := range sw.peers.List() { for _, peer := range sw.peers.List() {
wg.Add(1) wg.Add(1)
go func(peer Peer) { go func(peer Peer) {
defer wg.Done() defer wg.Done()
success := peer.Send(chID, msg)
success := peer.Send(chID, msgBytes)
successChan <- success successChan <- success
}(peer) }(peer)
} }


+ 9
- 10
p2p/switch_test.go View File

@ -12,7 +12,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
wire "github.com/tendermint/go-wire"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
@ -125,9 +124,9 @@ func TestSwitches(t *testing.T) {
} }
// Lets send some messages // Lets send some messages
ch0Msg := "channel zero"
ch1Msg := "channel foo"
ch2Msg := "channel bar"
ch0Msg := []byte("channel zero")
ch1Msg := []byte("channel foo")
ch2Msg := []byte("channel bar")
s1.Broadcast(byte(0x00), ch0Msg) s1.Broadcast(byte(0x00), ch0Msg)
s1.Broadcast(byte(0x01), ch1Msg) s1.Broadcast(byte(0x01), ch1Msg)
@ -138,15 +137,15 @@ func TestSwitches(t *testing.T) {
assertMsgReceivedWithTimeout(t, ch2Msg, byte(0x02), s2.Reactor("bar").(*TestReactor), 10*time.Millisecond, 5*time.Second) assertMsgReceivedWithTimeout(t, ch2Msg, byte(0x02), s2.Reactor("bar").(*TestReactor), 10*time.Millisecond, 5*time.Second)
} }
func assertMsgReceivedWithTimeout(t *testing.T, msg string, channel byte, reactor *TestReactor, checkPeriod, timeout time.Duration) {
func assertMsgReceivedWithTimeout(t *testing.T, msgBytes []byte, channel byte, reactor *TestReactor, checkPeriod, timeout time.Duration) {
ticker := time.NewTicker(checkPeriod) ticker := time.NewTicker(checkPeriod)
for { for {
select { select {
case <-ticker.C: case <-ticker.C:
msgs := reactor.getMsgs(channel) msgs := reactor.getMsgs(channel)
if len(msgs) > 0 { if len(msgs) > 0 {
if !bytes.Equal(msgs[0].Bytes, wire.BinaryBytes(msg)) {
t.Fatalf("Unexpected message bytes. Wanted: %X, Got: %X", wire.BinaryBytes(msg), msgs[0].Bytes)
if !bytes.Equal(msgs[0].Bytes, msgBytes) {
t.Fatalf("Unexpected message bytes. Wanted: %X, Got: %X", msgBytes, msgs[0].Bytes)
} }
return return
} }
@ -238,7 +237,7 @@ func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) {
defer sw.Stop() defer sw.Stop()
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -268,7 +267,7 @@ func TestSwitchReconnectsToPersistentPeer(t *testing.T) {
defer sw.Stop() defer sw.Stop()
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -338,7 +337,7 @@ func BenchmarkSwitchBroadcast(b *testing.B) {
// Send random message from foo channel to another // Send random message from foo channel to another
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
chID := byte(i % 4) chID := byte(i % 4)
successChan := s1.Broadcast(chID, "test data")
successChan := s1.Broadcast(chID, []byte("test data"))
for s := range successChan { for s := range successChan {
if s { if s {
numSuccess++ numSuccess++


+ 2
- 2
p2p/test_util.go View File

@ -24,7 +24,7 @@ func CreateRandomPeer(outbound bool) *peer {
}, },
nodeInfo: NodeInfo{ nodeInfo: NodeInfo{
ListenAddr: netAddr.DialString(), ListenAddr: netAddr.DialString(),
PubKey: crypto.GenPrivKeyEd25519().Wrap().PubKey(),
PubKey: crypto.GenPrivKeyEd25519().PubKey(),
}, },
mconn: &conn.MConnection{}, mconn: &conn.MConnection{},
} }
@ -131,7 +131,7 @@ func MakeSwitch(cfg *cfg.P2PConfig, i int, network, version string, initSwitch f
// new switch, add reactors // new switch, add reactors
// TODO: let the config be passed in? // TODO: let the config be passed in?
nodeKey := &NodeKey{ nodeKey := &NodeKey{
PrivKey: crypto.GenPrivKeyEd25519().Wrap(),
PrivKey: crypto.GenPrivKeyEd25519(),
} }
sw := NewSwitch(cfg) sw := NewSwitch(cfg)
sw.SetLogger(log.TestingLogger()) sw.SetLogger(log.TestingLogger())


+ 4
- 6
p2p/upnp/probe.go View File

@ -5,8 +5,6 @@ import (
"net" "net"
"time" "time"
"github.com/pkg/errors"
cmn "github.com/tendermint/tmlibs/common" cmn "github.com/tendermint/tmlibs/common"
"github.com/tendermint/tmlibs/log" "github.com/tendermint/tmlibs/log"
) )
@ -19,26 +17,26 @@ type UPNPCapabilities struct {
func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Listener, net.IP, error) { func makeUPNPListener(intPort int, extPort int, logger log.Logger) (NAT, net.Listener, net.IP, error) {
nat, err := Discover() nat, err := Discover()
if err != nil { if err != nil {
return nil, nil, nil, errors.Errorf("NAT upnp could not be discovered: %v", err)
return nil, nil, nil, fmt.Errorf("NAT upnp could not be discovered: %v", err)
} }
logger.Info(cmn.Fmt("ourIP: %v", nat.(*upnpNAT).ourIP)) logger.Info(cmn.Fmt("ourIP: %v", nat.(*upnpNAT).ourIP))
ext, err := nat.GetExternalAddress() ext, err := nat.GetExternalAddress()
if err != nil { if err != nil {
return nat, nil, nil, errors.Errorf("External address error: %v", err)
return nat, nil, nil, fmt.Errorf("External address error: %v", err)
} }
logger.Info(cmn.Fmt("External address: %v", ext)) logger.Info(cmn.Fmt("External address: %v", ext))
port, err := nat.AddPortMapping("tcp", extPort, intPort, "Tendermint UPnP Probe", 0) port, err := nat.AddPortMapping("tcp", extPort, intPort, "Tendermint UPnP Probe", 0)
if err != nil { if err != nil {
return nat, nil, ext, errors.Errorf("Port mapping error: %v", err)
return nat, nil, ext, fmt.Errorf("Port mapping error: %v", err)
} }
logger.Info(cmn.Fmt("Port mapping mapped: %v", port)) logger.Info(cmn.Fmt("Port mapping mapped: %v", port))
// also run the listener, open for all remote addresses. // also run the listener, open for all remote addresses.
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", intPort)) listener, err := net.Listen("tcp", fmt.Sprintf(":%v", intPort))
if err != nil { if err != nil {
return nat, nil, ext, errors.Errorf("Error establishing listener: %v", err)
return nat, nil, ext, fmt.Errorf("Error establishing listener: %v", err)
} }
return nat, listener, ext, nil return nat, listener, ext, nil
} }


+ 12
- 0
p2p/wire.go View File

@ -0,0 +1,12 @@
package p2p
import (
"github.com/tendermint/go-amino"
"github.com/tendermint/go-crypto"
)
var cdc = amino.NewCodec()
func init() {
crypto.RegisterAmino(cdc)
}

Loading…
Cancel
Save