github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/wire/msggetdata_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  	"io"
    11  	"reflect"
    12  	"testing"
    13  
    14  	"github.com/dashpay/godash/wire"
    15  	"github.com/davecgh/go-spew/spew"
    16  )
    17  
    18  // TestGetData tests the MsgGetData API.
    19  func TestGetData(t *testing.T) {
    20  	pver := wire.ProtocolVersion
    21  
    22  	// Ensure the command is expected value.
    23  	wantCmd := "getdata"
    24  	msg := wire.NewMsgGetData()
    25  	if cmd := msg.Command(); cmd != wantCmd {
    26  		t.Errorf("NewMsgGetData: wrong command - got %v want %v",
    27  			cmd, wantCmd)
    28  	}
    29  
    30  	// Ensure max payload is expected value for latest protocol version.
    31  	// Num inventory vectors (varInt) + max allowed inventory vectors.
    32  	wantPayload := uint32(1800009)
    33  	maxPayload := msg.MaxPayloadLength(pver)
    34  	if maxPayload != wantPayload {
    35  		t.Errorf("MaxPayloadLength: wrong max payload length for "+
    36  			"protocol version %d - got %v, want %v", pver,
    37  			maxPayload, wantPayload)
    38  	}
    39  
    40  	// Ensure inventory vectors are added properly.
    41  	hash := wire.ShaHash{}
    42  	iv := wire.NewInvVect(wire.InvTypeBlock, &hash)
    43  	err := msg.AddInvVect(iv)
    44  	if err != nil {
    45  		t.Errorf("AddInvVect: %v", err)
    46  	}
    47  	if msg.InvList[0] != iv {
    48  		t.Errorf("AddInvVect: wrong invvect added - got %v, want %v",
    49  			spew.Sprint(msg.InvList[0]), spew.Sprint(iv))
    50  	}
    51  
    52  	// Ensure adding more than the max allowed inventory vectors per
    53  	// message returns an error.
    54  	for i := 0; i < wire.MaxInvPerMsg; i++ {
    55  		err = msg.AddInvVect(iv)
    56  	}
    57  	if err == nil {
    58  		t.Errorf("AddInvVect: expected error on too many inventory " +
    59  			"vectors not received")
    60  	}
    61  
    62  	// Ensure creating the message with a size hint larger than the max
    63  	// works as expected.
    64  	msg = wire.NewMsgGetDataSizeHint(wire.MaxInvPerMsg + 1)
    65  	wantCap := wire.MaxInvPerMsg
    66  	if cap(msg.InvList) != wantCap {
    67  		t.Errorf("NewMsgGetDataSizeHint: wrong cap for size hint - "+
    68  			"got %v, want %v", cap(msg.InvList), wantCap)
    69  	}
    70  
    71  	return
    72  }
    73  
    74  // TestGetDataWire tests the MsgGetData wire encode and decode for various
    75  // numbers of inventory vectors and protocol versions.
    76  func TestGetDataWire(t *testing.T) {
    77  	// Block 203707 hash.
    78  	hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
    79  	blockHash, err := wire.NewShaHashFromStr(hashStr)
    80  	if err != nil {
    81  		t.Errorf("NewShaHashFromStr: %v", err)
    82  	}
    83  
    84  	// Transation 1 of Block 203707 hash.
    85  	hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
    86  	txHash, err := wire.NewShaHashFromStr(hashStr)
    87  	if err != nil {
    88  		t.Errorf("NewShaHashFromStr: %v", err)
    89  	}
    90  
    91  	iv := wire.NewInvVect(wire.InvTypeBlock, blockHash)
    92  	iv2 := wire.NewInvVect(wire.InvTypeTx, txHash)
    93  
    94  	// Empty MsgGetData message.
    95  	NoInv := wire.NewMsgGetData()
    96  	NoInvEncoded := []byte{
    97  		0x00, // Varint for number of inventory vectors
    98  	}
    99  
   100  	// MsgGetData message with multiple inventory vectors.
   101  	MultiInv := wire.NewMsgGetData()
   102  	MultiInv.AddInvVect(iv)
   103  	MultiInv.AddInvVect(iv2)
   104  	MultiInvEncoded := []byte{
   105  		0x02,                   // Varint for number of inv vectors
   106  		0x02, 0x00, 0x00, 0x00, // InvTypeBlock
   107  		0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
   108  		0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
   109  		0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
   110  		0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
   111  		0x01, 0x00, 0x00, 0x00, // InvTypeTx
   112  		0xf0, 0xfa, 0xcc, 0x7a, 0x48, 0x1b, 0xe7, 0xcf,
   113  		0x42, 0xbd, 0x7f, 0xe5, 0x4f, 0x2c, 0x2a, 0xf8,
   114  		0xef, 0x81, 0x9a, 0xdd, 0x93, 0xee, 0x55, 0x98,
   115  		0x0a, 0xf0, 0x2b, 0x39, 0xc7, 0x3d, 0x8a, 0xd2, // Tx 1 of block 203707 hash
   116  	}
   117  
   118  	tests := []struct {
   119  		in   *wire.MsgGetData // Message to encode
   120  		out  *wire.MsgGetData // Expected decoded message
   121  		buf  []byte           // Wire encoding
   122  		pver uint32           // Protocol version for wire encoding
   123  	}{
   124  		// Latest protocol version with no inv vectors.
   125  		{
   126  			NoInv,
   127  			NoInv,
   128  			NoInvEncoded,
   129  			wire.ProtocolVersion,
   130  		},
   131  
   132  		// Latest protocol version with multiple inv vectors.
   133  		{
   134  			MultiInv,
   135  			MultiInv,
   136  			MultiInvEncoded,
   137  			wire.ProtocolVersion,
   138  		},
   139  
   140  		// Protocol version BIP0035Version no inv vectors.
   141  		{
   142  			NoInv,
   143  			NoInv,
   144  			NoInvEncoded,
   145  			wire.BIP0035Version,
   146  		},
   147  
   148  		// Protocol version BIP0035Version with multiple inv vectors.
   149  		{
   150  			MultiInv,
   151  			MultiInv,
   152  			MultiInvEncoded,
   153  			wire.BIP0035Version,
   154  		},
   155  
   156  		// Protocol version BIP0031Version no inv vectors.
   157  		{
   158  			NoInv,
   159  			NoInv,
   160  			NoInvEncoded,
   161  			wire.BIP0031Version,
   162  		},
   163  
   164  		// Protocol version BIP0031Version with multiple inv vectors.
   165  		{
   166  			MultiInv,
   167  			MultiInv,
   168  			MultiInvEncoded,
   169  			wire.BIP0031Version,
   170  		},
   171  
   172  		// Protocol version NetAddressTimeVersion no inv vectors.
   173  		{
   174  			NoInv,
   175  			NoInv,
   176  			NoInvEncoded,
   177  			wire.NetAddressTimeVersion,
   178  		},
   179  
   180  		// Protocol version NetAddressTimeVersion with multiple inv vectors.
   181  		{
   182  			MultiInv,
   183  			MultiInv,
   184  			MultiInvEncoded,
   185  			wire.NetAddressTimeVersion,
   186  		},
   187  
   188  		// Protocol version MultipleAddressVersion no inv vectors.
   189  		{
   190  			NoInv,
   191  			NoInv,
   192  			NoInvEncoded,
   193  			wire.MultipleAddressVersion,
   194  		},
   195  
   196  		// Protocol version MultipleAddressVersion with multiple inv vectors.
   197  		{
   198  			MultiInv,
   199  			MultiInv,
   200  			MultiInvEncoded,
   201  			wire.MultipleAddressVersion,
   202  		},
   203  	}
   204  
   205  	t.Logf("Running %d tests", len(tests))
   206  	for i, test := range tests {
   207  		// Encode the message to wire format.
   208  		var buf bytes.Buffer
   209  		err := test.in.BtcEncode(&buf, test.pver)
   210  		if err != nil {
   211  			t.Errorf("BtcEncode #%d error %v", i, err)
   212  			continue
   213  		}
   214  		if !bytes.Equal(buf.Bytes(), test.buf) {
   215  			t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
   216  				spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
   217  			continue
   218  		}
   219  
   220  		// Decode the message from wire format.
   221  		var msg wire.MsgGetData
   222  		rbuf := bytes.NewReader(test.buf)
   223  		err = msg.BtcDecode(rbuf, test.pver)
   224  		if err != nil {
   225  			t.Errorf("BtcDecode #%d error %v", i, err)
   226  			continue
   227  		}
   228  		if !reflect.DeepEqual(&msg, test.out) {
   229  			t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
   230  				spew.Sdump(msg), spew.Sdump(test.out))
   231  			continue
   232  		}
   233  	}
   234  }
   235  
   236  // TestGetDataWireErrors performs negative tests against wire encode and decode
   237  // of MsgGetData to confirm error paths work correctly.
   238  func TestGetDataWireErrors(t *testing.T) {
   239  	pver := wire.ProtocolVersion
   240  	wireErr := &wire.MessageError{}
   241  
   242  	// Block 203707 hash.
   243  	hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
   244  	blockHash, err := wire.NewShaHashFromStr(hashStr)
   245  	if err != nil {
   246  		t.Errorf("NewShaHashFromStr: %v", err)
   247  	}
   248  
   249  	iv := wire.NewInvVect(wire.InvTypeBlock, blockHash)
   250  
   251  	// Base message used to induce errors.
   252  	baseGetData := wire.NewMsgGetData()
   253  	baseGetData.AddInvVect(iv)
   254  	baseGetDataEncoded := []byte{
   255  		0x02,                   // Varint for number of inv vectors
   256  		0x02, 0x00, 0x00, 0x00, // InvTypeBlock
   257  		0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
   258  		0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
   259  		0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
   260  		0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
   261  	}
   262  
   263  	// Message that forces an error by having more than the max allowed inv
   264  	// vectors.
   265  	maxGetData := wire.NewMsgGetData()
   266  	for i := 0; i < wire.MaxInvPerMsg; i++ {
   267  		maxGetData.AddInvVect(iv)
   268  	}
   269  	maxGetData.InvList = append(maxGetData.InvList, iv)
   270  	maxGetDataEncoded := []byte{
   271  		0xfd, 0x51, 0xc3, // Varint for number of inv vectors (50001)
   272  	}
   273  
   274  	tests := []struct {
   275  		in       *wire.MsgGetData // Value to encode
   276  		buf      []byte           // Wire encoding
   277  		pver     uint32           // Protocol version for wire encoding
   278  		max      int              // Max size of fixed buffer to induce errors
   279  		writeErr error            // Expected write error
   280  		readErr  error            // Expected read error
   281  	}{
   282  		// Latest protocol version with intentional read/write errors.
   283  		// Force error in inventory vector count
   284  		{baseGetData, baseGetDataEncoded, pver, 0, io.ErrShortWrite, io.EOF},
   285  		// Force error in inventory list.
   286  		{baseGetData, baseGetDataEncoded, pver, 1, io.ErrShortWrite, io.EOF},
   287  		// Force error with greater than max inventory vectors.
   288  		{maxGetData, maxGetDataEncoded, pver, 3, wireErr, wireErr},
   289  	}
   290  
   291  	t.Logf("Running %d tests", len(tests))
   292  	for i, test := range tests {
   293  		// Encode to wire format.
   294  		w := newFixedWriter(test.max)
   295  		err := test.in.BtcEncode(w, test.pver)
   296  		if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
   297  			t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
   298  				i, err, test.writeErr)
   299  			continue
   300  		}
   301  
   302  		// For errors which are not of type wire.MessageError, check
   303  		// them for equality.
   304  		if _, ok := err.(*wire.MessageError); !ok {
   305  			if err != test.writeErr {
   306  				t.Errorf("BtcEncode #%d wrong error got: %v, "+
   307  					"want: %v", i, err, test.writeErr)
   308  				continue
   309  			}
   310  		}
   311  
   312  		// Decode from wire format.
   313  		var msg wire.MsgGetData
   314  		r := newFixedReader(test.max, test.buf)
   315  		err = msg.BtcDecode(r, test.pver)
   316  		if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
   317  			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
   318  				i, err, test.readErr)
   319  			continue
   320  		}
   321  
   322  		// For errors which are not of type wire.MessageError, check
   323  		// them for equality.
   324  		if _, ok := err.(*wire.MessageError); !ok {
   325  			if err != test.readErr {
   326  				t.Errorf("BtcDecode #%d wrong error got: %v, "+
   327  					"want: %v", i, err, test.readErr)
   328  				continue
   329  			}
   330  		}
   331  	}
   332  }