msggetdata_test.go raw

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