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