github.com/palcoin-project/palcd@v1.0.0/wire/msggetheaders_test.go (about)

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