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.
13 "github.com/btcsuite/btcd/chaincfg/chainhash"
14 "github.com/davecgh/go-spew/spew"
17 // TestGetHeaders tests the MsgGetHeader API.
18 func TestGetHeaders(t *testing.T) {
19 pver := ProtocolVersion
22 hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
23 locatorHash, err := chainhash.NewHashFromStr(hashStr)
25 t.Errorf("NewHashFromStr: %v", err)
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",
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)
47 // Ensure block locator hashes are added properly.
48 err = msg.AddBlockLocatorHash(locatorHash)
50 t.Errorf("AddBlockLocatorHash: %v", err)
52 if msg.BlockLocatorHashes[0] != locatorHash {
53 t.Errorf("AddBlockLocatorHash: wrong block locator added - "+
55 spew.Sprint(msg.BlockLocatorHashes[0]),
56 spew.Sprint(locatorHash))
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)
65 t.Errorf("AddBlockLocatorHash: expected error on too many " +
66 "block locator hashes not received")
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.
79 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
80 hashLocator, err := chainhash.NewHashFromStr(hashStr)
82 t.Errorf("NewHashFromStr: %v", err)
86 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
87 hashLocator2, err := chainhash.NewHashFromStr(hashStr)
89 t.Errorf("NewHashFromStr: %v", err)
93 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
94 hashStop, err := chainhash.NewHashFromStr(hashStr)
96 t.Errorf("NewHashFromStr: %v", err)
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
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
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
141 // Latest protocol version with no block locators.
150 // Latest protocol version with multiple block locators.
154 multiLocatorsEncoded,
159 // Protocol version BIP0035Version with no block locators.
168 // Protocol version BIP0035Version with multiple block locators.
172 multiLocatorsEncoded,
177 // Protocol version BIP0031Version with no block locators.
186 // Protocol version BIP0031Versionwith multiple block locators.
190 multiLocatorsEncoded,
195 // Protocol version NetAddressTimeVersion with no block locators.
200 NetAddressTimeVersion,
204 // Protocol version NetAddressTimeVersion multiple block locators.
208 multiLocatorsEncoded,
209 NetAddressTimeVersion,
213 // Protocol version MultipleAddressVersion with no block locators.
218 MultipleAddressVersion,
222 // Protocol version MultipleAddressVersion multiple block locators.
226 multiLocatorsEncoded,
227 MultipleAddressVersion,
232 t.Logf("Running %d tests", len(tests))
233 for i, test := range tests {
234 // Encode the message to wire format.
236 err := test.in.BtcEncode(&buf, test.pver, test.enc)
238 t.Errorf("BtcEncode #%d error %v", i, err)
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))
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)
252 t.Errorf("BtcDecode #%d error %v", i, err)
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))
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{}
273 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
274 hashLocator, err := chainhash.NewHashFromStr(hashStr)
276 t.Errorf("NewHashFromStr: %v", err)
280 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
281 hashLocator2, err := chainhash.NewHashFromStr(hashStr)
283 t.Errorf("NewHashFromStr: %v", err)
286 // Block 100000 hash.
287 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
288 hashStop, err := chainhash.NewHashFromStr(hashStr)
290 t.Errorf("NewHashFromStr: %v", err)
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
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)
322 maxGetHeaders.BlockLocatorHashes = append(maxGetHeaders.BlockLocatorHashes,
324 maxGetHeadersEncoded := []byte{
325 0x62, 0xea, 0x00, 0x00, // Protocol version 60002
326 0xfd, 0xf5, 0x01, // Varint for number of block loc hashes (501)
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
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},
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)
361 // For errors which are not of type MessageError, check them for
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)
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)
381 // For errors which are not of type MessageError, check them for
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)