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