// TestMessage tests the Read/WriteMessage and Read/WriteMessageN API. func TestMessage(t *testing.T) { pver := wire.ProtocolVersion // Create the various types of messages to test. // MsgVersion. addrYou := &net.TCPAddr{IP: net.ParseIP("192.168.0.1"), Port: 8333} you, err := wire.NewNetAddress(addrYou, wire.SFNodeNetwork) if err != nil { t.Errorf("NewNetAddress: %v", err) } you.Timestamp = time.Time{} // Version message has zero value timestamp. addrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333} me, err := wire.NewNetAddress(addrMe, wire.SFNodeNetwork) if err != nil { t.Errorf("NewNetAddress: %v", err) } me.Timestamp = time.Time{} // Version message has zero value timestamp. msgVersion := wire.NewMsgVersion(me, you, 123123, 0) msgVerack := wire.NewMsgVerAck() msgGetAddr := wire.NewMsgGetAddr() msgAddr := wire.NewMsgAddr() msgGetBlocks := wire.NewMsgGetBlocks(&wire.ShaHash{}) msgBlock := &blockOne msgInv := wire.NewMsgInv() msgGetData := wire.NewMsgGetData() msgNotFound := wire.NewMsgNotFound() msgTx := wire.NewMsgTx() msgPing := wire.NewMsgPing(123123) msgPong := wire.NewMsgPong(123123) msgGetHeaders := wire.NewMsgGetHeaders() msgHeaders := wire.NewMsgHeaders() msgAlert := wire.NewMsgAlert([]byte("payload"), []byte("signature")) msgMemPool := wire.NewMsgMemPool() msgFilterAdd := wire.NewMsgFilterAdd([]byte{0x01}) msgFilterClear := wire.NewMsgFilterClear() msgFilterLoad := wire.NewMsgFilterLoad([]byte{0x01}, 10, 0, wire.BloomUpdateNone) bh := wire.NewBlockHeader(&wire.ShaHash{}, &wire.ShaHash{}, 0, 0) msgMerkleBlock := wire.NewMsgMerkleBlock(bh) msgReject := wire.NewMsgReject("block", wire.RejectDuplicate, "duplicate block") tests := []struct { in wire.Message // Value to encode out wire.Message // Expected decoded value pver uint32 // Protocol version for wire encoding btcnet wire.BitcoinNet // Network to use for wire encoding bytes int // Expected num bytes read/written }{ {msgVersion, msgVersion, pver, wire.MainNet, 125}, {msgVerack, msgVerack, pver, wire.MainNet, 24}, {msgGetAddr, msgGetAddr, pver, wire.MainNet, 24}, {msgAddr, msgAddr, pver, wire.MainNet, 25}, {msgGetBlocks, msgGetBlocks, pver, wire.MainNet, 61}, {msgBlock, msgBlock, pver, wire.MainNet, 239}, {msgInv, msgInv, pver, wire.MainNet, 25}, {msgGetData, msgGetData, pver, wire.MainNet, 25}, {msgNotFound, msgNotFound, pver, wire.MainNet, 25}, {msgTx, msgTx, pver, wire.MainNet, 34}, {msgPing, msgPing, pver, wire.MainNet, 32}, {msgPong, msgPong, pver, wire.MainNet, 32}, {msgGetHeaders, msgGetHeaders, pver, wire.MainNet, 61}, {msgHeaders, msgHeaders, pver, wire.MainNet, 25}, {msgAlert, msgAlert, pver, wire.MainNet, 42}, {msgMemPool, msgMemPool, pver, wire.MainNet, 24}, {msgFilterAdd, msgFilterAdd, pver, wire.MainNet, 26}, {msgFilterClear, msgFilterClear, pver, wire.MainNet, 24}, {msgFilterLoad, msgFilterLoad, pver, wire.MainNet, 35}, {msgMerkleBlock, msgMerkleBlock, pver, wire.MainNet, 110}, {msgReject, msgReject, pver, wire.MainNet, 79}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode to wire format. var buf bytes.Buffer nw, err := wire.WriteMessageN(&buf, test.in, test.pver, test.btcnet) if err != nil { t.Errorf("WriteMessage #%d error %v", i, err) continue } // Ensure the number of bytes written match the expected value. if nw != test.bytes { t.Errorf("WriteMessage #%d unexpected num bytes "+ "written - got %d, want %d", i, nw, test.bytes) } // Decode from wire format. rbuf := bytes.NewReader(buf.Bytes()) nr, msg, _, err := wire.ReadMessageN(rbuf, test.pver, test.btcnet) if err != nil { t.Errorf("ReadMessage #%d error %v, msg %v", i, err, spew.Sdump(msg)) continue } if !reflect.DeepEqual(msg, test.out) { t.Errorf("ReadMessage #%d\n got: %v want: %v", i, spew.Sdump(msg), spew.Sdump(test.out)) continue } // Ensure the number of bytes read match the expected value. if nr != test.bytes { t.Errorf("ReadMessage #%d unexpected num bytes read - "+ "got %d, want %d", i, nr, test.bytes) } } // Do the same thing for Read/WriteMessage, but ignore the bytes since // they don't return them. t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode to wire format. var buf bytes.Buffer err := wire.WriteMessage(&buf, test.in, test.pver, test.btcnet) if err != nil { t.Errorf("WriteMessage #%d error %v", i, err) continue } // Decode from wire format. rbuf := bytes.NewReader(buf.Bytes()) msg, _, err := wire.ReadMessage(rbuf, test.pver, test.btcnet) if err != nil { t.Errorf("ReadMessage #%d error %v, msg %v", i, err, spew.Sdump(msg)) continue } if !reflect.DeepEqual(msg, test.out) { t.Errorf("ReadMessage #%d\n got: %v want: %v", i, spew.Sdump(msg), spew.Sdump(test.out)) continue } } }
// TestAddrWireErrors performs negative tests against wire encode and decode // of MsgAddr to confirm error paths work correctly. func TestAddrWireErrors(t *testing.T) { pver := wire.ProtocolVersion pverMA := wire.MultipleAddressVersion wireErr := &wire.MessageError{} // A couple of NetAddresses to use for testing. na := &wire.NetAddress{ Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST Services: wire.SFNodeNetwork, IP: net.ParseIP("127.0.0.1"), Port: 8333, } na2 := &wire.NetAddress{ Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST Services: wire.SFNodeNetwork, IP: net.ParseIP("192.168.0.1"), Port: 8334, } // Address message with multiple addresses. baseAddr := wire.NewMsgAddr() baseAddr.AddAddresses(na, na2) baseAddrEncoded := []byte{ 0x02, // Varint for number of addresses 0x29, 0xab, 0x5f, 0x49, // Timestamp 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFNodeNetwork 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01, // IP 127.0.0.1 0x20, 0x8d, // Port 8333 in big-endian 0x29, 0xab, 0x5f, 0x49, // Timestamp 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFNodeNetwork 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x01, // IP 192.168.0.1 0x20, 0x8e, // Port 8334 in big-endian } // Message that forces an error by having more than the max allowed // addresses. maxAddr := wire.NewMsgAddr() for i := 0; i < wire.MaxAddrPerMsg; i++ { maxAddr.AddAddress(na) } maxAddr.AddrList = append(maxAddr.AddrList, na) maxAddrEncoded := []byte{ 0xfd, 0x03, 0xe9, // Varint for number of addresses (1001) } tests := []struct { in *wire.MsgAddr // Value to encode buf []byte // Wire encoding pver uint32 // Protocol version for wire encoding max int // Max size of fixed buffer to induce errors writeErr error // Expected write error readErr error // Expected read error }{ // Latest protocol version with intentional read/write errors. // Force error in addresses count {baseAddr, baseAddrEncoded, pver, 0, io.ErrShortWrite, io.EOF}, // Force error in address list. {baseAddr, baseAddrEncoded, pver, 1, io.ErrShortWrite, io.EOF}, // Force error with greater than max inventory vectors. {maxAddr, maxAddrEncoded, pver, 3, wireErr, wireErr}, // Force error with greater than max inventory vectors for // protocol versions before multiple addresses were allowed. {maxAddr, maxAddrEncoded, pverMA - 1, 3, wireErr, wireErr}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode to wire format. w := newFixedWriter(test.max) err := test.in.BtcEncode(w, test.pver) if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) { t.Errorf("BtcEncode #%d wrong error got: %v, want: %v", i, err, test.writeErr) continue } // For errors which are not of type wire.MessageError, check // them for equality. if _, ok := err.(*wire.MessageError); !ok { if err != test.writeErr { t.Errorf("BtcEncode #%d wrong error got: %v, "+ "want: %v", i, err, test.writeErr) continue } } // Decode from wire format. var msg wire.MsgAddr r := newFixedReader(test.max, test.buf) err = msg.BtcDecode(r, test.pver) if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) { t.Errorf("BtcDecode #%d wrong error got: %v, want: %v", i, err, test.readErr) continue } // For errors which are not of type wire.MessageError, check // them for equality. if _, ok := err.(*wire.MessageError); !ok { if err != test.readErr { t.Errorf("BtcDecode #%d wrong error got: %v, "+ "want: %v", i, err, test.readErr) continue } } } }
// TestAddrWire tests the MsgAddr wire encode and decode for various numbers // of addreses and protocol versions. func TestAddrWire(t *testing.T) { // A couple of NetAddresses to use for testing. na := &wire.NetAddress{ Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST Services: wire.SFNodeNetwork, IP: net.ParseIP("127.0.0.1"), Port: 8333, } na2 := &wire.NetAddress{ Timestamp: time.Unix(0x495fab29, 0), // 2009-01-03 12:15:05 -0600 CST Services: wire.SFNodeNetwork, IP: net.ParseIP("192.168.0.1"), Port: 8334, } // Empty address message. noAddr := wire.NewMsgAddr() noAddrEncoded := []byte{ 0x00, // Varint for number of addresses } // Address message with multiple addresses. multiAddr := wire.NewMsgAddr() multiAddr.AddAddresses(na, na2) multiAddrEncoded := []byte{ 0x02, // Varint for number of addresses 0x29, 0xab, 0x5f, 0x49, // Timestamp 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFNodeNetwork 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01, // IP 127.0.0.1 0x20, 0x8d, // Port 8333 in big-endian 0x29, 0xab, 0x5f, 0x49, // Timestamp 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SFNodeNetwork 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x01, // IP 192.168.0.1 0x20, 0x8e, // Port 8334 in big-endian } tests := []struct { in *wire.MsgAddr // Message to encode out *wire.MsgAddr // Expected decoded message buf []byte // Wire encoding pver uint32 // Protocol version for wire encoding }{ // Latest protocol version with no addresses. { noAddr, noAddr, noAddrEncoded, wire.ProtocolVersion, }, // Latest protocol version with multiple addresses. { multiAddr, multiAddr, multiAddrEncoded, wire.ProtocolVersion, }, // Protocol version MultipleAddressVersion-1 with no addresses. { noAddr, noAddr, noAddrEncoded, wire.MultipleAddressVersion - 1, }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Encode the message to wire format. var buf bytes.Buffer err := test.in.BtcEncode(&buf, test.pver) if err != nil { t.Errorf("BtcEncode #%d error %v", i, err) continue } if !bytes.Equal(buf.Bytes(), test.buf) { t.Errorf("BtcEncode #%d\n got: %s want: %s", i, spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) continue } // Decode the message from wire format. var msg wire.MsgAddr rbuf := bytes.NewReader(test.buf) err = msg.BtcDecode(rbuf, test.pver) if err != nil { t.Errorf("BtcDecode #%d error %v", i, err) continue } if !reflect.DeepEqual(&msg, test.out) { t.Errorf("BtcDecode #%d\n got: %s want: %s", i, spew.Sdump(msg), spew.Sdump(test.out)) continue } } }
// TestAddr tests the MsgAddr API. func TestAddr(t *testing.T) { pver := wire.ProtocolVersion // Ensure the command is expected value. wantCmd := "addr" msg := wire.NewMsgAddr() if cmd := msg.Command(); cmd != wantCmd { t.Errorf("NewMsgAddr: wrong command - got %v want %v", cmd, wantCmd) } // Ensure max payload is expected value for latest protocol version. // Num addresses (varInt) + max allowed addresses. wantPayload := uint32(30009) maxPayload := msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ "protocol version %d - got %v, want %v", pver, maxPayload, wantPayload) } // Ensure NetAddresses are added properly. tcpAddr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333} na, err := wire.NewNetAddress(tcpAddr, wire.SFNodeNetwork) if err != nil { t.Errorf("NewNetAddress: %v", err) } err = msg.AddAddress(na) if err != nil { t.Errorf("AddAddress: %v", err) } if msg.AddrList[0] != na { t.Errorf("AddAddress: wrong address added - got %v, want %v", spew.Sprint(msg.AddrList[0]), spew.Sprint(na)) } // Ensure the address list is cleared properly. msg.ClearAddresses() if len(msg.AddrList) != 0 { t.Errorf("ClearAddresses: address list is not empty - "+ "got %v [%v], want %v", len(msg.AddrList), spew.Sprint(msg.AddrList[0]), 0) } // Ensure adding more than the max allowed addresses per message returns // error. for i := 0; i < wire.MaxAddrPerMsg+1; i++ { err = msg.AddAddress(na) } if err == nil { t.Errorf("AddAddress: expected error on too many addresses " + "not received") } err = msg.AddAddresses(na) if err == nil { t.Errorf("AddAddresses: expected error on too many addresses " + "not received") } // Ensure max payload is expected value for protocol versions before // timestamp was added to NetAddress. // Num addresses (varInt) + max allowed addresses. pver = wire.NetAddressTimeVersion - 1 wantPayload = uint32(26009) maxPayload = msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ "protocol version %d - got %v, want %v", pver, maxPayload, wantPayload) } // Ensure max payload is expected value for protocol versions before // multiple addresses were allowed. // Num addresses (varInt) + a single net addresses. pver = wire.MultipleAddressVersion - 1 wantPayload = uint32(35) maxPayload = msg.MaxPayloadLength(pver) if maxPayload != wantPayload { t.Errorf("MaxPayloadLength: wrong max payload length for "+ "protocol version %d - got %v, want %v", pver, maxPayload, wantPayload) } return }
// TestPeerListeners tests that the peer listeners are called as expected. func TestPeerListeners(t *testing.T) { verack := make(chan struct{}, 1) ok := make(chan wire.Message, 20) peerCfg := &peer.Config{ Listeners: peer.MessageListeners{ OnGetAddr: func(p *peer.Peer, msg *wire.MsgGetAddr) { ok <- msg }, OnAddr: func(p *peer.Peer, msg *wire.MsgAddr) { ok <- msg }, OnPing: func(p *peer.Peer, msg *wire.MsgPing) { ok <- msg }, OnPong: func(p *peer.Peer, msg *wire.MsgPong) { ok <- msg }, OnAlert: func(p *peer.Peer, msg *wire.MsgAlert) { ok <- msg }, OnMemPool: func(p *peer.Peer, msg *wire.MsgMemPool) { ok <- msg }, OnTx: func(p *peer.Peer, msg *wire.MsgTx) { ok <- msg }, OnBlock: func(p *peer.Peer, msg *wire.MsgBlock, buf []byte) { ok <- msg }, OnInv: func(p *peer.Peer, msg *wire.MsgInv) { ok <- msg }, OnHeaders: func(p *peer.Peer, msg *wire.MsgHeaders) { ok <- msg }, OnNotFound: func(p *peer.Peer, msg *wire.MsgNotFound) { ok <- msg }, OnGetData: func(p *peer.Peer, msg *wire.MsgGetData) { ok <- msg }, OnGetBlocks: func(p *peer.Peer, msg *wire.MsgGetBlocks) { ok <- msg }, OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) { ok <- msg }, OnFilterAdd: func(p *peer.Peer, msg *wire.MsgFilterAdd) { ok <- msg }, OnFilterClear: func(p *peer.Peer, msg *wire.MsgFilterClear) { ok <- msg }, OnFilterLoad: func(p *peer.Peer, msg *wire.MsgFilterLoad) { ok <- msg }, OnMerkleBlock: func(p *peer.Peer, msg *wire.MsgMerkleBlock) { ok <- msg }, OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { ok <- msg }, OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} }, OnReject: func(p *peer.Peer, msg *wire.MsgReject) { ok <- msg }, }, UserAgentName: "peer", UserAgentVersion: "1.0", ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeBloom, } inConn, outConn := pipe( &conn{raddr: "10.0.0.1:8333"}, &conn{raddr: "10.0.0.2:8333"}, ) inPeer := peer.NewInboundPeer(peerCfg, inConn) err := inPeer.Start() if err != nil { t.Errorf("TestPeerListeners: unexpected err %v\n", err) return } peerCfg.Listeners = peer.MessageListeners{ OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} }, } outPeer, err := peer.NewOutboundPeer(peerCfg, "10.0.0.1:8333") if err != nil { t.Errorf("NewOutboundPeer: unexpected err %v\n", err) return } if err := outPeer.Connect(outConn); err != nil { t.Errorf("TestPeerListeners: unexpected err %v\n", err) return } for i := 0; i < 2; i++ { select { case <-verack: case <-time.After(time.Second * 1): t.Errorf("TestPeerListeners: verack timeout\n") return } } tests := []struct { listener string msg wire.Message }{ { "OnGetAddr", wire.NewMsgGetAddr(), }, { "OnAddr", wire.NewMsgAddr(), }, { "OnPing", wire.NewMsgPing(42), }, { "OnPong", wire.NewMsgPong(42), }, { "OnAlert", wire.NewMsgAlert([]byte("payload"), []byte("signature")), }, { "OnMemPool", wire.NewMsgMemPool(), }, { "OnTx", wire.NewMsgTx(), }, { "OnBlock", wire.NewMsgBlock(wire.NewBlockHeader(&wire.ShaHash{}, &wire.ShaHash{}, 1, 1)), }, { "OnInv", wire.NewMsgInv(), }, { "OnHeaders", wire.NewMsgHeaders(), }, { "OnNotFound", wire.NewMsgNotFound(), }, { "OnGetData", wire.NewMsgGetData(), }, { "OnGetBlocks", wire.NewMsgGetBlocks(&wire.ShaHash{}), }, { "OnGetHeaders", wire.NewMsgGetHeaders(), }, { "OnFilterAdd", wire.NewMsgFilterAdd([]byte{0x01}), }, { "OnFilterClear", wire.NewMsgFilterClear(), }, { "OnFilterLoad", wire.NewMsgFilterLoad([]byte{0x01}, 10, 0, wire.BloomUpdateNone), }, { "OnMerkleBlock", wire.NewMsgMerkleBlock(wire.NewBlockHeader(&wire.ShaHash{}, &wire.ShaHash{}, 1, 1)), }, // only one version message is allowed // only one verack message is allowed { "OnMsgReject", wire.NewMsgReject("block", wire.RejectDuplicate, "dupe block"), }, } t.Logf("Running %d tests", len(tests)) for _, test := range tests { // Queue the test message outPeer.QueueMessage(test.msg, nil) select { case <-ok: case <-time.After(time.Second * 1): t.Errorf("TestPeerListeners: %s timeout", test.listener) return } } inPeer.Shutdown() outPeer.Shutdown() }