msggetheaders_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  // TestGetHeaders tests the MsgGetHeader API.
  15  func TestGetHeaders(t *testing.T) {
  16  	pver := ProtocolVersion
  17  	// Block 99500 hash.
  18  	hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
  19  	locatorHash, e := chainhash.NewHashFromStr(hashStr)
  20  	if e != nil {
  21  		t.Errorf("NewHashFromStr: %v", e)
  22  	}
  23  	// Ensure the command is expected value.
  24  	wantCmd := "getheaders"
  25  	msg := NewMsgGetHeaders()
  26  	if cmd := msg.Command(); cmd != wantCmd {
  27  		t.Errorf("NewMsgGetHeaders: wrong command - got %v want %v",
  28  			cmd, wantCmd,
  29  		)
  30  	}
  31  	// Ensure max payload is expected value for latest protocol version. Protocol version 4 bytes + num hashes (varInt)
  32  	// + max block locator hashes + hash stop.
  33  	wantPayload := uint32(16045)
  34  	maxPayload := msg.MaxPayloadLength(pver)
  35  	if maxPayload != wantPayload {
  36  		t.Errorf("MaxPayloadLength: wrong max payload length for "+
  37  			"protocol version %d - got %v, want %v", pver,
  38  			maxPayload, wantPayload,
  39  		)
  40  	}
  41  	// Ensure block locator hashes are added properly.
  42  	e = msg.AddBlockLocatorHash(locatorHash)
  43  	if e != nil {
  44  		t.Errorf("AddBlockLocatorHash: %v", e)
  45  	}
  46  	if msg.BlockLocatorHashes[0] != locatorHash {
  47  		t.Errorf("AddBlockLocatorHash: wrong block locator added - "+
  48  			"got %v, want %v",
  49  			spew.Sprint(msg.BlockLocatorHashes[0]),
  50  			spew.Sprint(locatorHash),
  51  		)
  52  	}
  53  	// Ensure adding more than the max allowed block locator hashes per message returns an error.
  54  	for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
  55  		e = msg.AddBlockLocatorHash(locatorHash)
  56  	}
  57  	if e == nil {
  58  		t.Errorf("AddBlockLocatorHash: expected error on too many " +
  59  			"block locator hashes not received",
  60  		)
  61  	}
  62  }
  63  
  64  // TestGetHeadersWire tests the MsgGetHeaders wire encode and decode for various numbers of block locator hashes and
  65  // protocol versions.
  66  func TestGetHeadersWire(t *testing.T) {
  67  	// Set protocol inside getheaders message. Use protocol version 60002 specifically here instead of the latest
  68  	// because the test data is using bytes encoded with that protocol version.
  69  	pver := uint32(60002)
  70  	// Block 99499 hash.
  71  	hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
  72  	hashLocator, e := chainhash.NewHashFromStr(hashStr)
  73  	if e != nil {
  74  		t.Errorf("NewHashFromStr: %v", e)
  75  	}
  76  	// Block 99500 hash.
  77  	hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
  78  	hashLocator2, e := chainhash.NewHashFromStr(hashStr)
  79  	if e != nil {
  80  		t.Errorf("NewHashFromStr: %v", e)
  81  	}
  82  	// Block 100000 hash.
  83  	hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
  84  	hashStop, e := chainhash.NewHashFromStr(hashStr)
  85  	if e != nil {
  86  		t.Errorf("NewHashFromStr: %v", e)
  87  	}
  88  	// MsgGetHeaders message with no block locators or stop hash.
  89  	noLocators := NewMsgGetHeaders()
  90  	noLocators.ProtocolVersion = pver
  91  	noLocatorsEncoded := []byte{
  92  		0x62, 0xea, 0x00, 0x00, // Protocol version 60002
  93  		0x00, // Varint for number of block locator hashes
  94  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  95  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  96  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  97  		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
  98  	}
  99  	// MsgGetHeaders message with multiple block locators and a stop hash.
 100  	multiLocators := NewMsgGetHeaders()
 101  	multiLocators.ProtocolVersion = pver
 102  	multiLocators.HashStop = *hashStop
 103  	e = multiLocators.AddBlockLocatorHash(hashLocator2)
 104  	if e != nil {
 105  		t.Log(e)
 106  	}
 107  	e = multiLocators.AddBlockLocatorHash(hashLocator)
 108  	if e != nil {
 109  		t.Log(e)
 110  	}
 111  	multiLocatorsEncoded := []byte{
 112  		0x62, 0xea, 0x00, 0x00, // Protocol version 60002
 113  		0x02, // Varint for number of block locator hashes
 114  		0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63,
 115  		0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65,
 116  		0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b,
 117  		0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash
 118  		0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60,
 119  		0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9,
 120  		0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40,
 121  		0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash
 122  		0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39,
 123  		0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2,
 124  		0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa,
 125  		0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
 126  	}
 127  	tests := []struct {
 128  		in   *MsgGetHeaders  // Message to encode
 129  		out  *MsgGetHeaders  // Expected decoded message
 130  		buf  []byte          // Wire encoding
 131  		pver uint32          // Protocol version for wire encoding
 132  		enc  MessageEncoding // Message encoding format
 133  	}{
 134  		// Latest protocol version with no block locators.
 135  		{
 136  			noLocators,
 137  			noLocators,
 138  			noLocatorsEncoded,
 139  			ProtocolVersion,
 140  			BaseEncoding,
 141  		},
 142  		// Latest protocol version with multiple block locators.
 143  		{
 144  			multiLocators,
 145  			multiLocators,
 146  			multiLocatorsEncoded,
 147  			ProtocolVersion,
 148  			BaseEncoding,
 149  		},
 150  		// Protocol version BIP0035Version with no block locators.
 151  		{
 152  			noLocators,
 153  			noLocators,
 154  			noLocatorsEncoded,
 155  			BIP0035Version,
 156  			BaseEncoding,
 157  		},
 158  		// Protocol version BIP0035Version with multiple block locators.
 159  		{
 160  			multiLocators,
 161  			multiLocators,
 162  			multiLocatorsEncoded,
 163  			BIP0035Version,
 164  			BaseEncoding,
 165  		},
 166  		// Protocol version BIP0031Version with no block locators.
 167  		{
 168  			noLocators,
 169  			noLocators,
 170  			noLocatorsEncoded,
 171  			BIP0031Version,
 172  			BaseEncoding,
 173  		},
 174  		// Protocol version BIP0031Versionwith multiple block locators.
 175  		{
 176  			multiLocators,
 177  			multiLocators,
 178  			multiLocatorsEncoded,
 179  			BIP0031Version,
 180  			BaseEncoding,
 181  		},
 182  		// Protocol version NetAddressTimeVersion with no block locators.
 183  		{
 184  			noLocators,
 185  			noLocators,
 186  			noLocatorsEncoded,
 187  			NetAddressTimeVersion,
 188  			BaseEncoding,
 189  		},
 190  		// Protocol version NetAddressTimeVersion multiple block locators.
 191  		{
 192  			multiLocators,
 193  			multiLocators,
 194  			multiLocatorsEncoded,
 195  			NetAddressTimeVersion,
 196  			BaseEncoding,
 197  		},
 198  		// Protocol version MultipleAddressVersion with no block locators.
 199  		{
 200  			noLocators,
 201  			noLocators,
 202  			noLocatorsEncoded,
 203  			MultipleAddressVersion,
 204  			BaseEncoding,
 205  		},
 206  		// Protocol version MultipleAddressVersion multiple block locators.
 207  		{
 208  			multiLocators,
 209  			multiLocators,
 210  			multiLocatorsEncoded,
 211  			MultipleAddressVersion,
 212  			BaseEncoding,
 213  		},
 214  	}
 215  	t.Logf("Running %d tests", len(tests))
 216  	for i, test := range tests {
 217  		// Encode the message to wire format.
 218  		var buf bytes.Buffer
 219  		e := test.in.BtcEncode(&buf, test.pver, test.enc)
 220  		if e != nil {
 221  			t.Errorf("BtcEncode #%d error %v", i, e)
 222  			continue
 223  		}
 224  		if !bytes.Equal(buf.Bytes(), test.buf) {
 225  			t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
 226  				spew.Sdump(buf.Bytes()), spew.Sdump(test.buf),
 227  			)
 228  			continue
 229  		}
 230  		// Decode the message from wire format.
 231  		var msg MsgGetHeaders
 232  		rbuf := bytes.NewReader(test.buf)
 233  		e = msg.BtcDecode(rbuf, test.pver, test.enc)
 234  		if e != nil {
 235  			t.Errorf("BtcDecode #%d error %v", i, e)
 236  			continue
 237  		}
 238  		if !reflect.DeepEqual(&msg, test.out) {
 239  			t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
 240  				spew.Sdump(&msg), spew.Sdump(test.out),
 241  			)
 242  			continue
 243  		}
 244  	}
 245  }
 246  
 247  // TestGetHeadersWireErrors performs negative tests against wire encode and decode of MsgGetHeaders to confirm error
 248  // paths work correctly.
 249  func TestGetHeadersWireErrors(t *testing.T) {
 250  	// Set protocol inside getheaders message. Use protocol version 60002 specifically here instead of the latest
 251  	// because the test data is using bytes encoded with that protocol version.
 252  	pver := uint32(60002)
 253  	wireErr := &MessageError{}
 254  	// Block 99499 hash.
 255  	hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
 256  	hashLocator, e := chainhash.NewHashFromStr(hashStr)
 257  	if e != nil {
 258  		t.Errorf("NewHashFromStr: %v", e)
 259  	}
 260  	// Block 99500 hash.
 261  	hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
 262  	hashLocator2, e := chainhash.NewHashFromStr(hashStr)
 263  	if e != nil {
 264  		t.Errorf("NewHashFromStr: %v", e)
 265  	}
 266  	// Block 100000 hash.
 267  	hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
 268  	hashStop, e := chainhash.NewHashFromStr(hashStr)
 269  	if e != nil {
 270  		t.Errorf("NewHashFromStr: %v", e)
 271  	}
 272  	// MsgGetHeaders message with multiple block locators and a stop hash.
 273  	baseGetHeaders := NewMsgGetHeaders()
 274  	baseGetHeaders.ProtocolVersion = pver
 275  	baseGetHeaders.HashStop = *hashStop
 276  	e = baseGetHeaders.AddBlockLocatorHash(hashLocator2)
 277  	if e != nil {
 278  		t.Log(e)
 279  	}
 280  	e = baseGetHeaders.AddBlockLocatorHash(hashLocator)
 281  	if e != nil {
 282  		t.Log(e)
 283  	}
 284  	baseGetHeadersEncoded := []byte{
 285  		0x62, 0xea, 0x00, 0x00, // Protocol version 60002
 286  		0x02, // Varint for number of block locator hashes
 287  		0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63,
 288  		0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65,
 289  		0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b,
 290  		0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash
 291  		0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60,
 292  		0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9,
 293  		0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40,
 294  		0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash
 295  		0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39,
 296  		0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2,
 297  		0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa,
 298  		0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
 299  	}
 300  	// Message that forces an error by having more than the max allowed
 301  	// block locator hashes.
 302  	maxGetHeaders := NewMsgGetHeaders()
 303  	for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
 304  		e = maxGetHeaders.AddBlockLocatorHash(&mainNetGenesisHash)
 305  		if e != nil {
 306  			t.Log(e)
 307  		}
 308  	}
 309  	maxGetHeaders.BlockLocatorHashes = append(maxGetHeaders.BlockLocatorHashes,
 310  		&mainNetGenesisHash,
 311  	)
 312  	maxGetHeadersEncoded := []byte{
 313  		0x62, 0xea, 0x00, 0x00, // Protocol version 60002
 314  		0xfd, 0xf5, 0x01, // Varint for number of block loc hashes (501)
 315  	}
 316  	tests := []struct {
 317  		in       *MsgGetHeaders  // value to encode
 318  		buf      []byte          // Wire encoding
 319  		pver     uint32          // Protocol version for wire encoding
 320  		enc      MessageEncoding // Message encoding format
 321  		max      int             // Max size of fixed buffer to induce errors
 322  		writeErr error           // Expected write error
 323  		readErr  error           // Expected read error
 324  	}{
 325  		// Force error in protocol version.
 326  		{baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
 327  		// Force error in block locator hash count.
 328  		{baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 4, io.ErrShortWrite, io.EOF},
 329  		// Force error in block locator hashes.
 330  		{baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 5, io.ErrShortWrite, io.EOF},
 331  		// Force error in stop hash.
 332  		{baseGetHeaders, baseGetHeadersEncoded, pver, BaseEncoding, 69, io.ErrShortWrite, io.EOF},
 333  		// Force error with greater than max block locator hashes.
 334  		{maxGetHeaders, maxGetHeadersEncoded, pver, BaseEncoding, 7, wireErr, wireErr},
 335  	}
 336  	t.Logf("Running %d tests", len(tests))
 337  	for i, test := range tests {
 338  		// Encode to wire format.
 339  		w := newFixedWriter(test.max)
 340  		e := test.in.BtcEncode(w, test.pver, test.enc)
 341  		if reflect.TypeOf(e) != reflect.TypeOf(test.writeErr) {
 342  			t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
 343  				i, e, test.writeErr,
 344  			)
 345  			continue
 346  		}
 347  		// For errors which are not of type MessageError, check them for equality.
 348  		if _, ok := e.(*MessageError); !ok {
 349  			if e != test.writeErr {
 350  				t.Errorf("BtcEncode #%d wrong error got: %v, "+
 351  					"want: %v", i, e, test.writeErr,
 352  				)
 353  				continue
 354  			}
 355  		}
 356  		// Decode from wire format.
 357  		var msg MsgGetHeaders
 358  		r := newFixedReader(test.max, test.buf)
 359  		e = msg.BtcDecode(r, test.pver, test.enc)
 360  		if reflect.TypeOf(e) != reflect.TypeOf(test.readErr) {
 361  			t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
 362  				i, e, test.readErr,
 363  			)
 364  			continue
 365  		}
 366  		// For errors which are not of type MessageError, check them for equality.
 367  		if _, ok := e.(*MessageError); !ok {
 368  			if e != test.readErr {
 369  				t.Errorf("BtcDecode #%d wrong error got: %v, "+
 370  					"want: %v", i, e, test.readErr,
 371  				)
 372  				continue
 373  			}
 374  		}
 375  	}
 376  }
 377