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