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 // TestGetBlocks tests the MsgGetBlocks API.
18 func TestGetBlocks(t *testing.T) {
19 pver := ProtocolVersion
22 hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
23 locatorHash, err := chainhash.NewHashFromStr(hashStr)
25 t.Errorf("NewHashFromStr: %v", err)
29 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
30 hashStop, err := chainhash.NewHashFromStr(hashStr)
32 t.Errorf("NewHashFromStr: %v", err)
35 // Ensure we get the same data back out.
36 msg := NewMsgGetBlocks(hashStop)
37 if !msg.HashStop.IsEqual(hashStop) {
38 t.Errorf("NewMsgGetBlocks: wrong stop hash - got %v, want %v",
39 msg.HashStop, hashStop)
42 // Ensure the command is expected value.
43 wantCmd := "getblocks"
44 if cmd := msg.Command(); cmd != wantCmd {
45 t.Errorf("NewMsgGetBlocks: wrong command - got %v want %v",
49 // Ensure max payload is expected value for latest protocol version.
50 // Protocol version 4 bytes + num hashes (varInt) + max block locator
51 // hashes + hash stop.
52 wantPayload := uint32(16045)
53 maxPayload := msg.MaxPayloadLength(pver)
54 if maxPayload != wantPayload {
55 t.Errorf("MaxPayloadLength: wrong max payload length for "+
56 "protocol version %d - got %v, want %v", pver,
57 maxPayload, wantPayload)
60 // Ensure block locator hashes are added properly.
61 err = msg.AddBlockLocatorHash(locatorHash)
63 t.Errorf("AddBlockLocatorHash: %v", err)
65 if msg.BlockLocatorHashes[0] != locatorHash {
66 t.Errorf("AddBlockLocatorHash: wrong block locator added - "+
68 spew.Sprint(msg.BlockLocatorHashes[0]),
69 spew.Sprint(locatorHash))
72 // Ensure adding more than the max allowed block locator hashes per
73 // message returns an error.
74 for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
75 err = msg.AddBlockLocatorHash(locatorHash)
78 t.Errorf("AddBlockLocatorHash: expected error on too many " +
79 "block locator hashes not received")
83 // TestGetBlocksWire tests the MsgGetBlocks wire encode and decode for various
84 // numbers of block locator hashes and protocol versions.
85 func TestGetBlocksWire(t *testing.T) {
86 // Set protocol inside getblocks message.
90 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
91 hashLocator, err := chainhash.NewHashFromStr(hashStr)
93 t.Errorf("NewHashFromStr: %v", err)
97 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
98 hashLocator2, err := chainhash.NewHashFromStr(hashStr)
100 t.Errorf("NewHashFromStr: %v", err)
103 // Block 100000 hash.
104 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
105 hashStop, err := chainhash.NewHashFromStr(hashStr)
107 t.Errorf("NewHashFromStr: %v", err)
110 // MsgGetBlocks message with no block locators or stop hash.
111 noLocators := NewMsgGetBlocks(&chainhash.Hash{})
112 noLocators.ProtocolVersion = pver
113 noLocatorsEncoded := []byte{
114 0x62, 0xea, 0x00, 0x00, // Protocol version 60002
115 0x00, // Varint for number of block locator hashes
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
122 // MsgGetBlocks message with multiple block locators and a stop hash.
123 multiLocators := NewMsgGetBlocks(hashStop)
124 multiLocators.AddBlockLocatorHash(hashLocator2)
125 multiLocators.AddBlockLocatorHash(hashLocator)
126 multiLocators.ProtocolVersion = pver
127 multiLocatorsEncoded := []byte{
128 0x62, 0xea, 0x00, 0x00, // Protocol version 60002
129 0x02, // Varint for number of block locator hashes
130 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63,
131 0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65,
132 0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b,
133 0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash
134 0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60,
135 0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9,
136 0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40,
137 0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash
138 0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39,
139 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2,
140 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa,
141 0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
145 in *MsgGetBlocks // Message to encode
146 out *MsgGetBlocks // Expected decoded message
147 buf []byte // Wire encoding
148 pver uint32 // Protocol version for wire encoding
149 enc MessageEncoding // Message encoding format
151 // Latest protocol version with no block locators.
160 // Latest protocol version with multiple block locators.
164 multiLocatorsEncoded,
169 // Protocol version BIP0035Version with no block locators.
178 // Protocol version BIP0035Version with multiple block locators.
182 multiLocatorsEncoded,
187 // Protocol version BIP0031Version with no block locators.
196 // Protocol version BIP0031Versionwith multiple block locators.
200 multiLocatorsEncoded,
205 // Protocol version NetAddressTimeVersion with no block locators.
210 NetAddressTimeVersion,
214 // Protocol version NetAddressTimeVersion multiple block locators.
218 multiLocatorsEncoded,
219 NetAddressTimeVersion,
223 // Protocol version MultipleAddressVersion with no block locators.
228 MultipleAddressVersion,
232 // Protocol version MultipleAddressVersion multiple block locators.
236 multiLocatorsEncoded,
237 MultipleAddressVersion,
242 t.Logf("Running %d tests", len(tests))
243 for i, test := range tests {
244 // Encode the message to wire format.
246 err := test.in.BtcEncode(&buf, test.pver, test.enc)
248 t.Errorf("BtcEncode #%d error %v", i, err)
251 if !bytes.Equal(buf.Bytes(), test.buf) {
252 t.Errorf("BtcEncode #%d\n got: %s want: %s", i,
253 spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
257 // Decode the message from wire format.
259 rbuf := bytes.NewReader(test.buf)
260 err = msg.BtcDecode(rbuf, test.pver, test.enc)
262 t.Errorf("BtcDecode #%d error %v", i, err)
265 if !reflect.DeepEqual(&msg, test.out) {
266 t.Errorf("BtcDecode #%d\n got: %s want: %s", i,
267 spew.Sdump(&msg), spew.Sdump(test.out))
273 // TestGetBlocksWireErrors performs negative tests against wire encode and
274 // decode of MsgGetBlocks to confirm error paths work correctly.
275 func TestGetBlocksWireErrors(t *testing.T) {
276 // Set protocol inside getheaders message. Use protocol version 60002
277 // specifically here instead of the latest because the test data is
278 // using bytes encoded with that protocol version.
279 pver := uint32(60002)
280 wireErr := &MessageError{}
283 hashStr := "2710f40c87ec93d010a6fd95f42c59a2cbacc60b18cf6b7957535"
284 hashLocator, err := chainhash.NewHashFromStr(hashStr)
286 t.Errorf("NewHashFromStr: %v", err)
290 hashStr = "2e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
291 hashLocator2, err := chainhash.NewHashFromStr(hashStr)
293 t.Errorf("NewHashFromStr: %v", err)
296 // Block 100000 hash.
297 hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
298 hashStop, err := chainhash.NewHashFromStr(hashStr)
300 t.Errorf("NewHashFromStr: %v", err)
303 // MsgGetBlocks message with multiple block locators and a stop hash.
304 baseGetBlocks := NewMsgGetBlocks(hashStop)
305 baseGetBlocks.ProtocolVersion = pver
306 baseGetBlocks.AddBlockLocatorHash(hashLocator2)
307 baseGetBlocks.AddBlockLocatorHash(hashLocator)
308 baseGetBlocksEncoded := []byte{
309 0x62, 0xea, 0x00, 0x00, // Protocol version 60002
310 0x02, // Varint for number of block locator hashes
311 0xe0, 0xde, 0x06, 0x44, 0x68, 0x13, 0x2c, 0x63,
312 0xd2, 0x20, 0xcc, 0x69, 0x12, 0x83, 0xcb, 0x65,
313 0xbc, 0xaa, 0xe4, 0x79, 0x94, 0xef, 0x9e, 0x7b,
314 0xad, 0xe7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99500 hash
315 0x35, 0x75, 0x95, 0xb7, 0xf6, 0x8c, 0xb1, 0x60,
316 0xcc, 0xba, 0x2c, 0x9a, 0xc5, 0x42, 0x5f, 0xd9,
317 0x6f, 0x0a, 0x01, 0x3d, 0xc9, 0x7e, 0xc8, 0x40,
318 0x0f, 0x71, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 99499 hash
319 0x06, 0xe5, 0x33, 0xfd, 0x1a, 0xda, 0x86, 0x39,
320 0x1f, 0x3f, 0x6c, 0x34, 0x32, 0x04, 0xb0, 0xd2,
321 0x78, 0xd4, 0xaa, 0xec, 0x1c, 0x0b, 0x20, 0xaa,
322 0x27, 0xba, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // Hash stop
325 // Message that forces an error by having more than the max allowed
326 // block locator hashes.
327 maxGetBlocks := NewMsgGetBlocks(hashStop)
328 for i := 0; i < MaxBlockLocatorsPerMsg; i++ {
329 maxGetBlocks.AddBlockLocatorHash(&mainNetGenesisHash)
331 maxGetBlocks.BlockLocatorHashes = append(maxGetBlocks.BlockLocatorHashes,
333 maxGetBlocksEncoded := []byte{
334 0x62, 0xea, 0x00, 0x00, // Protocol version 60002
335 0xfd, 0xf5, 0x01, // Varint for number of block loc hashes (501)
339 in *MsgGetBlocks // Value to encode
340 buf []byte // Wire encoding
341 pver uint32 // Protocol version for wire encoding
342 enc MessageEncoding // Message encoding format
343 max int // Max size of fixed buffer to induce errors
344 writeErr error // Expected write error
345 readErr error // Expected read error
347 // Force error in protocol version.
348 {baseGetBlocks, baseGetBlocksEncoded, pver, BaseEncoding, 0, io.ErrShortWrite, io.EOF},
349 // Force error in block locator hash count.
350 {baseGetBlocks, baseGetBlocksEncoded, pver, BaseEncoding, 4, io.ErrShortWrite, io.EOF},
351 // Force error in block locator hashes.
352 {baseGetBlocks, baseGetBlocksEncoded, pver, BaseEncoding, 5, io.ErrShortWrite, io.EOF},
353 // Force error in stop hash.
354 {baseGetBlocks, baseGetBlocksEncoded, pver, BaseEncoding, 69, io.ErrShortWrite, io.EOF},
355 // Force error with greater than max block locator hashes.
356 {maxGetBlocks, maxGetBlocksEncoded, pver, BaseEncoding, 7, wireErr, wireErr},
359 t.Logf("Running %d tests", len(tests))
360 for i, test := range tests {
361 // Encode to wire format.
362 w := newFixedWriter(test.max)
363 err := test.in.BtcEncode(w, test.pver, test.enc)
364 if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
365 t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
366 i, err, test.writeErr)
370 // For errors which are not of type MessageError, check them for
372 if _, ok := err.(*MessageError); !ok {
373 if err != test.writeErr {
374 t.Errorf("BtcEncode #%d wrong error got: %v, "+
375 "want: %v", i, err, test.writeErr)
380 // Decode from wire format.
382 r := newFixedReader(test.max, test.buf)
383 err = msg.BtcDecode(r, test.pver, test.enc)
384 if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
385 t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
386 i, err, test.readErr)
390 // For errors which are not of type MessageError, check them for
392 if _, ok := err.(*MessageError); !ok {
393 if err != test.readErr {
394 t.Errorf("BtcDecode #%d wrong error got: %v, "+
395 "want: %v", i, err, test.readErr)