github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/wire/message_test.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package wire_test
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/binary"
    11  	"io"
    12  	"net"
    13  	"reflect"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/dashpay/godash/wire"
    18  	"github.com/davecgh/go-spew/spew"
    19  )
    20  
    21  // makeHeader is a convenience function to make a message header in the form of
    22  // a byte slice.  It is used to force errors when reading messages.
    23  func makeHeader(btcnet wire.BitcoinNet, command string,
    24  	payloadLen uint32, checksum uint32) []byte {
    25  
    26  	// The length of a bitcoin message header is 24 bytes.
    27  	// 4 byte magic number of the bitcoin network + 12 byte command + 4 byte
    28  	// payload length + 4 byte checksum.
    29  	buf := make([]byte, 24)
    30  	binary.LittleEndian.PutUint32(buf, uint32(btcnet))
    31  	copy(buf[4:], []byte(command))
    32  	binary.LittleEndian.PutUint32(buf[16:], payloadLen)
    33  	binary.LittleEndian.PutUint32(buf[20:], checksum)
    34  	return buf
    35  }
    36  
    37  // TestMessage tests the Read/WriteMessage and Read/WriteMessageN API.
    38  func TestMessage(t *testing.T) {
    39  	pver := wire.ProtocolVersion
    40  
    41  	// Create the various types of messages to test.
    42  
    43  	// MsgVersion.
    44  	addrYou := &net.TCPAddr{IP: net.ParseIP("192.168.0.1"), Port: 8333}
    45  	you, err := wire.NewNetAddress(addrYou, wire.SFNodeNetwork)
    46  	if err != nil {
    47  		t.Errorf("NewNetAddress: %v", err)
    48  	}
    49  	you.Timestamp = time.Time{} // Version message has zero value timestamp.
    50  	addrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333}
    51  	me, err := wire.NewNetAddress(addrMe, wire.SFNodeNetwork)
    52  	if err != nil {
    53  		t.Errorf("NewNetAddress: %v", err)
    54  	}
    55  	me.Timestamp = time.Time{} // Version message has zero value timestamp.
    56  	msgVersion := wire.NewMsgVersion(me, you, 123123, 0)
    57  
    58  	msgVerack := wire.NewMsgVerAck()
    59  	msgGetAddr := wire.NewMsgGetAddr()
    60  	msgAddr := wire.NewMsgAddr()
    61  	msgGetBlocks := wire.NewMsgGetBlocks(&wire.ShaHash{})
    62  	msgBlock := &blockOne
    63  	msgInv := wire.NewMsgInv()
    64  	msgGetData := wire.NewMsgGetData()
    65  	msgNotFound := wire.NewMsgNotFound()
    66  	msgTx := wire.NewMsgTx()
    67  	msgPing := wire.NewMsgPing(123123)
    68  	msgPong := wire.NewMsgPong(123123)
    69  	msgGetHeaders := wire.NewMsgGetHeaders()
    70  	msgHeaders := wire.NewMsgHeaders()
    71  	msgAlert := wire.NewMsgAlert([]byte("payload"), []byte("signature"))
    72  	msgMemPool := wire.NewMsgMemPool()
    73  	msgFilterAdd := wire.NewMsgFilterAdd([]byte{0x01})
    74  	msgFilterClear := wire.NewMsgFilterClear()
    75  	msgFilterLoad := wire.NewMsgFilterLoad([]byte{0x01}, 10, 0, wire.BloomUpdateNone)
    76  	bh := wire.NewBlockHeader(&wire.ShaHash{}, &wire.ShaHash{}, 0, 0)
    77  	msgMerkleBlock := wire.NewMsgMerkleBlock(bh)
    78  	msgReject := wire.NewMsgReject("block", wire.RejectDuplicate, "duplicate block")
    79  
    80  	tests := []struct {
    81  		in     wire.Message    // Value to encode
    82  		out    wire.Message    // Expected decoded value
    83  		pver   uint32          // Protocol version for wire encoding
    84  		btcnet wire.BitcoinNet // Network to use for wire encoding
    85  		bytes  int             // Expected num bytes read/written
    86  	}{
    87  		{msgVersion, msgVersion, pver, wire.MainNet, 125},
    88  		{msgVerack, msgVerack, pver, wire.MainNet, 24},
    89  		{msgGetAddr, msgGetAddr, pver, wire.MainNet, 24},
    90  		{msgAddr, msgAddr, pver, wire.MainNet, 25},
    91  		{msgGetBlocks, msgGetBlocks, pver, wire.MainNet, 61},
    92  		{msgBlock, msgBlock, pver, wire.MainNet, 239},
    93  		{msgInv, msgInv, pver, wire.MainNet, 25},
    94  		{msgGetData, msgGetData, pver, wire.MainNet, 25},
    95  		{msgNotFound, msgNotFound, pver, wire.MainNet, 25},
    96  		{msgTx, msgTx, pver, wire.MainNet, 34},
    97  		{msgPing, msgPing, pver, wire.MainNet, 32},
    98  		{msgPong, msgPong, pver, wire.MainNet, 32},
    99  		{msgGetHeaders, msgGetHeaders, pver, wire.MainNet, 61},
   100  		{msgHeaders, msgHeaders, pver, wire.MainNet, 25},
   101  		{msgAlert, msgAlert, pver, wire.MainNet, 42},
   102  		{msgMemPool, msgMemPool, pver, wire.MainNet, 24},
   103  		{msgFilterAdd, msgFilterAdd, pver, wire.MainNet, 26},
   104  		{msgFilterClear, msgFilterClear, pver, wire.MainNet, 24},
   105  		{msgFilterLoad, msgFilterLoad, pver, wire.MainNet, 35},
   106  		{msgMerkleBlock, msgMerkleBlock, pver, wire.MainNet, 110},
   107  		{msgReject, msgReject, pver, wire.MainNet, 79},
   108  	}
   109  
   110  	t.Logf("Running %d tests", len(tests))
   111  	for i, test := range tests {
   112  		// Encode to wire format.
   113  		var buf bytes.Buffer
   114  		nw, err := wire.WriteMessageN(&buf, test.in, test.pver, test.btcnet)
   115  		if err != nil {
   116  			t.Errorf("WriteMessage #%d error %v", i, err)
   117  			continue
   118  		}
   119  
   120  		// Ensure the number of bytes written match the expected value.
   121  		if nw != test.bytes {
   122  			t.Errorf("WriteMessage #%d unexpected num bytes "+
   123  				"written - got %d, want %d", i, nw, test.bytes)
   124  		}
   125  
   126  		// Decode from wire format.
   127  		rbuf := bytes.NewReader(buf.Bytes())
   128  		nr, msg, _, err := wire.ReadMessageN(rbuf, test.pver, test.btcnet)
   129  		if err != nil {
   130  			t.Errorf("ReadMessage #%d error %v, msg %v", i, err,
   131  				spew.Sdump(msg))
   132  			continue
   133  		}
   134  		if !reflect.DeepEqual(msg, test.out) {
   135  			t.Errorf("ReadMessage #%d\n got: %v want: %v", i,
   136  				spew.Sdump(msg), spew.Sdump(test.out))
   137  			continue
   138  		}
   139  
   140  		// Ensure the number of bytes read match the expected value.
   141  		if nr != test.bytes {
   142  			t.Errorf("ReadMessage #%d unexpected num bytes read - "+
   143  				"got %d, want %d", i, nr, test.bytes)
   144  		}
   145  	}
   146  
   147  	// Do the same thing for Read/WriteMessage, but ignore the bytes since
   148  	// they don't return them.
   149  	t.Logf("Running %d tests", len(tests))
   150  	for i, test := range tests {
   151  		// Encode to wire format.
   152  		var buf bytes.Buffer
   153  		err := wire.WriteMessage(&buf, test.in, test.pver, test.btcnet)
   154  		if err != nil {
   155  			t.Errorf("WriteMessage #%d error %v", i, err)
   156  			continue
   157  		}
   158  
   159  		// Decode from wire format.
   160  		rbuf := bytes.NewReader(buf.Bytes())
   161  		msg, _, err := wire.ReadMessage(rbuf, test.pver, test.btcnet)
   162  		if err != nil {
   163  			t.Errorf("ReadMessage #%d error %v, msg %v", i, err,
   164  				spew.Sdump(msg))
   165  			continue
   166  		}
   167  		if !reflect.DeepEqual(msg, test.out) {
   168  			t.Errorf("ReadMessage #%d\n got: %v want: %v", i,
   169  				spew.Sdump(msg), spew.Sdump(test.out))
   170  			continue
   171  		}
   172  	}
   173  }
   174  
   175  // TestReadMessageWireErrors performs negative tests against wire decoding into
   176  // concrete messages to confirm error paths work correctly.
   177  func TestReadMessageWireErrors(t *testing.T) {
   178  	pver := wire.ProtocolVersion
   179  	btcnet := wire.MainNet
   180  
   181  	// Ensure message errors are as expected with no function specified.
   182  	wantErr := "something bad happened"
   183  	testErr := wire.MessageError{Description: wantErr}
   184  	if testErr.Error() != wantErr {
   185  		t.Errorf("MessageError: wrong error - got %v, want %v",
   186  			testErr.Error(), wantErr)
   187  	}
   188  
   189  	// Ensure message errors are as expected with a function specified.
   190  	wantFunc := "foo"
   191  	testErr = wire.MessageError{Func: wantFunc, Description: wantErr}
   192  	if testErr.Error() != wantFunc+": "+wantErr {
   193  		t.Errorf("MessageError: wrong error - got %v, want %v",
   194  			testErr.Error(), wantErr)
   195  	}
   196  
   197  	// Wire encoded bytes for main and testnet3 networks magic identifiers.
   198  	testNet3Bytes := makeHeader(wire.TestNet3, "", 0, 0)
   199  
   200  	// Wire encoded bytes for a message that exceeds max overall message
   201  	// length.
   202  	mpl := uint32(wire.MaxMessagePayload)
   203  	exceedMaxPayloadBytes := makeHeader(btcnet, "getaddr", mpl+1, 0)
   204  
   205  	// Wire encoded bytes for a command which is invalid utf-8.
   206  	badCommandBytes := makeHeader(btcnet, "bogus", 0, 0)
   207  	badCommandBytes[4] = 0x81
   208  
   209  	// Wire encoded bytes for a command which is valid, but not supported.
   210  	unsupportedCommandBytes := makeHeader(btcnet, "bogus", 0, 0)
   211  
   212  	// Wire encoded bytes for a message which exceeds the max payload for
   213  	// a specific message type.
   214  	exceedTypePayloadBytes := makeHeader(btcnet, "getaddr", 1, 0)
   215  
   216  	// Wire encoded bytes for a message which does not deliver the full
   217  	// payload according to the header length.
   218  	shortPayloadBytes := makeHeader(btcnet, "version", 115, 0)
   219  
   220  	// Wire encoded bytes for a message with a bad checksum.
   221  	badChecksumBytes := makeHeader(btcnet, "version", 2, 0xbeef)
   222  	badChecksumBytes = append(badChecksumBytes, []byte{0x0, 0x0}...)
   223  
   224  	// Wire encoded bytes for a message which has a valid header, but is
   225  	// the wrong format.  An addr starts with a varint of the number of
   226  	// contained in the message.  Claim there is two, but don't provide
   227  	// them.  At the same time, forge the header fields so the message is
   228  	// otherwise accurate.
   229  	badMessageBytes := makeHeader(btcnet, "addr", 1, 0xeaadc31c)
   230  	badMessageBytes = append(badMessageBytes, 0x2)
   231  
   232  	// Wire encoded bytes for a message which the header claims has 15k
   233  	// bytes of data to discard.
   234  	discardBytes := makeHeader(btcnet, "bogus", 15*1024, 0)
   235  
   236  	tests := []struct {
   237  		buf     []byte          // Wire encoding
   238  		pver    uint32          // Protocol version for wire encoding
   239  		btcnet  wire.BitcoinNet // Bitcoin network for wire encoding
   240  		max     int             // Max size of fixed buffer to induce errors
   241  		readErr error           // Expected read error
   242  		bytes   int             // Expected num bytes read
   243  	}{
   244  		// Latest protocol version with intentional read errors.
   245  
   246  		// Short header.
   247  		{
   248  			[]byte{},
   249  			pver,
   250  			btcnet,
   251  			0,
   252  			io.EOF,
   253  			0,
   254  		},
   255  
   256  		// Wrong network.  Want MainNet, but giving TestNet3.
   257  		{
   258  			testNet3Bytes,
   259  			pver,
   260  			btcnet,
   261  			len(testNet3Bytes),
   262  			&wire.MessageError{},
   263  			24,
   264  		},
   265  
   266  		// Exceed max overall message payload length.
   267  		{
   268  			exceedMaxPayloadBytes,
   269  			pver,
   270  			btcnet,
   271  			len(exceedMaxPayloadBytes),
   272  			&wire.MessageError{},
   273  			24,
   274  		},
   275  
   276  		// Invalid UTF-8 command.
   277  		{
   278  			badCommandBytes,
   279  			pver,
   280  			btcnet,
   281  			len(badCommandBytes),
   282  			&wire.MessageError{},
   283  			24,
   284  		},
   285  
   286  		// Valid, but unsupported command.
   287  		{
   288  			unsupportedCommandBytes,
   289  			pver,
   290  			btcnet,
   291  			len(unsupportedCommandBytes),
   292  			&wire.MessageError{},
   293  			24,
   294  		},
   295  
   296  		// Exceed max allowed payload for a message of a specific type.
   297  		{
   298  			exceedTypePayloadBytes,
   299  			pver,
   300  			btcnet,
   301  			len(exceedTypePayloadBytes),
   302  			&wire.MessageError{},
   303  			24,
   304  		},
   305  
   306  		// Message with a payload shorter than the header indicates.
   307  		{
   308  			shortPayloadBytes,
   309  			pver,
   310  			btcnet,
   311  			len(shortPayloadBytes),
   312  			io.EOF,
   313  			24,
   314  		},
   315  
   316  		// Message with a bad checksum.
   317  		{
   318  			badChecksumBytes,
   319  			pver,
   320  			btcnet,
   321  			len(badChecksumBytes),
   322  			&wire.MessageError{},
   323  			26,
   324  		},
   325  
   326  		// Message with a valid header, but wrong format.
   327  		{
   328  			badMessageBytes,
   329  			pver,
   330  			btcnet,
   331  			len(badMessageBytes),
   332  			io.EOF,
   333  			25,
   334  		},
   335  
   336  		// 15k bytes of data to discard.
   337  		{
   338  			discardBytes,
   339  			pver,
   340  			btcnet,
   341  			len(discardBytes),
   342  			&wire.MessageError{},
   343  			24,
   344  		},
   345  	}
   346  
   347  	t.Logf("Running %d tests", len(tests))
   348  	for i, test := range tests {
   349  		// Decode from wire format.
   350  		r := newFixedReader(test.max, test.buf)
   351  		nr, _, _, err := wire.ReadMessageN(r, test.pver, test.btcnet)
   352  		if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
   353  			t.Errorf("ReadMessage #%d wrong error got: %v <%T>, "+
   354  				"want: %T", i, err, err, test.readErr)
   355  			continue
   356  		}
   357  
   358  		// Ensure the number of bytes written match the expected value.
   359  		if nr != test.bytes {
   360  			t.Errorf("ReadMessage #%d unexpected num bytes read - "+
   361  				"got %d, want %d", i, nr, test.bytes)
   362  		}
   363  
   364  		// For errors which are not of type wire.MessageError, check
   365  		// them for equality.
   366  		if _, ok := err.(*wire.MessageError); !ok {
   367  			if err != test.readErr {
   368  				t.Errorf("ReadMessage #%d wrong error got: %v <%T>, "+
   369  					"want: %v <%T>", i, err, err,
   370  					test.readErr, test.readErr)
   371  				continue
   372  			}
   373  		}
   374  	}
   375  }
   376  
   377  // TestWriteMessageWireErrors performs negative tests against wire encoding from
   378  // concrete messages to confirm error paths work correctly.
   379  func TestWriteMessageWireErrors(t *testing.T) {
   380  	pver := wire.ProtocolVersion
   381  	btcnet := wire.MainNet
   382  	wireErr := &wire.MessageError{}
   383  
   384  	// Fake message with a command that is too long.
   385  	badCommandMsg := &fakeMessage{command: "somethingtoolong"}
   386  
   387  	// Fake message with a problem during encoding
   388  	encodeErrMsg := &fakeMessage{forceEncodeErr: true}
   389  
   390  	// Fake message that has payload which exceeds max overall message size.
   391  	exceedOverallPayload := make([]byte, wire.MaxMessagePayload+1)
   392  	exceedOverallPayloadErrMsg := &fakeMessage{payload: exceedOverallPayload}
   393  
   394  	// Fake message that has payload which exceeds max allowed per message.
   395  	exceedPayload := make([]byte, 1)
   396  	exceedPayloadErrMsg := &fakeMessage{payload: exceedPayload, forceLenErr: true}
   397  
   398  	// Fake message that is used to force errors in the header and payload
   399  	// writes.
   400  	bogusPayload := []byte{0x01, 0x02, 0x03, 0x04}
   401  	bogusMsg := &fakeMessage{command: "bogus", payload: bogusPayload}
   402  
   403  	tests := []struct {
   404  		msg    wire.Message    // Message to encode
   405  		pver   uint32          // Protocol version for wire encoding
   406  		btcnet wire.BitcoinNet // Bitcoin network for wire encoding
   407  		max    int             // Max size of fixed buffer to induce errors
   408  		err    error           // Expected error
   409  		bytes  int             // Expected num bytes written
   410  	}{
   411  		// Command too long.
   412  		{badCommandMsg, pver, btcnet, 0, wireErr, 0},
   413  		// Force error in payload encode.
   414  		{encodeErrMsg, pver, btcnet, 0, wireErr, 0},
   415  		// Force error due to exceeding max overall message payload size.
   416  		{exceedOverallPayloadErrMsg, pver, btcnet, 0, wireErr, 0},
   417  		// Force error due to exceeding max payload for message type.
   418  		{exceedPayloadErrMsg, pver, btcnet, 0, wireErr, 0},
   419  		// Force error in header write.
   420  		{bogusMsg, pver, btcnet, 0, io.ErrShortWrite, 0},
   421  		// Force error in payload write.
   422  		{bogusMsg, pver, btcnet, 24, io.ErrShortWrite, 24},
   423  	}
   424  
   425  	t.Logf("Running %d tests", len(tests))
   426  	for i, test := range tests {
   427  		// Encode wire format.
   428  		w := newFixedWriter(test.max)
   429  		nw, err := wire.WriteMessageN(w, test.msg, test.pver, test.btcnet)
   430  		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
   431  			t.Errorf("WriteMessage #%d wrong error got: %v <%T>, "+
   432  				"want: %T", i, err, err, test.err)
   433  			continue
   434  		}
   435  
   436  		// Ensure the number of bytes written match the expected value.
   437  		if nw != test.bytes {
   438  			t.Errorf("WriteMessage #%d unexpected num bytes "+
   439  				"written - got %d, want %d", i, nw, test.bytes)
   440  		}
   441  
   442  		// For errors which are not of type wire.MessageError, check
   443  		// them for equality.
   444  		if _, ok := err.(*wire.MessageError); !ok {
   445  			if err != test.err {
   446  				t.Errorf("ReadMessage #%d wrong error got: %v <%T>, "+
   447  					"want: %v <%T>", i, err, err,
   448  					test.err, test.err)
   449  				continue
   450  			}
   451  		}
   452  	}
   453  }